Jak edytować elisp bez zgubienia się w nawiasach

13

Zmieniam kod elisp z linum.el:

(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Byłem w stanie naprawić błąd, w którym wcięcie występowało osobno, zmieniając (count-lines (point-min) (point-max))na (+ (count-lines (point-min) (point-max)) 1). To było łatwe.

Ale teraz chcę to zmodyfikować tak, aby minimalna szerokość (concat " %" (number-to-string w) "2d ")wynosiła 2 poprzez dodanie warunkowego warunku, w którym jeśli liczba wierszy wynosi <10.

To powinno być łatwe! Dodaj jeden warunkowy i skopiuj / wklej konkat. Bułka z masłem, prawda? To znaczy, wiem, co powinienem zrobić, ale rzadko dotykam elisp i zawsze jestem zniechęcony, gdy muszę modyfikować cokolwiek z dużą ilością nawiasów.

Z tego, co rozumiem, „poprawny” styl polega na struktury kodu opartego na wcięciach i zawijaniu nawiasu końcowego na końcu linii, a nie samodzielnie. Pochodząc z innych języków w stylu „C”, mam problemy z czytaniem i pisaniem kodu w ten sposób. Więc moje pytanie brzmi: co robię źle? Jak mam edytować elisp i poruszać się po kodzie, aby nie musiałem tam siedzieć i liczyć każdego nawiasu?

Kiedy pracuję z czymś w elipsie, która robi się zbyt głęboka, muszę zamknąć drzwi, pociągnąć żaluzje i zacząć ustawiać nawiasy w stylu K & R, aby nie tylko móc czytać, ale modyfikować tę cholerną rzecz, nie wariując.

Oczywiście robię to wszystko źle. Jak mogę dotykać elisp w ten sposób bez strachu?

Pamiętaj, że moim pytaniem jest nawigacja i edycja elisp, a nie pytanie o styl. Używam już tego jako przewodnika po stylu: https://github.com/bbatsov/emacs-lisp-style-guide

Aktualizacje:

Jak poprawnie sformatować elisp przed zawstydzeniem się na emacs.stackexchange:

Oznacz swój elisp i wykonaj M-x indent-region.

Rozwiązanie problemu:

Dla tych, którzy chcą wiedzieć, jak wykonać justowanie dla linum z minimalną szerokością dwóch, oto rozwiązanie:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (if (> w 1)
                           (concat " %" (number-to-string w) "d ")
                         " %2d ")))
    ad-do-it))
Zhro
źródło
1
Wszyscy mają trudności z czytaniem seplenienia pochodzącego z C. To zajmuje trochę czasu, ale w końcu staje się niezwykle naturalne. Prawdopodobnie możesz rozwiązać problem, zmieniając format linum na ciąg formatu, np. „% 2d”.
Jordon Biondo,
Nie mogę tak po prostu użyć, %2dponieważ gdy szerokość przewinie się do 3 lub więcej znaków, wówczas przesuwa się od wyrównania do prawej do wyrównania do lewej.
Zhro
Istnieje kilka bibliotek, które podkreślają pasujące nawiasy, które są nieocenione (moim zdaniem), np highlight-parentheses.; rainbow-delimiters; itp. Oto moja własna uproszczona wersja, highlight-parenthesesktóra umożliwia przewijanie bez usuwania nawiasów, które zostały ostatnio pokolorowane: stackoverflow.com/a/23998965/2112489 W przyszłości będzie jedno pytanie na klienta / wątek.
prawnik
1
Wygląda na to, że twoim problemem jest czytanie , a nie edytowanie kodu Elisp. Brzmisz tak, jakbyś miał problemy ze zrozumieniem struktury Lisp, a to utrudnia edytowanie.
PythonNut,
1
W twojej obronie jest to dość źle wcięty fragment kodu. Z tego powodu przeczytałem to źle 3 razy. Również paredit .
Malabarba,

Odpowiedzi:

12

Istnieje wiele pakietów dodatków, które mogą pomóc, takich jak paredit, smartparens i lispy. Pakiety te ułatwiają nawigację i manipulowanie kodem lisp, dzięki czemu możesz myśleć w wyrażeniach s i pozwolić edytorowi martwić się równoważeniem parens.

