Come posso ottenere un righello nella colonna 80?


81

Come programmatore, voglio vedere un righello in una colonna specifica (di solito 80), sia così vedo quando attraverso quella colonna, ma anche per vedere quanto mi sto avvicinando in modo da poter riformattare il mio codice in anticipo.

Le opzioni che ho trovato finora non stanno raggiungendo questo obiettivo:

  • whitespace-mode, column-enforce-modeed column-markerevidenzia le singole righe solo dopo che il testo nella riga ha già superato il fill-column. Mi piacerebbe vedere quando mi sto avvicinando alla colonna, non solo quando la attraverso.
  • fill-column-indicatorsarebbe una buona soluzione, se non si rompe auto-complete-mode, company-mode, avy, e altro ancora. Questi sono problemi che sembrano difficili da risolvere, ognuno dei quali richiede una soluzione alternativa individuale - ad esempio, vedere il company-modeproblema e il auto-complete-modeproblema , quest'ultimo con più di due anni).

Ci sono alternative migliori?


8
Questa non è una risposta alla tua domanda in sé, ma una soluzione pratica è quella di impostare la larghezza della finestra / cornice a 80 caratteri.
Eric Brown,

Grazie per il suggerimento Penso che preferirei avere la larghezza opzionale disponibile quando necessario, ma è certamente un'opzione. :-)
Jorgen Schäfer,

5
Vorrei aggiungere al suggerimento di @ EricBrown, non cambiare l'effettiva larghezza della finestra, ma piuttosto impostare il margine destro della finestra in modo che lo spazio di modifica sia di 80 caratteri. (set-window-margins nil 0 (max (- (window-width) 80) 0))Quindi, se hai una finestra larga 120 caratteri, ridurrà lo spazio necessario per visualizzare il codice a 80 caratteri. In questo modo non rovinerà la configurazione della tua finestra e puoi disattivarla se lo desideri. Se hai le frange, in realtà ci sarà una linea tracciata su 80 colonne.
Jordon Biondo,


@ jordon-biondo: mancano questi hook di aggiornamento per il ridimensionamento delle finestre, vedi: bitbucket.org/snippets/ideasman42/zexMG5
ideasman42

Risposte:


39

