2009-02-17 5 views
11

Większość trybów emacs zawiera pewien rodzaj prefiksu, który aktywuje ich funkcje. Na przykład, gdy używa się "następnego", to "C-c C-n". Z tych trybów wielu zapewnia specjalne bufory, w których można użyć jednego klawisza do aktywacji niektórych funkcji (wystarczy "n" lub "p", aby przeczytać następną/poprzednią pocztę na przykład w postaci GNUS).Semi-modalne przyciski edycji/automatycznego dodawania prefiksów

Nie wszystkie tryby zapewniają taki bufor, a wielokrotne wpisywanie prefiksu może być męczące. Czy jest dobrze znany fragment elipsy, który pozwoli na ad-hoc specyfikację klawiszy prefiksowych, które będą przekazywane na wszystkie dane wejściowe przez pewien czas? (Aż do uderzenia ESC lub jakiegoś innego usankcjonowanego klucza, na przykład)

+0

Czy mówisz o trybach drugorzędnych lub trybach głównych? Czy możesz podać konkretny przykład? –

+0

Właściwie byłbym zadowolony z czegoś jeszcze mniej uporządkowanego: po prostu sposób na wprowadzenie prefiksu i dotyczy to wszystkich klawiszy, które wciskam, aż nacisnę specjalną serię klawiszy, aby wyjść z tego trybu. – fdr

Odpowiedz

15

Zgadzam się z odpowiedzią Joe Casadonte'a, że ​​sposób, w jaki należy pójść, to zdefiniowanie własnego, mniejszego (lub większego) trybu.

W związku z tym twoje pytanie jest interesujące.

Oto rozwiązanie, które monituje o sekwencję klawiszy, która pobiera prefiks naciśnięcia klawiszy i promuje ten układ klawiatury do najwyższego poziomu.

np. Zakładamy następujące mapy klawiszy:

M-g ESC   Prefix Command 
M-g g   goto-line 
M-g n   next-error 
M-g p   previous-error 

Po uruchomieniu M-x semi-modal-minor-mode, to poprosi o niektórych klawiszy. Jeśli wpiszesz M-g n, wówczas następujące skróty klawiaturowe są:

ESC   Prefix Command (same as M-g ESC) 
g   goto-line 
n   next-error 
p   previous-error 

Więc teraz n nie self-insert, ale przechodzi do następnego błędu. Zobacz poniższy kod.

Uwaga: gdy włączony jest ten tryb pomocniczy, <f12> jest powiązany z poleceniem, które wyłącza tryb pomocniczy. Dzieje się tak dlatego, że klawisze skrótów mogą bardzo dobrze wyłączyć twoje Emacs (na przykład, jeśli pojawił się nowy kod dla M-x).

Edited by dodać te myśli: zmienna tryb moll została pierwotnie bufor lokalny, ale to nie działa, chyba że również zrobić bufor zmienna minor-mode-alist lokalny (duh). Ale ty też (prawdopodobnie) nie chcesz tych wiązań w minibuforze ... Więc nie zamierzam tego testować b/c to naprawdę zależy od tego, co chcesz, ale dodałem komentarz do kodu odzwierciedlając tę ​​myśl.

Bez zbędnych ceregieli:

(defvar semi-modal-minor-mode-keymap (make-sparse-keymap) 
    "keymap holding the prefix key's keymapping, not really used") 
(defvar semi-modal-minor-mode-disable-key (kbd "<f12>") 
    "key to disable the minor mode") 
(defun semi-modal-minor-mode-disable() 
    "disable the minor mode" 
    (interactive) 
    (semi-modal-minor-mode 0)) 

