Emacs dizinindeki / alt dizinlerindeki / grep dosya içeriklerini özyinelemeli olarak nasıl arayabilirim?


14

Emacs oldukça uzun bir süre kullanıyorum ve hala bir şekilde (özyinelemeli) bir (proje) dizini içinde bir dize için grep için en iyi yolu nedir anlamak ve başarısız bir direk tampon veya daha da fazla sunulan sonuçları almak için başarısız yararlı bir yol. Lütfen beni aydınlat.


helm-projectile-grepKomut kullanmayı denediniz mi (yüklü dümen merminiz varsa) veya projectile-grep?
Chakravarthy Raghunandan

Ne olduğunu helmveya ne olduğunu bilmiyorum projectile, ancak önerilen bir araçsa, kurar ve öğrenirim.
Boris Stitnicky

Evet, mermi, komutta soruda belirttiklerinizi yapmanın kolay bir yolunu sunan bir pakettir projectile-grep. Ayrıca, helmpaketi yüklemenizi şiddetle tavsiye ederim . Ben olmadan emacs çalıştıran düşünemiyorum helmve helm-projectile. Ayrıca helm-agpakette de ilginç olabilirsiniz (emacs'ta gümüş arama yapan için grep veya ack'ten daha hızlı olduğu söylenen bir dümen arayüzü sağlar).
Chakravarthy Raghunandan

2
Sorunun gelecekteki Google ve forum arayanlar için daha yararlı ve daha kolay bulunması için, belki de sorunun başlığını kelimeyi özyinelemeli olarak içerecek şekilde değiştirmeyi ve kapsamı sınırlamayı düşünün - örneğin, Bir dizindeki dosya içeriğini yinelemeli olarak nasıl grep / alt dizinler . Bu sadece bir örnek - bunun yerine başka bir şey olabilir.
hukukçu

1
Şimdiye kadar yapılan yorumlar ve cevaplar bunu çeşitli süslü yollarla yapmak için bir takım paketler önermekle birlikte, neden basit M-x grepolanın neye ihtiyacınız olduğunu yapmadığını sorunuzdan anlamıyorum . Rastgele bir komut satırı verelim find, özyineleme gerektiğinde bazen orada kullanıyorum .
HARİTA

Yanıtlar:


15

Orijinal sorudan bahsetmediği için rgrep, devam edeceğim ve burada göstereceğim. Bu zaten Emacs'ta yerleşik en basit seçenektir ve çoğu şey için fazlasıyla yeterli buldum.

Belgelerden,

Recursively grep for REGEXP in FILES in directory tree rooted at DIR.

Arama, kabuk deseni FILES ile eşleşen dosya adları ile sınırlıdır.

Dolayısıyla, örneğin, bir kullanımlar için benim ev dizinine altındaki tüm piton dosyaları aramak için some_functionben onu çağırır, some_function, *.py, ~/argüman olarak. Sonuçlar yeni bir arabellekte görüntülenir.


1
find-grep-diredOP de "sonuçlar bir
dired

@npostavs find-grep-diredKendimi kullanmadım, cevaba eklemek için çekinmeyin.
user2699

