Skip to content

Commit e12baf4

Browse files
authored
Add bake-format.el and flymake-bake.el for adding emacs support using reformatter and flymake(built into emacs) (#96)
1 parent 77c59b3 commit e12baf4

2 files changed

Lines changed: 180 additions & 0 deletions

File tree

bake-format.el

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
;;; bake-format.el --- Format Makefiles using mbake -*- lexical-binding: t; -*-
2+
3+
;; Version: 0.1.0
4+
;; Keywords: languages, tools
5+
;; URL: https://github.com/EbodShojaei/bake
6+
;; Package-Requires: ((emacs "26.1") (reformatter "0.3"))
7+
8+
;;; Commentary:
9+
10+
;; Provides `bake-format-buffer', `bake-format-region', and
11+
;; `bake-format-on-save-mode' for formatting Makefiles via mbake.
12+
;;
13+
;; Requires the mbake Python package to be installed:
14+
;; pip install mbake
15+
;;
16+
;; Basic setup in your Emacs config:
17+
;;
18+
;; (require 'bake-format)
19+
;; (bake-format-setup)
20+
;;
21+
;; This enables on-save formatting in all `makefile-mode' buffers.
22+
;; To enable it manually in a buffer: M-x bake-format-on-save-mode
23+
;; To format once without enabling the mode: M-x bake-format-buffer
24+
25+
;;; Code:
26+
27+
(require 'reformatter)
28+
29+
(defgroup bake-format nil
30+
"Format Makefiles using the mbake formatter."
31+
:group 'languages
32+
:link '(url-link "https://github.com/EbodShojaei/bake"))
33+
34+
(defcustom bake-format-command "mbake"
35+
"Name or full path of the mbake executable."
36+
:type 'string
37+
:group 'bake-format)
38+
39+
(reformatter-define bake-format
40+
:program bake-format-command
41+
:args '("format" "--stdin")
42+
:lighter " BakeFmt"
43+
:group 'bake-format)
44+
45+
;;;###autoload
46+
(defun bake-format-setup ()
47+
"Enable `bake-format-on-save-mode' in all `makefile-mode' buffers.
48+
Call this in your Emacs init file after loading bake-format."
49+
(add-hook 'makefile-mode-hook #'bake-format-on-save-mode))
50+
51+
(provide 'bake-format)
52+
;;; bake-format.el ends here

flymake-bake.el

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
;;; flymake-bake.el --- Flymake backend for Makefiles using mbake -*- lexical-binding: t; -*-
2+
3+
;; Version: 0.1.0
4+
;; Keywords: languages, tools
5+
;; URL: https://github.com/EbodShojaei/bake
6+
;; Package-Requires: ((emacs "26.1"))
7+
8+
;;; Commentary:
9+
10+
;; Provides a Flymake backend that runs `mbake validate' on the current
11+
;; Makefile buffer and reports diagnostics inline.
12+
;;
13+
;; Note: `mbake validate' does not support --stdin; it requires a real
14+
;; file on disk. This backend writes the buffer contents to a temporary
15+
;; file, runs validation against it, then cleans up.
16+
;;
17+
;; Requires the mbake Python package to be installed:
18+
;; pip install mbake
19+
;;
20+
;; Basic setup in your Emacs config:
21+
;;
22+
;; (require 'flymake-bake)
23+
;; (flymake-bake-setup)
24+
;;
25+
;; Or to enable it manually in a single buffer:
26+
;; M-x flymake-bake-load
27+
;; M-x flymake-mode
28+
29+
;;; Code:
30+
31+
(defgroup flymake-bake nil
32+
"Flymake backend for Makefiles using mbake."
33+
:group 'languages
34+
:link '(url-link "https://github.com/EbodShojaei/bake"))
35+
36+
(defcustom flymake-bake-program "mbake"
37+
"Name or full path of the mbake executable."
38+
:group 'flymake-bake
39+
:type 'string)
40+
41+
(defcustom flymake-bake-program-args '("validate")
42+
"Arguments passed to mbake before the filename.
43+
The temporary file path is always appended as the final argument."
44+
:group 'flymake-bake
45+
:type '(repeat string))
46+
47+
;; mbake validate output format: "<file>:<line>: <message>"
48+
;; The filename portion is the temp file path, so we match on anything
49+
;; up to the first colon to stay flexible.
50+
(defvar flymake-bake--output-regex
51+
"^[^:\n]+:\\([0-9]+\\): \\(.*\\)"
52+
"Regexp matching mbake validate diagnostic output.
53+
Group 1 is the line number, group 2 is the message.")
54+
55+
(defvar-local flymake-bake--process nil
56+
"Current flymake-bake checker process for this buffer.")
57+
58+
(defun flymake-bake--run-checker (report-fn &rest _args)
59+
"Run `mbake validate' on a temp file and report diagnostics to REPORT-FN."
60+
;; Cancel any existing process for this buffer.
61+
(when (and flymake-bake--process
62+
(process-live-p flymake-bake--process))
63+
(kill-process flymake-bake--process))
64+
65+
(let* ((source-buffer (current-buffer))
66+
;; Write buffer to a named temp file so mbake validate can read it.
67+
;; Use .mk extension so mbake recognises it as a Makefile.
68+
(tmp-file (make-temp-file "flymake-bake-" nil ".mk"))
69+
(command (append (list flymake-bake-program)
70+
flymake-bake-program-args
71+
(list tmp-file))))
72+
;; Populate the temp file with the current buffer contents.
73+
(write-region (point-min) (point-max) tmp-file nil 'silent)
74+
75+
(setq flymake-bake--process
76+
(make-process
77+
:name "flymake-bake"
78+
:buffer (generate-new-buffer " *flymake-bake*")
79+
:command command
80+
:noquery t
81+
:connection-type 'pipe
82+
:sentinel
83+
(lambda (process _event)
84+
(when (eq (process-status process) 'exit)
85+
(unwind-protect
86+
(if (buffer-live-p source-buffer)
87+
(with-current-buffer (process-buffer process)
88+
(goto-char (point-min))
89+
(let ((diagnostics nil))
90+
(while (re-search-forward
91+
flymake-bake--output-regex nil t)
92+
(let* ((line (string-to-number (match-string 1)))
93+
(msg (match-string 2))
94+
(region (flymake-diag-region
95+
source-buffer line))
96+
(diag (flymake-make-diagnostic
97+
source-buffer
98+
(car region)
99+
(cdr region)
100+
:error
101+
msg)))
102+
(push diag diagnostics)))
103+
(funcall report-fn diagnostics)))
104+
;; Source buffer was killed before we finished; nothing to do.
105+
(funcall report-fn nil))
106+
;; Always clean up, regardless of errors.
107+
(ignore-errors (delete-file tmp-file))
108+
(kill-buffer (process-buffer process)))))))))
109+
110+
;;;###autoload
111+
(defun flymake-bake-load ()
112+
"Register the mbake Flymake backend in the current buffer.
113+
Enable `flymake-mode' separately, or use `flymake-bake-setup' to
114+
do both automatically via a hook."
115+
(interactive)
116+
(add-hook 'flymake-diagnostic-functions #'flymake-bake--run-checker nil t))
117+
118+
;;;###autoload
119+
(defun flymake-bake-setup ()
120+
"Enable the mbake Flymake backend in all `makefile-mode' buffers.
121+
Call this in your Emacs init file after loading flymake-bake."
122+
(add-hook 'makefile-mode-hook
123+
(lambda ()
124+
(flymake-bake-load)
125+
(flymake-mode 1))))
126+
127+
(provide 'flymake-bake)
128+
;;; flymake-bake.el ends here

0 commit comments

Comments
 (0)