diff options
| -rw-r--r-- | .alias.d/00-general | 4 | ||||
| -rw-r--r-- | .bashrc | 4 | ||||
| -rw-r--r-- | .emacs.d/early-init.el | 63 | ||||
| -rw-r--r-- | .emacs.d/init.el | 1 | ||||
| -rw-r--r-- | .emacs.d/rul-emacs.org | 619 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-bindings.el | 11 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-dashboard.el | 22 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-fonts.el | 13 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-io.el | 5 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-mail.el | 6 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-modeline.el | 4 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-org-agenda.el | 114 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-org.el | 47 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-prog.el | 3 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-terminals.el | 53 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-vc.el | 40 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-wm.el | 27 | ||||
| -rw-r--r-- | .emacs.d/rul-lisp/packages/rul-write.el | 37 | ||||
| -rw-r--r-- | .environment.d/00-languages | 4 | ||||
| -rw-r--r-- | .inputrc | 2 | ||||
| -rwxr-xr-x | bin/gnome-move-windows | 2 | ||||
| -rwxr-xr-x | bin/gnome-set-config | 8 |
22 files changed, 754 insertions, 335 deletions
diff --git a/.alias.d/00-general b/.alias.d/00-general index ab57817..3feaef4 100644 --- a/.alias.d/00-general +++ b/.alias.d/00-general @@ -17,4 +17,6 @@ alias e=$EDITOR alias mtr='mtr --curses' alias t='cd ~/src/' -alias by='batcat -l yaml'
\ No newline at end of file +alias by='batcat -l yaml' + +alias fd=fdfind
\ No newline at end of file @@ -130,3 +130,7 @@ PROMPT_DIRTRIM=2 if [ -e ~/.bashrc.post ]; then . ~/.bashrc.post fi + +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm +[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion diff --git a/.emacs.d/early-init.el b/.emacs.d/early-init.el index 5a34cb3..9d4ce2c 100644 --- a/.emacs.d/early-init.el +++ b/.emacs.d/early-init.el @@ -3,25 +3,6 @@ (tool-bar-mode -1) (scroll-bar-mode -1) -;; Avoid initial flash of light. -(defun prot-emacs-re-enable-frame-theme (_frame) - "Re-enable active theme, if any, upon FRAME creation. -Add this to `after-make-frame-functions' so that new frames do -not retain the generic background set by the function -`prot-emacs-avoid-initial-flash-of-light'." - (when-let* ((theme (car custom-enabled-themes))) - (enable-theme theme))) - -(defun prot-emacs-avoid-initial-flash-of-light () - "Avoid flash of light when starting Emacs, if needed. -New frames are instructed to call `prot-emacs-re-enable-frame-theme'." - (setq mode-line-format nil) - (set-face-attribute 'default nil :background "#000000" :foreground "#ffffff") - (set-face-attribute 'mode-line nil :background "#000000" :foreground "#ffffff" :box 'unspecified) - (add-hook 'after-make-frame-functions #'prot-emacs-re-enable-frame-theme)) - -(prot-emacs-avoid-initial-flash-of-light) - ;; Do not resize when font size changes (setq frame-resize-pixelwise t) @@ -29,8 +10,48 @@ New frames are instructed to call `prot-emacs-re-enable-frame-theme'." (add-to-list 'default-frame-alist '(fullscreen . maximized)) (add-to-list 'default-frame-alist '(undecorated . t)) -;; Name frames to ease switching between them -(add-hook 'after-init-hook (lambda () (set-frame-name "main"))) +;; Extend this list from to add more startup frames. +(defvar rul-startup-frames + '(("main" . nil) + ("terminals" . multi-vterm)) + "Startup frame specifications. +Each entry has the form (NAME . SETUP). NAME is the frame name. +SETUP is an optional function or interactive command called in that frame.") + +(defun rul-run-startup-frame-setup (setup) + "Run startup frame SETUP." + (cond + ((null setup) nil) + ((commandp setup) (call-interactively setup)) + ((functionp setup) (funcall setup)) + (t (message "Ignoring invalid startup frame setup: %S" setup)))) + +(defun rul-apply-startup-frame-name (frame name) + "Set FRAME name and title to NAME." + (with-selected-frame frame + (set-frame-name name) + (modify-frame-parameters frame `((title . ,name))))) + +(defun rul-create-startup-frames () + "Create the configured startup frames." + (when (display-graphic-p) + (let ((initial-frame (selected-frame)) + (specs rul-startup-frames)) + (when specs + (pcase-let ((`(,name . ,setup) (car specs))) + (rul-apply-startup-frame-name initial-frame name) + (with-selected-frame initial-frame + (rul-run-startup-frame-setup setup))) + (dolist (spec (cdr specs)) + (pcase-let ((`(,name . ,setup) spec)) + (let ((frame (make-frame `((name . ,name) + (title . ,name))))) + (rul-apply-startup-frame-name frame name) + (with-selected-frame frame + (rul-run-startup-frame-setup setup))))) + (select-frame initial-frame))))) + +(add-hook 'emacs-startup-hook #'rul-create-startup-frames) ;; Initialise installed packages, otherwise, basic functions are not ;; available during the initialization stage. diff --git a/.emacs.d/init.el b/.emacs.d/init.el index a07d86f..43b9e06 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -76,6 +76,7 @@ (require 'rul-themes) (require 'rul-bindings) (require 'rul-completion) +(require 'rul-dashboard) (require 'rul-fm) (require 'rul-fonts) (require 'rul-io) diff --git a/.emacs.d/rul-emacs.org b/.emacs.d/rul-emacs.org index e7162c8..1b984d8 100644 --- a/.emacs.d/rul-emacs.org +++ b/.emacs.d/rul-emacs.org @@ -38,25 +38,6 @@ Customization of graphical aspects of Emacs, such as size, panels, etc. (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) - -;; Avoid initial flash of light. -(defun prot-emacs-re-enable-frame-theme (_frame) - "Re-enable active theme, if any, upon FRAME creation. -Add this to `after-make-frame-functions' so that new frames do -not retain the generic background set by the function -`prot-emacs-avoid-initial-flash-of-light'." - (when-let* ((theme (car custom-enabled-themes))) - (enable-theme theme))) - -(defun prot-emacs-avoid-initial-flash-of-light () - "Avoid flash of light when starting Emacs, if needed. -New frames are instructed to call `prot-emacs-re-enable-frame-theme'." - (setq mode-line-format nil) - (set-face-attribute 'default nil :background "#000000" :foreground "#ffffff") - (set-face-attribute 'mode-line nil :background "#000000" :foreground "#ffffff" :box 'unspecified) - (add-hook 'after-make-frame-functions #'prot-emacs-re-enable-frame-theme)) - -(prot-emacs-avoid-initial-flash-of-light) #+end_src ** Frame configuration @@ -76,8 +57,48 @@ environment. (add-to-list 'default-frame-alist '(fullscreen . maximized)) (add-to-list 'default-frame-alist '(undecorated . t)) -;; Name frames to ease switching between them -(add-hook 'after-init-hook (lambda () (set-frame-name "main"))) +;; Extend this list from to add more startup frames. +(defvar rul-startup-frames + '(("main" . nil) + ("terminals" . multi-vterm)) + "Startup frame specifications. +Each entry has the form (NAME . SETUP). NAME is the frame name. +SETUP is an optional function or interactive command called in that frame.") + +(defun rul-run-startup-frame-setup (setup) + "Run startup frame SETUP." + (cond + ((null setup) nil) + ((commandp setup) (call-interactively setup)) + ((functionp setup) (funcall setup)) + (t (message "Ignoring invalid startup frame setup: %S" setup)))) + +(defun rul-apply-startup-frame-name (frame name) + "Set FRAME name and title to NAME." + (with-selected-frame frame + (set-frame-name name) + (modify-frame-parameters frame `((title . ,name))))) + +(defun rul-create-startup-frames () + "Create the configured startup frames." + (when (display-graphic-p) + (let ((initial-frame (selected-frame)) + (specs rul-startup-frames)) + (when specs + (pcase-let ((`(,name . ,setup) (car specs))) + (rul-apply-startup-frame-name initial-frame name) + (with-selected-frame initial-frame + (rul-run-startup-frame-setup setup))) + (dolist (spec (cdr specs)) + (pcase-let ((`(,name . ,setup) spec)) + (let ((frame (make-frame `((name . ,name) + (title . ,name))))) + (rul-apply-startup-frame-name frame name) + (with-selected-frame frame + (rul-run-startup-frame-setup setup))))) + (select-frame initial-frame))))) + +(add-hook 'emacs-startup-hook #'rul-create-startup-frames) #+end_src ** Miscellany @@ -203,6 +224,7 @@ Now, I simply start it from Emacs itself. This approach works well for me. (require 'rul-themes) (require 'rul-bindings) (require 'rul-completion) +(require 'rul-dashboard) (require 'rul-fm) (require 'rul-fonts) (require 'rul-io) @@ -344,17 +366,6 @@ together, offering a menu on the way. ("=" gofmt :exit t) ("c" go-coverage :exit t)) -;; vterm -(defhydra hydra-vterm () - "zoom" - ("t" multi-vterm "Open a terminal" :exit t) - ("d" multi-vterm-dedicated-open "Dedicated" :exit t) - ("p" multi-vterm-prev "Previous terminal") - ("n" multi-vterm-next "Next terminal") - ("r" multi-vterm-rename-buffer "Rename buffer" :exit t) - ) - -(global-set-key (kbd "C-c t") 'hydra-vterm/body) (global-set-key (kbd "C-c m") 'hydra-go/body) #+end_src @@ -522,6 +533,31 @@ context-specific actions in the minibuffer, or common buffers. (provide 'rul-completion) #+end_src +** The =dashboard= module +#+begin_src emacs-lisp :tangle "rul-lisp/packages/rul-dashboard.el" +(use-package page-break-lines :ensure t) + +(use-package dashboard + :ensure t + + :config + (dashboard-setup-startup-hook) + + :custom + (dashboard-center-content t) + (dashboard-startup-banner 3) + (dashboard-items '((recents . 5) + (bookmarks . 5) + (projects . 5) + (agenda . 5) + )) + (dashboard-icon-type 'nerd-icons) + (dashboard-set-heading-icons t) + (dashboard-set-file-icons t) +) + +(provide 'rul-dashboard) +#+end_src ** The =fm= module The =fm= module contains code pertaining to file management. In particular, it's the module that configures =dired= and adds a few extra @@ -565,7 +601,9 @@ installs =fontaine=, a software that allows defining font presets. (small :default-height 120) (medium - :default-height 140) + :default-height 150) + (wayland-medium + :default-height 320) (large :default-weight semilight :default-height 180 @@ -578,13 +616,16 @@ installs =fontaine=, a software that allows defining font presets. :default-weight semilight :default-height 230 :bold-weight extrabold) + (writing + :default-height 140 + :default-family "Lato" + :variable-pitch-family "Regular" + ) (t :default-family "Iosevka" :default-weight regular - :default-height 140 + :default-height 150 :variable-pitch-family "Iosevka Aile"))) - - ;; Set desired style from `fontaine-presets' (fontaine-set-preset 'medium)) (provide 'rul-fonts) @@ -619,7 +660,10 @@ Internet radio channels. It requires =mpv= to be installed. ("SomaFM - Metal" . "https://somafm.com/metal.pls") ("SomaFM - Lush" . "https://somafm.com/lush130.pls") ("KCSM Jazz 91" . "http://ice5.securenetsystems.net/KCSM") - ))) + ("KSUA 91.5 FM" . "https://stream.radio.co/se776fab22/listen") + )) + (setq empv-fd-binary "fdfind") + ) (provide 'rul-io) #+end_src @@ -643,7 +687,11 @@ Emacs can act as Mail User Agent. My preferred package for this is notmuch-hello-auto-refresh t notmuch-hello-recent-searches-max 20 notmuch-hello-thousands-separator "" - notmuch-show-all-tags-list t) + notmuch-show-all-tags-list t + notmuch-show-text/html-blocked-images nil + ) + + (setq notmuch-draft-folder "current/Drafts") ;; Keymaps (defun rul/capture-mail() @@ -880,10 +928,14 @@ Specific to the current window's mode line.") mode-line-front-space mode-line-buffer-identification mode-line-front-space + mode-line-percent-position + mode-line-front-space rul-modeline-major-mode prot-modeline-eglot mode-line-format-right-align rul-modeline-misc-info + mode-line-front-space + mode-line-front-space )) (provide 'rul-modeline) @@ -946,6 +998,11 @@ My org mode configuration is quite big, so I split it across multiple files. (global-set-key (kbd "C-c c") #'org-capture) (global-set-key (kbd "C-c s") #'org-schedule) +(global-set-key (kbd "<f6>") 'org-clock-goto) +(global-set-key (kbd "<f9>") 'org-clock-in-last) +(global-set-key (kbd "<f10>") 'org-clock-out) +(global-set-key (kbd "<f12>") 'org-agenda) + ;; ORG STATES ;; (setq org-todo-keywords (quote ((sequence "TODO(t)" "MAYBE(m)" "NEXT(n)" "|" "DONE(d)") @@ -966,6 +1023,7 @@ My org mode configuration is quite big, so I split it across multiple files. (setq org-log-done (quote time)) (setq org-log-redeadline (quote time)) (setq org-log-reschedule (quote time)) +(setq org-log-into-drawer t) ;; CAPTURE ;; (setq org-capture-templates @@ -990,13 +1048,12 @@ My org mode configuration is quite big, so I split it across multiple files. ("L" "Web Link" entry (file+headline org-refile-path "Read later") - "* %?[[%:link][%:description]] \"\")\n %:initial\n \nCaptured On: %U" + "* %?[[%:link][%:description]]\n %:initial\n \nCaptured On: %U" ) ("l" "Web Link with Selection" entry (file+headline org-refile-path "Read later") - "* [[%:link][%:description]] \n %:initial\n \nCaptured On: %U") - + "* [[%:link][%:description]]\n %:initial\n \nCaptured On: %U") ))) ;; REFILE ;; @@ -1062,6 +1119,40 @@ My org mode configuration is quite big, so I split it across multiple files. ;; Honor ATTR_ORG attribute. Defaults to image's width if not set. (setq org-image-actual-width nil) +(setq org-clock-mode-line-total 'today) + +;; org-tempus +(unless (package-installed-p 'org-tempus) + (package-vc-install "https://github.com/rul/org-tempus.git")) + +(use-package org-tempus + :init + (org-tempus-mode 1)) + +(use-package org-remark-global-tracking + ;; It is recommended that `org-remark-global-tracking-mode' be + ;; enabled when Emacs initializes. You can set it in + ;; `after-init-hook'. + :hook after-init + :config + ;; Selectively keep or comment out the following if you want to use + ;; extensions for Info-mode, EWW, and NOV.el (EPUB) respectively. + (use-package org-remark-eww :after eww :config (org-remark-eww-mode +1)) + (use-package org-remark-nov :after nov :config (org-remark-nov-mode +1))) + +(use-package org-remark + :bind (;; :bind keyword also implicitly defers org-remark itself. + ;; Keybindings before :map is set for global-map. Adjust the keybinds + ;; as you see fit. + ("C-c n m" . org-remark-mark) + ("C-c n l" . org-remark-mark-line) + :map org-remark-mode-map + ("C-c n o" . org-remark-open) + ("C-c n ]" . org-remark-view-next) + ("C-c n [" . org-remark-view-prev) + ("C-c n r" . org-remark-remove) + ("C-c n d" . org-remark-delete))) + (provide 'rul-org) #+end_src @@ -1336,8 +1427,6 @@ Skip project and sub-project tasks, habits, and loose non-project tasks." (setq org-clock-history-length 23) ;; Resume clocking task on clock-in if the clock is open (setq org-clock-in-resume t) -;; Change tasks to NEXT when clocking in -(setq org-clock-in-switch-to-state 'bh/clock-in-to-next) ;; Separate drawers for clocking and logs (setq org-drawers (quote ("PROPERTIES" "LOGBOOK"))) ;; Save clock data and state changes and notes in the LOGBOOK drawer @@ -1355,22 +1444,6 @@ Skip project and sub-project tasks, habits, and loose non-project tasks." ;; Include current clocking task in clock reports (setq org-clock-report-include-clocking-task t) - -(setq bh/keep-clock-running nil) - -(defun bh/clock-in-to-next (kw) - "Switch a task from TODO to NEXT when clocking in. -Skips capture tasks, projects, and subprojects. -Switch projects and subprojects from NEXT back to TODO" - (when (not (and (boundp 'org-capture-mode) org-capture-mode)) - (cond - ((and (member (org-get-todo-state) (list "TODO")) - (bh/is-task-p)) - "NEXT") - ((and (member (org-get-todo-state) (list "NEXT")) - (bh/is-project-p)) - "TODO")))) - (defun bh/find-project-task () "Move point to the parent (project) task if any" (save-restriction @@ -1382,60 +1455,6 @@ Switch projects and subprojects from NEXT back to TODO" (goto-char parent-task) parent-task))) -(defun bh/punch-in (arg) - "Start continuous clocking and set the default task to the -selected task. If no task is selected set the Organization task -as the default task." - (interactive "p") - (setq bh/keep-clock-running t) - (if (equal major-mode 'org-agenda-mode) - ;; - ;; We're in the agenda - ;; - (let* ((marker (org-get-at-bol 'org-hd-marker)) - (tags (org-with-point-at marker (org-get-tags-at)))) - (if (and (eq arg 4) tags) - (org-agenda-clock-in '(16)) - (bh/clock-in-organization-task-as-default))) - ;; - ;; We are not in the agenda - ;; - (save-restriction - (widen) - ; Find the tags on the current task - (if (and (equal major-mode 'org-mode) (not (org-before-first-heading-p)) (eq arg 4)) - (org-clock-in '(16)) - (bh/clock-in-organization-task-as-default))))) - -(defun bh/punch-out () - (interactive) - (setq bh/keep-clock-running nil) - (when (org-clock-is-active) - (org-clock-out)) - (org-agenda-remove-restriction-lock)) - -(defun bh/clock-in-default-task () - (save-excursion - (org-with-point-at org-clock-default-task - (org-clock-in)))) - -(defun bh/clock-in-parent-task () - "Move point to the parent (project) task if any and clock in" - (let ((parent-task)) - (save-excursion - (save-restriction - (widen) - (while (and (not parent-task) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - (if parent-task - (org-with-point-at parent-task - (org-clock-in)) - (when bh/keep-clock-running - (bh/clock-in-default-task))))))) - -(defvar bh/organization-task-id "eb155a82-92b2-4f25-a3c6-0304591af2f9") - ;; https://stackoverflow.com/a/10091330 (defun zin/org-agenda-skip-tag (tag &optional others) "Skip all entries that correspond to TAG. @@ -1453,20 +1472,6 @@ If OTHERS is true, skip all entries that do not correspond to TAG." next-headline nil)))) -(defun bh/clock-in-organization-task-as-default () - (interactive) - (org-with-point-at (org-id-find bh/organization-task-id 'marker) - (org-clock-in '(16)))) - -(defun bh/clock-out-maybe () - (when (and bh/keep-clock-running - (not org-clock-clocking-in) - (marker-buffer org-clock-default-task) - (not org-clock-resolving-clocks-due-to-idleness)) - (bh/clock-in-parent-task))) - -(add-hook 'org-clock-out-hook 'bh/clock-out-maybe 'append) - ;; AGENDA VIEW ;; ;; Do not dim blocked tasks @@ -1504,9 +1509,7 @@ on a single file. (progn (bind-key [remap find-tag] #'godef-jump)) :config - (add-hook 'go-mode-hook #'yas-minor-mode) (add-hook 'go-mode-hook 'electric-pair-mode) - (add-hook 'go-mode-hook 'my-go-mode-hook) (add-hook 'before-save-hook 'gofmt-before-save)) (use-package go-eldoc @@ -1533,7 +1536,6 @@ on a single file. ;; Python (use-package blacken :ensure t :defer t) -(add-hook 'python-mode-hook 'py-autopep8-enable-on-save) ;; Terraform (use-package terraform-mode :ensure t :defer t) @@ -1551,3 +1553,360 @@ on a single file. (provide 'rul-prog) #+end_src +** The =terminals= module +TODO + +#+begin_src emacs-lisp :tangle "rul-lisp/packages/rul-terminals.el" +(use-package vterm + :ensure t + :init + (setq vterm-always-compile-module t + vterm-max-scrollback 100000) + :hook + (vterm-mode . goto-address-mode) + :bind + (:map vterm-mode-map + ("C-c C-t" . vterm-copy-mode) + ("C-l" . vterm-clear)) + :config + (define-key vterm-mode-map (kbd "C-c C-c") + (lambda () + (interactive) + (vterm-send-string "\C-c"))) + + (defun rul/vterm-copy-and-exit (beg end) + "Copy region and exit `vterm-copy-mode'." + (interactive "r") + (kill-ring-save beg end) + (vterm-copy-mode -1)) + + (define-key vterm-copy-mode-map (kbd "w") #'rul/vterm-copy-and-exit) + (define-key vterm-copy-mode-map (kbd "M-w") #'rul/vterm-copy-and-exit)) + +(use-package multi-vterm + :ensure t + :after vterm + :bind (("C-c t" . multi-vterm)) + :config + (setq vterm-kill-buffer-on-exit t) + + (defvar-local rul/vterm-close-tab-on-kill nil + "When non-nil, close this buffer's tab when the vterm buffer is killed.") + + (defun rul/vterm-maybe-close-tab () + "Close the current tab if this vterm buffer was opened in its own tab." + (when rul/vterm-close-tab-on-kill + (tab-close))) + + (defun rul/vterm-new-tab () + "Create a new tab and open a new vterm." + (interactive) + (tab-new) + (multi-vterm) + (setq-local rul/vterm-close-tab-on-kill t) + (add-hook 'kill-buffer-hook #'rul/vterm-maybe-close-tab nil t)) + + ;; Inside vterm buffers, make C-c t spawn a new tab + vterm + (define-key vterm-mode-map (kbd "C-c t") #'rul/vterm-new-tab) + (define-key vterm-mode-map (kbd "C-S-t") #'rul/vterm-new-tab)) + +(provide 'rul-terminals) +#+end_src + +** The =vc= module +TODO + +#+begin_src emacs-lisp :tangle "rul-lisp/packages/rul-vc.el" +;;; rul-vc.el --- Version control configuration -*- lexical-binding: t; -*- + +(setq vc-follow-symlinks nil) + +(use-package magit + :ensure t + :bind (("C-c g s" . magit-status) + ("C-c g F" . magit-pull-from-upstream) + ("C-c g b" . magit-blame)) + :hook (git-commit-setup . rul/git-commit-setup) + :config + (defun rul/git-commit-setup () + "Enable useful text modes for Git commit buffers." + (flyspell-mode 1) + (auto-fill-mode 1)) + + (defun rul/magit-status-save-window-config (&rest _) + "Save current window configuration before invoking `magit-status'." + (window-configuration-to-register :magit-fullscreen)) + + (defun rul/magit-status-single-window (&rest _) + "Display `magit-status' in a single window." + (delete-other-windows)) + + (advice-add 'magit-status :before #'rul/magit-status-save-window-config) + (advice-add 'magit-status :after #'rul/magit-status-single-window)) + +(with-eval-after-load 'project + (add-to-list 'project-switch-commands + '(magit-project-status "Magit" "m"))) + +(provide 'rul-vc) +;;; rul-vc.el ends here +#+end_src + +** The =wm= module +TODO + +#+begin_src emacs-lisp :tangle "rul-lisp/packages/rul-wm.el" +;;;; window.el +;; Inspiration: https://christiantietze.de/posts/2022/12/updated-org-mode-agenda-display-buffer-alist/ +(defun rul/display-buffer-org-agenda-managed-p (buffer-name action) + "Determine whether BUFFER-NAME is an org-agenda managed buffer." + (with-current-buffer buffer-name + (or (derived-mode-p 'org-mode 'org-agenda-mode) + (member (buffer-file-name) (org-agenda-files))))) + +;; Side window for dictionary +(setq switch-to-buffer-obey-display-actions t) +(add-to-list 'display-buffer-alist + '("^\\*Dictionary\\*" display-buffer-in-side-window + (side . bottom) + (window-height . 12) + )) + +;;;; tab-bar.el +(let ((map global-map)) +(define-key map (kbd "C-<next>") 'tab-bar-switch-to-next-tab) +(define-key map (kbd "C-<prior>") 'tab-bar-switch-to-prev-tab) +(define-key map (kbd "<f8>") 'tab-bar-mode)) + +(setq tab-bar-format + '(tab-bar-format-tabs + ;; tab-bar-format-align-right + ;; tab-bar-format-global + )) + +(setq tab-bar-new-tab-to 'rightmost) +(setq tab-bar-close-button-show nil) +(set-face-attribute 'tab-bar nil :height 0.8) + +;; I've moved to a frame oriented workflow, so I no longer use tabs. +;; (tab-bar-mode 1) + +;; Pop-up buffers +;; https://protesilaos.com/codelog/2024-09-19-emacs-command-popup-frame-emacsclient/ +(defun prot-window-delete-popup-frame (&rest _) + "Kill selected selected frame if it has parameter `prot-window-popup-frame'. +Use this function via a hook." + (when (frame-parameter nil 'prot-window-popup-frame) + (delete-frame))) + +(defmacro prot-window-define-with-popup-frame (command) + "Define interactive function which calls COMMAND in a new frame. +Make the new frame have the `prot-window-popup-frame' parameter." + `(defun ,(intern (format "prot-window-popup-%s" command)) () + ,(format "Run `%s' in a popup frame with `prot-window-popup-frame' parameter. +Also see `prot-window-delete-popup-frame'." command) + (interactive) + (let ((frame (make-frame '((prot-window-popup-frame . t))))) + (select-frame frame) + ;; Placeholder for frame, otherwise it'll get autoclosed. + (switch-to-buffer " prot-window-hidden-buffer-for-popup-frame") + (condition-case nil + (call-interactively ',command) + ((quit error user-error) + (delete-frame frame)))))) + +(declare-function org-capture "org-capture" (&optional goto keys)) +(defvar org-capture-after-finalize-hook) + +;;;###autoload (autoload 'prot-window-popup-org-capture "prot-window") +(prot-window-define-with-popup-frame org-capture) + +(add-hook 'org-capture-after-finalize-hook #'prot-window-delete-popup-frame) + +(use-package olivetti + :ensure t + :defer t + :config + (setq olivetti-body-width 100)) + +(use-package logos +:ensure t +:config + +;; If you want to use outlines instead of page breaks (the ^L) +(setq logos-outlines-are-pages t) +(setq logos-outline-regexp-alist + `((emacs-lisp-mode . "^;;;+ ") + (org-mode . "^\\*+ +") + (markdown-mode . "^\\#+ +") + )) + +;; These apply when `logos-focus-mode' is enabled. Their value is +;; buffer-local. +(setq-default logos-hide-mode-line t + logos-hide-buffer-boundaries t + logos-hide-fringe t + logos-variable-pitch nil + logos-buffer-read-only nil + logos-scroll-lock nil + logos-olivetti t + olivetti-body-width 100 + ) + + +(let ((map global-map)) + (define-key map [remap narrow-to-region] #'logos-narrow-dwim) + (define-key map [remap forward-page] #'logos-forward-page-dwim) + (define-key map [remap backward-page] #'logos-backward-page-dwim) + (define-key map (kbd "<f7>") #'logos-focus-mode)) +) + +(use-package beframe + :ensure t + :hook (after-init . beframe-mode) + :config + (setq beframe-functions-in-frames '(project-prompt-project-dir)) + (setq beframe-global-buffers nil) + (define-key global-map (kbd "C-c b") beframe-prefix-map) + + ;;Integration with Consult + (defvar consult-buffer-sources) + (declare-function consult--buffer-state "consult") + + (with-eval-after-load 'consult + (defface beframe-buffer + '((t :inherit font-lock-string-face)) + "Face for `consult' framed buffers.") + + (defun my-beframe-buffer-names-sorted (&optional frame) + "Return the list of buffers from `beframe-buffer-names' sorted by visibility. +With optional argument FRAME, return the list of buffers of FRAME." + (beframe-buffer-names frame :sort #'beframe-buffer-sort-visibility)) + + (defvar beframe-consult-source + `( :name "Frame-specific buffers (current frame)" + :narrow ?F + :category buffer + :face beframe-buffer + :history beframe-history + :items ,#'my-beframe-buffer-names-sorted + :action ,#'switch-to-buffer + :state ,#'consult--buffer-state)) + + (add-to-list 'consult-buffer-sources 'beframe-consult-source))) + +(defun kill-project-buffers-and-close-frame () + (interactive) + (project-kill-buffers) + (delete-frame (selected-frame))) + +(define-key global-map (kbd "C-x p K") 'kill-project-buffers-and-close-frame) + +(add-hook 'text-mode-hook 'context-menu-mode) + +(defun my-context-menu (menu click) + "My context menu" + (define-key-after menu [dictionary-lookup] + '(menu-item "Dict" dictionary-search-word-at-mouse + :help "Look up in dictionary")) + menu) + +;; hook into context menu +(add-hook 'context-menu-functions #'my-context-menu) + +(provide 'rul-wm) +#+end_src + +** The =write= module +TODO + +#+begin_src emacs-lisp :tangle "rul-lisp/packages/rul-write.el" +;;;; `dictionary' +(setq dictionary-server "localhost" + dictionary-default-popup-strategy "lev" + dictionary-create-buttons nil + dictionary-use-single-buffer t) +(define-key global-map (kbd "C-c d") #'dictionary-lookup-definition) + +(use-package denote + :ensure t + :hook (dired-mode . denote-dired-mode) + :bind + (("C-c n n" . denote) + ("C-c n r" . denote-rename-file) + ("C-c n l" . denote-link) + ("C-c n b" . denote-backlinks)) + :config + (denote-rename-buffer-mode 1) + (setq denote-infer-keywords t) + (setq denote-sort-keywords t) + (setq denote-file-type 'org) + (setq denote-excluded-directories-regexp nil) + (setq denote-allow-multi-word-keywords nil) + (setq denote-link-fontify-backlinks t) + (setq denote-rename-no-confirm t) + + (let ((map global-map)) + (define-key map (kbd "C-c n j") #'denote-journal-new-or-existing-entry) + (define-key map (kbd "C-c n n") #'denote) + (define-key map (kbd "C-c n f") #'denote-open-or-create) + (define-key map (kbd "C-c n i") #'denote-link) + (define-key map (kbd "C-c n r") #'denote-rename-file) + ) +) + +(use-package electric + :init + (setq electric-quote-replace-double t) + :hook + (message-mode . electric-quote-local-mode)) + +(use-package message + :hook + (message-mode . my/message-mode-setup)) + +(defun my/message-mode-setup () + (setq fill-column 72 + sentence-end-double-space nil) + (auto-fill-mode 1)) + +;; Flycheck +(use-package flycheck + :ensure t + :config + +(flycheck-define-checker proselint + "A linter for prose." + :command ("proselint" source-inplace) + :error-patterns + ((warning line-start (file-name) ":" line ":" column ": " + (id (one-or-more (not (any " ")))) + (message) line-end)) + :modes (text-mode markdown-mode gfm-mode org-mode)) + +(add-to-list 'flycheck-checkers 'proselint) + +;; TODO: docker run --rm -p 8010:8010 erikvl87/languagetool +(use-package flycheck-languagetool + :ensure t + :hook (message-mode . flycheck-languagetool-setup) + :init + (setq flycheck-languagetool-url "http://localhost:8010") +)) + +;; Flyspell +(defcustom flyspell-delayed-commands nil + "List of commands that are \"delayed\" for Flyspell mode. +After these commands, Flyspell checking is delayed for a short time, +whose length is specified by `flyspell-delay'." + :group 'flyspell + :type '(repeat (symbol))) + +(setq ispell-dictionary "en") +(setq flyspell-default-dictionary "en") + +(setq flyspell-issue-welcome-flag nil) +(setq-default ispell-list-command "list") + +(provide 'rul-write) +#+end_src diff --git a/.emacs.d/rul-lisp/packages/rul-bindings.el b/.emacs.d/rul-lisp/packages/rul-bindings.el index 96d14b0..3a608c0 100644 --- a/.emacs.d/rul-lisp/packages/rul-bindings.el +++ b/.emacs.d/rul-lisp/packages/rul-bindings.el @@ -43,17 +43,6 @@ ("=" gofmt :exit t) ("c" go-coverage :exit t)) -;; vterm -(defhydra hydra-vterm () - "zoom" - ("t" multi-vterm "Open a terminal" :exit t) - ("d" multi-vterm-dedicated-open "Dedicated" :exit t) - ("p" multi-vterm-prev "Previous terminal") - ("n" multi-vterm-next "Next terminal") - ("r" multi-vterm-rename-buffer "Rename buffer" :exit t) - ) - -(global-set-key (kbd "C-c t") 'hydra-vterm/body) (global-set-key (kbd "C-c m") 'hydra-go/body) (use-package which-key diff --git a/.emacs.d/rul-lisp/packages/rul-dashboard.el b/.emacs.d/rul-lisp/packages/rul-dashboard.el new file mode 100644 index 0000000..67bd188 --- /dev/null +++ b/.emacs.d/rul-lisp/packages/rul-dashboard.el @@ -0,0 +1,22 @@ +(use-package page-break-lines :ensure t) + +(use-package dashboard + :ensure t + + :config + (dashboard-setup-startup-hook) + + :custom + (dashboard-center-content t) + (dashboard-startup-banner 3) + (dashboard-items '((recents . 5) + (bookmarks . 5) + (projects . 5) + (agenda . 5) + )) + (dashboard-icon-type 'nerd-icons) + (dashboard-set-heading-icons t) + (dashboard-set-file-icons t) +) + +(provide 'rul-dashboard) diff --git a/.emacs.d/rul-lisp/packages/rul-fonts.el b/.emacs.d/rul-lisp/packages/rul-fonts.el index 8395292..c3b7202 100644 --- a/.emacs.d/rul-lisp/packages/rul-fonts.el +++ b/.emacs.d/rul-lisp/packages/rul-fonts.el @@ -9,7 +9,9 @@ (small :default-height 120) (medium - :default-height 140) + :default-height 150) + (wayland-medium + :default-height 320) (large :default-weight semilight :default-height 180 @@ -22,13 +24,16 @@ :default-weight semilight :default-height 230 :bold-weight extrabold) + (writing + :default-height 140 + :default-family "Lato" + :variable-pitch-family "Regular" + ) (t :default-family "Iosevka" :default-weight regular - :default-height 140 + :default-height 150 :variable-pitch-family "Iosevka Aile"))) - - ;; Set desired style from `fontaine-presets' (fontaine-set-preset 'medium)) (provide 'rul-fonts) diff --git a/.emacs.d/rul-lisp/packages/rul-io.el b/.emacs.d/rul-lisp/packages/rul-io.el index eb2c1c7..50e5a68 100644 --- a/.emacs.d/rul-lisp/packages/rul-io.el +++ b/.emacs.d/rul-lisp/packages/rul-io.el @@ -14,6 +14,9 @@ ("SomaFM - Metal" . "https://somafm.com/metal.pls") ("SomaFM - Lush" . "https://somafm.com/lush130.pls") ("KCSM Jazz 91" . "http://ice5.securenetsystems.net/KCSM") - ))) + ("KSUA 91.5 FM" . "https://stream.radio.co/se776fab22/listen") + )) + (setq empv-fd-binary "fdfind") + ) (provide 'rul-io) diff --git a/.emacs.d/rul-lisp/packages/rul-mail.el b/.emacs.d/rul-lisp/packages/rul-mail.el index dbf9c9b..6206118 100644 --- a/.emacs.d/rul-lisp/packages/rul-mail.el +++ b/.emacs.d/rul-lisp/packages/rul-mail.el @@ -13,7 +13,11 @@ notmuch-hello-auto-refresh t notmuch-hello-recent-searches-max 20 notmuch-hello-thousands-separator "" - notmuch-show-all-tags-list t) + notmuch-show-all-tags-list t + notmuch-show-text/html-blocked-images nil + ) + + (setq notmuch-draft-folder "current/Drafts") ;; Keymaps (defun rul/capture-mail() diff --git a/.emacs.d/rul-lisp/packages/rul-modeline.el b/.emacs.d/rul-lisp/packages/rul-modeline.el index e20bb2c..32c6048 100644 --- a/.emacs.d/rul-lisp/packages/rul-modeline.el +++ b/.emacs.d/rul-lisp/packages/rul-modeline.el @@ -105,10 +105,14 @@ Specific to the current window's mode line.") mode-line-front-space mode-line-buffer-identification mode-line-front-space + mode-line-percent-position + mode-line-front-space rul-modeline-major-mode prot-modeline-eglot mode-line-format-right-align rul-modeline-misc-info + mode-line-front-space + mode-line-front-space )) (provide 'rul-modeline) diff --git a/.emacs.d/rul-lisp/packages/rul-org-agenda.el b/.emacs.d/rul-lisp/packages/rul-org-agenda.el index ddfbd7e..719d4e6 100644 --- a/.emacs.d/rul-lisp/packages/rul-org-agenda.el +++ b/.emacs.d/rul-lisp/packages/rul-org-agenda.el @@ -268,8 +268,6 @@ Skip project and sub-project tasks, habits, and loose non-project tasks." (setq org-clock-history-length 23) ;; Resume clocking task on clock-in if the clock is open (setq org-clock-in-resume t) -;; Change tasks to NEXT when clocking in -(setq org-clock-in-switch-to-state 'bh/clock-in-to-next) ;; Separate drawers for clocking and logs (setq org-drawers (quote ("PROPERTIES" "LOGBOOK"))) ;; Save clock data and state changes and notes in the LOGBOOK drawer @@ -287,22 +285,6 @@ Skip project and sub-project tasks, habits, and loose non-project tasks." ;; Include current clocking task in clock reports (setq org-clock-report-include-clocking-task t) - -(setq bh/keep-clock-running nil) - -(defun bh/clock-in-to-next (kw) - "Switch a task from TODO to NEXT when clocking in. -Skips capture tasks, projects, and subprojects. -Switch projects and subprojects from NEXT back to TODO" - (when (not (and (boundp 'org-capture-mode) org-capture-mode)) - (cond - ((and (member (org-get-todo-state) (list "TODO")) - (bh/is-task-p)) - "NEXT") - ((and (member (org-get-todo-state) (list "NEXT")) - (bh/is-project-p)) - "TODO")))) - (defun bh/find-project-task () "Move point to the parent (project) task if any" (save-restriction @@ -314,60 +296,6 @@ Switch projects and subprojects from NEXT back to TODO" (goto-char parent-task) parent-task))) -(defun bh/punch-in (arg) - "Start continuous clocking and set the default task to the -selected task. If no task is selected set the Organization task -as the default task." - (interactive "p") - (setq bh/keep-clock-running t) - (if (equal major-mode 'org-agenda-mode) - ;; - ;; We're in the agenda - ;; - (let* ((marker (org-get-at-bol 'org-hd-marker)) - (tags (org-with-point-at marker (org-get-tags-at)))) - (if (and (eq arg 4) tags) - (org-agenda-clock-in '(16)) - (bh/clock-in-organization-task-as-default))) - ;; - ;; We are not in the agenda - ;; - (save-restriction - (widen) - ; Find the tags on the current task - (if (and (equal major-mode 'org-mode) (not (org-before-first-heading-p)) (eq arg 4)) - (org-clock-in '(16)) - (bh/clock-in-organization-task-as-default))))) - -(defun bh/punch-out () - (interactive) - (setq bh/keep-clock-running nil) - (when (org-clock-is-active) - (org-clock-out)) - (org-agenda-remove-restriction-lock)) - -(defun bh/clock-in-default-task () - (save-excursion - (org-with-point-at org-clock-default-task - (org-clock-in)))) - -(defun bh/clock-in-parent-task () - "Move point to the parent (project) task if any and clock in" - (let ((parent-task)) - (save-excursion - (save-restriction - (widen) - (while (and (not parent-task) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - (if parent-task - (org-with-point-at parent-task - (org-clock-in)) - (when bh/keep-clock-running - (bh/clock-in-default-task))))))) - -(defvar bh/organization-task-id "redefine") ;; org-id-get-create - ;; https://stackoverflow.com/a/10091330 (defun zin/org-agenda-skip-tag (tag &optional others) "Skip all entries that correspond to TAG. @@ -385,48 +313,6 @@ If OTHERS is true, skip all entries that do not correspond to TAG." next-headline nil)))) -(defun bh/clock-in-organization-task-as-default () - (interactive) - (org-with-point-at (org-id-find bh/organization-task-id 'marker) - (org-clock-in '(16)))) - -(defun bh/clock-out-maybe () - (when (and bh/keep-clock-running - (not org-clock-clocking-in) - (marker-buffer org-clock-default-task) - (not org-clock-resolving-clocks-due-to-idleness)) - (bh/clock-in-parent-task))) - -(add-hook 'org-clock-out-hook 'bh/clock-out-maybe 'append) - -;;; Focusing on current work - -(global-set-key (kbd "<f5>") 'bh/org-todo) -(defun bh/org-todo (arg) - (interactive "p") - (if (equal arg 4) - (save-restriction - (bh/narrow-to-org-subtree) - (org-show-todo-tree nil)) - (bh/narrow-to-org-subtree) - (org-show-todo-tree nil))) - -(global-set-key (kbd "<S-f5>") 'bh/widen) -(defun bh/widen () - (interactive) - (if (equal major-mode 'org-agenda-mode) - (progn - (org-agenda-remove-restriction-lock) - (when org-agenda-sticky - (org-agenda-redo))) - (widen))) - -(defun bh/narrow-to-org-subtree () - (widen) - (org-narrow-to-subtree) - (save-restriction - (org-agenda-set-restriction-lock))) - ;; AGENDA VIEW ;; ;; Do not dim blocked tasks diff --git a/.emacs.d/rul-lisp/packages/rul-org.el b/.emacs.d/rul-lisp/packages/rul-org.el index 9439b86..7c33922 100644 --- a/.emacs.d/rul-lisp/packages/rul-org.el +++ b/.emacs.d/rul-lisp/packages/rul-org.el @@ -51,10 +51,9 @@ (global-set-key (kbd "C-c c") #'org-capture) (global-set-key (kbd "C-c s") #'org-schedule) - -(global-set-key (kbd "<f9>") 'bh/punch-in) -(global-set-key (kbd "<f10>") 'bh/punch-out) -(global-set-key (kbd "<f11>") 'org-clock-goto) +(global-set-key (kbd "<f6>") 'org-clock-goto) +(global-set-key (kbd "<f9>") 'org-clock-in-last) +(global-set-key (kbd "<f10>") 'org-clock-out) (global-set-key (kbd "<f12>") 'org-agenda) ;; ORG STATES ;; @@ -77,6 +76,7 @@ (setq org-log-done (quote time)) (setq org-log-redeadline (quote time)) (setq org-log-reschedule (quote time)) +(setq org-log-into-drawer t) ;; CAPTURE ;; (setq org-capture-templates @@ -101,13 +101,12 @@ ("L" "Web Link" entry (file+headline org-refile-path "Read later") - "* %?[[%:link][%:description]] \"\")\n %:initial\n \nCaptured On: %U" + "* %?[[%:link][%:description]]\n %:initial\n \nCaptured On: %U" ) ("l" "Web Link with Selection" entry (file+headline org-refile-path "Read later") - "* [[%:link][%:description]] \n %:initial\n \nCaptured On: %U") - + "* [[%:link][%:description]]\n %:initial\n \nCaptured On: %U") ))) ;; REFILE ;; @@ -173,4 +172,38 @@ ;; Honor ATTR_ORG attribute. Defaults to image's width if not set. (setq org-image-actual-width nil) +(setq org-clock-mode-line-total 'today) + +;; org-tempus +(unless (package-installed-p 'org-tempus) + (package-vc-install "https://github.com/rul/org-tempus.git")) + +(use-package org-tempus + :init + (org-tempus-mode 1)) + +(use-package org-remark-global-tracking + ;; It is recommended that `org-remark-global-tracking-mode' be + ;; enabled when Emacs initializes. You can set it in + ;; `after-init-hook'. + :hook after-init + :config + ;; Selectively keep or comment out the following if you want to use + ;; extensions for Info-mode, EWW, and NOV.el (EPUB) respectively. + (use-package org-remark-eww :after eww :config (org-remark-eww-mode +1)) + (use-package org-remark-nov :after nov :config (org-remark-nov-mode +1))) + +(use-package org-remark + :bind (;; :bind keyword also implicitly defers org-remark itself. + ;; Keybindings before :map is set for global-map. Adjust the keybinds + ;; as you see fit. + ("C-c n m" . org-remark-mark) + ("C-c n l" . org-remark-mark-line) + :map org-remark-mode-map + ("C-c n o" . org-remark-open) + ("C-c n ]" . org-remark-view-next) + ("C-c n [" . org-remark-view-prev) + ("C-c n r" . org-remark-remove) + ("C-c n d" . org-remark-delete))) + (provide 'rul-org) diff --git a/.emacs.d/rul-lisp/packages/rul-prog.el b/.emacs.d/rul-lisp/packages/rul-prog.el index 581dbc1..72625cb 100644 --- a/.emacs.d/rul-lisp/packages/rul-prog.el +++ b/.emacs.d/rul-lisp/packages/rul-prog.el @@ -9,9 +9,7 @@ (progn (bind-key [remap find-tag] #'godef-jump)) :config - (add-hook 'go-mode-hook #'yas-minor-mode) (add-hook 'go-mode-hook 'electric-pair-mode) - (add-hook 'go-mode-hook 'my-go-mode-hook) (add-hook 'before-save-hook 'gofmt-before-save)) (use-package go-eldoc @@ -38,7 +36,6 @@ ;; Python (use-package blacken :ensure t :defer t) -(add-hook 'python-mode-hook 'py-autopep8-enable-on-save) ;; Terraform (use-package terraform-mode :ensure t :defer t) diff --git a/.emacs.d/rul-lisp/packages/rul-terminals.el b/.emacs.d/rul-lisp/packages/rul-terminals.el index 9678b55..f6a8913 100644 --- a/.emacs.d/rul-lisp/packages/rul-terminals.el +++ b/.emacs.d/rul-lisp/packages/rul-terminals.el @@ -1,9 +1,54 @@ -(use-package multi-vterm +(use-package vterm :ensure t :init - (setq vterm-always-compile-module t) + (setq vterm-always-compile-module t + vterm-max-scrollback 100000) + :hook + (vterm-mode . goto-address-mode) + :bind + (:map vterm-mode-map + ("C-c C-t" . vterm-copy-mode) + ("C-l" . vterm-clear)) :config - (setq vterm-max-scrollback 100000) - (add-hook 'vterm-mode-hook 'goto-address-mode)) + (define-key vterm-mode-map (kbd "C-c C-c") + (lambda () + (interactive) + (vterm-send-string "\C-c"))) + + (defun rul/vterm-copy-and-exit (beg end) + "Copy region and exit `vterm-copy-mode'." + (interactive "r") + (kill-ring-save beg end) + (vterm-copy-mode -1)) + + (define-key vterm-copy-mode-map (kbd "w") #'rul/vterm-copy-and-exit) + (define-key vterm-copy-mode-map (kbd "M-w") #'rul/vterm-copy-and-exit)) + +(use-package multi-vterm + :ensure t + :after vterm + :bind (("C-c t" . multi-vterm)) + :config + (setq vterm-kill-buffer-on-exit t) + + (defvar-local rul/vterm-close-tab-on-kill nil + "When non-nil, close this buffer's tab when the vterm buffer is killed.") + + (defun rul/vterm-maybe-close-tab () + "Close the current tab if this vterm buffer was opened in its own tab." + (when rul/vterm-close-tab-on-kill + (tab-close))) + + (defun rul/vterm-new-tab () + "Create a new tab and open a new vterm." + (interactive) + (tab-new) + (multi-vterm) + (setq-local rul/vterm-close-tab-on-kill t) + (add-hook 'kill-buffer-hook #'rul/vterm-maybe-close-tab nil t)) + + ;; Inside vterm buffers, make C-c t spawn a new tab + vterm + (define-key vterm-mode-map (kbd "C-c t") #'rul/vterm-new-tab) + (define-key vterm-mode-map (kbd "C-S-t") #'rul/vterm-new-tab)) (provide 'rul-terminals) diff --git a/.emacs.d/rul-lisp/packages/rul-vc.el b/.emacs.d/rul-lisp/packages/rul-vc.el index a2ab563..8551647 100644 --- a/.emacs.d/rul-lisp/packages/rul-vc.el +++ b/.emacs.d/rul-lisp/packages/rul-vc.el @@ -1,19 +1,33 @@ +;;; rul-vc.el --- Version control configuration -*- lexical-binding: t; -*- + +(setq vc-follow-symlinks nil) + (use-package magit :ensure t - :bind - (("C-c g s" . magit-status) - ("C-c g F" . magit-pull-from-upstream) - ("C-c g b" . magit-blame)) + :bind (("C-c g s" . magit-status) + ("C-c g F" . magit-pull-from-upstream) + ("C-c g b" . magit-blame)) + :hook (git-commit-setup . rul/git-commit-setup) :config - (progn - (defun inkel/magit-log-edit-mode-hook () - (flyspell-mode t) - (turn-on-auto-fill)) - (defadvice magit-status (around magit-fullscreen activate) - (window-configuration-to-register :magit-fullscreen) - ad-do-it - (delete-other-windows)))) + (defun rul/git-commit-setup () + "Enable useful text modes for Git commit buffers." + (flyspell-mode 1) + (auto-fill-mode 1)) + + (defun rul/magit-status-save-window-config (&rest _) + "Save current window configuration before invoking `magit-status'." + (window-configuration-to-register :magit-fullscreen)) + + (defun rul/magit-status-single-window (&rest _) + "Display `magit-status' in a single window." + (delete-other-windows)) + + (advice-add 'magit-status :before #'rul/magit-status-save-window-config) + (advice-add 'magit-status :after #'rul/magit-status-single-window)) -(add-to-list 'project-switch-commands '(magit-project-status "Magit" "m")) +(with-eval-after-load 'project + (add-to-list 'project-switch-commands + '(magit-project-status "Magit" "m"))) (provide 'rul-vc) +;;; rul-vc.el ends here diff --git a/.emacs.d/rul-lisp/packages/rul-wm.el b/.emacs.d/rul-lisp/packages/rul-wm.el index 5a2293c..90bd031 100644 --- a/.emacs.d/rul-lisp/packages/rul-wm.el +++ b/.emacs.d/rul-lisp/packages/rul-wm.el @@ -6,6 +6,14 @@ (or (derived-mode-p 'org-mode 'org-agenda-mode) (member (buffer-file-name) (org-agenda-files))))) +;; Side window for dictionary +(setq switch-to-buffer-obey-display-actions t) +(add-to-list 'display-buffer-alist + '("^\\*Dictionary\\*" display-buffer-in-side-window + (side . bottom) + (window-height . 12) + )) + ;;;; tab-bar.el (let ((map global-map)) (define-key map (kbd "C-<next>") 'tab-bar-switch-to-next-tab) @@ -129,4 +137,23 @@ With optional argument FRAME, return the list of buffers of FRAME." (add-to-list 'consult-buffer-sources 'beframe-consult-source))) +(defun kill-project-buffers-and-close-frame () + (interactive) + (project-kill-buffers) + (delete-frame (selected-frame))) + +(define-key global-map (kbd "C-x p K") 'kill-project-buffers-and-close-frame) + +(add-hook 'text-mode-hook 'context-menu-mode) + +(defun my-context-menu (menu click) + "My context menu" + (define-key-after menu [dictionary-lookup] + '(menu-item "Dict" dictionary-search-word-at-mouse + :help "Look up in dictionary")) + menu) + +;; hook into context menu +(add-hook 'context-menu-functions #'my-context-menu) + (provide 'rul-wm) diff --git a/.emacs.d/rul-lisp/packages/rul-write.el b/.emacs.d/rul-lisp/packages/rul-write.el index 719baaf..385c1e9 100644 --- a/.emacs.d/rul-lisp/packages/rul-write.el +++ b/.emacs.d/rul-lisp/packages/rul-write.el @@ -1,5 +1,5 @@ ;;;; `dictionary' -(setq dictionary-server "dict.org" +(setq dictionary-server "localhost" dictionary-default-popup-strategy "lev" dictionary-create-buttons nil dictionary-use-single-buffer t) @@ -24,7 +24,7 @@ (setq denote-rename-no-confirm t) (let ((map global-map)) - (define-key map (kbd "C-c n j") #'rul/denote-journal) + (define-key map (kbd "C-c n j") #'denote-journal-new-or-existing-entry) (define-key map (kbd "C-c n n") #'denote) (define-key map (kbd "C-c n f") #'denote-open-or-create) (define-key map (kbd "C-c n i") #'denote-link) @@ -32,27 +32,20 @@ ) ) -(defun rul/denote-journal () - "Create an entry tagged 'journal' with the date as its title. -If a journal for the current day exists, visit it. If multiple -entries exist, prompt with completion for a choice between them. -Else create a new file." - (interactive) - (let* ((today (format-time-string "%A %e %B %Y")) - (string (denote-sluggify today "title")) - (files (denote-directory-files-matching-regexp string))) - (cond - ((> (length files) 1) - (find-file (completing-read "Select file: " files nil :require-match))) - (files - (find-file (car files))) - (t - (denote - today - '("journal")))))) +(use-package electric + :init + (setq electric-quote-replace-double t) + :hook + (message-mode . electric-quote-local-mode)) + +(use-package message + :hook + (message-mode . my/message-mode-setup)) -;; auto-fill mode -(add-hook 'text-mode-hook 'turn-on-auto-fill) +(defun my/message-mode-setup () + (setq fill-column 72 + sentence-end-double-space nil) + (auto-fill-mode 1)) ;; Flycheck (use-package flycheck diff --git a/.environment.d/00-languages b/.environment.d/00-languages index e3ad179..3bba1f4 100644 --- a/.environment.d/00-languages +++ b/.environment.d/00-languages @@ -12,6 +12,10 @@ if [ -d "$HOME/.cargo/bin" ]; then PATH="$HOME/.cargo/bin:$PATH" fi +if [ -d "$HOME/.npm-global/bin" ]; then + PATH="$HOME/.npm-global/bin:$PATH" +fi + # Local Go installation if [ -d "/usr/local/go/bin" ]; then PATH="/usr/local/go/bin:$PATH" diff --git a/.inputrc b/.inputrc new file mode 100644 index 0000000..a8e424b --- /dev/null +++ b/.inputrc @@ -0,0 +1,2 @@ +"\M-\C-f": shell-forward-word +"\M-\C-b": shell-backward-word
\ No newline at end of file diff --git a/bin/gnome-move-windows b/bin/gnome-move-windows index f4fcd4e..04698e8 100755 --- a/bin/gnome-move-windows +++ b/bin/gnome-move-windows @@ -13,7 +13,7 @@ misc=$(wmctrl -l | awk '/isco|eepa/ {print $1}') main="$(wmctrl -xl | awk '/ emacs/ {print $1}')" communications="$(wmctrl -l | awk '/ebex|lack|communications|notmuch|Outlook|elfeed/ {print $1}')" media="$(wmctrl -l | awk '/YouTube|Spotify/ {print $1}')" -terminals="$(wmctrl -l | awk '/Alacritty|kitty|terminal/ {print $1}')" +terminals="$(wmctrl -l | awk '/Alacritty|kitty|terminal|Teleport/ {print $1}')" browsers="$(wmctrl -xl | awk '/irefox|hrom/ {print $1}')" for window_id in $misc; do diff --git a/bin/gnome-set-config b/bin/gnome-set-config index 15771d7..eb5d1f8 100755 --- a/bin/gnome-set-config +++ b/bin/gnome-set-config @@ -18,7 +18,7 @@ for i in $(seq 1 $NUM_WORKSPACES); do done # This configuration is not present in gsettings; we need to fall back to dconf -bindings="emacs org-mode move-windows rofi" +bindings="emacs org-mode move-windows rofi rofi-run" keybindings_key="/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings" keybindings=$(echo $bindings | awk -v key="$keybindings_key" '{for(i=1;i<=NF;i++) printf("'\''" key "/" $i "/'\''%s", (i==NF ? "" : ","))}') keybindings="[$keybindings]" @@ -42,5 +42,9 @@ gsettings set org.gnome.desktop.wm.keybindings switch-input-source "[]" gsettings set org.gnome.desktop.wm.keybindings switch-input-source-backward '[]' dconf write /org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi/binding "'<Super>space'" -dconf write /org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi/command "'rofi -show window'" +dconf write /org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi/command "'rofi -x11 -show window'" dconf write /org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi/name "'rofi'" + +dconf write /org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi-run/binding "'<Super>f2'" +dconf write /org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi-run/command "'rofi -x11 -show run'" +dconf write /org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/rofi-run/name "'rofi-run'" |