Bir zamanlar, ack ve ag gibi şeyleri denedim, rgrep'ten bunları kullanan bir şeye geçmem gerektiği varsayımı üzerine, çünkü daha iyi olmaları gerekiyordu. Sonunda ben rgrep kaldı, çünkü değiştirmek için hiçbir fayda bulunamadı! Komut satırında kesinlikle yapılması gereken bir durum var, ancak Emacs'da rgreparamayı hedeflemek için o kadar iyi bir iş var ki aralarında önemli bir hız farkı yoktu. ( Bazı durumlarda rgrep'in fraksiyonel olarak daha hızlı olduğunu söylemek istiyorum , ama kesin olarak hatırlamıyorum.)
phils

1
O Not next-errorve previous-errorsonuç kümesinde gezinmek için kullanılabilir. Ben bulmak M-g M-nve M-g M-pstandart ciltleri en uygun.
phils

find-grep-diredbana çapraz referans bağlantıları olan bir tampon vermez. rgrepbenim için yapar ve bu hakkında son öneri next-error previous-errorfantastic! Benim tek kelime oyunu tamponun başlangıcında tüm dağınık komut yürütme çıktısı.
robert

11

M-x find-grep-diredYıllarca mutlu kullanıyorum . Sonuçları kullanabileceğiniz bir yönlendirilmiş arabellek olarak döndürür.


Bunun için çapraz referans bağlantısı elde etmekte biraz zorluk yaşadım. Yapılandırması oldukça kötü ( find-ls-option) ve sonuçta dosya adından önceki bir tarih olmadan çalışmadığı için oldukça ayrıntılı bir şeyle sonuçlanıyorsunuz!
robert

5

Çözüm 1 (en iyi çözüm):

Danışmanı kurun ( https://github.com/abo-abo/swiper/blob/master/counsel.el )

Sonra M-x counsel-git-grep.

Kurulum gerekmez (git, proje kökünü ve hariç tutulacak dosyaları bilir). Hem git grepve counselverimlidir.

Projenin git tarafından yönetilmesi gerekiyor.

öğüt sarmaşık modu gerektirir.

Çözüm 2:

Bu çözüm grep kullanır ve herhangi bir projede çalışır. Çözüm 1'den daha düşüktür, çünkü daha yavaştır ve manuel kuruluma ihtiyaç duyar. Ayrıca sarmaşık moduna da dayanıyor.

(defvar simple-project-root "~/.emacs.d")
(defun simple-grep ()
  (interactive)
  (unless (featurep 'ivy)
    (require 'ivy))
  (let* ((default-directory (file-name-as-directory simple-project-root))
         (keyword (read-string "Keyword:")))
    (ivy-read (format "Grep at %s:" simple-project-root)
              (split-string (shell-command-to-string (format "grep -rsnI %s ." keyword)) "\n" t)
              :action (lambda (val)
                        (let* ((lst (split-string val ":"))
                               (linenum (string-to-number (cadr lst))))
                          ;; open file
                          (find-file (car lst))
                          ;; goto line if line number exists
                          (when (and linenum (> linenum 0))
                            (goto-char (point-min))
                            (forward-line (1- linenum))))))))

Kurulum için .dir-locals.el oluşturmanız gerekir simple-project-root, teknik ayrıntılar için https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html adresine bakın.

Çözüm 2'deki kod sadece bir prototiptir. Benim gerçek uygulamam çok daha karmaşık. Bkz counsel-etags-grep. Https://github.com/redguardtoo/counsel-etags/blob/master/counsel-etags.el

Özet:

Bunlar bildiğim en iyi iki çözüm.

Başka daha iyi çözümler varsa, üretime hazır olmak için en azından aşağıdaki sorunları çözmeleri gerekir,

  • anahtar kelimenin grep'e nasıl getirileceği (örneğin, seçilen bölgeden anahtar kelime nasıl alınır)

  • anahtar kelimeden kaç

  • daha verimli bir grep programı varsa, onu kullanmalıyız (ripgrep, the_silver_searcher / ag, ... vb) veya başka bir şekilde varsayılan grep

  • aday penceresi tam ekran genişliğini kullanmalıdır ve kullanıcılar adayları etkileşimli olarak filtreleyebilir (bu yüzden insanlar sarmaşık veya dümen kullanır)

  • göreceli yolu aday penceresinde göstermeliyiz

  • önceki açılmış sonucu yeniden kullanabilir. Bu yüzden önceki sonuç kaydedilmelidir. Sen kullanabilirsiniz ivy-resumegelen ivyveya helm-resumegelenhelm

  • Önceki açılmış sonucu kaydettiğinizde, önceki sonucun içeriği de kaydedilmelidir. Örneğin, Çözüm 2 kodunda default-directorybağlamdır. Daha fazla bilgi için https://github.com/abo-abo/swiper/issues/591 adresine bakın.

  • Genişletilmiş normal ifade kullanılmalıdır çünkü daha basittir ve counsel-git-grepthe_silver_searcher / ag tarafından zaten kullanılır .


4

@Chen bin'in çözümünün de kullandığı başka bir çözüm eklemek istiyorum counsel(ancak bunun için bir projeye sahip olmanıza gerek yok git).

Ag (silver searcher) kurmanız ve geçerli dizinde girilen dizeyi arayan counselkomutu sağlar counsel-ag.

Bir proje içinde (sadece geçerli çalışma dizinini değil) aramak istiyorsanız, bunu şu adrese ekleyin .emacs: -

  (defun rag/counsel-ag-project-at-point ()
    "use counsel ag to search for the word at point in the project"
    (interactive)
    (counsel-ag (thing-at-point 'symbol) (projectile-project-root)))

Bu işlev ag, proje kök dizininde özyinelemeli olarak arama yapmak için kullanılır .

Düzenle : yukarıdaki işlev, arama noktasındaki simgeyi varsayılan olarak kullanır. Eğer böyle bir davranış gibi yapmazsanız, yerini (thing-at-point 'symbol)ile nil. Ve eğer arama sonuçlarını kendi tampon belleğinde istiyorsanızC-c C-o

Edit2 : Eğer verdiyseniz ripgrepyüklü, sen yerini alabilir counsel-agile counsel-rgyukarıdaki işlevinde ve sadece para cezası olarak olacak :)


projectile-project-rootRaylar proje kökünü bulmak için kullanışlı?
Boris Stitnicky

Evet, geçerli bir mermi projesi olduğu sürece çalışacaktır. Sanırım mermi rayları adı verilen bir paket vardı.
Chakravarthy Raghunandan

Neden işlevi adlandırdınız rag/...?
Boris Stitnicky

İnsanların kendi işlevlerini yazarken sıklıkla kullandıkları yaygın bir stildir (emacs yapılandırmasına göz atarsanız, birçok kişi tarafından yapıldığını görebilirsiniz). Tanımladığım tüm fonksiyonlar rag/önek ile başlar ve bu onların altında bulunmasını kolaylaştırır M-x:)
Chakravarthy Raghunandan

Ic, bu senin adın :-)
Boris Stitnicky

2

Aşağıda, bir dizinde ve alt dizinlerinde dosya içeriğini (arama terimi için regexp kullanarak) özyinelemeli olarak çağıran ve sonuçları önce ve sonra bağlam çizgileriyle görüntüleyen özel bir grep işlevine bir örnek verilmiştir. Dahili içinde compile.elve grep.elçeşitli yöntemler arama sonuçlarını içeren dosyada konuma atlamak için kütüphaneler sağlarlar. Bu örneğin çalışması için başka bir şey yüklemeye gerek yoktur - tek gereken Emacs'ın tam sürümü ve grepyardımcı programın yüklü olduğu bir bilgisayardır . Değişken grep-programbelirli bir konuma işaret için ayarlanabilir grepvarsayılan yeterli değilse yarar.

(defun recursive-grep ()
"Recursively grep file contents.  `i` case insensitive; `n` print line number;
`I` ignore binary files; `E` extended regular expressions; `r` recursive"
(interactive)
  (let* ((search-term (read-string "regex:  "))
         (search-path
           (directory-file-name (expand-file-name (read-directory-name "directory:  "))))
         (default-directory (file-name-as-directory search-path))
         (grep-command
           (concat
             grep-program
             " "
             "-inIEr --color=always -C2"
             " "
             search-term
             " "
             search-path)))
    (compilation-start grep-command 'grep-mode (lambda (mode) "*grep*") nil)))

Sorusu aynı anda yukarıda grep işlevi tarafından sonuçlar olarak döndürülen birden fazla dosya nasıl değiştirileceğini aramak etmese de, bunu çok yararlı kullanmak bulmak multiple-cursorsve wgrep. Tek seferde birden fazla dosyayı değiştirmeyi çok kolaylaştırır. Ancak, söz konusu özellikler isteniyorsa, söz konusu kütüphanelerin kurulması gerekir.
hukukçu

Bunu yerleşik olarak kullanmanın avantajı nedir rgrep?
npostavs

1
@npostavs - Yerleşikin, rgreptercih edilen normal ifade arama ölçütlerimi özelleştirmek için zaman alıcı olduğunu buldum ve özel bir işlevdeki (her gün birkaç kez kullandığım) her şeyi zor kodlamayı seçtim. Nasıl özelleştirileceğini açıklayan alternatif bir cevap yazmak isterseniz rgrep, bu, gelecekte diğer forum okuyucularına yardımcı olacaktır.
kanun listesi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.