Comment puis-je obtenir une règle à la colonne 80?

81

En tant que programmeur, je veux voir une règle sur une colonne spécifique (généralement 80), les deux pour que je voie quand je traverse cette colonne, mais aussi pour voir à quel point je me rapproche de celle-ci afin de pouvoir reformater mon code plus tôt.

Les options que j'ai trouvées jusqu'à présent n'atteignent pas cet objectif:

  • whitespace-mode, column-enforce-modeet column-markerne mettez en évidence que des lignes individuelles après que le texte de la ligne a déjà passé le fill-column. J'aimerais voir quand je m'approche de la colonne, pas seulement quand je la traverse.
  • fill-column-indicatorserait une bonne solution, sauf qu'il se casse auto-complete-mode, company-mode, avyet plus encore. Ce sont des problèmes qui semblent difficiles à résoudre, chacun nécessitant une solution de contournement individuelle - par exemple, voyez le company-modeproblème et le auto-complete-modeproblème , celui-ci ayant plus de deux ans).

Existe-t-il de meilleures alternatives?

Jorgen Schäfer
la source
8
Ce n’est pas une réponse à votre question en tant que telle, mais une solution pratique consiste à définir la largeur de votre fenêtre / cadre sur 80 caractères.
Eric Brown
Merci pour la suggestion. Je pense que je préférerais avoir la largeur optionnelle disponible lorsque cela est nécessaire, mais c'est certainement une option. :-)
Jorgen Schäfer
5
J'ajouterais à la suggestion de @ EricBrown: ne changez pas la largeur réelle de la fenêtre, mais définissez plutôt la marge droite de la fenêtre afin que l'espace d'édition soit de 80 caractères. (set-window-margins nil 0 (max (- (window-width) 80) 0))Donc, si vous avez une fenêtre large de 120 caractères, cela réduira l'espace dont vous disposez pour afficher le code à 80 caractères. De cette façon, votre configuration de fenêtre ne sera pas gâchée et vous pourrez l’activer / désactiver si vous le souhaitez. Si vous avez des franges, il y aura une ligne à 80 colonnes.
Jordon Biondo
1
Voici l'essentiel de l'idée: gist.github.com/jordonbiondo/aa6d68b680abdb1a5f70 et la voici en action: i.imgur.com/dUx4bNz.gif
Jordon Biondo le
@ jordon-biondo - cela manque les points de mise à jour pour le redimensionnement de la fenêtre, voir: bitbucket.org/snippets/ideasman42/zexMG5
ideasman42

Réponses:

39

fill-column-indicatorest la solution la plus mature et si vous trouvez un code basé sur la superposition avec lequel il entre en conflit, vous pouvez ajouter du code à suspendre tant fci-modeque le code en conflit est actif. Par exemple, le code suivant le fait fonctionner avec 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)))
santé mentale
la source
5
Ou consultez github.com/company-mode/company-mode/issues/… pour une solution similaire pour company-mode.
Dmitry
Bonjour, merci de partager cette idée. Comment puis-je obtenir que cela fonctionne? J'ai le code dans mes .emacs, mais je suppose que je dois ajouter des crochets pour que cela fonctionne?
PierreE
Oui, l'exemple ci-dessus conseille popup-createet popup-delete, selon votre cas d'utilisation, vous devrez peut-être conseiller différentes fonctions.
sanityinc
2
Inacceptablement lent .
Alexander Shukaev
21

Voici une option plus robuste, qui ne casse presque rien (le mode entreprise étant parfois une exception notable), mais qui n’est pas aussi pratique que fill-column-indicator.

Utilisez le format de ligne d'en-tête pour marquer la 80ème colonne de l'en-tête.
Quelque chose comme ce qui suit devrait suffire:

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

Vous devez modifier le nombre d'espaces dans cette première chaîne en fonction de la taille de votre frange gauche. Mais à part cela, cela devrait fonctionner assez bien. Ce n'est pas aussi pratique qu'une règle dans le tampon réel, mais ça aide.

Vous pouvez également le configurer pour s’appliquer uniquement aux tampons de programmation.

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

