Come modificare elisp senza perdersi tra parentesi


13

Sto modificando un po 'di codice elisp da 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))

Sono stato in grado di correggere un bug in cui il rientro era uno alla volta modificando (count-lines (point-min) (point-max))in (+ (count-lines (point-min) (point-max)) 1). È stato facile.

Ma ora voglio modificarlo in modo che la larghezza minima sia 2 aggiungendo un if-condizionale dove (concat " %" (number-to-string w) "2d ")se il conteggio del numero di riga è <10.

Questo dovrebbe essere facile! Aggiungi un condizionale e copia / incolla il concat. Pezzo di torta, vero? Voglio dire, so cosa dovrei fare, ma tocco raramente elisp e sono sempre scoraggiato quando devo modificare qualsiasi cosa con molta parentesi.

Lo stile "corretto", da quello che ho capito, è strutturare il codice in base al rientro e racchiudere la parentesi finale alla fine di una riga anziché da sola. Provenendo da altri linguaggi in stile 'C', faccio fatica a leggere e scrivere codice in questo modo. Quindi la mia domanda è: cosa sto facendo di sbagliato? Come posso modificare elisp e navigare nel codice in modo da non dover sedere lì e contare ogni parentesi?

Quando lavoro con qualcosa in elis che diventa troppo profondo, devo chiudere la porta, tirare le persiane e iniziare a posizionare la parentesi in stile K & R in modo che non solo possa leggere ma modificare il maledetto senza impazzire.

Ovviamente sto sbagliando tutto. Come posso toccare elisp in questo modo senza paura?

Si prega di notare che la mia domanda è come navigare e modificare elisp non come una domanda di stile. Sto già usando quanto segue come guida di stile: https://github.com/bbatsov/emacs-lisp-style-guide

aggiornamenti:

Come formattare correttamente elisp prima di metterti in imbarazzo su emacs.stackexchange:

Segna il tuo elisp ed esibisciti M-x indent-region.

La soluzione del problema:

Per coloro che vogliono sapere come eseguire un giustificato a destra per linum con una larghezza minima di due, ecco la soluzione:

(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))

1
Tutti hanno difficoltà a leggere lisp che proviene da C. Ci vuole solo tempo, ma alla fine diventa estremamente naturale. Inoltre puoi probabilmente risolvere il tuo problema cambiando il formato linum in una stringa di formato come "% 2d".
Jordon Biondo,

Non posso semplicemente usarlo %2dperché una volta che la larghezza passa a 3 o più caratteri, passa da giustificato a destra a giustificato a sinistra.
Zhro

Ci sono alcune librerie che mettono in evidenza le parentesi corrispondenti che sono inestimabili (secondo me), ad esempio highlight-parentheses; rainbow-delimiters; ecc. Ecco la mia versione semplificata di highlight-parenthesesciò che consente lo scorrimento senza rimuovere le parentesi che sono state colorate l'ultima volta: stackoverflow.com/a/23998965/2112489 In futuro, è una domanda per cliente / thread.
elenco delle leggi

1
Sembra molto che il tuo problema sia davvero leggere , non modificare il codice Elisp. Sembra che tu abbia problemi a comprendere la struttura di Lisp e ciò compromette il tuo editing.
PythonNut il

1
A tua difesa, questo è un pezzo di codice piuttosto male rientrato. L'ho letto da solo le prime 3 volte a causa di ciò. Inoltre, paredit .
Malabarba,

Risposte:


12

Esistono numerosi pacchetti aggiuntivi che potrebbero essere d'aiuto, come paredit, smartparens e lispy. Questi pacchetti semplificano la navigazione e la manipolazione del codice lisp in modo da poter pensare in espressioni s e lasciare che l'editor si preoccupi del bilanciamento delle parentesi.

