Use noweb for magit customisation

This commit is contained in:
TEC 2022-08-12 00:23:11 +08:00
parent e78d7b5d40
commit 001ae6f96a
Signed by: tec
SSH Key Fingerprint: SHA256:eobz41Mnm0/iYWBvWThftS0ElEs1ftBr6jamutnXc/A
1 changed files with 72 additions and 59 deletions

View File

@ -1914,6 +1914,9 @@ already clear, and there's no need for a different face.
#+end_src
*** Magit
:PROPERTIES:
:header-args:emacs-lisp: :tangle no :noweb-ref magit-tweaks
:END:
#+begin_quote
From the =:tools magit= module.
@ -1923,79 +1926,89 @@ From the =:tools magit= module.
Magit is great as-is, thanks for making such a lovely package [[https://github.com/tarsius][Jonas]]!
There's still a room for a little tweaking though...
#+begin_src emacs-lisp :tangle yes :noweb no-export :noweb-prefix no :noweb-ref nil
(after! magit
<<magit-tweaks>>)
#+end_src
**** Commit message templates
One little thing I want to add is some per-project commit message templates.
#+begin_src emacs-lisp
#+begin_src emacs-lisp :tangle yes :noweb-ref none
(defvar +magit-project-commit-templates-alist nil
"Alist of toplevel dirs and template strings/functions.")
(after! magit
(defun +magit-fill-in-commit-template ()
"Insert template from `+magit-fill-in-commit-template' if applicable."
(when-let ((template (and (save-excursion (goto-char (point-min)) (string-match-p "\\`\\s-*$" (thing-at-point 'line)))
(cdr (assoc (file-name-base (directory-file-name (magit-toplevel)))
+magit-project-commit-templates-alist)))))
(goto-char (point-min))
(insert (if (stringp template) template (funcall template)))
(goto-char (point-min))
(end-of-line)))
(add-hook 'git-commit-setup-hook #'+magit-fill-in-commit-template 90))
"Alist of toplevel dirs and template hf strings/functions.")
#+end_src
#+begin_src emacs-lisp
(defun +magit-fill-in-commit-template ()
"Insert template from `+magit-fill-in-commit-template' if applicable."
(when-let ((template (and (save-excursion (goto-char (point-min)) (string-match-p "\\`\\s-*$" (thing-at-point 'line)))
(cdr (assoc (file-name-base (directory-file-name (magit-toplevel)))
+magit-project-commit-templates-alist)))))
(goto-char (point-min))
(insert (if (stringp template) template (funcall template)))
(goto-char (point-min))
(end-of-line)))
(add-hook 'git-commit-setup-hook #'+magit-fill-in-commit-template 90)
#+end_src
This is particularly useful when creating commits for Org, as they need to
follow [[https://orgmode.org/worg/org-contribute.html#commit-messages][a certain format]] and sometimes I forget elements (oops!).
#+begin_src emacs-lisp
(after! magit
(defun +org-commit-message-template ()
"Create a skeleton for an Org commit message based on the staged diff."
(let (change-data last-file file-changes temp-point)
(with-temp-buffer
(apply #'call-process magit-git-executable
nil t nil
(append
magit-git-global-arguments
(list "diff" "--cached")))
(goto-char (point-min))
(while (re-search-forward "^@@\\|^\\+\\+\\+ b/" nil t)
(if (looking-back "^\\+\\+\\+ b/" (line-beginning-position))
(progn
(push (list last-file file-changes) change-data)
(setq last-file (buffer-substring-no-properties (point) (line-end-position))
file-changes nil))
(setq temp-point (line-beginning-position))
(re-search-forward "^\\+\\|^-" nil t)
(end-of-line)
(cond
((string-match-p "\\.el$" last-file)
(when (re-search-backward "^\\(?:[+-]? *\\|@@[ +-\\d,]+@@ \\)(\\(?:cl-\\)?\\(?:defun\\|defvar\\|defmacro\\|defcustom\\)" temp-point t)
(re-search-forward "\\(?:cl-\\)?\\(?:defun\\|defvar\\|defmacro\\|defcustom\\) " nil t)
(add-to-list 'file-changes (buffer-substring-no-properties (point) (forward-symbol 1)))))
((string-match-p "\\.org$" last-file)
(when (re-search-backward "^[+-]\\*+ \\|^@@[ +-\\d,]+@@ \\*+ " temp-point t)
(re-search-forward "@@ \\*+ " nil t)
(add-to-list 'file-changes (buffer-substring-no-properties (point) (line-end-position)))))))))
(push (list last-file file-changes) change-data)
(setq change-data (delete '(nil nil) change-data))
(concat
(if (= 1 (length change-data))
(replace-regexp-in-string "^.*/\\|.[a-z]+$" "" (caar change-data))
"?")
": \n\n"
(mapconcat
(lambda (file-changes)
(if (cadr file-changes)
(format "* %s (%s): "
(car file-changes)
(mapconcat #'identity (cadr file-changes) ", "))
(format "* %s: " (car file-changes))))
change-data
"\n\n"))))
(defun +org-commit-message-template ()
"Create a skeleton for an Org commit message based on the staged diff."
(let (change-data last-file file-changes temp-point)
(with-temp-buffer
(apply #'call-process magit-git-executable
nil t nil
(append
magit-git-global-arguments
(list "diff" "--cached")))
(goto-char (point-min))
(while (re-search-forward "^@@\\|^\\+\\+\\+ b/" nil t)
(if (looking-back "^\\+\\+\\+ b/" (line-beginning-position))
(progn
(push (list last-file file-changes) change-data)
(setq last-file (buffer-substring-no-properties (point) (line-end-position))
file-changes nil))
(setq temp-point (line-beginning-position))
(re-search-forward "^\\+\\|^-" nil t)
(end-of-line)
(cond
((string-match-p "\\.el$" last-file)
(when (re-search-backward "^\\(?:[+-]? *\\|@@[ +-\\d,]+@@ \\)(\\(?:cl-\\)?\\(?:defun\\|defvar\\|defmacro\\|defcustom\\)" temp-point t)
(re-search-forward "\\(?:cl-\\)?\\(?:defun\\|defvar\\|defmacro\\|defcustom\\) " nil t)
(add-to-list 'file-changes (buffer-substring-no-properties (point) (forward-symbol 1)))))
((string-match-p "\\.org$" last-file)
(when (re-search-backward "^[+-]\\*+ \\|^@@[ +-\\d,]+@@ \\*+ " temp-point t)
(re-search-forward "@@ \\*+ " nil t)
(add-to-list 'file-changes (buffer-substring-no-properties (point) (line-end-position)))))))))
(push (list last-file file-changes) change-data)
(setq change-data (delete '(nil nil) change-data))
(concat
(if (= 1 (length change-data))
(replace-regexp-in-string "^.*/\\|.[a-z]+$" "" (caar change-data))
"?")
": \n\n"
(mapconcat
(lambda (file-changes)
(if (cadr file-changes)
(format "* %s (%s): "
(car file-changes)
(mapconcat #'identity (cadr file-changes) ", "))
(format "* %s: " (car file-changes))))
change-data
"\n\n"))))
(add-to-list '+magit-project-commit-templates-alist (cons "org-mode" #'+org-commit-message-template)))
(add-to-list '+magit-project-commit-templates-alist (cons "org-mode" #'+org-commit-message-template))
#+end_src
This relies on two small entries in the git config files which improves the hunk
heading line selection for elisp and Org files.
#+begin_src gitconfig
[diff "lisp"]
xfuncname = "^(((;;;+ )|\\(|([ \t]+\\(((cl-|el-patch-)?def(un|var|macro|method|custom)|gb/))).*)$"