Jak dowiedzieć się, co naprawdę robi sekwencja klawiszy

14

Od czasu do czasu obserwuję nieoczekiwane zachowanie podczas edycji tekstu. Moim pierwszym rozwiązaniem jest zazwyczaj C-h ksprawdzenie, jakie funkcje wywoływane są przez daną sekwencję klawiszy. Czasami jednak dokumentacja jest sprzeczna z zaobserwowanym zachowaniem. W takich przypadkach zwykle zakładam, że jakiś inny pakiet zaczepił się w tej funkcji lub sekwencji klawiszy i modyfikuje swoje zachowanie.

Jak mogę dowiedzieć się, które funkcje zaczepiają się w mojej sekwencji klawiszy?

Jednym z przykładów, które ostatnio spotkałem, było naciśnięcie "klawisza, a znaki cudzysłowu zostały wstawione na początku i na końcu aktywnego regionu. Podejrzewałem, że nie jest to domyślne zachowanie Emacsa, więc szukałem C-h k ", jaka funkcja jest faktycznie wywoływana.

describe-keyDokumentacja powiedział mi, że funkcja self-insert-commandzostała miano, która jest wbudowana funkcja. Krótko mówiąc, po pewnym czasie prób i błędów udało mi się ustalić, że zachowanie było spowodowane electric-pair-mode. Czy w przyszłości można szybciej dojść do takiego wniosku, niż wyłączać podejrzane pakiety pojedynczo, aż do znalezienia winowajcy?

nispio
źródło
Czy to możliwe, że electric-pair-modezostał aktywowany tylko w niektórych głównych trybach? Czy nadal zobaczyć self-insert-commandna "kiedy to zrobić C-h k, gdy electric-pair-modejest aktywny?
Kaushal Modi
@kaushalmodi: Okazuje się, że electric-pair-modedziała poprzez zaczepienie się post-self-insert-hook, a nie zmianę przypisania klawiszy.
nispio
C-h kmówi dokładnie, co dzieje się po naciśnięciu klawisza. Jeśli spojrzysz na dokumentację self-insert-command, wyraźnie widać, że post-self-insert-hookjest uruchamiana po zakończeniu polecenia.
shosti
@shosti: W tym prostym przykładzie tak. Ale co jeśli, jeśli rozszerzenie użyje after-change-functionstak, jak Jordon wspomina w swojej odpowiedzi? Dokumentacja funkcji prawdopodobnie nie wspomina konkretnie o tym haku, prawda?
nispio
Przepraszam, powinienem był bardziej konkretny. C-h k+ standardowe zaczepy == pełne zachowanie (mniej więcej). Oczywiście czasami pozostawia to wiele możliwości, ale wciąż jest o wiele bardziej przejrzysta niż jakikolwiek inny złożony system oprogramowania, o którym wiem.
shosti

Odpowiedzi:

13

Nie ma łatwego sposobu, aby dokładnie wiedzieć, co zrobi jedno naciśnięcie klawisza.

Jeśli widzisz dodatkowe zachowanie, zawsze sprawdzaj wspólne haki. Zobacz listę tutaj: http://www.gnu.org/software/emacs/manual/html_node/elisp/Standard-Hooks.html

W większości przypadków najważniejsze to:

  • funkcje po zmianie
  • funkcje przed zmianą
  • hak pierwszej zmiany
  • hak post-Command
  • hak przed dowództwem
  • hak post-self-insert

Musisz sprawdzić te haczyki i przejrzeć zawarte w nich funkcje, aby zobaczyć, który z nich modyfikuje twoje zachowanie.

Jeśli funkcje w tych zaczepach nie w pełni opisują zaobserwowane zachowanie, sprawdź funkcje, aby uzyskać porady, które pojawią się w ich dokumentacji describe-function.


Edycja: Napisałem kilka funkcji, które pomagają lepiej opisać hak, niż przeglądanie funkcji jedna po drugiej: https://gist.github.com/jordonbiondo/bad03e44bb053db0f1eb Można describe-hooktam zdefiniować tak jak inne funkcje opisujące. Oto próbka jego wyników:

A oto cały kod, na wypadek gdyby istota zniknęła:

(defun guess-all-hooks ()
  "Return a list of all variables that are probably hook lists."
  (let ((syms '()))
    (mapatoms
     (lambda (sym)
       (if (ignore-errors (symbol-value sym))
           (let ((name (symbol-name sym)))
             (when (string-match "-\\(hook[s]?\\|functions\\)$" name)
               (push sym syms))))))
    syms))

(defun face-it (str face)
  "Apply FACE to STR and return."
  (propertize str 'face face))

(defun describe-hook (hook)
  "Display documentation about a hook variable and the
functions it contains."
  (interactive
   (list (completing-read
          "Hook: " (mapcar (lambda (x) (cons x nil)) (guess-all-hooks)))))
  (let* ((sym (intern hook))
         (sym-doc (documentation-property sym 'variable-documentation))
         (hook-docs (mapcar
                     (lambda (func)
                       (cons func (ignore-errors (documentation func))))
                     (symbol-value sym))))
    (switch-to-buffer
     (with-current-buffer (get-buffer-create "*describe-hook*")
       (let ((inhibit-read-only t))
         (delete-region (point-min) (point-max))
         (insert (face-it "Hook: " 'font-lock-constant-face) "\n\n")
         (insert (face-it (concat "`" hook "'") 'font-lock-variable-name-face))
         (replace-string "\n" "\n\t" nil
                         (point)
                         (save-excursion
                           (insert "\n" sym-doc "\n\n")
                           (1- (point))))
         (goto-char (point-max))
         (insert (face-it "Hook Functions: " 'font-lock-constant-face) "\n\n")
         (dolist (hd hook-docs)
           (insert (face-it (concat "`" (symbol-name (car hd)) "'")
                            'font-lock-function-name-face)
                   ": \n\t")
           (replace-string "\n" "\n\t" nil
                           (point)
                           (save-excursion
                             (insert (or (cdr hd) "No Documentation") "\n\n")
                             (1- (point))))
           (goto-char (point-max))))
       (help-mode)
       (help-make-xrefs)
       (read-only-mode t)
       (setq truncate-lines nil)
       (current-buffer)))))
Jordon Biondo
źródło
Czy to oznacza, że ​​kiedy funkcja zostanie powiadomiona, dokumentacja jest automatycznie aktualizowana, aby odzwierciedlić zmianę?
nispio
Nie wiem, czy rzeczywiste właściwości zostaną zaktualizowane, ale wartość zwracana przez documentationjest aktualizowana w celu odzwierciedlenia.
Jordon Biondo
1
@nispio tak, jest.
Malabarba
1
Kod / funkcja w gist.github.com/jordonbiondo/bad03e44bb053db0f1eb może i moim zdaniem powinien zostać uwzględniony w odpowiedzi. Myślę, że odpowiedź SE ma limit 30 000 znaków.
Faheem Mitha,
4

Być może nie jest to pełna odpowiedź na twoje pytanie, ale pakiet helm-descbindspomaga przeszukać wszystkie zdefiniowane wiązania klawiatury z ascii reprezentacji skrótu. Przy każdym trafieniu wyświetla interaktywną funkcję związaną ze skrótem klawiaturowym, możesz też poprosić helm-descbindso jej opisanie lub wykonanie bezpośrednio z wyników wyszukiwania.

wprowadź opis zdjęcia tutaj

Oto opis pakietu ze strony GitHub:

Helm Descbinds zapewnia interfejs do powiązań opisujących emacsa, dzięki czemu aktualnie aktywne powiązania klawiszy można interaktywnie przeszukiwać za pomocą steru.

Dodatkowo masz następujące działania

  • Wykonaj polecenie
  • Opisz polecenie
  • Znajdź polecenie

I C-zda ci trwały opis bieżącego polecenia.

Amelio Vazquez-Reina
źródło
2
To jest świetne. Na pewno to powiążę C-h b. Moim jedynym życzeniem jest to, że mogę przejść do pozycji na liście, wpisując rzeczywistą sekwencję klawiszy zamiast wpisywaćC - c _ C - p
nispio