fill-column-indicatorè la soluzione più matura e se trovi codice basato su overlay con cui è in conflitto, puoi aggiungere codice da sospendere fci-modementre il codice in conflitto è attivo. Ad esempio, il codice seguente lo fa funzionare con auto-complete:

  (defun sanityinc/fci-enabled-p () (symbol-value 'fci-mode))

  (defvar sanityinc/fci-mode-suppressed nil)
  (make-variable-buffer-local 'sanityinc/fci-mode-suppressed)

  (defadvice popup-create (before suppress-fci-mode activate)
    "Suspend fci-mode while popups are visible"
    (let ((fci-enabled (sanityinc/fci-enabled-p)))
      (when fci-enabled
        (setq sanityinc/fci-mode-suppressed fci-enabled)
        (turn-off-fci-mode))))

  (defadvice popup-delete (after restore-fci-mode activate)
    "Restore fci-mode when all popups have closed"
    (when (and sanityinc/fci-mode-suppressed
               (null popup-instances))
      (setq sanityinc/fci-mode-suppressed nil)
      (turn-on-fci-mode)))

5
Oppure vedi github.com/company-mode/company-mode/issues/… per una soluzione simile per company-mode.
Dmitry,

Ciao, grazie per aver condiviso l'idea. Come faccio a farlo funzionare? Ho il codice nel mio .emacs, ma suppongo di dover aggiungere alcuni hook per farlo funzionare?
PierreE,

Sì, l'esempio sopra indica popup-createe popup-delete, a seconda del caso d'uso, potrebbe essere necessario avvisare diverse funzioni.
sanityinc


21

Ecco un'opzione che è più robusta, non rompe quasi nulla (a volte la modalità aziendale è un'eccezione degna di nota), ma non è così conveniente fill-column-indicator.

Usa il formato della riga di intestazione per contrassegnare l'80a colonna nell'intestazione.
Qualcosa di simile al seguente dovrebbe essere sufficiente:

(setq-default header-line-format 
              (list " " (make-string 79 ?-) "|"))

È necessario modificare il numero di spazi in quella prima stringa in base alla dimensione della frangia sinistra. Ma a parte questo, dovrebbe funzionare abbastanza bene. Non è conveniente come un righello nel buffer effettivo, ma aiuta.

È inoltre possibile impostarlo per applicare solo ai buffer di programmazione.

(defun prog-mode-header-line ()
  "Setup the `header-line-format' on for buffers."
  (setq header-line-format 
        (list " " (make-string 79 ?-) "|")))

(add-hook 'prog-mode-hook #'prog-mode-header-line)

Risultato:
dovresti ottenere qualcosa di simile al seguente (la prima riga non è effettivamente nel buffer, ma nell'intestazione).

-------------------------------------------------------------------------------|
;; This is what your buffer should look like all the way up to column number 80.
(setq some-dummy-variable we-are-all-friends)

1
Nota che in Emacs 24.3 anche questa modalità verrà interrotta, almeno in alcuni casi limite. Emacs 24.3 non riesce a tenere correttamente conto della riga di intestazione quando calcola l'altezza di una finestra. Di conseguenza, la Società non riesce a disegnare i popup appropriati nei casi in cui l'altezza è importante, cioè nella parte inferiore del buffer.
lunaryorn,

1
Questa è un'idea davvero interessante. Peccato che non riesca a contrassegnare due risposte come corrette, la risposta "patch fci" presenta alcuni inconvenienti e, a seconda delle circostanze, questa può essere una scelta migliore. Grazie!
Jorgen Schäfer,

10
C'è anche M-x ruler-mode.
sanityinc

Questo non disegna a partire da quello dei numeri (quando vengono visualizzati i numeri di riga)
ideasman42

17

Dopo aver sofferto molte sofferenze a causa di vari bug fill-column-indicator, l'ho eliminato definitivamente dalla mia configurazione.

Quello che attualmente uso è la funzionalità Emacs integrata per evidenziare linee troppo lunghe. Anche questo sembra migliore, non lo abiliterei fill-column-indicatorora anche se fosse privo di bug.

Per cominciare puoi prendere la mia configurazione:

(setq-default
 whitespace-line-column 80
 whitespace-style       '(face lines-tail))

Quindi abilitalo dove vuoi. Lo uso solo nel contesto di programmazione:

(add-hook 'prog-mode-hook #'whitespace-mode)

9

Ci sono alternative migliori?

Emacs 27 supporterà nativamente un indicatore di colonna di riempimento tramite la modalità minore buffer locale display-fill-column-indicator-modee la sua controparte globale global-display-fill-column-indicator-mode.

Eccolo in azione:

inserisci qui la descrizione dell'immagine

Quoth (emacs) Displaying Boundaries:

14.15 Displaying Boundaries
===========================

Emacs can add an indicator to display a fill column position.  The fill
column indicator is a useful functionality specially in prog-mode to
indicate the position of an specific column.

   You can set the buffer-local variables
‘display-fill-column-indicator’ and
‘display-fill-column-indicator-character’ to activate the indicator and
controls how the indicator looks.

   Alternatively you can type ‘M-x display-fill-column-indicator-mode’
or ‘M-x global-display-fill-column-indicator-mode’ which enables the
indicator locally and globally respectively and also chooses the
character to use if none is set already.  It is possible to use the
first one to activate the indicator in a hook or the second one to
enable it globally.

   There are 2 buffer local variables and 1 face to customize this mode:

‘display-fill-column-indicator-column’
     Specifies the column number where the indicator should be set.  It
     can take positive numerical values for the column or the special
     value ‘t’ which means that the variable ‘fill-column’ will be used.

     Any other value disables the indicator.  The default value is ‘t’.

‘display-fill-column-indicator-character’
     Specifies the character used for the indicator.  This character can
     be any valid char including unicode ones if the actual font
     supports them.

     When the mode is enabled through the functions
     ‘display-fill-column-indicator-mode’ or
     ‘global-display-fill-column-indicator-mode’, the initialization
     functions check if this variable is ‘non-nil’, otherwise the
     initialization tries to set it to U+2502 or ‘|’.

‘fill-column-indicator’
     Specifies the face used to display the indicator.  It inherits its
     default values from shadow but without background color.  To change
     the indicator color you need to set only the foreground color of
     this face.

7

Questa pagina di EmacsWiki contiene molte informazioni su diversi modi per contrassegnare una determinata colonna o per farti sapere quando la passi.

Quello che uso è Mode Line Position .

Altri includono la visualizzazione di una linea verticale nella colonna ( indicatore colonna , indicatore colonna di riempimento ) e l'uso della modalità spazi bianchi per evidenziare il testo che passa oltre la colonna.

(Se hai bisogno che la riga sia lontana a destra di tutto il testo in tutte le righe, puoi sempre attivarla picture-mode, ma questo è probabilmente utile qui solo come soluzione temporanea.)

Vedi anche Trova linee lunghe per i modi per trovare linee lunghe su richiesta.


6

Non esattamente quello che vuoi, ma un righello come @ Malabarba ♦ perderà spazio, ecco una soluzione migliore:

Esiste un pacchetto integrato in emacs-goodies-el(consiglio di installarlo nel terminale) chiamato highlight-beyond-fill-column.el , aggiungilo al tuo .emacso init.el:

(setq-default fill-column 80)
(add-hook 'prog-mode-hook 'highlight-beyond-fill-column)
(custom-set-faces '(highlight-beyond-fill-column-face
                    ((t (:foreground "red" )))))

Il testo oltre il fill-columnquale è 80 nello snippet verrà evidenziato con il colore di red. Puoi impostare il viso come preferisci.


1

Poiché fill-column-indicatorè piuttosto pesante, questa soluzione mostra un carattere a destra della riga corrente.

Quindi, quando stai digitando, puoi vedere il limite di linea prima di superarlo.

Questo definisce la modalità minore hl-line-margin-mode:

;; Global, ensures one active margin for the active buffer.
(defvar hl-line-margin--overlay nil)

(defun hl-line-margin--overlay-clear ()
  "Clear the overlays."
  (when hl-line-margin--overlay
    (delete-overlay hl-line-margin--overlay)
    (setq hl-line-margin--overlay nil)))

(defun hl-line-margin--overlay ()
  "Create the line highlighting overlay."
  ;; Remove in the event of a changed buffer,
  ;; ensures we update for a modified fill-column.
  (when (and hl-line-margin--overlay
             (not (eq (current-buffer)
                      (overlay-buffer hl-line-margin--overlay))))
    (hl-line-margin--overlay-clear))
  (unless hl-line-margin--overlay
    (setq hl-line-margin--overlay (make-overlay 0 0))
    (let ((space `((space :align-to ,fill-column)
                   (space :width 0))))
      (overlay-put hl-line-margin--overlay 'after-string
                   (concat (propertize " " 'display space 'cursor t)
                           (propertize " " 'face '(:inverse-video t))))))
  (let ((eol (line-end-position)))
    (unless (eql eol (overlay-start hl-line-margin--overlay))
      (move-overlay hl-line-margin--overlay eol eol))))

(defun hl-line-margin-mode-enable ()
  "Turn on `hl-line-margin-mode' for the current buffer."
  (add-hook 'post-command-hook #'hl-line-margin--overlay nil t))

(defun hl-line-margin-mode-disable ()
  "Turn off `hl-line-margin-mode' for the current buffer."
  (hl-line-margin--overlay-clear)
  (remove-hook 'post-command-hook #'hl-line-margin--overlay t))

;;;###autoload
(define-minor-mode hl-line-margin-mode
  "Show a character at the fill column of the current line."
  :lighter ""
  (cond (hl-line-margin-mode
         (jit-lock-unregister #'hl-line-margin-mode-enable)
         (hl-line-margin-mode-enable))
        (t
         (jit-lock-unregister #'hl-line-margin-mode-disable)
         (hl-line-margin-mode-disable))))

Se si utilizza evil-modee si desidera limitare questa modalità di inserimento, è possibile aggiungere i seguenti hook:

(add-hook 'evil-insert-state-entry-hook #'hl-line-margin-mode-enable)
(add-hook 'evil-insert-state-exit-hook #'hl-line-margin-mode-disable)
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.