diff --git a/.config/emacs/init.org b/.config/emacs/init.org index 4386d76..68586ed 100644 --- a/.config/emacs/init.org +++ b/.config/emacs/init.org @@ -247,8 +247,9 @@ Finish up ob-rust haskell-mode clojure-mode - sly cider + flycheck-clj-kondo + sly fsharp-mode go-mode json-mode @@ -268,7 +269,7 @@ Finish up (gptel :url "https://github.com/karthink/gptel") (indent-bars :url "https://github.com/jdtsmith/indent-bars") (pyenv :url "https://github.com/jorgenschaefer/pyvenv") - (doom-themes :url "https://github.com/JosephFerano/doom-themes") + (time-zones :url "https://github.com/xenodium/time-zones") (org-timeblock :url "https://github.com/ichernyshovvv/org-timeblock") (dape :url "https://github.com/svaante/dape") (odin-mode :url "https://github.com/mattt-b/odin-mode") @@ -516,7 +517,9 @@ Setup other stuff (doom-modeline-mode) (doom-modeline-def-modeline 'main '(bar modals bar window-number matches buffer-info remote-host buffer-position word-count selection-info) - '(parrot objed-state misc-info battery grip irc mu4e gnus github debug repl lsp bar input-method indent-info buffer-encoding bar major-mode process)) + '(parrot objed-state misc-info battery grip irc mu4e gnus github debug repl lsp vcs bar input-method indent-info buffer-encoding bar major-mode process)) +(setq doom-modeline-vcs-max-length 20) + ;; Show the tab names, just put this at the car of the previous list ;; workspace-name ;; Set default mode-line @@ -933,7 +936,7 @@ Fill region is great, except when you don't need it... (kbd "SPC p") project-prefix-map (kbd "SPC q") 'kill-buffer-and-window (kbd "SPC h") 'help-command - (kbd "SPC k") 'kill-this-buffer + (kbd "SPC k") 'kill-current-buffer (kbd "SPC hf") 'helpful-callable (kbd "SPC hv") 'helpful-variable (kbd "SPC hk") 'helpful-key @@ -1012,7 +1015,7 @@ Fill region is great, except when you don't need it... ** Buffers #+begin_src emacs-lisp -(global-set-key (kbd "C-x k") #'kill-this-buffer) +(global-set-key (kbd "C-x k") #'kill-current-buffer) (global-set-key (kbd "C-x M-k") #'kill-buffer) (require 'all-the-icons-ibuffer) @@ -1119,15 +1122,15 @@ Harpoon lets you quickly switch between bookmarked buffers (windmove-down) (joe/qtile-move-dir "down"))) -;; (global-set-key (kbd "s-h") #'joe/windmove-left) -;; (global-set-key (kbd "s-l") #'joe/windmove-right) -;; (global-set-key (kbd "s-k") #'joe/windmove-up) -;; (global-set-key (kbd "s-j") #'joe/windmove-down) +(global-set-key (kbd "s-h") #'joe/windmove-left) +(global-set-key (kbd "s-l") #'joe/windmove-right) +(global-set-key (kbd "s-k") #'joe/windmove-up) +(global-set-key (kbd "s-j") #'joe/windmove-down) -(global-set-key (kbd "s-h") #'windmove-left) -(global-set-key (kbd "s-l") #'windmove-right) -(global-set-key (kbd "s-k") #'windmove-up) -(global-set-key (kbd "s-j") #'windmove-down) +;; (global-set-key (kbd "s-h") #'windmove-left) +;; (global-set-key (kbd "s-l") #'windmove-right) +;; (global-set-key (kbd "s-k") #'windmove-up) +;; (global-set-key (kbd "s-j") #'windmove-down) ;; There's a bug in Gnome where frames are resized to the wrong dimensions (defun joe/resize-frames () @@ -2232,6 +2235,29 @@ These help speed eglot up apparently [[https://www.reddit.com/r/emacs/comments/1 (evil-global-set-key 'normal (kbd "SPC lD") #'consult-lsp-diagnostics) (evil-global-set-key 'normal (kbd "SPC lf") #'consult-lsp-file-symbols)) +#+end_src + +Omnisharp is very slow to start, so I want to start it manually, but not if the +buffer already belongs to the current lsp workspace. This function checks if a +newly opened buffer belongs to an LSP session and if it does, start lsp + +#+begin_src emacs-lisp +(defun lsp-mode-server-exists-p+ (mode &optional all-workspaces) + (when (buffer-file-name) ; Needed for lsp--matching-clients? + (let ((major-mode mode)) + (seq-intersection + (lsp--filter-clients (-andfn #'lsp--supports-buffer? + #'lsp--server-binary-present?)) + (when-let ((workspaces + (if all-workspaces + (-flatten (hash-table-values (lsp-session-folder->servers (lsp-session)))) + (gethash (lsp-workspace-root) (lsp-session-folder->servers (lsp-session)))))) + (mapcar #'lsp--workspace-client workspaces)) + #'equal)))) + +;; (setq treesit-load-name-override-list '((csharp "libtree-sitter-c-sharp.so"))) +#+end_src + #+end_src *** Flycheck @@ -2438,87 +2464,48 @@ This checks if it’s a ts mode then runs their counterparts. (add-hook 'prog-mode-hook 'run-non-ts-hooks) #+end_src -*** CSharp - -Omnisharp is very slow to start, so I want to start it manually, but not if the -buffer already belongs to the current lsp workspace. This function checks if a -newly opened buffer belongs to an LSP session and if it does, start lsp - +*** Clojure #+begin_src emacs-lisp -(defun lsp-mode-server-exists-p+ (mode &optional all-workspaces) - (when (buffer-file-name) ; Needed for lsp--matching-clients? - (let ((major-mode mode)) - (seq-intersection - (lsp--filter-clients (-andfn #'lsp--supports-buffer? - #'lsp--server-binary-present?)) - (when-let ((workspaces - (if all-workspaces - (-flatten (hash-table-values (lsp-session-folder->servers (lsp-session)))) - (gethash (lsp-workspace-root) (lsp-session-folder->servers (lsp-session)))))) - (mapcar #'lsp--workspace-client workspaces)) - #'equal)))) +(require 'clojure-mode) +(require 'cider) +(require 'flycheck-clj-kondo) +(setq cider-use-xref nil) -;; (setq treesit-load-name-override-list '((csharp "libtree-sitter-c-sharp.so"))) -#+end_src +(defvar joe/cider-last-reported-exception nil + "The last exception string reported by Cider.") -And we do the rest here, including a macro - -#+begin_src emacs-lisp -(defun joe/csharp-mode-hook () - (yas-minor-mode t) - (defalias 'joe/serialized-private-public-getter - (kmacro "^ W W Y o C-y ^ i p u b l i c SPC l W y i w P a SPC = > SPC B B ~")) - (evil-set-register ?g (lambda nil "Unity/C#" - (call-interactively 'joe/serialized-private-public-getter))) - ;; (schmo/reapply-csharp-ts-mode-font-lock-settings) - - (electric-pair-local-mode t) - (when (lsp-mode-server-exists-p+ 'csharp-mode) - (lsp))) -(add-hook 'csharp-mode-hook #'joe/csharp-mode-hook) -#+end_src -*** Common Lisp -#+begin_src emacs-lisp -(setq inferior-lisp-program "/usr/local/bin/sbcl") -(setq sly-lisp-implementations '((sbcl ("/usr/local/bin/sbcl" - "--dynamic-space-size" "4096" - "--core" "/home/joe/.config/emacs/sbcl.core-for-sly")) - (ecl ("/usr/bin/ecl")))) -(setq sly-symbol-completion-mode nil) - -(defun joe/sly-copy-call-to-repl () - "Copy name/symbol of toplevel sexp to sly-mREPL and select sly-mREPL." +(defun joe/clojure-cider-throw-last-error () (interactive) - (let (string - replwin) - (save-excursion - (beginning-of-defun) - (forward-thing 'symbol 2) - (setq string (format "(%s )" (thing-at-point 'symbol 'no-props)))) - (setq replwin (get-buffer-window (call-interactively #'sly-mrepl))) - (with-selected-window replwin - (insert string) - (forward-char -1)))) + (let* ((error-str (nrepl-dict-get + (cider-nrepl-sync-request:eval "@error-reporting/last-exception") + "value")) + (error-buffer (get-buffer "*cider-error*")) + (same-error-p (and error-buffer + (string= joe/cider-last-reported-exception error-str)))) + (unless same-error-p + (setq joe/cider-last-reported-exception error-str) + (cider-interactive-eval "(throw @error-reporting/last-exception)"))) + (defun joe/cider-repl-preoutput-hook (output) + (if (string-match "EMACS-CIDER-REPORT-EXCEPTION" output) + (progn + (joe/clojure-cider-throw-last-error) + "") + output))) + +(add-hook 'cider-repl-preoutput-hook #'joe/cider-repl-preoutput-hook) + +(defun joe/clojure-mode-hook () + (hs-minor-mode +1) + (when (lsp-mode-server-exists-p+ 'clojure-mode) + (lsp))) + +(add-hook 'clojure-mode-hook #'joe/clojure-mode-hook) #+end_src -*** Odin +*** Elisp #+begin_src emacs-lisp -(with-eval-after-load 'lsp-mode - (setq-default lsp-auto-guess-root t) ;; Helps find the ols.json file with Projectile or project.el - (setq lsp-language-id-configuration (cons '(odin-mode . "odin") lsp-language-id-configuration)) - - (lsp-register-client - (make-lsp-client :new-connection (lsp-stdio-connection "~/.local/bin/ols") ;; Adjust the path here - :major-modes '(odin-mode) - :server-id 'ols - :multi-root t))) ;; Ensures lsp-mode sends "workspaceFolders" to the server - -;; (add-hook 'odin-mode-hook #'lsp) - -(defun joe/odin-mode-hook () - (electric-pair-local-mode)) -(add-hook 'odin-mode-hook #'joe/odin-mode-hook) - +(global-set-key (kbd "C-x C-r") 'eval-region) +(evil-define-key 'insert emacs-lisp-mode-map (kbd "C-j") 'eval-print-last-sexp) #+end_src *** C @@ -2603,56 +2590,29 @@ it doesn't close it. ;; (setq lsp-rust-analyzer-display-reborrow-hints t) ;; (setq lsp-rust-analyzer-cargo-watch-command "clippy")) #+end_src -*** OCaml +*** Common Lisp #+begin_src emacs-lisp -(require 'tuareg) -(require 'dune) -(require 'utop) -;; (require 'merlin) -;; (require 'merlin-eldoc) -;; Might be worth checking out, depeding on whether we stick with flycheck or not -;; (elpaca 'flycheck-ocaml) -;; Also check this out, see if it adds anything -;; (require 'ocp-indent) +(setq inferior-lisp-program "/usr/local/bin/sbcl") +(setq sly-lisp-implementations '((sbcl ("/usr/local/bin/sbcl" + "--dynamic-space-size" "4096" + "--core" "/home/joe/.config/emacs/sbcl.core-for-sly")) + (ecl ("/usr/bin/ecl")))) +(setq sly-symbol-completion-mode nil) -(defun opam-env () - "Load the opam env to get the PATH variables so everything works" - (interactive nil) - (dolist (var - (car (read-from-string - (shell-command-to-string "opam config env --sexp")))) - (setenv (car var) (cadr var)))) -(setq opam-share - (substring (shell-command-to-string - "opam config var share 2> /dev/null") 0 -1)) -(add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share)) -(add-to-list 'exec-path "/home/joe/.opam/default/bin/") -#+end_src +(defun joe/sly-copy-call-to-repl () + "Copy name/symbol of toplevel sexp to sly-mREPL and select sly-mREPL." + (interactive) + (let (string + replwin) + (save-excursion + (beginning-of-defun) + (forward-thing 'symbol 2) + (setq string (format "(%s )" (thing-at-point 'symbol 'no-props)))) + (setq replwin (get-buffer-window (call-interactively #'sly-mrepl))) + (with-selected-window replwin + (insert string) + (forward-char -1)))) -We won't use the LSP server but rather directly talk to Merlin, since I guess LSP just wraps Merlin -and there's no need for a middle-man when it's already been implemented. - -#+begin_src emacs-lisp - -;; (require 'utop) -;; Use the opam installed utop -(setq utop-command "opam exec -- utop -emacs") - -(let ((opam-share (ignore-errors (car (process-lines "opam" "var" "share"))))) - (when (and opam-share (file-directory-p opam-share)) - ;; Register Merlin - (add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share)) - (autoload 'merlin-mode "merlin" nil t nil) - ;; Automatically start it in OCaml buffers - (add-hook 'tuareg-mode-hook 'merlin-mode t) - (add-hook 'caml-mode-hook 'merlin-mode t) - ;; Use opam switch to lookup ocamlmerlin binary - (setq merlin-command 'opam))) -#+end_src -*** Elisp -#+begin_src emacs-lisp -(global-set-key (kbd "C-x C-r") 'eval-region) -(evil-define-key 'insert emacs-lisp-mode-map (kbd "C-j") 'eval-print-last-sexp) #+end_src *** Web #+begin_src emacs-lisp @@ -2728,6 +2688,89 @@ and there's no need for a middle-man when it's already been implemented. (add-hook 'sql-login-hook 'joe/sql-login-hook) #+end_src +*** Odin +#+begin_src emacs-lisp +(with-eval-after-load 'lsp-mode + (setq-default lsp-auto-guess-root t) ;; Helps find the ols.json file with Projectile or project.el + (setq lsp-language-id-configuration (cons '(odin-mode . "odin") lsp-language-id-configuration)) + + (lsp-register-client + (make-lsp-client :new-connection (lsp-stdio-connection "~/.local/bin/ols") ;; Adjust the path here + :major-modes '(odin-mode) + :server-id 'ols + :multi-root t))) ;; Ensures lsp-mode sends "workspaceFolders" to the server + +;; (add-hook 'odin-mode-hook #'lsp) + +(defun joe/odin-mode-hook () + (electric-pair-local-mode)) +(add-hook 'odin-mode-hook #'joe/odin-mode-hook) + +#+end_src +*** CSharp + +And we do the rest here, including a macro + +#+begin_src emacs-lisp +(defun joe/csharp-mode-hook () + (yas-minor-mode t) + (defalias 'joe/serialized-private-public-getter + (kmacro "^ W W Y o C-y ^ i p u b l i c SPC l W y i w P a SPC = > SPC B B ~")) + (evil-set-register ?g (lambda nil "Unity/C#" + (call-interactively 'joe/serialized-private-public-getter))) + ;; (schmo/reapply-csharp-ts-mode-font-lock-settings) + + (electric-pair-local-mode t) + (when (lsp-mode-server-exists-p+ 'csharp-mode) + (lsp))) +(add-hook 'csharp-mode-hook #'joe/csharp-mode-hook) +#+end_src +*** COMMENT OCaml +#+begin_src emacs-lisp +(require 'tuareg) +(require 'dune) +(require 'utop) +;; (require 'merlin) +;; (require 'merlin-eldoc) +;; Might be worth checking out, depeding on whether we stick with flycheck or not +;; (elpaca 'flycheck-ocaml) +;; Also check this out, see if it adds anything +;; (require 'ocp-indent) + +(defun opam-env () + "Load the opam env to get the PATH variables so everything works" + (interactive nil) + (dolist (var + (car (read-from-string + (shell-command-to-string "opam config env --sexp")))) + (setenv (car var) (cadr var)))) +(setq opam-share + (substring (shell-command-to-string + "opam config var share 2> /dev/null") 0 -1)) +(add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share)) +(add-to-list 'exec-path "/home/joe/.opam/default/bin/") +#+end_src + +We won't use the LSP server but rather directly talk to Merlin, since I guess LSP just wraps Merlin +and there's no need for a middle-man when it's already been implemented. + +#+begin_src emacs-lisp + +;; (require 'utop) +;; Use the opam installed utop +(setq utop-command "opam exec -- utop -emacs") + +(let ((opam-share (ignore-errors (car (process-lines "opam" "var" "share"))))) + (when (and opam-share (file-directory-p opam-share)) + ;; Register Merlin + (add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share)) + (autoload 'merlin-mode "merlin" nil t nil) + ;; Automatically start it in OCaml buffers + (add-hook 'tuareg-mode-hook 'merlin-mode t) + (add-hook 'caml-mode-hook 'merlin-mode t) + ;; Use opam switch to lookup ocamlmerlin binary + (setq merlin-command 'opam))) +#+end_src *** COMMENT Haskell #+begin_src emacs-lisp (require 'haskell-mode) @@ -2736,12 +2779,6 @@ and there's no need for a middle-man when it's already been implemented. (evil-define-key 'insert haskell-interactive-mode-map (kbd "C-n") #'haskell-interactive-mode-history-next) (evil-define-key 'insert haskell-interactive-mode-map (kbd "C-p") #'haskell-interactive-mode-history-previous) -#+end_src -*** Clojure -#+begin_src emacs-lisp -(require 'clojure-mode) -(require 'cider) -;; (setq cider-show-error-buffer 'only-in-repl) #+end_src *** COMMENT FSharp #+begin_src emacs-lisp @@ -2816,7 +2853,7 @@ and there's no need for a middle-man when it's already been implemented. (define-key global-map (kbd "") #'joe/dape-toggle-breakpoint-and-rerun) #+end_src -Apparently this helps with the performance of dape +Apparently this helps with the performance of dape, as well as LSP #+begin_src emacs-lisp (setq read-process-output-max (* 1024 1024)) ;; 1mb