Emacs ma również wiele wbudowanych poleceń do radzenia sobie z sekstami i listami, które warto poznać i mogą pomóc ci bardziej przyzwyczaić się do struktury kodu lisp. Są one zazwyczaj powiązane z C-M-przedrostkiem, takim jak:

  • C-M-f/, C-M-baby przejść do przodu / do tyłu przez sexp
  • C-M-n/, C-M-paby przejść do przodu / do tyłu według listy
  • C-M-u/, C-M-daby przejść w górę / w dół o jeden poziom
  • C-M-t do zamiany dwóch sexps wokół punktu
  • C-M-k zabić sexp
  • C-M-SPC zaznaczyć sexp
  • C-M-q do ponownego wcięcia sexp

Podany przykładowy kod może być jaśniejszy, jeśli naprawisz wcięcie: umieść punkt na początku (defadvice...i naciśnij, C-M-qaby ponownie wciąć całe wyrażenie. Aby zastąpić (concat...I, zacznę od umieszczenia punktu na początku tego seksu i uderzenia, C-M-oaby rozdzielić linię, zachowując wcięcie. Następnie dodaj swój (if...i użyj powyższych poleceń, aby przeskoczyć na koniec listy, aby dodać kolejny zamykający paren, z powrotem na początek, aby ponownie wprowadzić wcięcie itp.

Możesz także włączyć show-paren-mode, który podświetli odpowiedni paren, gdy punkt znajduje się na początku lub na końcu listy. Możesz raczej podświetlić całe wyrażenie niż pasujący paren, więc spróbuj dostosować show-paren-style.

Jak @Tyler wspomniał w komentarzach do innej odpowiedzi, powinieneś zajrzeć do instrukcji, aby dowiedzieć się więcej o tych i powiązanych poleceniach.

glucas
źródło
Zauważ, że C-M-qmożna go wywołać z argumentem przedrostka ( C-u C-M-q), aby wydrukować wyrażenie w punkcie. Spowoduje to rozbicie wszystkiego na osobne linie i wcięcia, dzięki czemu zagnieżdżanie będzie bardzo oczywiste. Zasadniczo nie chcesz, aby twój kod lisp tak wyglądał, ale pomocne może być zrozumienie odrobiny kodu bez ręcznego przejścia pełnego K&R. (I zawsze możesz C-x ucofnąć).
glucas,
6

Dobrym sposobem na edycję LISP jest manipulowanie AST, zamiast pojedynczych znaków lub linii. Robiłem to z moim pakietem lispy, który zacząłem 2 lata temu. Myślę, że nauczenie się, jak robić to dobrze, może wymagać sporo praktyki, ale nawet korzystanie z podstaw powinno już ci pomóc.

Mogę wyjaśnić, jak bym dokonał zmiany:

Krok 1

Pozycja początkowa ma zwykle punkt przed seksem najwyższego poziomu. O |to chodzi.

|(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Będziesz chciał, aby kod był odpowiednio wcięty, więc naciśnij iraz. Ładnie wciśnie to.

Krok 2

Będziesz chciał oznaczyć "d "region, ponieważ obiekt, którym można manipulować, lispyjest albo listą, której nie trzeba zaznaczać, albo sekwencją symboli lub listami, które należy oznaczyć regionem.

Naciśnij, ataby to zrobić. aKomenda pozwala oznaczyć dowolny pojedynczy znak w liście macierzystej i tjest wskaźnikiem tego konkretnego symbolu.

Krok 3

  1. Aby owinąć bieżący region (), naciśnij (.
  2. Naciśnij, C-faby przejść o jeden znak do przodu i wstaw if.
  3. Naciśnij (ponownie, aby wstawić ().
  4. Insert > w 10.
  5. C-f C-m aby przenieść ciąg do nowej linii.

Krok 4

Aby sklonować ciąg:

  1. Oznacz symbol lub łańcuch w punkcie za pomocą M-m.
  2. Prasa c.

Jeśli chcesz dezaktywować region w fantazyjny sposób i umieścić punkt na samym początku ciągu, możesz nacisnąć idm:

  1. i wybierze wewnętrzną zawartość ciągu.
  2. d zamieni punkt i znak.
  3. m dezaktywuje region

Lub możesz zrobić m C-b C-b C-bw tym przypadku, lub C-g C-b C-b C-b. Myślę, że idmjest lepszy, ponieważ jest taki sam bez względu na długość łańcucha. Myślę, C-x C-x C-f C-g że działałoby również niezależnie od długości łańcucha.

Na koniec wstaw, 2aby uzyskać kod końcowy:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) (if (> w 10)
                                                             "2|d "
                                                           "d "))))
    ad-do-it))

