Jak aktualizujesz definicję trybu pomocniczego podczas jej opracowywania?

13

Zacząłem kodować mniejszy tryb, aby zapewnić kilka skrótów klawiszowych. Moja pierwsza próba miała literówkę:

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  nil nil
  '(([b] . 'previous-line)))

Miałem zamiar użyć bklucz i natychmiast zrozumiał, że powinien użyłem "b"zamiast [b]. Dlatego przedefiniowałem tryb drugorzędny:

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  nil nil
  '(("b" . 'previous-line)))

Jednak to nie zadziałało. To spowodowało, że zacząłem gonić za dziką gęsią skórką poprzez różne sposoby wiązania kluczy (tj. (Kbd ...), [...] itp.). W końcu zdałem sobie sprawę, że sama ponowna ocena (define-minor-mode ...)formularza nic nie zmienia, utknąłem z oryginalną, zepsutą mapą klawiszy. Następnie spróbowałem zmienić mapę klawiszy bezpośrednio przez (define-key borked-mode-map ...)i nadal nie udało mi się załadować poprawionej mapy klawiszy. W końcu zrestartowałem Emacsa i mój mniejszy tryb został poprawnie załadowany.

Moje pytanie brzmi: w jaki sposób aktualizujesz definicję trybu pomocniczego podczas jej opracowywania? Czy jest jakiś sposób, aby opróżnić zepsutą definicję, czy też musisz ponownie uruchomić emacsa, aby usunąć zepsute bity?

Tyler
źródło

Odpowiedzi:

11

Przy pierwszej ocenie define-minor-modeokreśla zmienną borked-mode-mapz określonymi powiązaniami klawiszy. Jednak po zdefiniowaniu tego symbolu ponowna ocena define-minor-modenie zmieni go.

Możesz usunąć różne borked-mode-xxxsymbole za pomocą, uninterna następnie ponownie ocenić kod. Próbować:

(unintern 'borked-mode-map)

Możesz być zainteresowany rozszerzeniem define-minor-modemakra, aby zobaczyć, co on faktycznie robi. Umieść punkt na końcu i zadzwoń M-x pp-macroexpand-last-sexp. Spowoduje to otwarcie nowego bufora pokazującego rozwinięte makro. Tam zobaczysz defvarwywołania użyte do skonfigurowania zmiennych trybu. Po przeczytaniu pomocy defvarzobaczysz, że początkowa wartość jest używana tylko wtedy, gdy definiowany symbol jest nieważny - gdy już istnieje, kolejne defvarwywołania nie zmienią jego wartości.

glucas
źródło
13

Myślę, że najlepszą odpowiedzią, jaką mogę ci dać, jest trzymanie się z dala od „wbudowanych funkcji skrótów klawiszowych” define-minor-mode. Posługiwać się

(defvar borked-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map [b] 'previous-line)
    ...
    map))

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  :global nil
  ...)

Zamiast. Następnie można użyć C-M-xdo ponownej oceny tych definicji.

Stefan
źródło
1
defvarnie oceni ponownie swojej wartości po C-M-x:) Będziesz potrzebować defparameterlub osobno setf.
wvxvw
Jak wskazuje @wvxvw, nie rozwiązuje to problemu. Twój przykładowy kod robi to samo, co define-minor-moderobi makro: wywoływanie w defvarcelu zdefiniowania mapy. Ocena tego defvarsu po raz drugi nie ma wpływu.
glucas
7
@wvxvw Jeśli użyjesz C-M-x( eval-defun) do ponownej oceny, defvarto zmienna zostanie zaktualizowana. Jest to szczególny przypadek w eval-defun; jeśli zadzwonisz eval-bufferlub eval-regionwówczas istniejąca wartość nie ulega zmianie.
Gilles „SO- przestań być zły”
Ach - wydaje się to kluczowe.
glucas,
1
Zauważ, że C-M-xw defvarformularzu aktualizuje tylko samą zmienną mapowania trybów. Musisz także C-M-xw define-minor-modeformularzu, aby zmienić mapę „zainstalować” w trybie pomocniczym. Próbowałem dowiedzieć się, dlaczego, rozszerzając makra, ale to mnie przerasta.
Tyler,
0

Możesz zdefiniować mapę trybu w następujący sposób:

(defvar dnd-mode-map
  (let ((map (make-sparse-keymap)))
    (prog1 map
      (define-key map "q" 'dnd-quit)
      (when (eq this-command 'eval-defun)
        (let ((mmap (assq 'dnd-mode minor-mode-map-alist)))
          (when mmap
            (setcdr mmap map)))))))

Teraz możesz ponownie ocenić definicję mapy za pomocą, eval-defuna ona automatycznie zaktualizuje zapisaną mapę w środku minor-mode-map-alist.

Clemera
źródło