(define-minor-mode semi-modal-minor-mode 
    "local minor mode that prompts for a prefix key and promotes that keymap to the toplevel 
e.g. If there are bindings like the following: 

M-g ESC   Prefix Command 
M-g g   goto-line 
M-g n   next-error 
M-g p   previous-error 

And you enter 'M-g n' when prompted, 
then the minor mode keymap has the bindings 
    g -> goto-line 
    n -> next-error 
    p -> previous-error 
    ESC -> Prefix Command (same as M-g ESC) 

The variable semi-modal-minor-mode-disable-key is bound to disable the minor mode map. 
This is provided because often the mappings make the keyboard unusable. 
Use at your own risk." 
    nil " Semi" semi-modal-minor-mode-keymap 
    (make-local-variable 'semi-modal-minor-mode) 
    (make-local-variable 'minor-mode-map-alist) 
    (let ((pair-holding-keymap-to-modify (assq 'semi-modal-minor-mode minor-mode-map-alist))) 
    (setcdr pair-holding-keymap-to-modify (make-sparse-keymap)) 
    (if semi-modal-minor-mode 
     (let (key 
       keymap) 
      ;; all but last (b/c we want a prefix 
      (setq key (substring (read-key-sequence "Enter a full key combination, the prefix will be used: ") 0 -1)) 
      (if (and (not (equal "" key)) 
        (not (equal (kbd "C-g") key)) 
        (let ((semi-modal-minor-mode nil)) 
        (keymapp (setq keymap (key-binding key))))) 
       (progn 
       (setcdr pair-holding-keymap-to-modify (copy-keymap keymap)) 
       (when semi-modal-minor-mode-disable-key 
        (define-key (cdr pair-holding-keymap-to-modify) 
        semi-modal-minor-mode-disable-key 'semi-modal-minor-mode-disable))) 
      (semi-modal-minor-mode 0)))))) 
+0

Tego właśnie szukałem. Mogę wprowadzić drobne modyfikacje , aby uczynić je bardziej globalnymi (czy masz jakieś sugestie? Gdy używasz cscope, wyskakiwanie z półmodalnego bufora sprawi, że stracę modalność ...), ale lokalny, mniejszy tryb również wydaje się przydatne . – fdr

+0

(Wydaje się, że wystarczyłby globalny układ klawiatury, ale pomyślałem, że powinienem zapytać, czy powinienem odpowiedzieć na wypadek, gdyby istniała inna alternatywa) – fdr

+0

Stary, to friggin 'awesome!Nie wiem, czy kiedykolwiek z niego skorzystam, ale jest to świetny kawałek kodu. Gdybym mógł dać ci więcej niż jeden głos w górę, na pewno bym to zrobił! –

1

Specyficzna dla trybu (modalna?) Część wiązań klawiszy w Emacs jest realizowana przez różne lokalne mapy, które przyćmiewają uniwersalną mapę globalną. Większość trybów głównych i drugorzędnych definiuje własne mapy lokalne; na przykład istnieje mapa trybu gud. Powiązania klawiszy w lokalnej mapie klawiszy będą aktywowane tylko wtedy, gdy bufor bieżący znajduje się w odpowiednim trybie. Możesz dostosować mapę klawiszy specyficzną dla trybu, przechwytując tryb. Na przykład, można umieścić ten fragment w swoim ~/.emacs

 
    (add-hook 'gud-mode-hook 
     (lambda() 
     (local-set-key (kbd "C-n") 
         (lookup-key (current-local-map) (kbd "C-c C-n"))))) 

Więcej szczegółów na temat keymaps można znaleźć w Elisp reference manual.

+0

To przydatne informacje, ale nie do końca tego, czego szukam. Rozważmy tryb składania, który ma takie rzeczy jak "C-c C- @>". Chciałbym szybko określić "C-c C- @" jako mój prefiks, więc mogę po prostu wpisać ">", aby wprowadzić klapę bez bindowania kluczy w moich .emacs w każdym trybie jeden po drugim. – fdr

1

Podstawową kwestią jest brak aktualnej mapy klawiszy per se. Istnieje globalna mapa klawiszy, która jest nadpisywana przez mapę klawiszy głównego trybu, która z kolei jest nadpisywana przez jeden lub kilka mniejszych trybów mapowania klawiszy (i mogą się na siebie nawzajem w pewien określony sposób, jestem tego pewien). Definiowanie nowego trybu głównego nadal pozostawi funkcjonowanie klawiszy trybu podrzędnego, a zdefiniowanie nowego trybu podrzędnego wpłynie tylko na wszystkie klawisze zdefiniowane w mapie klawiszy trybu pomocniczego.

Na przykład można zdefiniować tryb pomocniczy, który będzie wykonywał dowolne czynności, o ile aktywny jest tryb pomocniczy. Użytkownik definiuje nowy tryb pomocniczy, który ma własną mapę klawiszy. Będziesz wtedy musiał zdefiniować wszystkie swoje mapowania dla niego (np. N, p, itp.) I będziesz musiał również zdefiniować wszystkie klucze, które nie chciałbyś pracować, aby były powiązane z funkcją ignore. To jest prawdziwy ból tego, remapowanie wszystkich innych kluczy. Tryb pomocniczy można łatwo włączać i wyłączać; to jest korzyść.

Definiowanie nowego trybu głównego byłoby łatwiejsze na pierwszy rzut oka, ponieważ pozwoli ci zastąpić więcej "bieżącej mapy klawiszy" w jednym ujęciu. Powinien zanotować bieżący tryb główny w lokalnej zmiennej buforowej, aby można go było przywrócić później, gdy tymczasowy tryb główny zostanie wyłączony. Ale nadal będziesz miał inne drobne tryby wtargnięcia do twojej mapy klawiszy, więc nie będzie ona "czysta".

To, co robię w tej sytuacji, to łatwiejszy prefiks! Dla rzeczy, których używam cały czas, przez cały dzień każdego dnia, osobiście daję im klucz funkcyjny (np. Mam odłożoną F1 jako klucz trybu Jabber). Dla mniej natychmiast przydatnych rzeczy, mam dwa inne klawisze funkcyjne odłożone na bok, F3 i F12 (jestem pewien, że był jakiś powód, dla którego wybrałem je dawno temu, ale już nie pamiętam dlaczego). F3 definiuje klucze, które są zawsze dostępne, niezależnie od trybu głównego. F12 definiuje klucze zależne od trybu głównego. Kilka przykładów:

Ustawiłem F3-m- jako przedrostek do przełączania trybów głównych (np. Przełączniki F3-mp na tryb cperl) i F3-M- jako prefiks dla mniejszych trybów (np. Przełączniki F3-Mv tryb podglądu). Są one zawsze dostępne, więc możesz zrobić coś takiego, jak powiązanie F3-g-, aby być prefiksem gud, i wpisać F3-g-p na poprzedni i tak dalej.

Mój klawisz F12 zależy od trybu. Tak więc, w trybie diodowym F12-e wywoła dired-nt-open-in-excel na bieżącym pliku, aw trybie emacs-seplp F12-e wywoła elint-current-buffer. Jakoś nigdy ich nie zdezorientowałem.

Jeśli potrzebujesz pomocy w definiowaniu takich map klawiszy, daj mi znać.

0

tryb Viper umożliwia mapowanie polecenia do klawiszy lub sekwencji w trybie wizualnym (wprowadzonego za pomocą klawisza „ESC”). Wróć do trybu wstawiania za pomocą "i".
Zajrzyj na viper-in-more-modes.el
Używa ona viper-modify-major-mode.
Chciałbym również użyć viper-vi-global-user-map: a snippet z mojego pliku .emacs.