mirror of
https://github.com/pestctrl/emacs-config.git
synced 2026-02-16 16:24:18 +00:00
32 KiB
32 KiB
- buffer-window management
- delete-other-side-windows
- Various tools
- pdf-tools use isearch
- freezing time
- colorful compilation buffer
- Profiler Keymap
- World time
- auto-save files in same directory
- New
- transpose-frame
- e2wm
- set-default-directory
- Scroll interval
- Open dev workspace
- Helpful view-mode
- man select window
- find-file-view
- rmsbolt
- ivy-posframe
- Elfeed
- pavucontrol switch speakers headphones
- shell-command+
- shackle-mode
- Emojis!
- Window splitting function
- dired-rsync
- keyfreq
- Hammy?
- Auto dim buffers
- Splitting functions
- Tramp configuration
- Visualization tools
buffer-window management
(defun switch-to-buffer-force-same-window (buffer)
(interactive
(list (read-buffer-to-switch "Switch to buffer: ")))
(let ((switch-to-buffer-obey-display-actions nil))
(switch-to-buffer buffer nil t)))
(global-set-key (kbd "C-x B") #'switch-to-buffer-force-same-window)
(setq switch-to-buffer-obey-display-actions t)
(add-to-list 'display-buffer-alist
`("COMMIT_EDITMSG"
display-buffer-in-side-window
(side . right)
(slot . 0)
(window-parameters . ((no-delete-other-windows . t)))
(window-width . 80)))
(add-to-list 'display-buffer-alist
`((major-mode . magit-status-mode)
display-buffer-in-side-window
(side . right)
(slot . 1)
(window-parameters . ((no-delete-other-windows . t)))
(window-width . 80)))
(add-to-list 'display-buffer-alist
`((major-mode . magit-log-mode)
display-buffer-in-side-window
(side . right)
(slot . 2)
(window-parameters . ((no-delete-other-windows . t)))
(window-width . 100)))
;; TODO: This should be fixed in future versions of emacs
(defun my/is-compilation-buffer (buffer &optional _rest)
(with-current-buffer buffer
(or compilation-minor-mode
(eq major-mode 'compilation-mode))))
;; TODO: Show multiple deadgrep buffers in side-window
(add-to-list 'display-buffer-alist
`((major-mode . deadgrep-mode)
display-buffer-in-side-window
(side . right)
(slot . 3)
(window-parameters . ((no-delete-other-windows . t)))
(window-width . 100)))
(add-to-list 'display-buffer-alist
`(my/is-compilation-buffer
display-buffer-in-side-window
(side . right)
(slot . 4)
(window-parameters . ((no-delete-other-windows . t)))
(window-width . 80)))
(add-to-list 'display-buffer-alist
`((major-mode . helpful-mode)
display-buffer-in-side-window
(side . right)
(slot . 5)
(window-width . 80)))
(add-to-list 'display-buffer-alist
`((major-mode . Info-mode)
display-buffer-in-side-window
(side . right)
(slot . 6)
(window-width . 80)))
(require 'org-capture)
(defun my/is-org-capture-buffer (buffer &optional _rest)
(with-current-buffer buffer
(and (eq major-mode 'org-mode)
org-capture-mode)))
(add-to-list 'display-buffer-alist
`(my/is-org-capture-buffer
display-buffer-in-side-window
(side . left)
(select . t)
(window-width . 85)
(window-parameters
. ((no-delete-other-windows . t)
(dedicated . t)))))
;; (defun my/is-org-capture-buffer (buffer &optional _rest)
;; (with-current-buffer buffer
;; org-capture-mode))
;; (add-to-list 'display-buffer-alist
;; `(my/is-org-capture-buffer
;; display-buffer-in-side-window
;; (side . left)
;; (slot . 0)
;; (window-width . 80)))
;; (pop display-buffer-alist)
delete-other-side-windows
(defun my/delete-other-windows (arg)
(interactive "p")
(if (not (window-parameter nil 'window-side))
(delete-other-windows)
(if (= arg 1)
(delete-other-windows-vertically)
(let ((buf (current-buffer)))
(window-toggle-side-windows)
(let ((switch-to-buffer-obey-display-actions nil))
(switch-to-buffer buf))))))
(define-key pestctrl-minor-mode-map (kbd "C-x 1") #'my/delete-other-windows)
Various tools
ledger
(use-package ledger-mode
:mode "\\.dat\\'"
:config
(setq ledger-narrow-on-reconcile nil)
(setq ledger-reports
`(("account" "%(binary) -f %(ledger-file) reg %(account)")
("credit card" "%(binary) -f %(ledger-file) reg %(account) --aux-date --sort -d")
("bal" "%(binary) -f %(ledger-file) bal")
("reg" "%(binary) -f %(ledger-file) reg")
("equity" "%(binary) -f %(ledger-file) bal ^Exp ^RE ^Rev")
("uncleared" "%(binary) -f %(ledger-file) reg --uncleared --limit=\"payee!='Texas Instruments Income'\"")
("last-superfluous" "%(binary) -f %(ledger-file) bal --limit='account =~ /^Exp:(Food|Luxury|NewTech|People)/ && date >= [this month]'")
("superfluous" "%(binary) -f %(ledger-file) reg --limit='account =~ /^Exp:(Food|Luxury|NewTech|People)/'")
("recurring" "%(binary) -f %(ledger-file) reg --limit='has_tag(\"RECURRING\")' ^Exp")
("expmonth" "%(binary) -f %(ledger-file) -M reg Expenses")
("owedmom" "%(binary) -f %(ledger-file) reg Liabilities")
("progress" "%(binary) -f %(ledger-file) reg Assets Equity Liabilities")
("payee" "%(binary) -f %(ledger-file) reg @%(payee)")
("lia1" "%(binary) -f %(ledger-file) bal ^Lia --cleared")
("lia2" "%(binary) -f %(ledger-file) reg ^Lia --uncleared")
("Ast:AR" "%(binary) -f %(ledger-file) bal ^Ast:AR")
("earned-money" "%(binary) -f %(ledger-file) bal ^Rev:TI ^Exp:Necessary:Tax ^Exp:Necessary:Insurance ^Exp:Necessary:GroupLife")))
(setq dynamic-reports
'(("budgetcal" "%(binary) -f ~/MEGA/org/entries/food.ledger --daily --add-budget reg Expenses")))
(defun ledger-dynamic-report ()
(interactive)
(let* ((ledger-reports dynamic-reports)
(report-name (ledger-report-read-name)))
(ledger-report report-name nil)))
(setq ledger-reconcile-buffer-line-format
"%(date)s %-4(code)s %-30(payee)s %-30(account)s %15(amount)s\n")
(defun ledger-account-check-dont-include-regexp (orig account)
(when (= (aref account 0)
?^)
(setq account
(substring account 1))))
(defun ledger-report-show-monthly-average ()
(interactive)
(let ((average-string "-A -M -n"))
(unless (string-match-p average-string ledger-report-cmd)
(setq ledger-report-cmd
(concat ledger-report-cmd " " average-string))
(ledger-report-redo))))
(setq ledger-amount-regexp
(concat
"\\( \\|\t\\| \t\\)[ \t]*-?"
"\\(?:" "?-" ledger-commodity-regexp " *\\)?"
;; We either match just a number after the commodity with no
;; decimal or thousand separators or a number with thousand
;; separators. If we have a decimal part starting with `,'
;; or `.', because the match is non-greedy, it must leave at
;; least one of those symbols for the following capture
;; group, which then finishes the decimal part.
"\\(-?\\(?:[0-9]+\\|[0-9,.]+?\\)\\)"
"\\([,.][0-9)]+\\)?"
"\\(?: *" ledger-commodity-regexp "\\)?"
"\\([ \t]*[@={]@?[^\n;]+?\\)?"
"\\([ \t]+;.+?\\|[ \t]*\\)?$"))
(define-key ledger-report-mode-map (kbd "M") #'ledger-report-show-monthly-average)
(defun my/ledger-complete-xact--remove-stars ()
(interactive)
(let* ((date-regexp (rx (and line-start (= 4 digit) "/" (= 2 digit) "/" (= 2 digit))))
(start (save-excursion
(re-search-backward date-regexp)
(point)))
(end (save-excursion
(or (re-search-forward date-regexp nil t)
(end-of-buffer))
(beginning-of-line)
(point))))
(save-window-excursion
(narrow-to-region start end)
(beginning-of-buffer)
(replace-regexp (rx " "
(or "*" "!")
" ")
" ")
(replace-regexp (rx (and " " (+ " ")
";; [" (+ (any digit "-" "=" "/")) "]"
line-end))
"")
(widen))))
(advice-add #'ledger-fully-complete-xact
:after
#'my/ledger-complete-xact--remove-stars)
(defun my/ledger-clean-commodity ()
(save-excursion
(beginning-of-buffer)
(replace-regexp (rx " -$") " $-")))
(advice-add #'ledger-mode-clean-buffer
:after
#'my/ledger-clean-commodity)
(defun my/ledger-convert-alias (account)
(save-excursion
(goto-char (point-min))
(let ((regexp
(rx line-start
"alias " (literal account) "="
(group (+ (or alphanumeric ":" "_")))
(* space)
line-end)))
(or (and (re-search-forward regexp nil t)
(aprog1 (match-string 1)
(set-text-properties 0 (length it) nil it)))
account))))
(advice-add #'ledger-read-account-with-prompt
:filter-return
#'my/ledger-convert-alias)
(defun my/ledger-field (orig context field)
(let ((res (funcall orig context field)))
(if (or (not (eq field 'account))
(null res)
(not (string-match (rx (group (separated-list ":" (separated-list " " (+ alphanumeric)))) " ") res)) )
res
(match-string 1 res))))
(advice-add #'ledger-context-field-value
:around
#'my/ledger-field))
Credit Card Statement Macro
(fset 'credit_card_statement
[?\M-x ?o ?r ?g ?- ?m ?o ?d ?e return ?\M-x ?q backspace ?r ?e ?p ?l ?a ?c ?e ?- ?r ?e ?g ?e ?x ?p return ?^ ?\C-q tab return ? ? ? ? return ?\M-< ?\C- ?\C-f ?\C-f ?\C-f ?\C-f ?\C-c ?m ?a ?\C-w ?- ? ?\[ ? ?\] ? ?\C-e ?\C-k ?\C-c ?m ? ?\C-q tab ?\C-q tab ?\C-e ?\C-j ?y ?\C-a ?_ ?_ ?_ ?_ backspace backspace backspace backspace ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?= ?\C-p ?\C-p ?\C-k ?\C-c ?m ? ?\C-q tab ?\C-q tab ?\C-d ?\C-d return ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n ?\C-n])
encryption
(require 'epa-file)
(epa-file-enable)
(setq epa-pinentry-mode 'loopback)
(setq epa-file-cache-passphrase-for-symmetric-encryption t)
(setenv "GPG_AGENT_INFO" nil)
(setq epg-gpg-program "gpg2")
;; (setq auth-source-debug t)
(setq auth-sources `((:source ,(ef "secrets/.authinfo.gpg"))))
debbugs
(use-package debbugs)
(defun my/debbugs-gnu-select-report ()
"Select the report on the current line."
(interactive)
(when (mouse-event-p last-input-event) (mouse-set-point last-input-event))
;; We open the report messages.
(let* ((status (debbugs-gnu-current-status))
(id (alist-get 'id status))
(merged (alist-get 'mergedwith status)))
(setq merged (if (listp merged) merged (list merged)))
(cond
((not id)
(message "No bug report on the current line"))
((eq debbugs-gnu-mail-backend 'rmail)
(debbugs-gnu-read-emacs-bug-with-rmail id status merged))
((eq debbugs-gnu-mail-backend 'gnus)
(debbugs-gnu-read-emacs-bug-with-gnus id status merged))
((eq debbugs-gnu-mail-backend 'notmuch)
(notmuch-tree (concat "tag:bug-gnu-emacs " (format "subject:\"bug#%s\"" id))))
(t (error "No valid mail backend specified")))))
(setq debbugs-gnu-mail-backend 'notmuch)
(advice-add #'debbugs-gnu-select-report
:override
#'my/debbugs-gnu-select-report)
erc
(use-package erc)
(use-package erc-hl-nicks)
(use-package erc-colorize)
(require 'netrc)
(erc-hl-nicks-mode)
(erc-colorize-mode)
(setq erc-user-full-name "Benson Chu")
(setq erc-kill-buffer-on-part t)
(setq erc-autojoin-channels-alist
'(("freenode.net" "#emacs" "#org-mode"
;; "##linux" "#compilers" "#pltclub"
;; "##cs" "##computerscience" "##programming" "#lisp" "##lisp"
;; "#sbcl" "#ecl"
)))
(defun get-authinfo (host port)
(let* ((netrc (netrc-parse (ef "secrets/.authinfo.gpg")))
(hostentry (netrc-machine netrc host port)))
(when hostentry (netrc-get hostentry "password"))))
(defun freenode-connect (nick password)
(erc :server "irc.freenode.net" :port 6667
:password password :nick nick))
(defun irc-connect ()
(interactive)
(when (y-or-n-p "Connect to IRC? ")
(freenode-connect "pest-ctrl" (get-authinfo "irc.freenode.net" "6667"))))
font-lock-studio
(use-package font-lock-studio)
(when (>= emacs-major-version 29)
(define-obsolete-function-alias 'font-lock-fontify-syntactically-region #'font-lock-default-fontify-syntactically "29.1"))
pdf-tools use isearch
(when (and (not (eq system-type 'windows-nt))
(not my-ec/at-ti))
(use-package pdf-tools)
(pdf-tools-install)
(define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward)
(define-key pdf-view-mode-map (kbd "d") (lambda () (interactive) (pdf-view-next-line-or-next-page 8)))
(define-key pdf-view-mode-map (kbd "u") (lambda () (interactive) (pdf-view-previous-line-or-previous-page 8))))
freezing time
(defvar my/frozen-time nil)
(defvar my/format-time-string-function nil)
(defun my/org-today ()
(time-to-days my/frozen-time))
(defun my/current-time ()
my/frozen-time)
(defun my/format-time-string (original format-string &optional time zone)
(apply original
format-string
(if time
time
my/frozen-time)
zone))
(defun my/decode-time (original &optional time zone)
(apply original
(if time
time
my/frozen-time)
zone))
;; Change and freeze time
(defun za-warudo ()
"Freeze `current-time' at the current active or inactive timestamp. If point
is not on a timestamp, the function prompts for one. If time is not specified,
either by the timstamp under point or prompt, the time defaults to the
current HH:MM of today at the selected date."
(interactive)
(let* ((org-read-date-prefer-future nil)
(time (org-read-date t 'totime nil "Input freeze time: ")))
(setq my/frozen-time (append time '(0 0)))
(advice-add #'current-time :override #'my/current-time)
(advice-add #'format-time-string :around #'my/format-time-string)
(advice-add #'decode-time :around #'my/decode-time)
(advice-add #'org-today :override #'my/org-today)
(set-face-background 'fringe "firebrick2")
(message "Toki yo tomare")))
(define-key *root-map* (kbd "C-z") 'za-warudo)
;; Release changed / frozen time
(defun un-za-warudo ()
"Release the time frozen by `freeze-time'."
(interactive)
(advice-remove #'current-time #'my/current-time)
(advice-remove #'format-time-string #'my/format-time-string)
(advice-remove #'decode-time #'my/decode-time)
(advice-remove #'org-today #'my/org-today)
(setq my/frozen-time nil)
(set-face-background 'fringe nil)
(message "Soshite, toki wa ugoki dasu"))
(define-key *root-map* (kbd "C-r") 'un-za-warudo)
colorful compilation buffer
(require 'ansi-color)
(defun colorize-compilation-buffer ()
(let ((buffer-read-only nil))
(ansi-color-apply-on-region (point-min) (point-max))))
(add-hook 'compilation-filter-hook 'colorize-compilation-buffer)
Profiler Keymap
(define-prefix-command '*profiler-map*)
(define-key *profiler-map* (kbd "s") #'profiler-start)
(define-key *profiler-map* (kbd "r") #'profiler-report)
(define-key *profiler-map* (kbd "S") #'profiler-stop)
(define-key *root-map* (kbd "p") '*profiler-map*)
World time
(setq world-clock-list
'(("America/Chicago" "Houston")
("Asia/Taipei" "Taiwan")
("Turkey" "Turkey")
("Asia/Shanghai" "China")
("Asia/Jakarta" "Indonesia")))
auto-save files in same directory
(setq backup-directory-alist `(("." . ,(ef "backups/"))))
(setq make-backup-files t ; backup of a file the first time it is saved.
backup-by-copying t ; don't clobber symlinks
version-control t ; version numbers for backup files
kept-old-versions 6 ; oldest versions to keep when a new numbered backup is made (default: 2)
kept-new-versions 9 ; newest versions to keep when a new numbered backup is made (default: 2)
auto-save-default t ; auto-save every buffer that visits a file
auto-save-timeout 20 ; number of seconds idle time before auto-save (default: 30)
auto-save-interval 200 ; number of keystrokes between auto-saves (default: 300)
)
New
transpose-frame
(use-package transpose-frame)
e2wm
(use-package e2wm
:bind (("M-+" . e2wm:start-management)))
set-default-directory
(defun set-default-directory (dir)
(interactive "f")
(setq default-directory dir))
Scroll interval
(setq scroll-margin 1
hscroll-margin 2
hscroll-step 1
scroll-conservatively 101
scroll-preserve-screen-position t
mouse-wheel-scroll-amount '(3)
mouse-wheel-progressive-speed nil)
Open dev workspace
(defun open-dev-workspace ()
(interactive)
(dired "~/big_files/workspace"))
Helpful view-mode
(defun helpful--navigate-view-mode (orig button)
(let ((w (window-parameter (selected-window) 'quit-restore)))
(funcall orig button)
(view-mode)
(setq-local view-exit-action
`(lambda (&rest args)
(set-window-parameter (selected-window) 'quit-restore ',w)))))
(advice-add #'helpful--navigate
:around
#'helpful--navigate-view-mode)
man select window
(setq Man-notify-method 'aggressive)
find-file-view
(defun view-mode-file ()
(interactive)
(call-interactively #'ido-find-file)
(view-mode))
(global-set-key (kbd "C-c C-v") #'view-mode-file)
rmsbolt
(use-package rmsbolt)
ivy-posframe
(require 'cl)
(unless my-ec/at-ti
(use-package ivy-posframe
:config
(setq ivy-posframe-display-functions-alist
'((swiper . ivy-posframe-display-at-frame-center)
(complete-symbol . ivy-posframe-display-at-point)
(iwc-switch-to-wc . nil)
(t . ivy-posframe-display-at-window-top-center)))
(defun ivy-posframe-display-at-window-top-center (str)
(ivy-posframe--display str #'posframe-poshandler-window-top-center))
(defun posframe-poshandler-window-top-center (info)
"Posframe's position handler.
Get a position which let posframe stay onto current window's
center. The structure of INFO can be found in docstring
of `posframe-show'."
(let* ((frame-width (plist-get info :parent-frame-width))
(window-left (plist-get info :parent-window-left))
(window-top (plist-get info :parent-window-top))
(window-width (plist-get info :parent-window-width))
(posframe-width (plist-get info :posframe-width)))
(cons (min (- frame-width posframe-width)
(+ window-left (max 0
(/ (- window-width posframe-width) 2))))
(+ window-top 50))))
(defun disable-ivy-posframe-on-exwm-windows (orig &rest args)
(if (not (eq major-mode 'exwm-mode))
(apply orig args)
(cl-letf (((symbol-function 'display-graphic-p) (lambda (&optional display) nil)))
(apply orig args))))
(advice-add #'ivy-posframe--read
:around
#'disable-ivy-posframe-on-exwm-windows))
(unless (eq 'hash-table (type-of face-new-frame-defaults))
;; (def-face-copier my/posframe-faces (sym)
;; (let ((name (symbol-name sym)))
;; (string-match-p "^ivy-.*"
;; name)))
;;(setq ivy-posframe-min-height 0)
;; (setq ivy-posframe-height 24)
;; (setq ivy-height-alist
;; '((t . 24)))
;; (setq ivy-posframe-height-alist
;; '((counsel-M-x . 8)
;; (t . 24)))
;; '((swiper . 24)))
))
Elfeed
(require 'elfeed)
(setq elfeed-use-curl t)
(elfeed-set-timeout 36000)
(setq elfeed-curl-extra-arguments '("--insecure"))
;; enable elfeed-protocol
(elfeed-protocol-enable)
pavucontrol switch speakers headphones
(require 'cl)
(defvar laptop-sink-index 0)
(defvar hdmi-pcie-interface nil)
(defun setup-headphone-stuff ()
(interactive)
(let* ((result (shell-command-to-string "pactl list short sinks")))
(when (string-match "\\([0-9]\\).*analog-stereo" result)
(setq laptop-sink-index
(string-to-number
(match-string 1 result))))
(when (string-match "[0-9].*\\(pci-.*\\)\\.hdmi-stereo" result)
(setq hdmi-pcie-interface
(match-string 1 result))))
(when hdmi-pcie-interface
(let* ((result (shell-command-to-string "pacmd list-modules"))
(split (cdr (split-string result "index: "))))
(cl-loop for mod in split
while (not
(string-match (format "\\([0-9]+\\)\n.*\n.*name=\"%s\"" hdmi-pcie-interface)
mod))
finally
do (shell-command
(format "pactl unload-module %s"
(match-string 1 mod)))))))
(defun current-speakers ()
(let ((string (shell-command-to-string "pactl list sinks | grep 'Active Port: '")))
(if (string-match-p "headphones" string)
'headphones
'speakers)))
(defun toggle-audio-output ()
(interactive)
(if (eq (current-speakers)
'headphones)
(shell-command (format "pactl set-sink-port %d analog-output-speaker"
laptop-sink-index))
(shell-command (format "pactl set-sink-port %d analog-output-headphones"
laptop-sink-index)))
(message (format "Switched to: %s" (current-speakers))))
(exwm-global-set-key (kbd "s-s") #'toggle-audio-output)
(use-exwm
:config
(add-hook 'exwm-init-hook #'setup-headphone-stuff))
shell-command+
(use-package shell-command+
:bind ("M-!" . shell-command+))
shackle-mode
(use-package shackle)
(defun shackle--display-buffer-reuse (buffer alist)
(let ((window (display-buffer-reuse-window buffer
;; Reuse frames
(cons '(reusable-frames . t) alist))))
(prog1 window
(when (and window (window-live-p window)
shackle-select-reused-windows)
(select-window window)))))
(setq switch-to-buffer-obey-display-actions t
shackle-select-reused-windows t)
(setq shackle-rules '(("the_plan" :select t)))
(shackle-mode 1)
(defun get-the-plan ()
(with-current-buffer (find-file-noselect (my/agenda-file "plan.org"))
(rename-buffer "the_plan")
(current-buffer)))
(defun the-plan ()
(interactive)
(switch-to-buffer (get-the-plan)))
(exwm-global-set-key (kbd "s-p") #'the-plan)
Emojis!
(use-package emojify)
Window splitting function
(defun split-window-sensibly-prefer-horizontal (&optional window)
"Based on split-window-sensibly, but designed to prefer a horizontal split,
i.e. windows tiled side-by-side."
(let ((window (or window (selected-window))))
(or (and (window-splittable-p window t)
;; Split window horizontally
(with-selected-window window
(split-window-right)))
(and (window-splittable-p window)
;; Split window vertically
(with-selected-window window
(split-window-below)))
(and
;; If WINDOW is the only usable window on its frame (it is
;; the only one or, not being the only one, all the other
;; ones are dedicated) and is not the minibuffer window, try
;; to split it horizontally disregarding the value of
;; `split-height-threshold'.
(let ((frame (window-frame window)))
(or
(eq window (frame-root-window frame))
(catch 'done
(walk-window-tree (lambda (w)
(unless (or (eq w window)
(window-dedicated-p w))
(throw 'done nil)))
frame)
t)))
(not (window-minibuffer-p window))
(let ((split-width-threshold 0))
(when (window-splittable-p window t)
(with-selected-window window
(split-window-right))))))))
(defun split-window-really-sensibly (&optional window)
(let ((window (or window (selected-window))))
(if (> (window-total-width window) (* 2 (window-total-height window)))
(with-selected-window window (split-window-sensibly-prefer-horizontal window))
(with-selected-window window (split-window-sensibly window)))))
(setq
split-height-threshold 4
split-width-threshold (if my/puppet-p 100 160)
split-window-preferred-function 'split-window-really-sensibly)
dired-rsync
(use-package dired-rsync
:config
(bind-key "C-c C-r" 'dired-rsync dired-mode-map)
(add-to-list 'global-mode-string 'dired-rsync-modeline-status t))
keyfreq
(use-package keyfreq
:init
(setq keyfreq-excluded-commands
'(self-insert-command
org-self-insert-command
exwm-input-send-simulation-key
tab-bar-mouse-1
abort-recursive-edit
forward-char
backward-char
previous-line
next-line))
(keyfreq-mode 1)
(keyfreq-autosave-mode 1))
Hammy?
(use-package hammy
:quelpa (hammy :fetcher github :repo "alphapapa/hammy.el"))
(hammy-define "Move"
:documentation "Don't forget to stretch your legs."
:intervals
;; A list of intervals, each defined with the `interval' function.
(list (interval
;; The name of the interval is a string, used when selecting
;; hammys and shown in the mode line.
:name "💺"
;; The duration of the interval: a number of seconds, a string
;; passed to `timer-duration', or a function which returns such.
:duration "10 seconds"
;; Optionally, a face in which to show the
;; interval's name in the mode line.
:face 'font-lock-type-face
;; A list of actions to take before starting the interval
;; (really, one or a list of functions to call with the hammy
;; as the argument). The `do' macro expands to a lambda,
;; which the interval's `before' slot is set to. In its
;; body, we call two built-in helper functions.
:before (do (announce "Whew!")
(notify "Whew!"))
;; We want this interval to not automatically advance to the
;; next one; rather, we want the user to call the
;; `hammy-next' command to indicate when the standing-up is
;; actually happening. So we provide a list of actions to
;; take when it's time to advance to the next interval. We
;; wrap the list in a call to the built-in `remind' function,
;; which causes the actions to be repeated every 10 minutes
;; until the user manually advances to the next interval.
:advance (remind "2 seconds"
;; Every 10 minutes, while the hammy is waiting
;; to be advanced to the next interval, remind
;; the user by doing these things:
(do (announce "Time to stretch your legs!")
(notify "Time to stretch your legs!")
(play-sound-file "~/Misc/Sounds/mooove-it.wav"))))
(interval :name "🤸"
:duration "2 seconds"
:face 'font-lock-builtin-face
:before (do (announce "Mooove it!")
(notify "Mooove it!"))
;; Again, the interval should not advance automatically
;; to the next--the user should indicate when he's
;; actually sat down again. (If we omitted the
;; `:advance' slot, the interval would automatically
;; advance when it reached its duration.)
:advance (do (announce "Time for a sit-down...")
(notify "Time for a sit-down...")
(play-sound-file "~/Misc/Sounds/relax.wav")))))
Auto dim buffers
(use-package auto-dim-other-buffers)
(set-face-attribute 'auto-dim-other-buffers-face nil :background "#700CB3")
Splitting functions
(defun mp-split-below (arg)
"Split window below from the parent or from root with ARG."
(interactive "P")
(split-window (if arg (frame-root-window)
(window-parent (selected-window)))
nil 'below nil))
(defun mp-split-left (arg)
"Split window below from the parent or from root with ARG."
(interactive "P")
(split-window (if arg (frame-root-window)
(window-parent (selected-window)))
nil 'left nil))
Tramp configuration
This is sort of implicit in the code, but I
;; This is sort the default in tramp, but I wanted to keep this here
;; as a reminder that THIS is the way to communicate to a shell that
;; we want a plain vanilla experience.
;; The way to check this is in shell is as follows:
;; if [[ "$TERM" != "dumb" ]]; then
;; # vterm configuration, etc.
;; fi
;; OR, the new way I've been doing this:
;; [[ "$TERM" = "dumb" ]] && return
(setq tramp-terminal-type "dumb")
;; To debug tramp, set the following variable (max value 11).
;; (setq tramp-verbose 3)
;; (setq tramp-verbose 9)
Visualization tools
(use-package graphviz-dot-mode)
;; TODO: There seems to be an issue with my face setup and svg
;; rendering.
(use-package pair-tree)