0

I want to be able to edit Git commit message without having to either manually break up the text into multiple lines as I write (I do that afterwords using M-x fill-region) or having to scroll horizontally to read everything that I have already written, and therefore want to set truncate-lines to nil to make Emacs wrap the lines at the window edge (it would be even better if I could get it to do Word Wrap (Visual Line Mode) instead, but I don't know what value to set truncate-lines to for that to happen). This works well if I use M-x set-variable to set the value of the variable, but I want this to happen automatically whenever I edit Git commit messages, and I have therefore added this to my ~/.emacs:

(define-derived-mode git-commit-message-mode fundamental-mode "Git commit message"
  "Major mode for composing or editing Git commit messages"
  ((lambda () ;; Create a lambda and call it immediately. Could maybe be solved differently...
     (require 'fill-column-indicator)
     (cond ((not fci-mode) (fci-mode))) ;; Activate fill column indicator if not already activated
     (setq line-move-visual nil)
     (custom-set-variables
      '(show-paren-mode t)
      '(fci-rule-column 70) ;; Git recommends using a max line length of 70 characters in the commit message body
      '(truncate-lines nil) ;; This is the line that doesn't seem to have any effect
      )
     )))

However, while the mode seems to be activated when I edit Git commits (it properly activates and sets up the fill column indicator), this does not work for making a persistent change to truncate-lines. Why not? Is truncate-lines changed to nil temporarily and then changed to some other value shortly after? How can I change truncate-lines changed to nil and make it keep that value?

Drew
  • 75,699
  • 9
  • 109
  • 225
HelloGoodbye
  • 121
  • 4
  • https://emacs.stackexchange.com/tags/elisp/info – Drew Sep 02 '22 at 16:56
  • 1
    How about *not* using `custom-set-variables` at all and instead use `(setq fci-rule-column 70 truncate-lines nil word-wrap t)` and as far as I am aware, `show-parens-mode` is a minor mode, so you probably want a separate line that activates the mode just in case there are other things that said minor mode does when starting up: `(show-parens-mode 1)` to activate. LIkewise, `visual-line-mode` is a minor-mode which should be deactivated with `(visual-line-mode -1)` instead of with `setq`, and that only needs to be done if that mode were enabled globally. – lawlist Sep 02 '22 at 19:08
  • 1
    ... and there is no need of the lambda either. – NickD Sep 02 '22 at 20:57
  • @Drew Okay. So is there some tag to use when you have a question about *using* Emacs Lisp? – HelloGoodbye Sep 19 '22 at 07:49
  • @NickD I agree about the lambda; that indirection seems very superfluous! I don't know why I had it. – HelloGoodbye Sep 19 '22 at 07:56
  • @lawlist Could you please explain your comment slightly? Why is using `setq` better than using `custom-set-variables`? And why does the fact that `show-parens-mode` (`show-paren-mode`?) is a minor mode make it desirable to have a separate line that activates the mode? Does `(show-parens-mode 1)` achieve the same thing as `(custom-set-variables '(show-paren-mode t))`? And I don't have `visual-line-mode` in my code so I'm not really sure what you mean by that. – HelloGoodbye Sep 19 '22 at 08:26
  • Use a tag that's specific to what you're trying to do, in "using" Elisp. "Using Elisp" in anyway far too vague to be useful. – Drew Sep 19 '22 at 15:31

1 Answers1

1

What @lawlist mentions in his comment, plus there is no need of the lambda:

(define-derived-mode git-commit-message-mode fundamental-mode "Git commit message"
  "Major mode for composing or editing Git commit messages"
  (require 'fill-column-indicator)
  (visual-line-mode -1)
  (fci-mode 1)
  (show-paren-mode 1)
  (setq-local fci-rule-column 70 ;; Git recommends using a max line
                                 ;; length of 70 characters in the
                                 ;; commit message body
              truncate-lines nil) ;; This is the line that doesn't
                                  ;; seem to have any effect
)

seems to work for me. Simpler is better...

NickD
  • 27,023
  • 3
  • 23
  • 42
  • I misread the variable `line-move-visual` as `visual-line-mode`, and erroneously thought the O.P. was seeking to disable that minor-mode. In addition, the O.P. mentioned an interest in the magic of `visual-line-mode`, which I interpreted as a desire to find out about setting the variable `word-wrap` to a `non-nil` value without the need to enable `visual-line-mode`. I haven't recently studied `line-move-visual`, but it may indeed be the case that the O.P. wants to set that to a `nil` value. – lawlist Sep 02 '22 at 21:07
  • Yes, perhaps - I was more interested in simplifying it and making sure that the `truncate-line` setting was effective. In any case, the OP should be able to tweak it the way he wants. – NickD Sep 02 '22 at 21:12
  • This solution does not work. Now the fill column indicator doesn't end up after column 70 which it should but after column 80, and Emacs still doesn't wrap lines at the window edge. – HelloGoodbye Sep 19 '22 at 08:38
  • If I use `setq` instead of `setq-local`, though, it does work as intended—the fill column indicator ends up after column 70 and Emacs wraps lines at the window edge—nice! What is the difference between `setq` instead of `setq-local`? – HelloGoodbye Sep 19 '22 at 08:41
  • Also, what does `(visual-line-mode -1)`, `(fci-mode 1)` and `(show-paren-mode 1)` do? – HelloGoodbye Sep 19 '22 at 08:42
  • Disable `visual-line-mode`, enable `fci-mode` and `show-paren-mode`. These were all carried over from your original function. – NickD Sep 19 '22 at 11:45
  • Are you sure the mode of the buffer is `git-commit-message-mode`? If it is, what is the value of `truncate-lines` in the buffer (that's with `setq-local` in the function, not your modification that "works": `setq-local` makes the variable buffer-local - that's the only difference with `setq`. It is equivalent to calling ‘make-local-variable’ followed by ‘setq’ for each of the variables.) – NickD Sep 19 '22 at 11:51
  • I see that `visual-line-mode` disabling was suggested by @lawlist, it is not part of your original function, Sorry about that. – NickD Sep 19 '22 at 11:53
  • Actually, it seems that both `(visual-line-mode -1)`, `(visual-line-mode 1)` and `(visual-line-mode)` work equally well (and I don't seem to need to set `truncate-line` to `nil` either). What is going on here? Is the argument to `visual-line-mode` ignored? – HelloGoodbye Sep 21 '22 at 08:31
  • Furthermore, if I do `(visual-line-mode)` once, it enables the behavior that I want, but then it doesn't seem to matter whether or not I do `(visual-line-mode)` subsequently. Isn't `(visual-line-mode)` supposed to toggle visual line mode on and off? Then why isn't anything happening when I do `(visual-line-mode)` subsequently? Should doing `(visual-line-mode)` twice be like not doing `(visual-line-mode)` at all? – HelloGoodbye Sep 21 '22 at 08:39
  • Yes, the major mode of the buffer is `git-commit-message-mode`. I'm checking this with `M-x describe-variable RET major-mode`. – HelloGoodbye Sep 21 '22 at 08:57
  • If I do `(visual-line-mode)` but don't set `truncate-lines` in my `~/.emacs`, the value of `truncate-lines` is `nil`, lines break at the window edge and up/down arrow keys move by a visual line. If I don't do `(visual-line-mode)` and don't set `truncate-lines` in my `~/.emacs`, the value of `truncate-lines` is `t` and lines don't break at the window edge. If I don't do `(visual-line-mode)` but set `truncate-lines` to `nil` in my `~/.emacs`, the value of `truncate-lines` is `nil` and lines break at the window edge, but up/down arrow keys move by a logical line instead of a visual line. – HelloGoodbye Sep 21 '22 at 08:59
  • Only if I do `(visual-line-mode)` (or `(visual-line-mode 1)` or `(visual-line-mode -1)`) I seem to get the behavior that I want, i.e., lines break at the window edge and up/down arrow keys move by a visual line and not by a logical line. – HelloGoodbye Sep 21 '22 at 09:00
  • What do you mean by "that's with `setq-local` in the function, not your modification that 'works' "? Right now, I'm using `setq-local` to set `truncate-lines`. `setq-local` doesn't seem to have any effect and leaves the value of `truncate-lines` unchanged, and if I do `describe-variable RET major-mode` it says `truncate-lines is a variable defined in ‘C source code’.`, `Its value is t` and `Original value was nil`. – HelloGoodbye Sep 21 '22 at 09:09
  • I mean right now I'm using `setq` to set `truncate-lines` (and not `setq-local` which I see that I wrote in my previous comment, so sorry for that typo). – HelloGoodbye Sep 26 '22 at 08:04