Jak zdobyć linijkę w kolumnie 80?

81

Jako programista chcę widzieć linijkę w określonej kolumnie (zwykle 80), więc widzę, kiedy przekraczam tę kolumnę, ale także, jak się do niej zbliżam, aby móc wcześniej sformatować kod.

Opcje, które do tej pory znalazłem, nie pozwalają osiągnąć tego celu:

  • whitespace-mode, column-enforce-modei column-markerpodświetl poszczególne wiersze tylko wtedy, gdy tekst w wierszu już minął fill-column. Chciałbym zobaczyć, kiedy zbliżam się do kolumny, nie tylko kiedy ją przekraczam.
  • fill-column-indicatorbyłoby to dobre rozwiązanie, oprócz tego, że łamie auto-complete-mode, company-mode, avy, i więcej. Są to kwestie, które wydają się trudne do ustalenia, z których każda wymaga indywidualnego obejście - na przykład zobaczyć ten company-modeproblem i ten auto-complete-modeproblem , te ostatnie ponad dwa lata).

Czy są jakieś lepsze alternatywy?

Jorgen Schäfer
źródło
8
Nie jest to odpowiedź na twoje pytanie, ale praktycznym rozwiązaniem jest ustawienie szerokości okna / ramki na 80 znaków.
Eric Brown,
Dzieki za sugestie. Myślę, że wolałbym mieć opcjonalną szerokość dostępną w razie potrzeby, ale z pewnością jest to opcja. :-)
Jorgen Schäfer
5
Dodałbym do sugestii @ EricBrown, nie zmieniaj rzeczywistej szerokości okna, ale raczej ustaw prawy margines okna, aby przestrzeń do edycji wynosiła 80 znaków. (set-window-margins nil 0 (max (- (window-width) 80) 0))Więc jeśli masz okno o szerokości 120 znaków, zmniejszy to miejsce, w którym musisz wyświetlić kod, do 80 znaków. W ten sposób nie zepsuje konfiguracji okna i możesz ją wyłączyć, jeśli chcesz. Jeśli masz prążki, w rzeczywistości 80 linii zostanie narysowana linia.
Jordon Biondo
1
Oto sedno pomysłu: gist.github.com/jordonbiondo/aa6d68b680abdb1a5f70 i oto jest w akcji: i.imgur.com/dUx4bNz.gif
Jordon Biondo
@ jordon-biondo - to pomija haki aktualizacji dla zmiany rozmiaru okna, patrz: bitbucket.org/snippets/ideasman42/zexMG5
ideasman42

Odpowiedzi:

39

fill-column-indicatorjest najbardziej dojrzałym rozwiązaniem, a jeśli znajdziesz kod oparty na nakładce, z którym jest on w konflikcie, możesz dodać kod do zawieszenia, fci-modegdy aktywny jest konflikt kodu. Na przykład poniższy kod sprawia, że ​​działa z 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
źródło
5
Lub zobacz github.com/company-mode/company-mode/issues/ ... podobne rozwiązanie dla company-mode.
Dmitry
Cześć, dziękuję za podzielenie się pomysłem. Jak mogę to uruchomić? Mam kod w .emacs, ale przypuszczam, że muszę dodać kilka haczyków, żeby zadziałało?
PierreE
Tak, powyższy przykład zaleca popup-createi popup-delete- w zależności od przypadku użycia może być konieczne podanie różnych funkcji.
sanityinc
2
Niedopuszczalnie powolne .
Alexander Shukaev
21

Oto jedna opcja, która jest bardziej niezawodna, prawie nic nie psuje (czasami tryb firmowy jest godnym uwagi wyjątkiem), ale nie jest tak wygodna jak fill-column-indicator.

Użyj formatu wiersza nagłówka, aby zaznaczyć 80. kolumnę nagłówka.
Powinno wystarczyć coś takiego:

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

Powinieneś zmienić liczbę spacji w tym pierwszym ciągu w zależności od rozmiaru lewej grzywki. Ale poza tym powinno to działać dość dobrze. Nie jest tak wygodny jak linijka w rzeczywistym buforze, ale pomaga.