Podsumowanie

Pełna sekwencja była: at( C-f, if, (, > w 10, C-f C-m M-m cidm, 2.

Zauważ, że jeśli policzysz wstawienie kodu, jedynymi kluczami niezwiązanymi z manipulacją AST były dwa C-fi jeden C-m.

abo-abo
źródło
3
Lispy brzmi interesująco! Do OP: możesz opracować podobne przepływy pracy za pomocą paredit: emacsrocks.com/e14.html i rozwinąć region: github.com/magnars/expand-region.el lub po prostu bawić się za pomocą wbudowanych poleceń dopasowywania nawiasów: gnu. org / software / emacs / manual / html_node / emacs / Parentheses.html
Tyler
Jestem pewien, że zgadywałeś, kiedy związałeś się ze mną, aby rozwiązać problem; dziękuję za próbę. Udało mi się przejść przez to, używając twojego kodu jako przykładu. Zobacz moją aktualizację dla właściwego rozwiązania.
Zhro
6

Z czasem się przyzwyczaisz, ale oczywiście możesz wiele zrobić, aby przyspieszyć:

Wcięcie

Istnieje metoda na to szaleństwo. W lisp możesz to zrobić:

(a-fun (another-fun (magic-macro 1)))

Załóżmy, że 1to naprawdę duże wyrażenie i chcesz wciąć je według własnej linii.

(a-fun (another-fun (magic-macro 
  1)))

To jest mylące. 1jest wcięty tylko o jedno miejsce, mimo że całe trzy poziomy gniazdowania są wyższe! Lepiej powiedz to rodzicowi.

(a-fun (another-fun (magic-macro 
                      1)))

Jeśli użyjemy tego schematu w twoim własnym kodzie, otrzymamy:

(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                      (+ (count-lines (point-min) (point-max)) 1))))       
          (linum-format 
            (concat " %" (number-to-string w) "d ")))
     ad-do-it))

Zwróć uwagę na silną korelację między wcięciem a poziomem zagnieżdżenia. Linie z większym poziomem zagnieżdżenia są zawsze wcięte bardziej niż linie z mniejszą liczbą.

Samo to bardzo pomoże. Możesz łatwo zobaczyć „kształt” kodu, a większość innych języków nauczyła cię kojarzyć wcięcia z blokami i blokami z jakąś formą zagnieżdżenia (jawną lub dorozumianą).

W ramach ćwiczenia usunąłem z kodu niepotrzebne nawiasy. Powinieneś być w stanie zarówno odczytać kod, jak i podać brakujące nawiasy, mając podstawową wiedzę na temat Elisp (a mianowicie, jakie są funkcje i wartości oraz strukturę let*).

custom-set-variables '(linum-format 'dynamic)
defadvice linum-update-window (around linum-dynamic activate)
  let* w length number-to-string
                  + 
                    count-lines (point-min) (point-max) 
                    1       
         linum-format 
           concat " %" (number-to-string w) "d "
     ad-do-it
PythonNut
źródło
1
Zauważ, że w Emacsie klawisz Trafienie prawie zawsze ustawia wcięcie poprawnie, jak opisano tutaj - nigdy nie powinieneś tego robić przez ręczne dodawanie spacji!
Tyler,
Powiązanie „Cm” z newline-and-indenttrybem emacs-lisp i trybem interakcji lisp rozwiązuje twój pierwszy przykład, PythonNut. A TAB wykona zadanie przez resztę czasu.
Davor Cubranic,
5

Podaję to jako inną odpowiedź.

Czasami wcięcie cię zawiedzie. W takim razie skorzystaj z czegoś takiego rainbow-delimiters:

wprowadź opis zdjęcia tutaj

To sprawia, że ​​poziom zagnieżdżenia każdego paren jest wyraźny i łatwy do skanowania.

Jest jednak jeden poważny problem: pareny są absurdalnie rozpraszające. Tutaj jest równowaga nacisku. rainbow-delimiterszwykle kładzie duży nacisk na pareny kosztem reszty kodu! Ale jeśli odcień tęczy jest skierowany w dół, stają się one coraz trudniejsze do zeskanowania.