Emacs ha anche molti comandi integrati per gestire i sexp e le liste che vale la pena imparare e che possono aiutarti ad abituarti maggiormente alla struttura del codice lisp. Questi sono generalmente associati a un C-M-prefisso, come ad esempio:

  • C-M-f/ C-M-bper spostarsi avanti / indietro di sexp
  • C-M-n/ C-M-pper spostarsi avanti / indietro per elenco
  • C-M-u/ C-M-dper spostarsi su / giù di un livello
  • C-M-t scambiare i due sexp intorno al punto
  • C-M-k per uccidere un sexp
  • C-M-SPC per contrassegnare un sexp
  • C-M-q per rientrare in un rientro di un sexp

Il codice di esempio che hai fornito potrebbe essere più chiaro se correggi il rientro: inserisci un punto all'inizio di (defadvice...e premi C-M-qper rientrare di nuovo nell'intera espressione. Per sostituire l' (concat...io inizierei mettendo il punto all'inizio di quel sexp e colpendo C-M-oper dividere la linea preservando il rientro. Quindi aggiungi il tuo (if...e usa i comandi sopra per saltare alla fine di un elenco per aggiungere un'altra parentesi chiusa, tornare all'inizio per rientrare di nuovo, ecc.

Potresti anche voler attivare show-paren-mode, che evidenzierà la corrispondente parentesi quando il punto è all'inizio o alla fine di un elenco. Puoi preferire evidenziare l'intera espressione piuttosto che la parentesi corrispondente, quindi prova a personalizzare show-paren-style.

Come @Tyler ha menzionato nei commenti su un'altra risposta, dovresti dare un'occhiata al manuale per saperne di più su questi e i relativi comandi.


Si noti che C-M-qpuò essere chiamato con un argomento prefisso ( C-u C-M-q) per stampare graziosamente l'espressione nel punto. Ciò interromperà tutto per separare le linee e il rientro in modo che l'annidamento sia molto evidente. In genere non vuoi che il tuo codice lisp assomigli a quello, ma potrebbe essere utile capire un po 'di codice senza andare manualmente su K&R completo. (E puoi sempre C-x uannullare).
Glucas,

6

Un buon modo per modificare LISP è manipolando l'AST, anziché i singoli caratteri o linee. L'ho fatto con il mio pacchetto lispy che ho iniziato 2 anni fa. Penso che in realtà possa richiedere un po 'di pratica per imparare a farlo bene, ma anche usare solo le basi dovrebbe già aiutarti.

Posso spiegare come farei per apportare questa modifica:

Passo 1

La posizione di partenza è di solito avere il punto prima del sexp di livello superiore. Ecco |il punto.

|(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))

Avrai bisogno di avere il codice correttamente rientrato, quindi premi iuna volta. Lo rientrerà bene.

Passo 2

Ti consigliamo di contrassegnare "d "con una regione, poiché un oggetto manipolabile in lispyè o un elenco, che non ha bisogno di essere contrassegnato, o una sequenza di simboli o / e elenchi che devono essere contrassegnati con una regione.

Premere atper farlo. Il acomando consente di contrassegnare qualsiasi singolo simbolo all'interno dell'elenco principale ed tè l'indice di questo particolare simbolo.

