W odpowiedzi na kolejne pytanie dotyczące nowego systemu porad :
W starym stylu advice.el
można było manipulować poszczególnymi elementami listy argumentów zalecanej funkcji, nie czyniąc żadnych twierdzeń dotyczących tych elementów, które nie są tak zmanipulowane. Na przykład następujące porady:
(defadvice ansi-term (around prompt-for-name last)
(let ((name (read-from-minibuffer "Tag: ")))
(and (not (string= name ""))
(ad-set-arg 1 (concat "Term: " name)))
ad-do-it))
pozwala na (opcjonalne) dostarczenie argumentu nazwy bufora do ansi-term
wywołania, podczas gdy ansi-term
nadal uzyska swój pierwszy argument, pytając zgodnie z własną interaktywną formą.
(W celu późniejszego wykorzystania ansi-term
podpis jest (PROGRAM &optional BUFFER-NAME)
, a jego interaktywna forma monituje o PROGRAM z kilkoma możliwymi ustawieniami domyślnymi, ale nie robi nic w odniesieniu do NAZWY BUFORA.)
Nie jestem pewien, czy jest to możliwe w nadvice.el
. Jeśli tak, nie jestem pewien, jak to zrobić. Znalazłem kilka sposobów na zastąpienie listy argumentów zalecanej funkcji.
Na przykład z * info * (elisp) Kombinatory porad :
`:filter-args' Call FUNCTION first and use the result (which should be a list) as the new arguments to pass to the old function. More specifically, the composition of the two functions behaves like: (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
Inne kombinatory zapewniają podobne możliwości, a wspólny wątek wśród nich polega na tym, że chociaż lista argumentów funkcji może zostać zastąpiona, obcięta, rozszerzona i in., Nie ma widocznego sposobu, aby porady funkcji modyfikowały argument na danej pozycji na liście bez twierdząc cokolwiek na temat reszty .
W omawianym przypadku autor porady nie wydaje ansi-term
tylko nazwy bufora, ponieważ nie jest możliwe zbudowanie listy, która ma wartość na pozycji 1, ale nic, nawet nil
na pozycji 0. W ogólnym przypadku autorowi porady wydaje się niemożliwe arbitralne modyfikowanie argumentów poza pozycją 0.
Wydaje się to niefortunne, ponieważ w celu uzyskania podobnego efektu konieczne jest skopiowanie i wklejenie kodu: w szczególności albo mogę skopiować ansi-term
interaktywną formę i rozszerzyć ją według własnego gustu, albo mogę ansi-term
całkowicie skopiować i rozszerzyć go w podobny sposób. W obu przypadkach muszę teraz przedefiniować część dystrybucji Emacs Lisp w moim pliku init, co wydaje mi się niepożądane ze względu zarówno na trwałość, jak i na estetykę.
Moje pytanie brzmi zatem: czy można tego rodzaju manipulowanie listą argumentów można wykonać nadvice.el
? Jeśli tak to jak?
Odpowiedzi:
Przeciwnie, myślę, że dobrym pomysłem byłoby skopiowanie i wklejenie interaktywnej formy zalecanej funkcji, nawet jeśli tak naprawdę nie musisz tego robić tutaj.
Czytam ci pytanie od góry do dołu. Kiedy dotarłem do bloku kodu, zgadłem, że twoja rada prawdopodobnie zmienia nazwę bufora. Ale nie wiedziałem, dopóki nie podałeś podpisu jako komentarza.
Rzeczywiście nic nie jest niczym innym jak niczym. :-) Ale tutaj nie ma to większego znaczenia.
Jak widać w cytowanej dokumentacji, wartość zwrócona przez poradę jest używana jako argumenty zalecanej funkcji. Zwracana wartość musi być listą wszystkich argumentów, a nie tylko tych, które uległy zmianie.
Pozostając jak najbliżej starej porady, oto co powinieneś zrobić, używając
nadvice
:Ale radzę zamiast tego zdefiniować takie porady:
Ten wariant w rzeczywistości jest oczywisty.
źródło
args
listę w przypadku połączenia typu „(ansi-term "foo")
inaczej”, w przeciwnym razie(setf (nth 1 args)...
pojawiłby się błąd.buffer-name
jest to obowiązkowe.:filter-args
rada otrzymuje pojedynczy argument, który jest listą argumentów zalecanej funkcji, więc pierwszy wariant powinien spaść,&rest
a drugi wariant musiałby użyć jakiegoś konstruktu destrukcyjnego, aby uzyskać ładne nazwy.Oto jak bym to zrobił:
kiedy to ja przedstawiłem
:filter-args
, osobiście uważam, że rzadko jest to wygodne.źródło