Как я могу получить линейку в столбце 80?

81

Как программист, я хочу видеть линейку в определенном столбце (обычно 80), так что я вижу, когда я пересекаю этот столбец, а также видеть, насколько близко я к нему подхожу, чтобы я мог переформатировать свой код на ранней стадии.

Все варианты, которые я нашел, не достигают этой цели:

  • whitespace-mode, column-enforce-modeи column-markerтолько выделять отдельные строки после того, как текст в строке уже прошел fill-column. Я хотел бы видеть, когда я приближаюсь к колонне, а не только когда я пересекаю ее.
  • fill-column-indicatorбыло бы хорошим решением, за исключением того, что ломается auto-complete-mode, company-mode, avyи многое другое. Это вопросы , которые кажутся трудно исправить, каждый из которых требует отдельного временного решения - например, см на company-modeвопрос и на auto-complete-modeвопрос , последний в течение двух лет).

Есть ли лучшие альтернативы?

Йорген Шефер
источник
8
Это не ответ на ваш вопрос как таковой, но практическое решение - установить ширину окна / фрейма в 80 символов.
Эрик Браун
Спасибо за предложение. Я думаю, что я предпочел бы иметь дополнительную ширину, когда это необходимо, но это, безусловно, вариант. :-)
Йорген Шефер
5
Я бы добавил к предложению @ EricBrown: не меняйте фактическую ширину окна, а просто установите правое поле окна, чтобы пространство для редактирования составляло 80 символов. (set-window-margins nil 0 (max (- (window-width) 80) 0))Поэтому, если у вас есть окно шириной 120 символов, оно уменьшит пространство, необходимое для отображения кода, до 80 символов. Таким образом, это не испортит вашу конфигурацию окна, и вы можете включить ее, если хотите. Если у вас есть полосы, на самом деле будет линия, нарисованная в 80 столбцах.
Джордон Биондо
1
Вот суть идеи: gist.github.com/jordonbiondo/aa6d68b680abdb1a5f70 и вот она в действии: i.imgur.com/dUx4bNz.gif
Джордон Биондо,
@ jordon-biondo - пропускаются обновления для изменения размера окна, см .: bitbucket.org/snippets/ideasman42/zexMG5
ideasman42

Ответы:

39

fill-column-indicatorявляется наиболее зрелым решением, и если вы найдете код на основе наложения, с которым он конфликтует, вы можете добавить код для приостановки, fci-modeпока конфликтующий код активен. Например, следующий код заставляет его работать 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
источник
5
Или посмотрите github.com/company-mode/company-mode/issues/… для аналогичного решения для company-mode.
Дмитрий
Привет, спасибо, что поделились идеей. Как мне заставить это работать? У меня есть код в моем .emacs, но я полагаю, мне нужно добавить несколько хуков, чтобы он работал?
PierreE
Да, приведенный выше пример советует popup-createи popup-delete- в зависимости от вашего варианта использования вам может потребоваться указать разные функции.
sanityinc
2
Недопустимо медленно .
Александр Шукаев
21

Вот один из вариантов, который является более надежным, он почти ничего не нарушает (иногда режим компании является заметным исключением), но не так удобен, как fill-column-indicator.

Используйте header-line-format, чтобы отметить 80-й столбец в заголовке.
Что-то вроде следующего должно быть достаточно:

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

Вы должны изменить количество пробелов в этой первой строке в зависимости от размера вашей левой полосы. Но кроме этого, это должно работать достаточно хорошо. Это не так удобно, как линейка в реальном буфере, но это помогает.

Вы также можете настроить его на применение только к программным буферам.

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

Результат:
вы должны получить что-то вроде следующего (первая строка на самом деле не в буфере, а в заголовке).

-------------------------------------------------------------------------------|
;; 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
источник
1
Обратите внимание, что в Emacs 24.3 это также нарушит режим компании, по крайней мере, в некоторых крайних случаях. Emacs 24.3 не может корректно учитывать строку заголовка при вычислении высоты окна. Следовательно, Компании не удается нарисовать правильные всплывающие окна в тех случаях, когда важна высота, то есть в самом низу буфера.
lunaryorn
1
Это действительно интересная идея. Жаль, что я не могу пометить два ответа как правильные, ответ «patch fci» имеет некоторые недостатки, и в зависимости от обстоятельств это может быть лучшим выбором. Спасибо!
Йорген Шефер
10
Там тоже M-x ruler-mode.
sanityinc
Это не рисует, начиная с номера (когда отображаются номера строк)
ideasman42
17

После долгих страданий из-за различных ошибок fill-column-indicatorя навсегда удалил их из своего конфига.

В настоящее время я использую встроенную функциональность Emacs для выделения слишком длинных строк. Это даже выглядит лучше, я бы не включил fill-column-indicatorсейчас, даже если бы это было без ошибок.

Для начала вы можете взять мои настройки:

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

Затем включите его там, где вы хотите. Я использую это только в контексте программирования:

(add-hook 'prog-mode-hook #'whitespace-mode)
Марк Карпов
источник
9

Есть ли лучшие альтернативы?

Emacs 27 будет изначально поддерживать индикатор заполнения столбца с помощью вспомогательного локального режима буфера display-fill-column-indicator-modeи его глобального аналога global-display-fill-column-indicator-mode.

Вот оно в действии:

введите описание изображения здесь

Квот (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

Эта страница EmacsWiki содержит много информации о различных способах пометить определенный столбец или иным образом сообщить вам, когда вы пройдете мимо него.

Тот, который я использую, является положением линии режима .

Но другие включают , показывающий вертикальную линию в колонке ( колонка Маркер , заполняющая Column индикатор ) и используя пробельные режим для выделения текста , который проходит мимо колонны.

(Если вам нужно, чтобы строка находилась далеко справа от всего текста во всех строках, вы всегда можете включить ее picture-mode, но это, вероятно, полезно здесь только в качестве временного обходного пути.)

См. Также Поиск длинных линий, чтобы узнать, как найти длинные строки по запросу.

Нарисовался
источник
6

Не совсем то, что вы хотите, но линейка @ Malabarba ♦ будет растрачивать пространство, вот лучшее решение:

Существует встроенный пакет emacs-goodies-el(рекомендуется установить его в терминале), называемый highlight-beyond-fill-column.el , добавьте его в свой .emacsили 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" )))))

Текст, fill-columnкоторый превышает 80 во фрагменте, будет выделен цветом red. Вы можете установить лицо, как вам нравится.

CodyChan
источник
1

Так как fill-column-indicatorэто довольно тяжелое, это решение показывает символ справа от текущей строки.

Поэтому, когда вы печатаете, вы можете увидеть предел строки, прежде чем превысить его.

Это определяет несовершеннолетний режим 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))))

Если вы используете evil-modeи хотите ограничить это режимом вставки, вы можете добавить следующие хуки:

(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
источник