Passaggio 3

  1. Per avvolgere la regione corrente con (), premere (.
  2. Premere C-fper avanzare di un carattere e inserire if.
  3. Premere di (nuovo per inserire ().
  4. Inserire > w 10.
  5. C-f C-m per spostare la stringa su una nuova riga.

Passaggio 4

Per clonare la stringa:

  1. Segna il simbolo o la stringa nel punto con M-m.
  2. Press c.

Se vuoi disattivare la regione in modo elegante e mettere il punto all'inizio della stringa, puoi premere idm:

  1. i selezionerà il contenuto interno della stringa.
  2. d scambia punto e segno.
  3. m disattiverà la regione

O potresti fare m C-b C-b C-bin questo caso, o C-g C-b C-b C-b. Penso che idmsia meglio, dal momento che è lo stesso indipendentemente dalla lunghezza della stringa. Penso C-x C-x C-f C-g che funzionerebbe anche indipendentemente dalla lunghezza della stringa.

Infine, inserisci 2per ottenere il codice finale:

(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))

Sommario

La sequenza completa era: at( C-f, if, (, > w 10, C-f C-m M-m cidm, 2.

Si noti che se si calcola l'inserimento del codice, le uniche chiavi non correlate alla manipolazione AST erano due C-fe una C-m.


3
Lispy sembra interessante! All'OP: puoi sviluppare flussi di lavoro simili con paredit: emacsrocks.com/e14.html ed espandere la regione: github.com/magnars/expand-region.el , o semplicemente giocare con i comandi di corrispondenza tra parentesi incorporati: gnu. org / software / emacs / manual / html_node / emacs / Parentheses.html
Tyler

Sono sicuro che stavi indovinando quando hai legato per risolvere il problema per me; grazie per il tentativo. Sono riuscito a confondermi usando il tuo codice come esempio. Vedi il mio aggiornamento per la soluzione corretta.
Zhro,

6

Ti abituerai nel tempo, ma ovviamente ci sono molte cose che puoi fare per accelerare:

dentellatura

C'è un metodo per questa follia. In lisp puoi fare questo:

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

Supponiamo che 1sia davvero una grande espressione e che vuoi rientrare sulla sua stessa riga.

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

Questo è fuorviante. 1è indentato solo uno slot, anche se è un intero tre livelli di nidificazione superiore! Meglio dirlo dal suo genitore.

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

Se utilizziamo questo schema sul tuo codice, otteniamo questo:

(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))

Nota la forte correlazione tra rientro e livello di annidamento. Le linee con un livello maggiore di annidamento sono sempre rientrate più delle linee con meno.

Questo da solo aiuterà molto. Puoi facilmente vedere la "forma" del codice e la maggior parte delle altre lingue ti ha insegnato ad associare il rientro a blocchi e blocchi con una qualche forma di annidamento (esplicito o implicito).

Come esercizio, ho rimosso le parentesi non essenziali dal codice. Dovresti essere in grado sia di leggere il codice che di fornire le parentesi mancanti, data la conoscenza di base di Elisp (vale a dire, quali cose sono funzioni e valori e la struttura di 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

1
Nota che in Emacs, colpire tab imposterà quasi sempre correttamente il rientro come descritto qui - non dovresti mai farlo aggiungendo spazi a mano!
Tyler,

Associa "Cm" a newline-and-indentper emacs-lisp-mode e lisp -action-mode risolve il tuo primo esempio, PythonNut. E TAB farà il lavoro per il resto del tempo.
Assapora Cubranic il

5

Sto includendo questo come una risposta diversa.

A volte, il rientro ti fallirà. Il tuo ricorso quindi è di usare qualcosa come rainbow-delimiters:

inserisci qui la descrizione dell'immagine

Ciò rende il livello di nidificazione di qualsiasi paren esplicito e facilmente scansionabile.

C'è un grosso problema: i genitori sono distrattamente ridicoli. C'è un equilibrio di enfasi qui. rainbow-delimitersnormalmente metterà molta enfasi sui genitori a spese del resto del codice! Ma se si tonifica l'arcobaleno a faccia in giù, diventano progressivamente più difficili da scansionare.

Se riesci a trovare un insieme di facce che bilanciano così bene, allora usalo sicuramente.

Detto questo, una soluzione (quella che mi fa ridere con gioia), è avere due serie di facce e passare da una all'altra al volo. Quando fai altre cose, i volti sono diluiti e si sbiadiscono sullo sfondo:

inserisci qui la descrizione dell'immagine

Ma quando metti il ​​punto su un paren, questo colpisce i parens in modo da poter vedere i livelli di annidamento:

inserisci qui la descrizione dell'immagine

Ed ecco il codice per farlo:

(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))

Questo è fantastico! Per quale motivo hai scelto i delimitatori arcobaleno piuttosto che le parentesi evidenziate?
Tyler,

@Tyler non ha un motivo particolare, anche se ora continuerei a usare i delimitatori arcobaleno (ma potrebbe essere solo perché ci sono abituato). Semplicemente non avevo sentito parlare di parentesi evidenziata fino a poco tempo fa.
PythonNut,

4

Se rientri nel tuo codice, devi davvero rientrarlo correttamente. Gli sviluppatori di Lisp si aspettano come dovrebbe essere un rientro corretto. Ciò non significa che il codice abbia lo stesso aspetto. Esistono ancora diversi modi per formattare il codice.

  • quanto dovrebbe essere lunga una linea?
  • come distribuire una chiamata funzione / macro su linee?
  • quanti spazi di rientro dovrebbero esserci?
(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))

Mi aspetto che il rientro mostri in qualche modo contenimento. Ma non nel tuo codice.

Per impostazione predefinita, il codice potrebbe essere rientrato in questo modo. Altre risposte hanno descritto come è possibile farlo con l'aiuto di Emacs:

(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))

