@@ 1472,6 1472,67 @@ minibuffer, even without explicitly focusing it."
)
;; Vhdl
+(defun flymake-ghdl-backend (report-fn &rest _args)
+ "GHDL syntax checking backend for Flymake."
+ (condition-case err
+ (progn
+ (unless (executable-find "ghdl")
+ (error "Cannot find ghdl executable"))
+ (when-let* ((source (buffer-file-name))
+ (source (file-truename source)))
+ (let* ((temp-file (make-temp-file "flymake-ghdl" nil ".vhdl"))
+ (command `("ghdl" "-s" "-Wall" "-fno-color-diagnostics" ,temp-file)))
+ (save-restriction
+ (widen)
+ (write-region (point-min) (point-max) temp-file nil 'silent))
+ (make-process
+ :name "flymake-ghdl"
+ :buffer (generate-new-buffer " *flymake-ghdl*")
+ :command command
+ :noquery t
+ :connection-type 'pipe
+ :sentinel
+ (lambda (proc _event)
+ (let ((proc-buffer (process-buffer proc)))
+ (when (memq (process-status proc) '(exit signal))
+ (unwind-protect
+ (if (with-current-buffer proc-buffer
+ (goto-char (point-min))
+ (zerop (buffer-size)))
+ (funcall report-fn nil)
+ (funcall report-fn
+ (with-current-buffer proc-buffer
+ (flymake-ghdl--parse-diagnostics source temp-file))))
+ (when (file-exists-p temp-file)
+ (delete-file temp-file))
+ (kill-buffer proc-buffer)))))))))))
+
+(defun flymake-ghdl--parse-diagnostics (source temp-file)
+ "Parse GHDL diagnostics from current buffer for SOURCE file."
+ (let (result)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward
+ (concat "\\(" (regexp-quote temp-file) "\\)"
+ ":\\([0-9]+\\):\\([0-9]+\\):\\s-*\\(.*?\\):\\s-*\\(.*\\)")
+ nil t)
+ (let* ((line-num (string-to-number (match-string 2)))
+ (col-num (string-to-number (match-string 3)))
+ (type-str (match-string 4))
+ (msg (match-string 5))
+ (type (cond ((string-match-p "error\\|Error" type-str) :error)
+ ((string-match-p "warning\\|Warning" type-str) :warning)
+ (t :note)))
+ (pos (flymake-diag-region (get-file-buffer source) line-num col-num)))
+ (when pos
+ (push (flymake-make-diagnostic
+ (get-file-buffer source)
+ (car pos) (cdr pos)
+ type
+ (format "%s: %s" type-str msg))
+ result)))))
+ result))
+
(my-use-package vhdl-mode
:ensure nil
:commands vhdl-mode
@@ 1486,7 1547,11 @@ minibuffer, even without explicitly focusing it."
"a c" '(vhdl-align-inline-comment-group :wk "Align comment group"))
:hook
((vhdl-mode . vhdl-electric-mode)
- (vhdl-mode . vhdl-stutter-mode))
+ (vhdl-mode . vhdl-stutter-mode)
+ (vhdl-mode . (lambda ()
+ (add-hook 'flymake-diagnostic-functions
+ #'flymake-ghdl-backend nil t)
+ (flymake-mode 1))))
:custom
(vhdl-clock-edge-condition 'function)
(vhdl-clock-name "clk_i")
@@ 1499,6 1564,7 @@ minibuffer, even without explicitly focusing it."
'(vhdl-mode . ("vhdl_ls")))
(my/indent-variable-mode-alist-add vhdl-mode vhdl-basic-offset)
+
(defun my/electric-space-not-in-strings (fun &rest args)
(if (vhdl-in-string-p)
(apply 'self-insert-command args)
@@ 1519,6 1585,11 @@ minibuffer, even without explicitly focusing it."
(vhdl-ts-indent-level tab-width)
:mode
("\\.vhdl?\\'" . vhdl-ts-mode)
+ :hook
+ (vhdl-ts-mode . (lambda ()
+ (add-hook 'flymake-diagnostic-functions
+ #'flymake-ghdl-backend nil t)
+ (flymake-mode 1)))
:init
(defun my/vhdl-ts/beautify-block-at-point ()
(interactive)