Jeśli możesz znaleźć jeden zestaw twarzy, który dobrze to równoważy, to z całą pewnością skorzystaj z niego.

To powiedziawszy, jednym rozwiązaniem (tym, które sprawia, że ​​mam śmiech z radości), jest posiadanie dwóch zestawów twarzy i przełączanie się między nimi w locie. Kiedy robisz inne rzeczy, twarze są rozcieńczone i znikają w tle:

wprowadź opis zdjęcia tutaj

Ale kiedy umieścisz punkt na parenie, przebije on pareny, abyś mógł zobaczyć poziomy zagnieżdżenia:

wprowadź opis zdjęcia tutaj

A oto kod do zrobienia tego:

(defvar rainbow-delimiters-switch nil
  "t if rainbow-delimiters are currently punched")
(defvar rainbow-delimiters-face-cookies nil
  "a list of face-remap-add-relative cookies to reset")

(make-variable-buffer-local 'rainbow-delimiters-switch)
(make-variable-buffer-local 'rainbow-delimiters-face-cookies)

(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
(add-hook 'text-mode-hook #'rainbow-delimiters-mode)

(with-eval-after-load 'rainbow-delimiters
  (set-face-foreground 'rainbow-delimiters-depth-1-face "#889899")
  (set-face-foreground 'rainbow-delimiters-depth-2-face "#9b7b6b")
  (set-face-foreground 'rainbow-delimiters-depth-3-face "#7b88a5")
  (set-face-foreground 'rainbow-delimiters-depth-4-face "#889899")
  (set-face-foreground 'rainbow-delimiters-depth-5-face "#839564")
  (set-face-foreground 'rainbow-delimiters-depth-6-face "#6391aa")
  (set-face-foreground 'rainbow-delimiters-depth-7-face "#9d748f")
  (set-face-foreground 'rainbow-delimiters-depth-8-face "#7b88a5")
  (set-face-foreground 'rainbow-delimiters-depth-9-face "#659896")

  (defun rainbow-delimiters-focus-on ()
    "Punch the rainbow-delimiters"
    (setq rainbow-delimiters-face-cookies
      (list
        (face-remap-add-relative 'rainbow-delimiters-depth-1-face
          '((:foreground "#3B9399") rainbow-delimiters-depth-1-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-2-face
          '((:foreground "#9B471D") rainbow-delimiters-depth-2-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-3-face
          '((:foreground "#284FA5") rainbow-delimiters-depth-3-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-4-face
          '((:foreground "#3B9399") rainbow-delimiters-depth-4-face))
            (face-remap-add-relative 'rainbow-delimiters-depth-5-face
          '((:foreground "#679519") rainbow-delimiters-depth-5-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-6-face
          '((:foreground "#0E73AA") rainbow-delimiters-depth-6-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-7-face
          '((:foreground "#9D2574") rainbow-delimiters-depth-7-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-8-face
          '((:foreground "#284FA5") rainbow-delimiters-depth-8-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-9-face
          '((:foreground "#199893") rainbow-delimiters-depth-9-face)))
      rainbow-delimiters-switch t))

  (defun rainbow-delimiters-focus-off ()
    "Reset the rainbow-delimiters faces"
    (mapc #'face-remap-remove-relative rainbow-delimiters-face-cookies)
    (setq rainbow-delimiters-switch nil))

  (defun rainbow-delimiters-focus-on-maybe ()
    "Punch the rainbow-delimiters if the point is on a paren"
    (when (looking-at "[][(){}]")
      (unless (or rainbow-delimiters-switch (minibufferp))
        (rainbow-delimiters-focus-on))))

  (defun rainbow-delimiters-focus-off-maybe ()
    "Reset the rainbow-delimiters if the point is not on a paren"
    (unless (looking-at "[][(){}]")
      (when rainbow-delimiters-switch
        (rainbow-delimiters-focus-off))))

  (run-with-idle-timer 0.6 t 'rainbow-delimiters-focus-on-maybe)
  (run-with-idle-timer 0.1 t 'rainbow-delimiters-focus-off-maybe))
PythonNut
źródło
To jest fajne! Czy jest jakiś powód, dla którego wybrałeś separatory tęczy zamiast nawiasów wyróżniających?
Tyler,
@Tyler nie ma konkretnego powodu, chociaż nadal trzymałbym się teraz ograniczników tęczy (ale może to być spowodowane tym, że jestem do tego przyzwyczajony). Do niedawna po prostu nie słyszałem o nawiasach głównych.
PythonNut,
4

Jeśli wcinasz swój kod, to naprawdę musisz go poprawnie wciąć. Deweloperzy Lisp mają oczekiwania, jak powinno wyglądać prawidłowe wcięcie. Nie oznacza to, że kod wygląda tak samo. Nadal istnieją różne sposoby formatowania kodu.

  • jak długa powinna być linia?
  • jak rozdzielić wywołanie funkcji / makra na linie?
  • ile przestrzeni wcięć powinno być?
(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Spodziewałbym się, że wcięcie w pewien sposób pokazuje ograniczenie. Ale nie w twoim kodzie.

Domyślnie twój kod może być wcięty w ten sposób. Inne odpowiedzi opisywały, jak możesz to zrobić za pomocą Emacsa:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
    ad-do-it))

Spodziewałbym się, że letzmienne powiązane zaczynają się od tej samej kolumny pionowej. Chciałbym również spodziewać się, że ciało z letjest mniej wcięte. Dowiadujemy się, jak letnależy wciąć. Gdy trochę to wytrenujesz, jest to wizualny wzór, który łatwo rozpoznać.

Głównymi wizualne cegiełki w kodzie są defadvice, let*i kilka wywołań funkcji. Nazwa defw nazwie mówi mi, że jest to definicja, po której następuje nazwa, lista argumentów i treść.

Dlatego lubię widzieć

defadvice name arglist
  body

let*Byłoby: let*wykaz wiązań i ciała.

Dlatego lubię widzieć:

let*  list of bindings
  body

Bardziej szczegółowe:

let*   binding1
       binding2
       binding3
  body

Dla wywołania funkcji lubię widzieć:

FUNCTIONNAME ARG1 ARG2 ARG3

lub

FUNCTIONNAME ARG1
             ARG2
             ARG3

lub

FUNCTIONNAME
  ARG1
  ARG2
  ARG3

To, które zostanie wykorzystane, zależy od długości argumentów. Nie chcemy, aby linie były zbyt długie, a każdy argument na własnej linii pozwala nam mieć większą strukturę.

Musisz więc napisać kod przy użyciu tych wzorców i upewnić się, że czytelnik może łatwo zidentyfikować te wzorce w kodzie.

Nawiasy powinny bezpośrednio otaczać ich konstrukcje.

(sin 10)

(sin
  10)

Unikaj przykładów białych znaków:

(  sin 10  )

lub

(
   sin
)

lub

(sin 10
)

W Lisp nawiasy nie mają funkcji składniowej języka, są one częścią składni struktury danych listy (wyrażeń s). Dlatego piszemy listy i formatujemy listy. Do formatowania zawartości listy wykorzystujemy wiedzę na temat języka programowania Lisp. letWyrażenie powinno być sformatowane inaczej niż wywołania funkcji. Nadal oba są listami, a nawiasy powinny bezpośrednio zawierać listy. Istnieje kilka przykładów, w których sensowne jest posiadanie pojedynczego nawiasu na linii, ale używaj go rzadko.

Użyj nawiasów, aby ułatwić znalezienie granic wyrażeń. Pozwól im pomóc Ci przechodzić z listy do listy, edytować listy, wycinać i kopiować listy, zastępować listy, listy wcięć / formatowania, wybierz listy, ...

Rainer Joswig
źródło
2

Aby uzyskać podstawową pomoc dotyczącą wcięć, użyj TAB i „CMq” ( indent-pp-sexp); przypisanie „Cm” do newline-and-indentpozwoli Ci uniknąć konieczności naciskania TAB po nowej linii.

Możesz poruszać się według sexp za pomocą „CM-left / right / up / down / home / end”, co jest bardzo przydatne.

Jeśli martwisz się utrzymaniem równowagi w nawiasach, użyj czegoś takiego jak smartparens (jest to nieco bardziej wybaczające temu paredit , który początkowo może wydawać się jak kaftan bezpieczeństwa). Zawiera również wiele powiązań do nawigacji i edycji na poziomie sexp.

Na koniec, aby podświetlić pareny, zacznij od włączenia opcji (menu Opcje-> Podkreśl pasujące nawiasy, lub show-paren-mode.) Możesz również użyć jednego z pakietów wymienionych przez listę prawników w jego komentarzu, takich jak „podświetl nawias” lub „ograniczniki tęczy” „.

Davor Cubranic
źródło
1

Jako dodatek do tego, co inni podali jako odpowiedzi, oto moje 2 centy:

  • Automatyczne wcięcie zapewnione przez emacs-lisp-modejest niezbędne.
  • blink-matching-parenjest nildomyślnie włączony (nie ). Zostaw to.
  • Używam show-paren-mode, aby podświetlić lewy paren odpowiadający prawemu paren przed kursorem.
  • Tymczasowo usuwam i ponownie wpisuję prawy paren przed kursorem, jeśli chcę lepiej zobaczyć, gdzie jest pasujący lewy paren.

Mam nie używać elektrycznego parowanie lub tęczowy niczego lub jakąkolwiek inną taką „pomoc”. Dla mnie to przeszkadza, a nie pomoc.

W szczególności electric-pair-modejest to dla mnie niewygodne. Ale niektórzy ludzie to uwielbiają. I wyobrażam sobie, że może być pomocny w innych kontekstach parowania poza nawiasami Lisp (tak sobie wyobrażam, ale nie jestem przekonany do takich przypadków użycia).

Znajdziesz to, co działa najlepiej dla Ciebie. Najważniejsze rzeczy, które chcę powiedzieć to: (1) automatyczne wcięcie jest twoim przyjacielem, podobnie jak sposób na wykrycie lewego paren, który pasuje do prawego paren przed punktem.

W szczególności zobaczenie, co robi dla ciebie automatyczne wcięcie, natychmiast uczy cię, że już nigdy nie chcesz samodzielnie ustawiać prawidłowych linii na linii. Ten styl kodowania, który jest wszechobecny w innych językach, jest po prostu głośny.

Oprócz automatycznego wcięcia, które otrzymujesz RETi TAB, możesz wygodnie korzystać C-M-q. (Użyj C-h kw, emacs-lisp-modeaby dowiedzieć się, co robią te klucze.)

Rysował
źródło
1

Zauważyłem, że niektórzy już wspominali ograniczniki tęczy, to także mój ulubiony tryb podczas edycji kodu lisp.

Tak naprawdę uwielbiam nawiasy, najlepsze w Lisp są nawiasy, fajnie jest sobie z nimi poradzić, jeśli wiesz jak:

  • zainstaluj zło-tryb i jego wtyczkę zło-otaczaj, abyś mógł z łatwością edytować nawiasy, na przykład naciśnij ci(usunie wszystko w środku (), va(wybierze rzecz owiniętą przez „()” i same „()”. i możesz nacisnąć, %aby przejść między dopasowanymi nawiasami

  • użyj flycheck lub flymake, niedopasowane nawiasy zostaną podkreślone w czasie rzeczywistym

Chen Bin
źródło
0

Trudność polega na tym, że chcesz dodać kod przed i po pewnym sexp. W tej sytuacji seks jest (concat " %" (number-to-string w) "d "). Chcesz wstawić instrukcję if (if (> w 1) przed nią, a instrukcję else " %2d ") po niej.

Główną częścią trudności jest izolowanie tego sexp, osobiście używam poniższego polecenia do izolowania asexp

(defun isolate-sexp () (interactive)
       (save-excursion (forward-sexp) (if (not (eolp-almost))
               (split-line) nil)))
(defun eolp-almost () (interactive)
(save-excursion (while (equal (char-after) ? ) (forward-char 1))
        (if (eolp) t nil )      ))

Wystarczy umieścić kursor na początku (concat " %" (number-to-string w) "d "), tj. Na początku (, a następnie zastosować powyższe isolate-sexp. Otrzymasz

(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")
                                  ))
            ad-do-it))

Następnie dodaj odpowiedni kod przed i po sexp, tj

(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (if (> w 1) (concat " %" (number-to-string w) "d ") " %2d ")
                                  ))
            ad-do-it))

I voila. Uzyskany w ten sposób kod może nie jest piękny, ale szansa na zgubienie jest mniejsza.

Nazwa
źródło