Mi aspetto che le letvariabili associate inizino sulla stessa colonna verticale. Mi aspetterei anche che il corpo del letviene meno rientrato. Impariamo come letdovrebbe essere rientrato. Una volta che ti alleni un po ', è un modello visivo che è facile da riconoscere.

Gli elementi principali visive nel codice sono il defadvice, let*e un gruppo di chiamate di funzione. Il defnel nome mi dice che è una definizione seguita da un nome, un elenco di argomenti e un corpo.

Quindi mi piace vedere

defadvice name arglist
  body

Il let*sarebbe: let*un elenco di attacchi e un corpo.

Quindi mi piace vedere:

let*  list of bindings
  body

Più dettagliato:

let*   binding1
       binding2
       binding3
  body

Per una chiamata di funzione mi piace vedere:

FUNCTIONNAME ARG1 ARG2 ARG3

o

FUNCTIONNAME ARG1
             ARG2
             ARG3

o

FUNCTIONNAME
  ARG1
  ARG2
  ARG3

Quale viene usato dipende da quanto tempo durano gli argomenti. Non vogliamo fare linee troppo lunghe e ogni argomento sulla propria linea ci permette di avere più struttura.

Quindi devi scrivere il tuo codice usando quei pattern e devi assicurarti che il lettore possa facilmente identificare quei pattern nel tuo codice.

Le parentesi dovrebbero racchiudere direttamente i loro costrutti.

(sin 10)

(sin
  10)

Evita esempi di spazi bianchi:

(  sin 10  )

o

(
   sin
)

o

(sin 10
)

In Lisp, le parentesi non hanno una funzione sintattica del linguaggio, fanno parte della sintassi della struttura dei dati dell'elenco (s-espressioni). Quindi scriviamo elenchi e formattiamo gli elenchi. Per formattare i contenuti dell'elenco utilizziamo la conoscenza del linguaggio di programmazione Lisp. letUn'espressione dovrebbe essere formattata diversa da una chiamata di funzione. Tuttavia, entrambi sono elenchi e le parentesi devono racchiudere direttamente gli elenchi. Ci sono alcuni esempi in cui ha senso avere una singola parentesi su una linea, ma usarla raramente.

Usa le parentesi per aiutarti a trovare i confini dell'espressione. Lascia che ti aiutino a passare da un elenco all'altro, a modificare elenchi, a tagliare e copiare elenchi, a sostituire elenchi, a rientri / formati elenchi, selezionare elenchi, ...


2

Per un aiuto di base sul rientro, utilizzare TAB e "CMq" ( indent-pp-sexp); rilegando "Cm" per newline-and-indentnon dover premere TAB dopo una nuova riga.

