Como posso obter uma régua na coluna 80?

81

Como programador, quero ver uma régua em uma coluna específica (geralmente 80), tanto para ver quando cruzo essa coluna, mas também para ver o quanto estou chegando perto para poder reformatar meu código mais cedo.

As opções que encontrei até agora nem todas estão atingindo esse objetivo:

  • whitespace-mode,, column-enforce-modee column-markerrealce apenas linhas individuais após o texto na linha já ter passado o fill-column. Gostaria de ver quando estou chegando perto da coluna, não apenas quando a atravesso.
  • fill-column-indicatorseria uma boa solução, exceto que ele quebra auto-complete-mode, company-mode, avy, e muito mais. Esses são problemas que parecem difíceis de resolver, cada um exigindo uma solução individual - por exemplo, veja o company-modeproblema e o auto-complete-modeproblema , este último com mais de dois anos).

Existem alternativas melhores?

Jorgen Schäfer
fonte
8
Esta não é uma resposta à sua pergunta propriamente dita, mas uma solução prática é definir a largura da sua janela / moldura para 80 caracteres.
Eric Brown
Obrigado pela sugestão. Acho que prefiro ter a largura opcional disponível quando necessário, mas certamente é uma opção. :-)
Jorgen Schäfer
5
Eu acrescentaria à sugestão do @ EricBrown, não altere a largura real da janela, mas defina a margem direita da janela para que o espaço de edição tenha 80 caracteres. (set-window-margins nil 0 (max (- (window-width) 80) 0))Portanto, se você tiver uma janela de 120 caracteres, ela reduzirá o espaço necessário para exibir o código para 80 caracteres. Dessa forma, não atrapalhará a configuração da janela e você poderá desativá-la, se desejar. Se você tiver franjas, na verdade haverá uma linha desenhada em 80 colunas.
Jordon Biondo 24/09
1
Aqui está uma essência da ideia: gist.github.com/jordonbiondo/aa6d68b680abdb1a5f70 e aqui está em ação: i.imgur.com/dUx4bNz.gif
Jordon Biondo
@ jordon-biondo - faltam ganchos de atualização para redimensionar janelas, consulte: bitbucket.org/snippets/ideasman42/zexMG5
ideasman42

Respostas:

39

fill-column-indicatoré a solução mais madura e, se você encontrar um código baseado em sobreposição com o qual entra em conflito, poderá adicionar um código para suspender fci-modeenquanto o código conflitante estiver ativo. Por exemplo, o código a seguir faz com que funcione 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)))
sanityinc
fonte
5
Ou consulte github.com/company-mode/company-mode/issues/… para obter uma solução semelhante company-mode.
Dmitry
Olá, obrigado por compartilhar a idéia. Como faço para que isso funcione? Eu tenho o código no meu .emacs, mas suponho que tenho que adicionar alguns ganchos para que ele funcione?
PierreE 9/10
Sim, o exemplo acima aconselha popup-createe popup-delete- dependendo do seu caso de uso, pode ser necessário aconselhar funções diferentes.
Sanityinc # 13/17
2
Inaceitavelmente lento .
Alexander Shukaev
21

Aqui está uma opção mais robusta: ela quebra quase nada (ocasionalmente o modo empresa é uma exceção notável), mas não é tão conveniente quanto fill-column-indicator.

Use o formato de linha de cabeçalho para marcar a 80ª coluna no cabeçalho.
Algo como o seguinte deve ser suficiente:

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

Você deve alterar o número de espaços nessa primeira sequência, dependendo do tamanho da sua margem esquerda. Mas, fora isso, isso deve funcionar razoavelmente bem. Não é tão conveniente quanto uma régua no buffer real, mas ajuda.

Você também pode configurá-lo para aplicar apenas em buffers de programação.

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

Resultado:
você deve obter algo como o seguinte (a primeira linha não está realmente no buffer, mas no cabeçalho).

-------------------------------------------------------------------------------|
;; 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
fonte
1
Observe que no Emacs 24.3 isso também interromperá o Modo Empresa, pelo menos em alguns casos extremos. O Emacs 24.3 falha ao considerar corretamente a linha do cabeçalho ao calcular a altura de uma janela. Consequentemente, a empresa falha em desenhar pop-ups apropriados nos casos em que a altura é importante, ou seja, na parte inferior do buffer.
lunaryorn 24/09
1
Esta é uma ideia realmente interessante. Pena que não consigo marcar duas respostas como corretas, a resposta "patch fci" tem algumas desvantagens e, dependendo das circunstâncias, essa pode ser uma escolha melhor. Obrigado!
Jorgen Schäfer
10
Há também M-x ruler-mode.
Sanidadeinc #
Isso não chamar a iniciar após o número de (quando os números de linha exibida)
ideasman42
17

Depois de muito sofrimento por causa de vários erros fill-column-indicatorintroduzidos, eliminei-o da minha configuração para sempre.

O que eu uso atualmente é a funcionalidade interna do Emacs para destacar linhas muito longas. Parece ainda melhor, eu não ativaria fill-column-indicatoragora, mesmo que estivesse livre de erros.

Para começar, você pode pegar minha configuração:

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

Em seguida, ative-o onde quiser. Eu o uso apenas no contexto de programação:

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

Existem alternativas melhores?

O Emacs 27 oferecerá suporte nativo a um indicador de coluna de preenchimento por meio do modo secundário local de buffer display-fill-column-indicator-modee sua contrapartida global global-display-fill-column-indicator-mode.

Aqui está em ação:

insira a descrição da imagem aqui

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.
Manjericão
fonte
7

Esta página do EmacsWiki possui muitas informações sobre diferentes maneiras de marcar uma coluna específica ou informar quando você a passa.

O que eu uso é a Posição da linha de modo .

Mas outros incluem mostrando uma linha vertical na coluna ( Coluna marcador , Encha-Column Indicator ) e utilizando o modo de espaço em branco para realçar o texto que vai além da coluna.

(Se você precisar que a linha esteja à direita de todo o texto em todas as linhas, sempre poderá ativar picture-mode, mas isso provavelmente é útil aqui apenas como uma solução temporária.)

Consulte também Encontrar linhas longas para obter maneiras de encontrar linhas longas sob demanda.

Desenhou
fonte
6

Não exatamente o que você deseja, mas uma régua como @ Malabarba ♦ desperdiçará espaço, eis a melhor solução:

Existe um pacote embutido no emacs-goodies-el(recomendo instalá-lo no terminal) chamado realce-além-da-coluna-de-preenchimento.el , adicione-o ao seu .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" )))))

O texto além do fill-columnqual é 80 no trecho será destacado com a cor de red. Você pode definir o rosto como quiser.

CodyChan
fonte
1

Como fill-column-indicatoré bastante pesada, esta solução mostra um caractere à direita da linha atual.

Portanto, ao digitar, você pode ver o limite da linha antes de exceder.

Isso define o modo secundário 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 você usar evil-modee quiser limitar isso ao modo de inserção, poderá adicionar os seguintes ganchos:

(add-hook 'evil-insert-state-entry-hook #'hl-line-margin-mode-enable)
(add-hook 'evil-insert-state-exit-hook #'hl-line-margin-mode-disable)
ideasman42
fonte