~ruther/emacs.d

c611c344c59e5a55d6911c5d00b0159969fc5d53 — Rutherther 6 days ago 0e8abf8 + 6f9d525
Merge branch 'lsp-mode'
M early-init.el => early-init.el +3 -2
@@ 69,8 69,9 @@
    (horizontal-scroll-bars . nil)
    ; Style
    (font . "Hack")
    (background-color . "#282828")
    (foreground-color . "#ebdbb2"))))
    ;; (background-color . "#fbf7f0")
    ;; (foreground-color . "#000000")
    )))

(when (fboundp 'startup-redirect-eln-cache)
  (startup-redirect-eln-cache

M init.el => init.el +93 -136
@@ 88,14 88,16 @@

;; NOTE: this is loaded so early as to prevent this issue
;; Fix eldoc loading before Elpaca activation (from issue #398)
(unload-feature 'eldoc t)
(setq custom-delayed-init-variables '())
(defvar global-eldoc-mode nil)
;; (unload-feature 'eldoc t)
;; (setq custom-delayed-init-variables '())
;; (defvar global-eldoc-mode nil)

(my-use-package eldoc
  :ensure t
  ;; :ensure t
  :custom
  (eldoc-documentation-strategy 'eldoc-documentation-compose-eagerly)
  (eldoc-echo-area-use-multiline-p nil)
  (eldoc-idle-delay 0.25)
  :config
  (require 'eldoc)
  (global-eldoc-mode)


@@ 411,8 413,6 @@
    "d m" '(consult-man :wk "Consult uan")
    "d i" '(consult-info :wk "Consult info")

    "e c" '(consult-flymake :wk "Consult flymake")

    "y" '(consult-yank-pop :wk "Yank pop")

    "s" '(:keymap search-map :wk "Search")


@@ 441,7 441,6 @@
         ("M-y" . consult-yank-pop)                ;; orig. yank-pop
         ;; M-g bindings in `goto-map'
         ("M-g e" . consult-compile-error)
         ("M-g f" . consult-flymake)               ;; Alternative: consult-flycheck
         ("M-g g" . consult-goto-line)             ;; orig. goto-line
         ("M-g M-g" . consult-goto-line)           ;; orig. goto-line
         ("M-g o" . consult-outline)               ;; Alternative: consult-org-heading


@@ 474,7 473,7 @@
              ("s" . consult-ripgrep-all)
              ("i" . consult-imenu)
              ("I" . consult-imenu-multi)
              ("f" . consult-flymake))
              ("f" . consult-flycheck))
  :custom
  (register-preview-delay 0.5)
  (register-preview-function #'consult-register-format)


@@ 487,6 486,12 @@
  (require 'consult-ripgrep-all)
  (recentf-mode 1))

(my-use-package consult-flycheck
  :ensure t
  :general
  (my-leader
    "e c" '(consult-flycheck :wk "Flycheck")))

(my-use-package orderless
  :ensure t
  :custom


@@ 566,6 571,7 @@
  (popper-reference-buffers
   '("\\*Messages\\*"
     "Output\\*$"
     "*lsp-help*"
     ;; "\\*Async Shell Command\\*"
     ;; "^\\*Embark Collect: "
     "^\\*eat\\*$"


@@ 806,13 812,12 @@
     (:eval (when buffer-read-only " RO"))))
    (vs-modeline-right
      '(
        (:eval (when which-func-mode which-func-format))
        (:eval (when which-function-mode " "))
        (:eval (when (and (boundp 'which-func-mode) which-func-mode) which-func-format))
        (:eval (when (and (boundp 'which-function-mode) which-function-mode) " "))
        (:eval (vs-modeline-input-method))
        (:eval (when flymake-mode " "))
        (:eval (when flymake-mode flymake-mode-line-exception))
        (:eval (when flymake-mode flymake-mode-line-counters))
        (:eval (when flymake-mode " "))
        (:eval (vs-modeline-flycheck))
        (:eval (vs-modeline-lsp-diagnostics))
        (:eval (vs-modeline-org-clock))
        mode-name
        " "
        (:eval (vs-modeline-position-rel))


@@ 909,6 914,9 @@
  :ensure t
  :custom
  (transient-levels-file (locate-user-emacs-file "transient-levels.el")))
(my-use-package cond-let
   :ensure (cond-let :type git :host github :repo "tarsius/cond-let"))

(my-use-package magit
  :ensure t
  :hook


@@ 949,6 957,15 @@
  (add-to-list 'git-link-web-host-alist
               '("ditigal\\.xyz" . "git.ditigal.xyz")))

(my-use-package agitjo
  :ensure (agitjo :type git :host codeberg :repo "halvin/agitjo"))

(my-use-package fj
  :custom
  (fj-host "https://codeberg.org")
  (fj-user "Rutherther")
  :ensure (fj :type git :host codeberg :repo "martianh/fj.el"))

(my-use-package hl-todo
  :ensure (:pin t :tag "v3.6.0")
  :after evil


@@ 1017,23 1034,21 @@
  )

;; Editing
(my-use-package flymake
(my-use-package flycheck
  :ensure t
  :demand t
  :config
  (global-flycheck-mode 1)
  :general
  (my-leader
    "e n" '(flymake-goto-next-error :wk "Next error")
    "e p" '(flymake-goto-prev-error :wk "Prev error")
    "e j" '(flymake-goto-next-error :wk "Next error")
    "e k" '(flymake-goto-prev-error :wk "Prev error")

    "e R" '(flymake-running-backends :wk "Running backends")
    "e d" '(flymake-disabled-backends :wk "Disabled backends")
    "e r" '(flymake-reporting-backends :wk "Reported backends")

    "e l" '(flymake-show-buffer-diagnostics :wk "Show buffer diagnostics")
    "e L" '(flymake-show-project-diagnostics :wk "Show project diagnostics")
    ))
    "e s" '(flycheck-buffer :wk "Start flycheck")

    "e n" '(flycheck-next-error :wk "Next error")
    "e p" '(flycheck-prev-error :wk "Prev error")
    "e j" '(flycheck-next-error :wk "Next error")
    "e k" '(flycheck-prev-error :wk "Prev error")

    "e l" '(flycheck-list-errors :wk "Show buffer diagnostics")))
;; TODO: what about isearch-lazy-count variable?
;; Added in emacs 27, could be an alternative.
(my-use-package evil-anzu


@@ 1205,6 1220,13 @@
            "r" 'cape-rfc1345))

;; Programming
(my-use-package yasnippet
  :ensure t
  :custom
  (yas-snippet-dirs `(,(locate-user-emacs-file "snippets")))
  :config
  (yas-global-mode))

(my-use-package gendoxy
  :ensure (gendoxy :type git :host gitlab :repo "mp81ss_repo/gendoxy")
  :custom


@@ 1261,6 1283,32 @@
    (setq eldoc-documentation-strategy
            'eldoc-documentation-compose-eagerly)))

(my-use-package lsp-mode
  :ensure t
  :commands (lsp lsp-mode)
  :hook
  (csharp-mode . lsp-conditional)
  (csharp-ts-mode . lsp-conditional)
  :general
  (my-leader
    "D" '(lsp-describe-thing-at-point :wk "LSP Documentation"))
  (normal lsp-managed-mode
   :definer 'minor-mode
   "gr" '(lsp-find-references :wk "Find references")
   "gR" '(lsp-rename :wk "Rename identifier")
   "g." '(lsp-execute-code-action :wk "Code actions"))
  :custom
  (lsp-enable-suggest-server-download nil)
  :config
  (defun lsp-conditional ()
    "Enable LSP only if already running in project."
    (lsp-deferred)))

(my-use-package lsp-ui
  :ensure t
  :hook
  (lsp-mode . lsp-ui-mode))

(my-use-package envrc
  :ensure t
  :demand t


@@ 1312,6 1360,9 @@
  :commands pdf-view-mode)

;; Treesit langs
(use-package ts-fold
  :ensure (ts-fold :type git :host github :repo "emacs-tree-sitter/ts-fold"))

(my-use-package emacs
  :ensure nil
  :custom


@@ 1393,39 1444,10 @@ minibuffer, even without explicitly focusing it."
  :mode (("\\.cs\\'" . csharp-mode))
  :config
  (my/indent-variable-mode-alist-add csharp-mode c-basic-offset)
  (my/indent-variable-mode-alist-add csharp-ts-mode csharp-ts-mode-indent-offset)

  (defun csharp--get-csproj-in-directory (dir)
    (car (directory-files dir
                          :mach-regexp ".*\\.csproj"
                          :count 1)))

  ;; Finds .csproj above current buffer directory, and returns path to the csproj
  (defun csharp--find-csproj (dir)
    (csharp--get-csproj-in-directory
     (locate-dominating-file
      dir #'get-csproj-in-directory)))
  (my/indent-variable-mode-alist-add csharp-ts-mode csharp-ts-mode-indent-offset))

  (defun csharp--find-current-csproj ()
    (csharp--find-csproj buffer-file-name))

  (defun csharp--extract-project-name ()
    (interactive)
    (let ((csproj (csharp--find-current-csproj)))
      (file-name-base csproj)))

  (defun csharp-file-path-to-namespace ()
    (interactive)
    (let* ((root (file-name-directory (csharp--find-current-csproj)))
           (base (file-name-nondirectory buffer-file-name))
           (project-name (csharp--extract-project-name))
           (subdirectory
            (replace-regexp-in-string "/" "\." (substring buffer-file-name (length root) (* -1 (length base))) t t)))
      (concat
       project-name
       (if (string= "" subdirectory)
           ""
         (concat "." (substring subdirectory 0 -1))))))
(my-use-package csharp-yasnippet
  :commands (csharp-file-path-to-namespace))

  ;; Build solution
  ;;  --debug / --release


@@ 1439,7 1461,6 @@ minibuffer, even without explicitly focusing it."
  ;; Run solution tests
  ;; Run csproj tests
  ;; Feeling lucky - run current file tests
  )

(my-use-package sharper
  :ensure t


@@ 1472,6 1493,17 @@ minibuffer, even without explicitly focusing it."
  (my/indent-variable-mode-alist-add python-mode python-indent-offset)
  (my/indent-variable-mode-alist-add python-ts-mode python-indent-offset))

;; Julia
(my-use-package julia-mode
  :ensure t)

(use-package julia-snail
  :ensure t
  :custom
  (julia-snail-terminal-type :eat)
  :hook
  (julia-mode . julia-snail-mode))

;; Matlab
(my-use-package matlab
  :ensure matlab-mode


@@ 1505,72 1537,6 @@ minibuffer, even without explicitly focusing it."
  (my/indent-variable-mode-alist-add matlab-mode matlab-indent-level)
  )

;; 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 '())
        (ignored-patterns '("cannot find resource library \".*\""
                           "entity \".*\" was not analysed")))
    (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))
               (should-ignore (cl-some (lambda (pattern)
                                        (string-match-p pattern msg))
                                      ignored-patterns)))
          (when (and pos (not should-ignore))
            (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


@@ 1586,11 1552,7 @@ 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 . (lambda ()
                   (add-hook 'flymake-diagnostic-functions
                             #'flymake-ghdl-backend nil t)
                   (flymake-mode 1))))
    (vhdl-mode . vhdl-stutter-mode))
  :custom
  (vhdl-clock-edge-condition 'function)
  (vhdl-clock-name "clk_i")


@@ 1624,11 1586,6 @@ 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)

A lisp/csharp-yasnippet.el => lisp/csharp-yasnippet.el +36 -0
@@ 0,0 1,36 @@
;;; csharp-yasnippet.el --- C# utility functions for yasnippet

(provide 'csharp-yasnippet)

(defun csharp--get-csproj-in-directory (dir)
  (car (directory-files dir
                        :mach-regexp ".*\\.csproj"
                        :count 1)))

(defun csharp--find-csproj (dir)
  (csharp--get-csproj-in-directory
   (locate-dominating-file
    dir #'csharp--get-csproj-in-directory)))

(defun csharp--find-current-csproj ()
  (csharp--find-csproj buffer-file-name))

(defun csharp--extract-project-name ()
  (interactive)
  (let ((csproj (csharp--find-current-csproj)))
    (file-name-base csproj)))

(defun csharp-file-path-to-namespace ()
  (interactive)
  (let* ((root (file-name-directory (csharp--find-current-csproj)))
         (base (file-name-nondirectory buffer-file-name))
         (project-name (csharp--extract-project-name))
         (subdirectory
          (replace-regexp-in-string "/" "\." (substring buffer-file-name (length root) (* -1 (length base))) t t)))
    (concat
     project-name
     (if (string= "" subdirectory)
         ""
       (concat "." (substring subdirectory 0 -1))))))

;;; csharp-yasnippet.el ends here
\ No newline at end of file

A snippets/csharp-mode/class.yasnippet => snippets/csharp-mode/class.yasnippet +8 -0
@@ 0,0 1,8 @@
# key: class
# contributor: Jason Imison <jasonimison@gmail.com>
# name: Class with name from file                             
# --
public class ${1:`(file-name-nondirectory (file-name-sans-extension (buffer-file-name)))`}
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/ctor.snippet => snippets/csharp-mode/ctor.snippet +11 -0
@@ 0,0 1,11 @@
# key: ctor
# contributor: Jason Imison <jasonimison@gmail.com>
# name: Constructor with name generated from filename
# --
/// <summary>
/// Initializes a new instance of the <see cref="`(file-name-nondirectory (file-name-sans-extension (buffer-file-name)))`"/> class.
/// </summary>
public `(file-name-nondirectory (file-name-sans-extension (buffer-file-name)))`($1)
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/cw.yasnippet => snippets/csharp-mode/cw.yasnippet +5 -0
@@ 0,0 1,5 @@
# key: cw
# contributor: Jason Imison <jasonimison@gmail.com>
# name: Console.WriteLine                             
# --
Console.WriteLine($1);$0
\ No newline at end of file

A snippets/csharp-mode/else.yasnippet => snippets/csharp-mode/else.yasnippet +8 -0
@@ 0,0 1,8 @@
# key: else
# contributor: Jason Imison <jasonimison@gmail.com>
# name: else
# --
else
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/else_if.yasnippet => snippets/csharp-mode/else_if.yasnippet +8 -0
@@ 0,0 1,8 @@
# key: elif
# contributor: Jason Imison <jasonimison@gmail.com>
# name: else if { .. Condition .. }                             
# --
else if (${1:Condition})
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/for.yasnippet => snippets/csharp-mode/for.yasnippet +8 -0
@@ 0,0 1,8 @@
# key: for
# contributor: Jason Imison <jasonimison@gmail.com>
# name: for                             
# --
for (${1:Initializer}; ${2:Condition}; ${3:Update})
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/foreach.yasnippet => snippets/csharp-mode/foreach.yasnippet +8 -0
@@ 0,0 1,8 @@
# key: foreach
# contributor: Jason Imison <jasonimison@gmail.com>
# name: foreach                             
# --
foreach (var ${1:Type} in ${2:Collection})
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/if.yasnippet => snippets/csharp-mode/if.yasnippet +8 -0
@@ 0,0 1,8 @@
# key: if
# contributor: Jason Imison <jasonimison@gmail.com>
# name: If                             
# --
if (${1:Condition})
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/namespace.yasnippet => snippets/csharp-mode/namespace.yasnippet +5 -0
@@ 0,0 1,5 @@
# key: namespace
# contributor: Jason Imison <jasonimison@gmail.com>
# name: Namespace from folder name
# --
namespace `(csharp-file-path-to-namespace)`;

A snippets/csharp-mode/private.yasnippet => snippets/csharp-mode/private.yasnippet +8 -0
@@ 0,0 1,8 @@
# key: private
# contributor: Jason Imison <jasonimison@gmail.com>
# name: private method                             
# --
private ${1:void} ${2:Method}($3)
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/property.yasnippet => snippets/csharp-mode/property.yasnippet +5 -0
@@ 0,0 1,5 @@
# key: prop
# contributor: Jason Imison <jasonimison@gmail.com>
# name: Public property                             
# --
public ${1:string} ${2:PropertyName} { get; set; }
\ No newline at end of file

A snippets/csharp-mode/public.yasnippet => snippets/csharp-mode/public.yasnippet +8 -0
@@ 0,0 1,8 @@
# key: public
# contributor: Jason Imison <jasonimison@gmail.com>
# name: public method                             
# --
public ${1:void} ${2:Method}($3)
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/tcf.yasnippet => snippets/csharp-mode/tcf.yasnippet +16 -0
@@ 0,0 1,16 @@
# key: tcf
# contributor: Jason Imison <jasonimison@gmail.com>
# name: Try Catch Finally                             
# --
try
{
    $1
}
catch (${2:Exception} ${3:e})
{
    $4
}
finally
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/test.yasnippet => snippets/csharp-mode/test.yasnippet +9 -0
@@ 0,0 1,9 @@
# key: test
# contributor: Jason Imison <jasonimison@gmail.com>
# name: NUnit test method
# --
[Test]
public void ${1:Should_$2}()
{
    $0
}
\ No newline at end of file

A snippets/csharp-mode/testfixture.yasnippet => snippets/csharp-mode/testfixture.yasnippet +19 -0
@@ 0,0 1,19 @@
# key: tf
# contributor: Jason Imison <jasonimison@gmail.com>
# name: testfixture
# --
using NUnit.Framework;
using Should;

namespace `(file-path-to-namespace)`
{
    [TestFixture]
    public class ${1:`(file-name-nondirectory (file-name-sans-extension (buffer-file-name)))`}
    {
        [Test]
        public void Should_$2()
        {
            $0
        }
    }
}
\ No newline at end of file

A snippets/csharp-mode/while.yasnippet => snippets/csharp-mode/while.yasnippet +8 -0
@@ 0,0 1,8 @@
# key: while
# contributor: Jason Imison <jasonimison@gmail.com>
# name: while                             
# --
while (${1:Condition})
{
    $0
}
\ No newline at end of file