Résultat:
vous devriez obtenir quelque chose comme ce qui suit (la première ligne n'est pas réellement dans le tampon, mais dans l'en-tête).

-------------------------------------------------------------------------------|
;; This is what your buffer should look like all the way up to column number 80.
(setq some-dummy-variable we-are-all-friends)
Malabarba
la source
1
Notez que dans Emacs 24.3, cela rompra également le mode société, du moins dans certains cas. Emacs 24.3 ne parvient pas à tenir correctement la ligne d’en-tête en compte lors du calcul de la hauteur d’une fenêtre. Par conséquent, la société ne parvient pas à dessiner les fenêtres contextuelles appropriées dans les cas où la hauteur est importante, c'est-à-dire au bas de la zone tampon.
lunaryorn
1
C'est une idée vraiment intéressante. Dommage que je ne puisse pas marquer deux réponses comme correctes, la réponse "patch fci" présente certains inconvénients et, selon les circonstances, cela peut être un meilleur choix. Je vous remercie!
Jorgen Schäfer
10
Il y a aussi M-x ruler-mode.
sanityinc
Cela ne dessine pas à partir des numéros (lorsque les numéros de lignes sont affichés)
ideasman42
17

Après beaucoup de souffrance à cause de divers bugs fill-column-indicatorintroduits, je l'ai définitivement supprimé de ma configuration.

Ce que j'utilise actuellement, c'est la fonctionnalité intégrée d'Emacs pour mettre en évidence les lignes trop longues. Même cela a l'air mieux, je ne l'activerais pas fill-column-indicatormaintenant même si c'était sans bug.

Pour commencer, vous pouvez saisir ma configuration:

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

Puis activez-le où vous voulez. Je ne l'utilise que dans un contexte de programmation:

(add-hook 'prog-mode-hook #'whitespace-mode)
Mark Karpov
la source
9

Existe-t-il de meilleures alternatives?

Emacs 27 supportera un indicateur de colonne de remplissage de manière native par le biais du mode mineur local du tampon display-fill-column-indicator-modeet de son équivalent global global-display-fill-column-indicator-mode.

Ici c'est en action:

entrez la description de l'image ici

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.
Basilic
la source
7

Cette page EmacsWiki contient de nombreuses informations sur les différentes manières de marquer une colonne particulière ou de vous laisser savoir quand vous la passez.

Celui que j'utilise est Mode Line Position .

Mais d' autres comprennent montrant une ligne verticale à la colonne ( colonne marqueur , fill-column indicateur ) et en utilisant le mode d' espaces pour mettre en évidence le texte qui passe devant la colonne.

(Si vous avez besoin que la ligne se trouve à l'extrême droite de tout le texte de toutes les lignes, vous pouvez toujours l'activer picture-mode, mais cela n'est probablement utile que comme solution de contournement temporaire.)

Reportez-vous également à la section Recherche de longues lignes pour savoir comment rechercher des lignes longues à la demande.

A dessiné
la source
6

Pas exactement ce que vous voulez, mais des règles comme @ Malabarba ♦ vous feront perdre de l’espace, voici la meilleure solution:

Il y a un paquet intégré dans emacs-goodies-el(il est recommandé de l'installer dans le terminal) appelé highlight-beyond-fill-column.el , ajoutez-le à votre .emacsou 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" )))))

Le texte au-delà de fill-column80 dans l'extrait sera mis en surbrillance avec la couleur red. Vous pouvez définir le visage comme vous le souhaitez.

CodyChan
la source
1

Comme il fill-column-indicatorest assez lourd, cette solution affiche un caractère à droite de la ligne actuelle.

Ainsi, lorsque vous tapez, vous pouvez voir la limite de ligne avant de la dépasser.

Ceci définit le mode mineur 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))))

Si vous utilisez evil-modeet souhaitez limiter cela au mode insertion, vous pouvez ajouter les points suivants:

(add-hook 'evil-insert-state-entry-hook #'hl-line-margin-mode-enable)
(add-hook 'evil-insert-state-exit-hook #'hl-line-margin-mode-disable)
idéesman42
la source