Możesz również ustawić, aby dotyczyło to tylko buforów programujących.

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

Wynik:
powinieneś otrzymać coś takiego (pierwszy wiersz nie znajduje się w buforze, ale w nagłówku).

-------------------------------------------------------------------------------|
;; 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
źródło
1
Zauważ, że w Emacs 24.3 spowoduje to również uszkodzenie trybu firmowego, przynajmniej w niektórych przypadkach krawędzi. Emacs 24.3 nie uwzględnia poprawnie linii nagłówka przy obliczaniu wysokości okna. W związku z tym Firma nie rysuje odpowiednich okien podręcznych w przypadkach, gdy wysokość jest ważna, tj. Na samym dole bufora.
lunaryorn
1
To naprawdę ciekawy pomysł. Szkoda, że ​​nie mogę oznaczyć dwóch odpowiedzi jako poprawnych, odpowiedź „łatka fci” ma pewne wady i w zależności od okoliczności może to być lepszy wybór. Dziękuję Ci!
Jorgen Schäfer,
10
Jest też M-x ruler-mode.
sanityinc
Nie rysuje się, zaczynając od numeru (gdy wyświetlane są numery linii)
ideasman42
17

Po wielu cierpieniach spowodowanych różnymi błędami fill-column-indicator, na dobre usunąłem go z mojej konfiguracji.

Obecnie używam wbudowanej funkcjonalności Emacsa do podświetlania zbyt długich linii. To nawet wygląda lepiej, nie włączałbym fill-column-indicatorteraz, nawet gdyby nie było błędów.

Na początek możesz pobrać moją konfigurację:

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

Następnie włącz go tam, gdzie chcesz. Używam go tylko w kontekście programowania:

(add-hook 'prog-mode-hook #'whitespace-mode)
Mark Karpov
źródło
9

Czy są jakieś lepsze alternatywy?

Emacs 27 będzie obsługiwał wskaźnik wypełnienia kolumny natywnie za pomocą lokalnego trybu buforowego display-fill-column-indicator-modei jego globalnego odpowiednika global-display-fill-column-indicator-mode.

Oto jest w akcji:

wprowadź opis zdjęcia tutaj

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.
Bazylia
źródło
7

Ta strona EmacsWiki zawiera wiele informacji na temat różnych sposobów oznaczania konkretnej kolumny lub w inny sposób informowania o jej przejściu.

Ten, którego używam, to pozycja linii trybu .

Ale inni to pokazano linię pionową w kolumnie ( Column Marker , Fill-Kolumna Indicator ) i stosując tryb białymi aby podświetlić tekst, który przechodzi obok kolumny.

(Jeśli chcesz, aby wiersz znajdował się daleko po prawej stronie całego tekstu we wszystkich wierszach, zawsze możesz go włączyć picture-mode, ale prawdopodobnie jest to przydatne tutaj tylko jako tymczasowe obejście).

Zobacz także Znajdź długie linie, aby dowiedzieć się, jak znaleźć długie linie na żądanie.

Rysował
źródło
6

Nie dokładnie to, czego chcesz, ale władca jak @ Malabarba ♦ zniszczy przestrzeń, oto lepsze rozwiązanie:

Jest wbudowany pakiet w emacs-goodies-el(zalecamy zainstalowanie go w terminalu) o nazwie highlight-poza-fill-column.el , dodaj to do swojego .emacslub 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" )))))

Tekst powyżej fill-column80 we fragmencie zostanie podświetlony kolorem red. Możesz ustawić twarz tak, jak chcesz.

CodyChan
źródło
1

Ponieważ fill-column-indicatorjest dość ciężkie, to rozwiązanie pokazuje znak po prawej stronie bieżącej linii.

Więc podczas pisania możesz zobaczyć limit linii, zanim go przekroczysz.

To definiuje tryb podrzędny 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))))

Jeśli używasz evil-modei chcesz ograniczyć to do trybu wstawiania, możesz dodać następujące zaczepy:

(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
źródło