~ruther/emacs.d

418e72e131489462874826117bf68cd36924508d — Rutherther a month ago dd541ed
feat: add flymake ghdl backend
1 files changed, 72 insertions(+), 1 deletions(-)

M init.el
M init.el => init.el +72 -1
@@ 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)