summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.org805
-rw-r--r--init.el2
2 files changed, 191 insertions, 616 deletions
diff --git a/config.org b/config.org
index 2ae460b..57600e8 100644
--- a/config.org
+++ b/config.org
@@ -146,6 +146,7 @@ use-package loads it from `load-path'; otherwise return REMOTE."
;; (add-to-list 'default-frame-alist '(alpha-background . 80))
(global-hl-line-mode 1) ;; Highlight the current line
(add-hook 'org-mode-hook (lambda () (setq-local global-hl-line-mode nil))) ;; hl-line repaints wipe kitty-graphics scaled headings
+ (add-hook 'markdown-mode-hook (lambda () (setq-local global-hl-line-mode nil))) ;; same conflict for kitty-graphics markdown headings
(global-auto-revert-mode 1) ;; Enable global auto-revert mode to keep buffers up to date with their corresponding files.
(setq-default indent-tabs-mode nil)
(when (daemonp)
@@ -192,11 +193,15 @@ use-package loads it from `load-path'; otherwise return REMOTE."
(derived-mode-p 'compilation-mode)))
(defun my/compile-or-recompile ()
- "Recompile with the last command if a compilation ran before, else prompt."
+ "Recompile with the last command if a ghostel compilation ran before, else prompt.
+Selects the compilation window so the cursor lands in it."
(interactive)
- (if (get-buffer "*compilation*")
- (recompile)
- (call-interactively #'compile)))
+ (if (get-buffer ghostel-compile-buffer-name)
+ (ghostel-recompile)
+ (call-interactively #'ghostel-compile))
+ (let ((buffer (get-buffer ghostel-compile-buffer-name)))
+ (when buffer
+ (pop-to-buffer buffer))))
(defun my/focus-async-shell-window (window)
"Focus the async-shell window and make q bury it without killing the process."
@@ -291,11 +296,9 @@ use-package loads it from `load-path'; otherwise return REMOTE."
(use-package async :ensure t)
#+end_src
-* erc
+* clatter
#+begin_src emacs-lisp
-;; Always-available IRC entry points so `M-x run-irc` works from any daemon
-;; (hub, work, standalone). Calling `erc-tls` autoloads ERC on demand.
(defun my/soju-password ()
"Read the Soju bouncer password from the sops-nix secret."
(string-trim
@@ -304,215 +307,83 @@ use-package loads it from `load-path'; otherwise return REMOTE."
"/home/cashmere/.config/sops-nix/secrets/senpai_password")
(buffer-string))))
-(defun run-irc ()
- "Connect to all IRC networks via Soju bouncer."
- (interactive)
- (let ((pw (my/soju-password)))
- (erc-tls :server "bouncer.cashmere.rs"
- :port 6699
- :nick "cashmere1337"
- :user "cashmere/irc.libera.chat@emacs"
- :password pw)
- (erc-tls :server "bouncer.cashmere.rs"
- :port 6699
- :nick "cashmere"
- :user "cashmere/ergo@emacs"
- :password pw)
- (erc-tls :server "bouncer.cashmere.rs"
- :port 6699
- :nick "cashmere"
- :user "cashmere/mansion@emacs"
- :password pw)))
-
-(use-package erc
- :ensure nil
- :defer t
+(use-package clatter
+ :ensure (:host github :repo "parenworks/clatter.el" :files ("*.el"))
+ :commands (clatter clatter-connect)
:custom
- ;; connection
- (erc-nick "cashmere1337")
- (erc-user-full-name "cashmere")
-
- ;; behaviour
- (erc-join-buffer 'buffer)
- (erc-kill-buffer-on-part nil)
- (erc-kill-queries-on-quit t)
- (erc-kill-server-buffer-on-quit t)
-
- ;; visuals
- (erc-fill-function 'erc-fill-wrap)
- (erc-timestamp-format "[%H:%M]")
- (erc-timestamp-format-left "[%H:%M]")
- (erc-timestamp-format-right "[%H:%M]")
- (erc-hide-list '("JOIN" "PART" "QUIT" "NICK" "MODE"))
- (erc-track-exclude-types '("JOIN" "PART" "QUIT" "NICK" "MODE" "324" "329" "332" "333" "353" "477"))
- (erc-track-shorten-start 4)
- (erc-track-visibility 'visible)
-
- ;; prompt
- (erc-prompt (lambda () (concat (buffer-name) ">")))
-
- ;; modules
- (erc-modules '(autojoin
- button
- completion
- fill
- irccontrols
- list
- match
- move-to-prompt
- netsplit
- networks
- nicks
- noncommands
- notifications
- readonly
- ring
- scrolltobottom
- stamp
- track))
+ (clatter-networks
+ '(("libera"
+ :server "bouncer.cashmere.rs" :port 6699 :tls t
+ :nick "cashmere1337"
+ :username "cashmere/irc.libera.chat@emacs")
+ ("ergo"
+ :server "bouncer.cashmere.rs" :port 6699 :tls t
+ :nick "cashmere"
+ :username "cashmere/ergo@emacs")
+ ("mansion"
+ :server "bouncer.cashmere.rs" :port 6699 :tls t
+ :nick "cashmere"
+ :username "cashmere/mansion@emacs")))
+ (clatter-flyspell-enable nil)
+ (clatter-format-strip-only t)
+ (clatter-message-order 'oldest-first)
+ (clatter-read-marker-enabled nil)
+ (clatter-chathistory-limit 1000)
:config
- ;; highlight own nick
- (setq erc-current-nick-highlight-type 'all)
- (setq erc-keywords '("cashmere"))
- (setq erc-pals '("cashmere"))
-
- ;; nicks module (built-in nick coloring in Emacs 30)
- (setq erc-nicks-contrast-range '(40 . 90))
+ (require 'gnutls)
+ (clatter-setup)
+ (setq clatter-hl-keywords '("cashmere"))
+ (advice-add 'clatter-buffer-name :override #'my/clatter-buffer-name)
+ (add-hook 'clatter-mode-hook (lambda () (setq-local corfu-auto nil)))
+ (general-def 'normal clatter-mode-map
+ "gb" #'my/clatter-switch-buffer
+ "gH" #'clatter-chathistory-request
+ "gh" #'clatter-chathistory-more))
- ;; scrolltobottom -- keep input always at bottom
- (setq erc-scrolltobottom-all t)
- (erc-scrolltobottom-mode 1)
+(defun my/clatter-buffer-name (network target)
+ "Name clatter buffers by bare channel/query TARGET, server by NETWORK."
+ (if (string= target "*server*")
+ (format "*%s*" network)
+ target))
- ;; fill-wrap -- modern chat-like wrapping
- (setq erc-fill-wrap-align-prompt nil)
- (setq erc-fill-static-center 14)
-
- ;; track -- activity in modeline
- (setq erc-track-position-in-mode-line t)
-
- ;; keep large buffer for soju history replay
- (setq erc-max-buffer-size 100000)
-
- (erc-update-modules))
-
-(defvar my/consult-source-erc
- (list :name "IRC"
- :narrow ?i
- :category 'buffer
- :face 'erc-default-face
- :state #'consult--buffer-state
- :items (lambda ()
- (mapcar #'buffer-name
- (cl-remove-if-not
- (lambda (buf)
- (with-current-buffer buf
- (derived-mode-p 'erc-mode)))
- (buffer-list))))))
-
-(defun my/erc-switch-channel ()
- "Switch to an ERC channel buffer via consult."
+(defun my/clatter-switch-buffer ()
+ "Switch to a clatter IRC buffer."
(interactive)
- (consult-buffer (list my/consult-source-erc)))
+ (let ((bufs (cl-remove-if-not
+ (lambda (b)
+ (with-current-buffer b (derived-mode-p 'clatter-mode)))
+ (buffer-list))))
+ (if bufs
+ (switch-to-buffer
+ (completing-read "IRC buffer: " (mapcar #'buffer-name bufs) nil t))
+ (message "No clatter buffers."))))
-(defun my/erc-fetch-history (&optional count)
- "Fetch COUNT previous messages from Soju via CHATHISTORY.
-Defaults to 1000 (soju max). With prefix arg, prompts for count.
-Temporarily disables notifications during the fetch."
- (interactive "P")
- (let ((target (erc-default-target)))
- (if (not target)
- (message "Not in a channel buffer.")
- (let ((n (min (if count
- (read-number "Messages to fetch: " 1000)
- 1000)
- 1000)))
- (erc-notifications-disable)
- (erc-server-send (format "CHATHISTORY LATEST %s * %d" target n))
- (run-at-time 5 nil #'erc-notifications-enable)))))
+(defvar my/clatter-inhibit-popup nil
+ "When non-nil, clatter buffers are not auto-displayed by `display-buffer'.")
-(defun my/erc-quit-all ()
- "Disconnect from IRC and kill all ERC buffers."
- (interactive)
- (erc-cmd-QUIT "bye")
- (run-at-time 1 nil
- (lambda ()
- (dolist (buf (buffer-list))
- (when (with-current-buffer buf (derived-mode-p 'erc-mode))
- (kill-buffer buf))))))
+(defun my/clatter-popup-suppressed-p (buf &rest _)
+ "Non-nil when BUF is a clatter buffer and popups are inhibited."
+ (and my/clatter-inhibit-popup
+ (get-buffer buf)
+ (with-current-buffer (get-buffer buf)
+ (derived-mode-p 'clatter-mode))))
-(defun my/erc-reconnect ()
- "Reconnect to the current ERC server."
- (interactive)
- (erc-cmd-RECONNECT))
+(add-to-list 'display-buffer-alist
+ '(my/clatter-popup-suppressed-p
+ display-buffer-no-window
+ (allow-no-window . t)))
-(defun my/erc-list-channels ()
- "Request channel list from the current ERC server."
- (interactive)
- (erc-cmd-LIST))
-
-(defun persp-irc ()
- "Switch to (or create) the IRC frame and show ERC buffers."
+(defun run-irc ()
+ "Connect to all IRC networks via the Soju bouncer, in the background."
(interactive)
- (let* ((erc-bufs (cl-remove-if-not
- (lambda (buf)
- (with-current-buffer buf
- (derived-mode-p 'erc-mode)))
- (buffer-list)))
- (irc-frame (cl-find-if
- (lambda (f)
- (string= (frame-parameter f 'name) "irc"))
- (frame-list))))
- (if irc-frame
- (select-frame-set-input-focus irc-frame)
- (select-frame-set-input-focus (make-frame '((name . "irc")))))
- (if erc-bufs
- (switch-to-buffer (car erc-bufs))
- (letrec ((hook-fn (lambda ()
- (switch-to-buffer (current-buffer))
- (remove-hook 'erc-join-hook hook-fn))))
- (add-hook 'erc-join-hook hook-fn))
- (run-irc))))
-
-;; ERC keybindings and hooks — register from any daemon, since `run-irc`
-;; autoloads ERC even outside the hub daemon.
-(with-eval-after-load 'erc
- (add-hook 'erc-mode-hook
- (lambda ()
- (setq-local scroll-margin 0)
- (setq-local maximum-scroll-margin 0.0)
- (setq-local corfu-auto nil)))
-
- ;; Prevent accidental ERC buffer kills from parting channels
- (add-hook 'kill-buffer-query-functions
- (lambda ()
- (if (and (derived-mode-p 'erc-mode)
- (erc-server-process-alive)
- (not (eq this-command 'my/erc-quit-all)))
- (yes-or-no-p
- (format "ERC buffer %s is connected. Really kill (will part channel)? "
- (buffer-name)))
- t)))
-
- (with-eval-after-load 'general
- (general-def 'normal erc-mode-map
- "q" 'quit-window
- "Q" 'my/erc-quit-all
- "gb" 'my/erc-switch-channel
- "gn" 'erc-track-switch-buffer
- "gH" 'my/erc-fetch-history
- "go" 'erc-channel-names
- "gj" 'erc-join-channel
- "gl" 'my/erc-list-channels
- "gr" 'my/erc-reconnect
- "RET" 'erc-send-current-line)
-
- (general-def '(normal insert) erc-mode-map
- "M-n" 'erc-track-switch-buffer
- "C-k" 'erc-previous-command
- "C-j" 'erc-next-command)))
+ (let ((pw (my/soju-password)))
+ (setq my/clatter-inhibit-popup t)
+ (dolist (net '("libera" "ergo" "mansion"))
+ (clatter-connect net :password pw))
+ (run-at-time 8 nil (lambda () (setq my/clatter-inhibit-popup nil)))))
#+end_src
-* TODO centered cursors
+* centered cursors
#+begin_src emacs-lisp
(defvar my/centered-cursor-enabled nil)
@@ -536,69 +407,6 @@ Temporarily disables notifications during the fetch."
(message "centered-cursor on"))))
#+end_src
-* cursory
-
-#+begin_src emacs-lisp
-(use-package cursory
- :ensure t
- :demand t
- :if (display-graphic-p)
- :config
- (setq cursory-presets
- '((box
- :cursor-color success ; will typically be green
- :blink-cursor-interval 1.2)
- (box-no-blink
- :inherit box
- :blink-cursor-mode -1)
- (bar
- :cursor-type (bar . 2)
- :cursor-color error ; will typically be red
- :blink-cursor-interval 0.8)
- (bar-no-other-window
- :inherit bar
- :cursor-in-non-selected-windows nil)
- (bar-no-blink
- :inherit bar
- :blink-cursor-mode -1)
- (underscore
- :cursor-color warning ; will typically be yellow
- :cursor-type (hbar . 3)
- :blink-cursor-interval 0.3
- :blink-cursor-blinks 50)
- (underscore-no-other-window
- :inherit underscore
- :cursor-in-non-selected-windows nil)
- (underscore-thick
- :inherit underscore
- :cursor-type (hbar . 8)
- :cursor-in-non-selected-windows (hbar . 3))
- (t ; the default values
- :cursor-color unspecified ; use the theme's original
- :cursor-type box
- :cursor-in-non-selected-windows hollow
- :blink-cursor-mode 1
- :blink-cursor-blinks 10
- :blink-cursor-interval 0.2
- :blink-cursor-delay 0.2)))
-
- ;; I am using the default value of `cursory-latest-state-file'.
-
- ;; Set last preset or fall back to desired style from
- ;; `cursory-presets'. Alternatively, use the function
- ;; `cursory-set-last-or-fallback' (can be added to the
- ;; `after-init-hook'.
- (cursory-set-preset (or (cursory-restore-latest-preset) 'box))
-
- ;; Persist configurations between Emacs sessions. Also apply the
- ;; :cursor-color again when swithcing to another theme.
- (cursory-mode 1)
- :bind
- ;; We have to use the "point" mnemonic, because C-c c is often the
- ;; suggested binding for `org-capture' and is the one I use as well.
- ("C-c p" . cursory-set-preset))
-#+end_src
-
* clipetty
Only =y= (evil-yank) reaches the system clipboard; deletes (=d=, =x=, =c=) and word kills (M-DEL, C-w in insert) stay in the kill-ring only. Clipetty's global mode would sync every kill via OSC 52, so instead the OSC 52 escape is emitted explicitly after each yank.
@@ -766,7 +574,7 @@ I adjusted the config accordingly to my modes which I use on a frequent.
(or
(mode . eca-chat-mode)))
- ("ERC" (or (mode . erc-mode)))
+ ("IRC" (or (mode . clatter-mode)))
("Emacs" (or
(mode . emacs-lisp-mode)
@@ -890,10 +698,6 @@ Defined early so later =with-eval-after-load 'general= callbacks find =my-leader
** claude-code-ide
-Native [[https://github.com/manzaltu/claude-code-ide.el][Claude Code IDE]] integration via MCP. Requires the =claude= CLI in
-PATH (already provided through the Nix profile) and uses =eat= as the
-terminal backend.
-
#+begin_src emacs-lisp
(use-package claude-code-ide
:ensure (:host github :repo "manzaltu/claude-code-ide.el"
@@ -918,7 +722,7 @@ terminal backend.
(claude-code-ide-cli-path "claude")
(claude-code-ide-cli-debug nil)
;; Terminal backend
- (claude-code-ide-terminal-backend 'eat)
+ (claude-code-ide-terminal-backend 'ghostel)
;; Window placement — mirror eca on the right side so the two AI assistants
;; don't fight over the same slot
@@ -971,27 +775,12 @@ terminal backend.
;; Leader-key bindings (SPC a …) — defined pre-load so :commands autoloads fire.
(with-eval-after-load 'general
+ ;; 2026-06-23: replaced claude-code-ide bindings with pi-coding-agent under `a'.
+ ;; pi-coding-agent only exposes 3 user-facing commands, so the prefix is intentionally sparse.
(my-leader
- "a" '(:ignore t :wk "claude-code")
- "aa" '(claude-code-ide :wk "start / toggle")
- "am" '(claude-code-ide-menu :wk "transient menu")
- "at" '(claude-code-ide-toggle :wk "toggle window")
- "aT" '(claude-code-ide-toggle-recent :wk "toggle recent")
- "ap" '(claude-code-ide-send-prompt :wk "send prompt")
- "a@" '(claude-code-ide-insert-at-mentioned :wk "@mention region")
- "ac" '(claude-code-ide-continue :wk "continue last")
- "ar" '(claude-code-ide-resume :wk "resume session")
- "as" '(claude-code-ide-switch-to-buffer :wk "switch buffer")
- "al" '(claude-code-ide-list-sessions :wk "list sessions")
- "aq" '(claude-code-ide-stop :wk "stop")
- "a?" '(claude-code-ide-check-status :wk "check status")
- "ad" '(claude-code-ide-show-debug :wk "show debug")
- "aD" '(claude-code-ide-clear-debug :wk "clear debug"))
-
- (my-leader 'visual
- "a@" '(claude-code-ide-insert-at-mentioned :wk "@mention region")))
-
- (global-set-key (kbd "C-c C-'") #'claude-code-ide-menu)
+ "aa" '(pi-coding-agent :wk "start")
+ "at" '(pi-coding-agent-toggle :wk "toggle")
+ "ao" '(pi-coding-agent-open-session-file :wk "open session")))
:config
;; Runs only on first invocation — not at Emacs startup.
@@ -1007,6 +796,16 @@ terminal backend.
(setopt evil-collection-eca-maps 't))
#+end_src
+** pi-coding-agent
+
+#+begin_src emacs-lisp
+(use-package pi-coding-agent
+ :ensure t
+ :commands (pi-coding-agent
+ pi-coding-agent-toggle
+ pi-coding-agent-open-session-file))
+#+end_src
+
* eldoc
#+begin_src emacs-lisp
@@ -1018,14 +817,6 @@ terminal backend.
(setq eldoc-echo-area-display-truncation-message nil)
:init
(global-eldoc-mode))
-
-(use-package eldoc-box
- :ensure t
- :defer t
- :config
- (setq eldoc-box-max-pixel-width 800)
- (setq eldoc-box-max-pixel-height 600))
-
#+end_src
* flymake
@@ -1150,6 +941,7 @@ terminal backend.
(setq org-src-fontify-natively t
org-src-tab-acts-natively t
org-edit-src-content-indentation 0)
+ (add-to-list 'org-src-lang-modes '("nix" . nix-ts))
(setq org-log-done t
org-auto-align-tags t
org-tags-column -80
@@ -1241,48 +1033,6 @@ Only activates when running in a Kitty terminal (not in GUI Emacs).
(kitty-graphics-setup))
#+end_src
-** org-fancy-properties
-
-#+begin_src emacs-lisp
-(use-package org-fancy-priorities
- :ensure t
- :hook
- (org-mode . org-fancy-priorities-mode)
- :config
- (setq org-fancy-priorities-list '("⚡" "⬆" "⬇" "☕")))
-
-(setq org-priority-faces
- '((?A . (:background "#e91e63" :foreground "#ffffff" :weight bold))
- (?B . (:background "#ff9800" :foreground "#1a1a1a" :weight bold))
- (?C . (:background "#2196f3" :foreground "#ffffff" :weight bold))
- (?D . (:background "#795548" :foreground "#ffffff" :weight bold))))
-#+end_src
-
-** TODO org-agenda settings :deprecated:
-
-Old config
-
-#+begin_src emacs-lisp
-;; (setq org-agenda-start-on-weekday nil
-;; org-agenda-block-separator nil
-;; org-agenda-remove-tags t)
-
-;; (setq org-agenda-skip-scheduled-if-done t
-;; org-agenda-skip-deadline-if-done t
-;; org-agenda-include-deadlines t
-;; org-agenda-block-separator nil
-;; org-agenda-compact-blocks t
-;; org-agenda-start-day nil
-;; org-agenda-span 1
-;; org-agenda-start-on-weekday nil
-;; org-agenda-hide-tags-regexp "task"
-;; org-agenda-prefix-format
-;; '((agenda . " %i %?-12t% s")
-;; (todo . " %i ")
-;; (tags . " %i ")
-;; (search . " %i ")))
-#+end_src
-
** org-babel
#+begin_src emacs-lisp
@@ -2087,35 +1837,6 @@ Skips capture tasks and projects."
#'my/org-agenda-fix-block-spacing)
#+end_src
-** agenda-app
-
-Standalone agenda kiosk. Launch with:
-
-=emacs --eval '(my/agenda-app)' --no-splash=
-
-#+begin_src emacs-lisp
-(defun my/agenda-app ()
- "Launch Emacs as a dedicated agenda kiosk.
-Opens the 'd' (Today) agenda view in a clean, distraction-free frame.
-Usage: emacs --eval '(my/agenda-app)' --no-splash"
- (interactive)
- (set-frame-name "Agenda")
- (delete-other-windows)
- (org-agenda nil "d")
- (delete-other-windows)
- (setq mode-line-format nil)
- (menu-bar-mode -1)
- (tool-bar-mode -1)
- (scroll-bar-mode -1)
- (when (bound-and-true-p tab-bar-mode)
- (tab-bar-mode -1))
- (when (find-font (font-spec :family "Lato"))
- (buffer-face-set '(:family "Lato")))
- (text-scale-increase 2)
- (hide-mode-line-mode 1)
- (winner-mode 1))
-#+end_src
-
** ox-contrib
#+begin_src emacs-lisp
@@ -2448,19 +2169,6 @@ Some goodies for better integration with org files.
)
#+end_src
-** denote-project-notes
-
-#+begin_src emacs-lisp
-
-#+end_src
-
-** denote-explore
-
-#+begin_src emacs-lisp
-(use-package denote-explore
- :ensure t)
-#+end_src
-
** denote-publish
#+begin_src emacs-lisp
@@ -2619,7 +2327,7 @@ Timers that expired while Emacs was closed fire immediately."
:custom
(corfu-cycle t)
(corfu-auto t)
- (corfu-auto-delay 0.001)
+ (corfu-auto-delay 0.2)
(corfu-auto-prefix 2)
:init
(global-corfu-mode)
@@ -2754,16 +2462,16 @@ completion-category-overrides '((file (styles partial-completion))))) ;; Customi
(setq eglot-connect-timeout 30)
(setq eglot-events-buffer-size 0)
(setq eglot-report-progress nil)
- (setq jsonrpc-default-request-timeout 10)
+ (setq jsonrpc-default-request-timeout 10))
- (add-hook 'eglot-managed-mode-hook
- (lambda ()
- (eglot-inlay-hints-mode -1)))
+ ;; (add-hook 'eglot-managed-mode-hook
+ ;; (lambda ()
+ ;; (eglot-inlay-hints-mode -1)))
- (setq eglot-code-action-indications '(eldoc-hint))
+ ;; (setq eglot-code-action-indications '(eldoc-hint))
- (setq eglot-ignored-server-capabilities
- '(:inlayHintProvider :documentHighlightProvider)))
+ ;; (setq eglot-ignored-server-capabilities
+ ;; '(:inlayHintProvider :documentHighlightProvider)))
#+end_src
** typst-mode
@@ -2811,6 +2519,29 @@ completion-category-overrides '((file (styles partial-completion))))) ;; Customi
(put 'eglot-workspace-configuration 'safe-local-variable #'listp)
#+end_src
+** c-ts-mode
+
+Built-in tree-sitter mode (Emacs 29+) driven by =clangd=. The =c= grammar ships via =treesit-grammars.with-all-grammars= in =emacs.nix=, so no on-the-fly compilation is needed. =clangd= picks up include paths and flags from a =compile_commands.json= in the project root (generate it with =bear -- make=, =cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON=, or =meson=); without one it falls back to sane defaults but cross-file navigation is limited.
+
+#+begin_src emacs-lisp
+(use-package c-ts-mode
+ :ensure nil
+ :mode (("\\.c\\'" . c-ts-mode)
+ ("\\.h\\'" . c-ts-mode))
+ :hook (c-ts-mode . eglot-ensure)
+ :custom
+ (c-ts-mode-indent-offset 2)
+ (c-ts-mode-indent-style 'k&r)
+ :config
+ (with-eval-after-load 'eglot
+ (add-to-list 'eglot-server-programs
+ '((c-ts-mode c-mode) .
+ ("clangd"
+ "--background-index"
+ "--clang-tidy"
+ "--header-insertion=never")))))
+#+end_src
+
** c3-ts-mode
Not on MELPA, so installed straight from GitHub. The tree-sitter grammar is built on first load via =treesit-install-language-grammar= (needs =cc= / =gcc= on PATH), and eglot drives the =c3-lsp= server. On NixOS install =c3c=, =c3-lsp= and =gcc=.
@@ -2822,6 +2553,8 @@ Not on MELPA, so installed straight from GitHub. The tree-sitter grammar is buil
("\\.c3i\\'" . c3-ts-mode)
("\\.c3t\\'" . c3-ts-mode))
:hook (c3-ts-mode . eglot-ensure)
+ :custom
+ (c3-ts-mode-indent-offset 2)
:init
(add-to-list 'treesit-language-source-alist
'(c3 "https://github.com/c3lang/tree-sitter-c3"))
@@ -3309,6 +3042,12 @@ so the working-tree diff stays visible until the user explicitly stages."
(message "auto-staged (intent-to-add): %s" (file-name-nondirectory file)))))))
(add-hook 'after-save-hook #'my/auto-git-add-new-file)
+
+(defun my/magit-uncommit ()
+ "Undo the last commit, leaving its changes in the working tree, unstaged."
+ (interactive)
+ (magit-reset-mixed "HEAD^")
+ (message "Uncommitted HEAD^ — changes preserved, unstaged"))
#+end_src
* indent-guide
@@ -3349,16 +3088,18 @@ so the working-tree diff stays visible until the user explicitly stages."
(evil-set-initial-state 'messages-buffer-mode 'normal)
(evil-set-initial-state 'dired-mode 'normal)
(evil-set-initial-state 'ibuffer-mode 'normal)
- (evil-set-initial-state 'erc-mode 'normal))
+ (evil-set-initial-state 'clatter-mode 'normal)
+ (define-key evil-insert-state-map (kbd "C-w") 'evil-window-map))
(modify-syntax-entry ?_ "w")
(defun my/eldoc-and-jump ()
"Show documentation at point. Works in both GUI and terminal."
(interactive)
- (if (display-graphic-p)
- (eldoc-box-help-at-point)
- (eldoc-doc-buffer t)))
+ ;; (if (display-graphic-p)
+ ;; (eldoc-box-help-at-point)
+ ;; (eldoc-doc-buffer t))
+ (eldoc-doc-buffer t))
(define-key evil-normal-state-map (kbd "K") #'my/eldoc-and-jump)
#+end_src
@@ -3640,67 +3381,22 @@ Native =undo-redo= (via =evil-undo-system='undo-redo=); just raise the undo limi
#+end_src
* modelines
-** hide modeline
-#+begin_src emacs-lisp
-(use-package hide-mode-line
- :ensure t)
-#+end_src
-
-** COMMENT punch-line
-
-#+begin_src emacs-lisp
-(use-package punch-line
- :ensure (:host github :repo "cashmeredev/punch-line")
- :config
- (setq punch-line-left-separator " "
- punch-line-right-separator " "
- punch-show-git-info nil
- punch-show-buffer-position t
- punch-show-column-info t
- punch-show-erc-info nil
- punch-line-music-max-length 80
- punch-line-modal-divider-style 'block
- punch-line-section-backgrounds 'auto
- punch-line-glyph-style 'nerd
- punch-show-weather-info t
- punch-weather-longitude "10.41"
- punch-weather-latitude "53.25"
- punch-cpu-usage nil
- punch-show-processes-info nil
- punch-line-music-info nil)
- (punch-line-mode 1))
-#+end_src
-
-** svg-line
+** doom-modeline
#+begin_src emacs-lisp
-(use-package svg-line
- :ensure (:host nil :repo "ssh://git.cashmere.rs/svg-line.git"
- :branch "feat/tty-kitty-modeline")
+(use-package doom-modeline
+ :ensure t
+ :init (doom-modeline-mode 1)
:config
- (require 'svg-line-segments)
- (setq svg-line-weather-latitude "53.25"
- svg-line-weather-longitude "10.41")
- (svg-line-weather-mode 1)
-
- (svg-line-define 'cashmere-mode-line
- :target 'mode-line
- :layout 'lines
- :active #'mode-line-window-selected-p
- :background (lambda () (face-background 'mode-line nil t))
- :foreground (lambda () (face-foreground 'mode-line nil t))
- :inactive-background (lambda () (face-background 'mode-line-inactive nil t))
- :inactive-foreground (lambda () (face-foreground 'mode-line-inactive nil t))
- :content
- (lambda ()
- (list (cons (list #'svg-line-segment-evil " "
- #'svg-line-segment-buffer #'svg-line-segment-vc)
- (list #'svg-line-segment-weather #'svg-line-segment-battery
- #'svg-line-segment-position " "
- #'svg-line-segment-major-mode)))))
-
- (svg-line-activate 'cashmere-mode-line))
+ (setq doom-modeline-hud t
+ doom-modeline-irc t
+ doom-modeline-irc-buffers nil
+ doom-modeline-mu4e t
+ doom-modeline-buffer-file-name-style 'relative-to-project
+ doom-modeline-buffer-encoding nil
+ doom-modeline-time t
+ doom-modeline-time-live-icon t))
#+end_src
* soph
@@ -3765,16 +3461,15 @@ created later still get them."
#+begin_src emacs-lisp
(use-package dirvish
- :ensure t
+ :ensure (:host github :repo "latiagertrutis/dirvish" :branch "main")
:init
(dirvish-override-dired-mode)
:custom
(dirvish-quick-access-entries
- '(("h" "~/" "Home")
- ("d" "~/Downloads/" "Downloads")
- ;; ("p" "~/projects/" "Projects")
- ))
+ '(("h" "~/" "home")
+ ("d" "~/Downloads/" "downloads")
+ ("c" "~/.config/" "config")))
(dirvish-reuse-session 'open)
(dirvish-attributes '(file-size))
@@ -3947,6 +3642,18 @@ activates automatically. Edit, then `C-c C-c' commits, `C-c C-k' aborts."
(advice-add 'embark-export :after #'my/embark-export-auto-wgrep))
#+end_src
+** search in arbitrary directories
+
+#+begin_src emacs-lisp
+(defun my/consult-fd-in (dir)
+ (interactive "DFind files in: ")
+ (consult-fd dir))
+
+(defun my/consult-ripgrep-in (dir)
+ (interactive "DGrep in: ")
+ (consult-ripgrep dir))
+#+end_src
+
* workspaces
#+begin_src emacs-lisp
@@ -3971,8 +3678,8 @@ activates automatically. Edit, then `C-c C-c' commits, `C-c C-k' aborts."
persp-add-buffer-on-after-change-major-mode t
persp-kill-foreign-buffer-behaviour 'kill
persp-remove-buffers-from-nil-persp-behaviour nil
- persp-auto-resume-time 1.0
- persp-auto-save-opt 1
+ persp-auto-resume-time -1
+ persp-auto-save-opt 0
uniquify-buffer-name-style nil)
(add-to-list 'persp-filter-save-buffers-functions
@@ -4146,7 +3853,6 @@ activates automatically. Edit, then `C-c C-c' commits, `C-c C-k' aborts."
(defun my/workspace-switch-to-project (&optional dir)
(let* ((dir (or dir default-directory))
- (default-directory dir)
(name (projectile-project-name dir)))
(when persp-mode
(if (or (eq my/workspaces-on-switch-project t)
@@ -4156,7 +3862,8 @@ activates automatically. Edit, then `C-c C-c' commits, `C-c C-k' aborts."
(my/workspace-switch name t)
(switch-to-buffer (my/workspace-fallback-buffer)))
(ignore-errors (persp-rename name (get-current-persp))))
- (funcall my/workspace-switch-project-function))))
+ (let ((default-directory dir))
+ (funcall my/workspace-switch-project-function)))))
(with-eval-after-load 'projectile
(setq projectile-switch-project-action #'my/workspace-switch-to-project))
@@ -4166,30 +3873,17 @@ activates automatically. Edit, then `C-c C-c' commits, `C-c C-k' aborts."
(define-key persp-mode-map [remap evil-window-delete]
#'my/workspace-close-window-or-workspace))
- (defun my/workspace-restore-services (&rest _)
- (run-with-idle-timer
- 1 nil
- (lambda ()
- (unless (and (fboundp 'mu4e-running-p) (mu4e-running-p))
- (mu4e t)))))
- (add-hook 'persp-after-load-state-functions #'my/workspace-restore-services)
-
(add-hook 'persp-filter-save-buffers-functions
(lambda (buf)
- (with-current-buffer buf (derived-mode-p 'erc-mode))))
-
- (run-with-timer (* 10 60) (* 10 60)
- (lambda () (when persp-mode (persp-save-state-to-file))))
+ (with-current-buffer buf (derived-mode-p 'clatter-mode))))
- (defun my/workspace--inhibit-erc-part (orig &rest args)
- (let ((erc-kill-channel-hook nil)
- (erc-kill-server-hook nil)
- (erc-kill-buffer-hook nil))
+ (defun my/workspace--inhibit-irc-part (orig &rest args)
+ (cl-letf (((symbol-function 'clatter--on-kill-buffer) #'ignore))
(apply orig args)))
- (advice-add 'my/workspace-kill :around #'my/workspace--inhibit-erc-part)
- (advice-add 'my/workspace-kill-session :around #'my/workspace--inhibit-erc-part)
+ (advice-add 'my/workspace-kill :around #'my/workspace--inhibit-irc-part)
+ (advice-add 'my/workspace-kill-session :around #'my/workspace--inhibit-irc-part)
- (when (daemonp) (persp-mode 1)))
+ (persp-mode 1))
#+end_src
#+begin_src emacs-lisp
@@ -4221,8 +3915,11 @@ activates automatically. Edit, then `C-c C-c' commits, `C-c C-k' aborts."
(defun my/ibuffer-workspace ()
(interactive)
- (ibuffer nil (format "*ibuffer: %s*" (my/workspace-current-name))
- (list (cons 'persp t))))
+ (let ((name (my/workspace-current-name)))
+ (if (equal name my/workspaces-master)
+ (ibuffer nil "*ibuffer: master*")
+ (ibuffer nil (format "*ibuffer: %s*" name)
+ (list (cons 'persp t))))))
#+end_src
#+begin_src emacs-lisp
@@ -4386,10 +4083,13 @@ activates automatically. Edit, then `C-c C-c' commits, `C-c C-k' aborts."
:wk "find file/switch project")
"sp" '(consult-projectile :wk "search project")
"ss" '(consult-line :wk "search project")
+ "sd" '(my/consult-ripgrep-in :wk "grep in dir")
+ "sf" '(my/consult-fd-in :wk "find file in dir")
"/" '(consult-ripgrep :wk "search project")
"." '(find-file :wk "find file")
"," '(consult-buffer :wk "switch buffer")
":" (lambda () (interactive) (execute-extended-command nil))
+ "u" '(universal-argument :wk "universal argument")
"d" '(:ignore t :wk "denote")
"dj" '(denote-journal-new-or-existing-entry :wk "journal")
@@ -4447,6 +4147,7 @@ activates automatically. Edit, then `C-c C-c' commits, `C-c C-k' aborts."
"gt" '(eglot-find-typeDefinition :wk "go to type definition")
"gr" '(xref-find-references :wk "find references")
"gs" '(magit-file-stage :wk "stage file")
+ "gu" '(my/magit-uncommit :wk "uncommit (keep & unstage)")
"gb" '(vc-annotate :wk "blame")
"gT" '(my/code-todos-harvest :wk "harvest code TODOs")
@@ -4479,8 +4180,8 @@ activates automatically. Edit, then `C-c C-c' commits, `C-c C-k' aborts."
"w L" '(buf-move-right :wk "Buffer move right")
"c" '(:ignore t :wk "code")
- "cc" '(my/compile-or-recompile :wk "compile / recompile")
- "cC" '(compile :wk "compile (new command)")
+ "cc" '(my/compile-or-recompile :wk "compile")
+ "cC" '(ghostel-compile :wk "recompile")
"ca" '(eglot-code-actions :wk "code actions")
"cr" '(eglot-rename :wk "lsp rename")
"cf" '(eglot-format :wk "format buffer")
@@ -5066,18 +4767,6 @@ date) and the dired header are never skipped."
(delete '(:eval mu4e-alert-mode-line) global-mode-string)))
#+end_src
-* color-tools
-
-this package provides the ability to display rgb and hex colors.
-
-#+begin_src emacs-lisp
-(use-package denote-project-notes
- :ensure t
- :after org
- :config
- (setq denote-project-notes-identifier '(project stayem)))
-#+end_src
-
* arrow.el
#+begin_src emacs-lisp
@@ -5193,16 +4882,6 @@ opening another file in same project does not re-notify."
'(("nh-switch" "nh os switch --quiet $*"))))
#+end_src
-* atuin-eshell
-
-#+begin_src emacs-lisp
-(use-package eshell-atuin
- :ensure t
- :after eshell
- :config
- (eshell-atuin-mode))
-#+end_src
-
* elfetch
#+begin_src emacs-lisp
@@ -5219,6 +4898,7 @@ opening another file in same project does not re-notify."
(ghostel-shell "xonsh")
(ghostel-ssh-install-terminfo t)
:config
+ (require 'ghostel-compile)
(setq-default window-adjust-process-window-size-function
#'window-adjust-process-window-size-largest)
(add-to-list 'ghostel-tramp-shells '("rpc" login-shell))
@@ -5245,6 +4925,8 @@ opening another file in same project does not re-notify."
:ensure (:host github :repo "dakra/ghostel"
:files ("extensions/evil-ghostel/*.el"))
:after (ghostel evil)
+ :custom
+ (evil-ghostel-escape 'evil)
:hook (ghostel-mode . evil-ghostel-mode))
#+end_src
@@ -5326,16 +5008,6 @@ Interactive commands: =garden-player= opens the player; =garden-player-play-next
tramp-verbose 1))
#+end_src
-* difftastic
-
-#+begin_src emacs-lisp
-(use-package difftastic
- :ensure t
- :defer t
- :init
- (difftastic-bindings-mode))
-#+end_src
-
* magit-delta
#+begin_src emacs-lisp
@@ -5354,103 +5026,6 @@ Interactive commands: =garden-player= opens the player; =garden-player-play-next
:ensure t)
#+end_src
-* dashboard
-
-#+begin_src emacs-lisp
-(use-package grid
- :ensure (:host github :repo "ichernyshovvv/grid.el")
- :demand t)
-
-(use-package enlight
- :ensure (:host github :repo "ichernyshovvv/enlight")
- :demand t
- :after grid
- :config
- (require 'enlight-menu)
- (defface my/enlight-header
- '((t (:inherit font-lock-keyword-face :weight bold)))
- "Enlight banner face.")
-
- (defvar my/enlight-banner
- (propertize
- "███████ ███ ███ █████ ██████ ███████
-██ ████ ████ ██ ██ ██ ██
-█████ ██ ████ ██ ███████ ██ ███████
-██ ██ ██ ██ ██ ██ ██ ██
-███████ ██ ██ ██ ██ ██████ ███████"
- 'face 'my/enlight-header))
-
- (defun my/enlight-stats ()
- (concat
- (format "%d packages" (length (elpaca--queued)))
- (when (bound-and-true-p after-init-time)
- (format " · %s" (emacs-init-time "%.2fs")))
- (format " · %s" (format-time-string "%a %d %b %H:%M"))))
-
- (defun my/enlight-recent ()
- (if (bound-and-true-p recentf-list)
- (mapconcat
- (lambda (f)
- (let ((s (abbreviate-file-name f)))
- (if (> (length s) 32)
- (concat "…" (substring s (- (length s) 31)))
- s)))
- (seq-take recentf-list 8)
- "\n")
- (propertize "no recent files" 'face 'shadow)))
-
- (defun my/enlight-content ()
- (concat
- (grid-make-box `(:align center :width 80 :content ,my/enlight-banner))
- "\n"
- (grid-make-box `(:align center :width 80
- :content ,(propertize (my/enlight-stats) 'face 'shadow)))
- "\n\n"
- (grid-make-row
- (list
- (grid-make-box
- `(:width 40 :border t :padding 1
- :content ,(enlight-menu
- '(("Quick actions"
- ("Agenda" (org-agenda nil "d") "a")
- ("Recent file" consult-recent-file "r")
- ("Switch project" projectile-switch-project "p")
- ("Find note" denote-open-or-create "n")
- ("Journal entry" denote-journal-new-or-existing-entry "j")
- ("Magit" magit-status "g")
- ("Files" dirvish "f")
- ("Mail" mu4e "m")
- ("IRC" run-irc "i")
- ("Switch workspace" my/workspace-switch-to "w")
- ("Restore session" my/workspace-load-session "S"))))))
- " "
- (grid-make-box
- `(:width 38 :border t :padding 1
- :content ,(concat (propertize "Recent files\n\n" 'face 'enlight-menu-section)
- (my/enlight-recent)))))))))
-
-(defun my/enlight-refresh (&rest _)
- (enlight--update 'enlight-content (my/enlight-content)))
-(advice-add 'enlight :before #'my/enlight-refresh)
-
-(defun my/session-exists-p ()
- (file-exists-p (file-name-concat persp-save-dir persp-auto-save-fname)))
-
-(setq initial-buffer-choice
- (lambda ()
- (if (and (fboundp 'enlight) (not (my/session-exists-p)))
- (enlight)
- (get-buffer-create "*scratch*"))))
-
-(add-hook 'elpaca-after-init-hook
- (lambda ()
- (when (and (fboundp 'enlight-open) (not (my/session-exists-p)))
- (enlight-open))))
-
-(with-eval-after-load 'evil
- (evil-set-initial-state 'enlight-mode 'emacs))
-#+end_src
-
* provide init
#+begin_src emacs-lisp
diff --git a/init.el b/init.el
index 7ecb63b..a3c7dcc 100644
--- a/init.el
+++ b/init.el
@@ -52,7 +52,7 @@
use-package-compute-statistics t))
;; Install org before tangling config.org
-(elpaca (org :wait t))
+(elpaca (org :ref "release_9.8.5" :depth nil :wait t))
;; Shadow built-in transient with newer version before magit loads
(elpaca (transient :wait t))