2012-12-04 12 views
5

Wiąże się to Emacs: regular expression replacing to change caseEmacs: wyrażenie regularne zastąpienie aby zmienić wielkość liter (w skryptach)

My dodatkowym problemem jest to, że muszę skrypt poszukiwania zamień ale rozwiązanie "\,()" działa (dla mnie) tylko wtedy, gdy używany interaktywnie (emacs 24.2.1). Wewnątrz skryptu pojawia się błąd: "Nieprawidłowe użycie \' w tekście zastępczym".

Zwykle piszę "perform-replace" do jakiegoś pliku, który ma być załadowany w razie potrzeby. Coś jak:

(wykonaj-zastąpić "<\\([^>]+\\)>" "<\\,(downcase \1)>" tt nil 1 nil (point-min) (point-max))

To powinno być możliwe do wywołania funkcji do generowania wymiany (pg 741 of the emacs lisp manual), ale próbowałem wiele warianty następujące bez powodzenia:

(defun myfun() 
    (downcase (match-string 0))) 

(perform-replace "..." (myfun .()) t t nil) 

Czy ktoś może pomóc?

Odpowiedz

3

Konstrukcje takie jak \,() są dozwolone tylko w rozmowach interaktywnych pod numerem query-replace, dlatego Emacs narzeka w Twoim przypadku.

Dokumentacja perform-replace wspomina, że ​​nie należy używać go w kodzie elisp i proponuje lepszą alternatywę, na której możemy budować następujący kod:

(while (re-search-forward "<\\([^>]+\\)>" nil t) 
    (replace-match (downcase (match-string 0)) t nil)) 

Jeśli nadal chcesz interaktywnie zapytania użytkownik o zamianie, używając perform-replace, tak jak to zrobiłeś, jest prawdopodobnie słuszny. Było kilka różnych problemów w kodzie:

  1. Jak stwierdzono w elisp manual funkcja zastępcza musi mieć dwa argumenty (Dane podać w komórce cons i liczby wymian już wykonane).

  2. Jak podano w dokumentacji query-replace-regexp (lub elisp manual), należy się upewnić, że case-fold-search lub case-replace jest ustawiony na zero, tak że sprawa wzór nie jest przekazywana do wymiany.

  3. Musisz zacytować komórkę cons, (myfun . nil), w przeciwnym razie zostanie ona zinterpretowana jako wywołanie funkcji i oceniona zbyt wcześnie.

Oto wersja robocza:

(let ((case-fold-search nil)) 
    (perform-replace "<\\([^>]+\\)>" 
        `(,(lambda (data count) 
         (downcase (match-string 0)))) 
        t t nil)) 
+0

nop, potrzebuję kwerendy (y/n /! Itp.) I podświetlić możliwości wykonania-zamień (wolę nie uzupełnić go ponownie) z y-or-np + highlight-regexp lub podobnym) –

+0

Możesz chcieć edytować swoje pytanie, aby odzwierciedlić to ograniczenie. W każdym razie zaproponowałem rozwiązanie oparte na 'perform-replace', które powinno spełnić twoje wymagania. – Francesco

2

C-h f perform-replace mówi:

Don't use this in your own program unless you want to query and set the mark 
just as `query-replace' does. Instead, write a simple loop like this: 

    (while (re-search-forward "foo[ \t]+bar" nil t) 
    (replace-match "foobar")) 

teraz "<\\,(downcase \1)>" musi być zastąpiona wyrazem Elisp który buduje właściwą ciąg, takich jak (format "<%s>" (downcase (match-string 1))) .

Jeśli potrzebujesz zapytania i innych rzeczy, możesz spróbować: C-M-% f\(o\)o RET bar \,(downcase \1) baz RET, a następnie C-x RET RET, aby zobaczyć, jakie argumenty zostały skonstruowane podczas rozmowy interaktywnej.

Zobaczysz odkryć (nawet lepiej, jeśli klikniesz na replace.el w C-h f perform-replace zobaczyć kod źródłowy funkcji), że replacements argument może przyjąć formę (funkcję. Argument). Dokładniej, kod zawiera komentarz podając pewne szczegóły:

;; REPLACEMENTS is either a string, a list of strings, or a cons cell 
;; containing a function and its first argument. The function is 
;; called to generate each replacement like this: 
;; (funcall (car replacements) (cdr replacements) replace-count) 
;; It must return a string. 
+0

Potrzebuję "zapytać" :-) –

Powiązane problemy