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))
źródło
%2d
ponieważ 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.highlight-parentheses
.;rainbow-delimiters
; itp. Oto moja własna uproszczona wersja,highlight-parentheses
któ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.Odpowiedzi:
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-b
aby przejść do przodu / do tyłu przez sexpC-M-n
/,C-M-p
aby przejść do przodu / do tyłu według listyC-M-u
/,C-M-d
aby przejść w górę / w dół o jeden poziomC-M-t
do zamiany dwóch sexps wokół punktuC-M-k
zabić sexpC-M-SPC
zaznaczyć sexpC-M-q
do ponownego wcięcia sexpPodany przykładowy kod może być jaśniejszy, jeśli naprawisz wcięcie: umieść punkt na początku
(defadvice...
i naciśnij,C-M-q
aby ponownie wciąć całe wyrażenie. Aby zastąpić(concat...
I, zacznę od umieszczenia punktu na początku tego seksu i uderzenia,C-M-o
aby 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.
źródło
C-M-q
moż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żeszC-x u
cofnąć).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.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ć,lispy
jest 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
()
, naciśnij (.if
.()
.> w 10
.Krok 4
Aby sklonować ciąg:
Jeśli chcesz dezaktywować region w fantazyjny sposób i umieścić punkt na samym początku ciągu, możesz nacisnąć idm:
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,
2
aby uzyskać kod końcowy: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.
źródło
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ć:
Załóżmy, że
1
to naprawdę duże wyrażenie i chcesz wciąć je według własnej linii.To jest mylące.
1
jest wcięty tylko o jedno miejsce, mimo że całe trzy poziomy gniazdowania są wyższe! Lepiej powiedz to rodzicowi.Jeśli użyjemy tego schematu w twoim własnym kodzie, otrzymamy:
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*
).źródło
newline-and-indent
trybem emacs-lisp i trybem interakcji lisp rozwiązuje twój pierwszy przykład, PythonNut. A TAB wykona zadanie przez resztę czasu.Podaję to jako inną odpowiedź.
Czasami wcięcie cię zawiedzie. W takim razie skorzystaj z czegoś takiego
rainbow-delimiters
: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-delimiters
zwykle 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:
Ale kiedy umieścisz punkt na parenie, przebije on pareny, abyś mógł zobaczyć poziomy zagnieżdżenia:
A oto kod do zrobienia tego:
źródło
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.
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:
Spodziewałbym się, że
let
zmienne powiązane zaczynają się od tej samej kolumny pionowej. Chciałbym również spodziewać się, że ciało zlet
jest mniej wcięte. Dowiadujemy się, jaklet
należ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. Nazwadef
w nazwie mówi mi, że jest to definicja, po której następuje nazwa, lista argumentów i treść.Dlatego lubię widzieć
let*
Byłoby:let*
wykaz wiązań i ciała.Dlatego lubię widzieć:
Bardziej szczegółowe:
Dla wywołania funkcji lubię widzieć:
lub
lub
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.
Unikaj przykładów białych znaków:
lub
lub
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.
let
Wyraż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, ...
źródło
Aby uzyskać podstawową pomoc dotyczącą wcięć, użyj TAB i „CMq” (
indent-pp-sexp
); przypisanie „Cm” donewline-and-indent
pozwoli 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” „.źródło
Jako dodatek do tego, co inni podali jako odpowiedzi, oto moje 2 centy:
emacs-lisp-mode
jest niezbędne.blink-matching-paren
jestnil
domyślnie włączony (nie ). Zostaw to.show-paren-mode
, aby podświetlić lewy paren odpowiadający prawemu paren przed kursorem.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-mode
jest 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
RET
iTAB
, możesz wygodnie korzystaćC-M-q
. (UżyjC-h k
w,emacs-lisp-mode
aby dowiedzieć się, co robią te klucze.)źródło
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 nawiasamiużyj flycheck lub flymake, niedopasowane nawiasy zostaną podkreślone w czasie rzeczywistym
źródło
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
Wystarczy umieścić kursor na początku
(concat " %" (number-to-string w) "d ")
, tj. Na początku(
, a następnie zastosować powyższeisolate-sexp
. OtrzymaszNastępnie dodaj odpowiedni kod przed i po
sexp
, tjI voila. Uzyskany w ten sposób kod może nie jest piękny, ale szansa na zgubienie jest mniejsza.
źródło