Puoi navigare per sexp con "CM-sinistra / destra / su / giù / home / fine", che è molto utile.

Se sei preoccupato di mantenere l'equilibrio tra parentesi, usa qualcosa come smartparens (è un po 'più indulgente con quel paredit , che inizialmente può sembrare una camicia di forza). Viene inoltre fornito con molti collegamenti per la navigazione e la modifica a livello di sexp.

Infine, per evidenziare le parentesi, inizia attivando l'opzione (menu Opzioni-> Evidenzia parentesi corrispondenti, o show-paren-mode.) Puoi anche usare uno dei pacchetti menzionati dalla lista della legge nel suo commento, come "evidenziazione-parentesi" o "arcobaleno-delimitatori ".


1

In aggiunta a ciò che altri hanno dato come risposte, ecco i miei 2 centesimi:

  • Il rientro automatico fornito da emacs-lisp-modeè essenziale.
  • blink-matching-parenè attivo (non nil) per impostazione predefinita. Lascialo così.
  • Uso show-paren-mode, per evidenziare la parentesi sinistra corrispondente alla parentesi destra prima del cursore.
  • Elimina temporaneamente e riscrivo la parentesi destra prima del cursore, se voglio vedere meglio dove si trova la parentesi sinistra corrispondente.

Io non uso l'accoppiamento elettrico o arcobaleno qualsiasi cosa o qualsiasi altro come "aiuto". Per me quelli sono un fastidio, non un aiuto.

In particolare, electric-pair-modeper me è un fastidio scomodo. Ma alcune persone lo adorano. E immagino che possa essere utile in alcuni altri contesti di associazione oltre alle parentesi di Lisp (lo immagino, ma non sono convinto neanche per tali casi d'uso).

Troverai ciò che funziona meglio per te. Le cose principali che voglio dire sono: (1) il rientro automatico è tuo amico, così come un modo per individuare la parentesi sinistra che corrisponde alla parentesi destra prima del punto.

In particolare, vedere cosa fa il rientro automatico per te ti insegna immediatamente che non vuoi mai più mettere i genitori giusti su una linea da soli. Quello stile di programmazione, che è onnipresente in altre lingue, è solo rumoroso.

Oltre al rientro automatico che ottieni con RETe TAB, mettiti comodo usando C-M-q. (Usa C-h kin emacs-lisp-modeper scoprire cosa fanno questi tasti.)


1

Ho notato che alcune persone hanno già menzionato delimitatori arcobaleno, questa è anche la mia modalità preferita durante la modifica del codice lisp.

In realtà adoro le parentesi, la cosa migliore di Lisp è quelle parentesi, è divertente affrontarle se sai come fare:

  • installa evil-mode e il suo plugin evil-surround, in modo da poter modificare facilmente le parentesi, ad esempio, premi ci(rimuoverà tutto all'interno (), va(selezionerà l'oggetto racchiuso tra "()" e "()". e puoi premere %per saltare tra le parentesi corrispondenti

  • usa flycheck o flymake, le parentesi senza pari saranno sottolineate in tempo reale


0

La difficoltà qui è che vuoi aggiungere del codice prima e dopo un certo sexp. In questa situazione il sexp è (concat " %" (number-to-string w) "d "). Si desidera inserire l' istruzione if (if (> w 1) prima di essa e l' istruzione else " %2d ") dopo di essa.

Una parte importante della difficoltà è quello di isolare questo sexp, personalmente uso il seguito di comando per isolare unsexp

(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 )      ))

Posiziona il cursore all'inizio di (concat " %" (number-to-string w) "d "), ovvero all'inizio (, quindi applica quanto sopra isolate-sexp. Ottieni

(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))

Quindi aggiungere il codice appropriato prima e dopo questo sexp, ad es

(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))

E voilà. Il codice ottenuto in questo modo forse non è bello ma la possibilità di perdersi è minore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.