This commit is contained in:
Pavel Korytov 2021-11-18 07:07:40 +03:00
parent 88f448647f
commit 7957ec52bc
11 changed files with 2311 additions and 503 deletions

View file

@ -99,8 +99,8 @@ fi
Use Guix fontconfig. Necessary for nix apps
```sh
if [ -d "$HOME/.guix-extra-profiles/desktop" ]; then
export FONTCONFIG_PATH="$HOME/.guix-extra-profiles/desktop/desktop/etc/fonts"
if [ -d "$HOME/.guix-extra-profiles/desktop-misc" ]; then
export FONTCONFIG_PATH="$HOME/.guix-extra-profiles/desktop-misc/desktop-misc/etc/fonts"
fi
```

View file

@ -13,11 +13,14 @@ draft = false
### Environment {#environment}
```sh
# export EDITOR=/usr/bin/vim
# export BROWSER=/usr/bin/firefox
export QT_QPA_PLATFORMTHEME="qt5ct"
export QT_AUTO_SCREEN_SCALE_FACTOR=0
# export GTK2_RC_FILES="$HOME/.gtkrc-2.0"
```
Set ripgrep config path
```sh
export RIPGREP_CONFIG_PATH=$HOME/.config/ripgrep/ripgreprc
```
@ -458,6 +461,7 @@ Enable vi keybindings & aliases. The alias syntax is the same as in bash, so it'
fish_vi_key_bindings
<<shell-aliases>>
alias cad="conda activate (basename (pwd))"
```
| Guix dependency |
@ -920,6 +924,24 @@ key_bindings:
| unzip | |
| jmtpfs | A tool to mount MTP devices (e.g. Android) |
| tokei | Count lines of code |
| sshfs | Mount stuff over SSH |
### ripgrep config {#ripgrep-config}
Occasionally I can't exclude certain files from ripgrep via the VCS settings, so here is a simple config to ignore certain files globally.
```text
--ignore-file=/home/pavel/.config/ripgrep/ripgrepignore
```
The corresponding ignore file:
```text
*.ts.snap
```
By default ripgrep doesn't read any configs, so it is necessary to set the `RIPGREP_CONFIG_PATH` variable in the [.profile.](#environment)
## Misc scripts {#misc-scripts}

View file

@ -20,6 +20,22 @@ Parts prefixed with (OFF) are not used, but kept for historic purposes. For some
- [Fonts](#fonts)
- [Themes](#themes)
- [Device-specific settings](#device-specific-settings)
- [EXWM](#exwm)
- [Xsession](#xsession)
- [Startup apps](#startup-apps)
- [Moving windows](#moving-windows)
- [Resizing windows](#resizing-windows)
- [App shortcuts](#app-shortcuts)
- [Move workspace to another monitor](#move-workspace-to-another-monitor)
- [Switch to the opposite monitor](#switch-to-the-opposite-monitor)
- [Switching buffers](#switching-buffers)
- [Add all EXWM buffers to current perspective](#add-all-exwm-buffers-to-current-perspective)
- [Revive perspectives](#revive-perspectives)
- [Locking up](#locking-up)
- [Keybindings](#keybindings)
- [Pinentry](#pinentry)
- [Modeline](#modeline)
- [EXWM config](#exwm-config)
- [i3wm](#i3wm)
- [General settings](#general-settings)
- [Managing windows](#managing-windows)
@ -50,6 +66,7 @@ Parts prefixed with (OFF) are not used, but kept for historic purposes. For some
- [ipstack-vpn](#ipstack-vpn)
- [weather](#weather)
- [aw-afk](#aw-afk)
- [pomm](#pomm)
- [sun](#sun)
- [SEP](#sep)
- [TSEP](#tsep)
@ -68,8 +85,8 @@ Parts prefixed with (OFF) are not used, but kept for historic purposes. For some
- [Scripts](#scripts)
- [Buku bookmarks](#buku-bookmarks)
- [Man pages](#man-pages)
- [Emojis](#emojis)
- [pass](#pass)
- [emojis](#emojis)
- [Flameshot](#flameshot)
- [dunst](#dunst)
- [keynav](#keynav)
@ -95,6 +112,7 @@ Parts prefixed with (OFF) are not used, but kept for historic purposes. For some
- [ActivityWatch](#activitywatch)
- [PulseEffects](#pulseeffects)
- [xsettingsd](#xsettingsd)
- [nm-applet](#nm-applet)
- [Discord rich presence](#discord-rich-presence)
- [Polkit Authentication agent](#polkit-authentication-agent)
- [Xmodmap](#xmodmap)
@ -251,6 +269,546 @@ fi
```
## EXWM {#exwm}
Settings for [Emacs X Window Manager](https://github.com/ch11ng/exwm), a tiling WM implemented in Emacs Lisp.
References:
- [EXWM Wiki](https://github.com/ch11ng/exwm/wiki)
- [Emacs From Scratch config](https://github.com/daviwil/emacs-from-scratch/blob/master/Desktop.org)
### Xsession {#xsession}
First things first, Emacs has to be launched as a window manager. On a more conventional system, I'd create a .desktop file in some system folder that can be seen by a login manager, but in the case of Guix, it's a bit more complicated, because all such folders are not meant to be changed manually.
However, GDM, the login manager that seems to default on Guix, launches `~/.xsession` on the startup if it's present, which is just fine for my purposes.
```sh
# Source .profile
. ~/.profile
# Disable access control for the current user
xhost +SI:localuser:$USER
# Fix for Java applications
export _JAVA_AWT_WM_NONREPARENTING=1
# Apply XResourses
xrdb -merge ~/.Xresources
# Turn off the system bell
xset -b
# Use i3lock as a screen locker
xss-lock -- i3lock &
# Some apps that have to be launched only once.
picom &
# nm-applet &
dunst &
copyq &
# Run the Emacs startup script as a session.
# exec dbus-launch --exit-with-session ~/.emacs.d/run-exwm.sh
exec dbus-launch --exit-with-session emacs -mm --debug-init -l ~/.emacs.d/desktop.el
```
### Startup apps {#startup-apps}
Now that Emacs is launched, it is necessary to set up the EXWM-specific parts of config.
I want to launch some apps from EXWM instead of the Xsession file for two purposes:
- the app may need to have the entire desktop environment set up
- or it may need to be restarted if Emacs is killed.
As of now, these are polybar, feh and, shepherd:
```emacs-lisp
(defun my/exwm-run-polybar ()
(call-process "~/bin/polybar.sh"))
(defun my/exwm-set-wallpaper ()
(call-process-shell-command "feh --bg-fill ~/Pictures/wallpaper.jpg"))
(defun my/exwm-run-shepherd ()
(when (string-empty-p (shell-command-to-string "pgrep -u pavel shepherd"))
(call-process "shepherd")))
```
### Moving windows {#moving-windows}
My functions for managing windows. I initially wrote these to mimic the i3 behavior for my Emacs + i3 integration, but I want to try to keep them for the EXWM config as well to make the transition less painful.
A predicate which checks whether there is space in the given direction:
```emacs-lisp
(defun my/exwm-direction-exists-p (dir)
(cl-some (lambda (dir)
(let ((win (windmove-find-other-window dir)))
(and win (not (window-minibuffer-p win)))))
(pcase dir
('width '(left right))
('height '(up down)))))
```
And a function to move windows with the following behavior:
- if there is space in the required direction, move the Emacs window there;
- if there is no space in the required direction, but space in two orthogonal directions, move the Emacs window so that there is no more space in the orthogonal directions;
<!--listend-->
```emacs-lisp
(defun my/exwm-move-window (dir)
(let ((other-window (windmove-find-other-window dir))
(other-direction (my/exwm-direction-exists-p
(pcase dir
('up 'width)
('down 'width)
('left 'height)
('right 'height)))))
(cond
((and other-window (not (window-minibuffer-p other-window)))
(window-swap-states (selected-window) other-window))
(other-direction
(evil-move-window dir)))))
```
### Resizing windows {#resizing-windows}
Something like this also goes for resizing windows. I'm used to the i3 "mode" for this functionality, and this seems to be a sensible approach.
```emacs-lisp
(use-package transient
:straight t)
(setq my/exwm-resize-value 5)
(defun my/exwm-resize-window (dir kind &optional value)
(unless value
(setq value my/exwm-resize-value))
(pcase kind
('shrink
(pcase dir
('width
(evil-window-decrease-width value))
('height
(evil-window-decrease-height value))))
('grow
(pcase dir
('width
(evil-window-increase-width value))
('height
(evil-window-increase-height value))))))
(defhydra my/exwm-resize-hydra (:color pink :hint nil :foreign-keys run)
"
^Resize^
_l_: Increase width _h_: Decrease width _j_: Increase height _k_: Decrease height
_=_: Balance "
("h" (lambda () (interactive) (my/exwm-resize-window 'width 'shrink)))
("j" (lambda () (interactive) (my/exwm-resize-window 'height 'grow)))
("k" (lambda () (interactive) (my/exwm-resize-window 'height 'shrink)))
("l" (lambda () (interactive) (my/exwm-resize-window 'width 'grow)))
("=" balance-windows)
("q" nil "quit" :color blue))
```
### App shortcuts {#app-shortcuts}
Also, a transient for shortcuts for the most frequent apps.
I wanted to make the interactive lambda a macro, but this doesn't seem to work the way I expect, so the code has a bit of duplication.
```emacs-lisp
(defun my/run-in-background (command)
(let ((command-parts (split-string command "[ ]+")))
(apply #'call-process `(,(car command-parts) nil 0 nil ,@(cdr command-parts)))))
(transient-define-prefix my/exwm-apps ()
["Apps"
("t" "Termnial (Alacritty)" (lambda () (interactive) (my/run-in-background "alacritty")))
("b" "Browser (Firefox)" (lambda () (interactive) (my/run-in-background "firefox")))
("v" "VK" (lambda () (interactive) (my/run-in-background "vk")))
("s" "Slack" (lambda () (interactive) (my/run-in-background "slack-wrapper")))
("d" "Discord" (lambda () (interactive) (my/run-in-background "flatpak run com.discordapp.Discord")))
("q" "Quit" transient-quit-one)])
```
### Move workspace to another monitor {#move-workspace-to-another-monitor}
A function to move the current workspace to another monitor.
```emacs-lisp
(defun my/exwm-workspace-switch-monitor ()
(interactive)
(if (plist-get exwm-randr-workspace-monitor-plist exwm-workspace-current-index)
(setq exwm-randr-workspace-monitor-plist
(map-delete exwm-randr-workspace-monitor-plist exwm-workspace-current-index))
(setq exwm-randr-workspace-monitor-plist
(plist-put exwm-randr-workspace-monitor-plist
exwm-workspace-current-index
my/exwm-another-monitor)))
(exwm-randr-refresh))
```
### Switch to the opposite monitor {#switch-to-the-opposite-monitor}
Store the information about which workspace is available on which monitor.
```emacs-lisp
(setq my/exwm-monitor-workspace '())
(defun my/exwm-get-current-monitor ()
(let* ((info (shell-command-to-string "xdotool getmouselocation --shell | head -n 1"))
(coord (string-to-number (substring info 2))))
(if (> coord 1920) 1 0)))
(defun my/exwm-update-current-monitor ()
(setf (alist-get (my/exwm-get-current-monitor) my/exwm-monitor-workspace)
exwm-workspace-current-index))
(add-hook 'exwm-workspace-switch-hook
#'my/exwm-update-current-monitor)
```
Switch to the opposite monitor.
```emacs-lisp
(defun my/exwm-switch-to-other-monitor ()
(interactive)
(let* ((current (my/exwm-get-current-monitor))
(other (seq-some
(lambda (m)
(and (not (= (car m) current)) (cdr m)))
my/exwm-monitor-workspace)))
(exwm-workspace-switch other)))
```
### Switching buffers {#switching-buffers}
A single perspective usually has only a handful of EXWM buffers, so here is a function to cycle them.
Those buffers that are visible in another window are highlighted blue and skipped. The current buffer is highlighted yellow.
```emacs-lisp
(defun my/cycle-persp-exwm-buffers (dir)
(let* ((current (current-buffer))
(ignore-rx (persp--make-ignore-buffer-rx))
(visible-buffers '())
(exwm-data
(cl-loop for buf in (persp-current-buffers)
for is-another = (and (get-buffer-window buf) (not (eq current buf)))
if (and (buffer-live-p buf)
(eq 'exwm-mode (buffer-local-value 'major-mode buf))
(not (string-match-p ignore-rx (buffer-name buf))))
collect buf into all-buffers
and if (not is-another) collect buf into cycle-buffers
finally (return (list all-buffers cycle-buffers))))
(all-buffers (nth 0 exwm-data))
(cycle-buffers (nth 1 exwm-data))
(current-pos (or (cl-position current cycle-buffers) -1)))
(if (seq-empty-p cycle-buffers)
(message "No EXWM buffers to cycle!")
(let* ((next-pos (% (+ current-pos (length cycle-buffers)
(if (eq dir 'forward) 1 -1))
(length cycle-buffers)))
(next-buffer (nth next-pos cycle-buffers)))
(switch-to-buffer next-buffer)
(message
"%s"
(mapconcat
(lambda (buf)
(let ((name (string-replace "EXWM :: " "" (buffer-name buf))))
(cond
((eq (current-buffer) buf)
(concat
"["
(propertize name 'face `(foreground-color . ,(doom-color 'yellow)))
"]"))
((not (member buf cycle-buffers))
(concat
"["
(propertize name 'face `(foreground-color . ,(doom-color 'blue)))
"]"))
(t (format " %s " name)))))
all-buffers
" "))))))
```
### Add all EXWM buffers to current perspective {#add-all-exwm-buffers-to-current-perspective}
```emacs-lisp
(defun my/add-exwm-buffers-to-current-perspective ()
(interactive)
(let ((ignore-rx (persp--make-ignore-buffer-rx)))
(cl-loop for buf in (buffer-list)
if (and (buffer-live-p buf)
(eq 'exwm-mode (buffer-local-value 'major-mode buf))
(not (string-match-p ignore-rx (buffer-name buf))))
do (persp-add-buffer (buffer-name buf)))))
```
### Revive perspectives {#revive-perspectives}
Occasionally the current perspective gets screwed up after a popup. This function attempts to fix it.
```emacs-lisp
(defun my/exwm-revive-perspectives ()
"Make perspectives in the current frame not killed."
(interactive)
(let ((to-switch nil))
(maphash
(lambda (_ v)
(setf (persp-killed v) nil)
(unless to-switch
(setq to-switch v)))
(frame-parameter nil 'persp--hash))
(when to-switch
(persp-switch (persp-name to-switch)))))
```
### Locking up {#locking-up}
Run i3lock.
```emacs-lisp
(defun my/exwm-lock ()
(interactive)
(my/run-in-background "i3lock -f -i /home/pavel/Pictures/lock-wallpaper.png"))
```
### Keybindings {#keybindings}
Setting keybindings for EXWM. This actually has to be in the `:config` block of the `use-package` form, that is it has to be run after EXWM is loaded, so I use noweb to put this block in the correct place.
First, some prefixes for keybindings that are always passed to EXWM instead of the X application in `line-mode`:
```emacs-lisp
(setq exwm-input-prefix-keys
`(?\C-x
?\C-w
?\M-x
?\M-u))
```
Also other local keybindings, that are also available only in `line-mode`:
```emacs-lisp
(defmacro my/app-command (command)
`(lambda () (interactive) (my/run-in-background ,command)))
(general-define-key
:keymaps '(exwm-mode-map)
"C-q" 'exwm-input-send-next-key
"<print>" (my/app-command "flameshot gui")
"M-x" 'counsel-M-x
"M-SPC" (general-key "SPC"))
```
Simulation keys.
```emacs-lisp
(setq exwm-input-simulation-keys `((,(kbd "M-w") . ,(kbd "C-w"))
(,(kbd "M-c") . ,(kbd "C-c"))))
```
And keybindings that are available in both `char-mode` and `line-mode`:
```emacs-lisp
(setq exwm-input-global-keys
`(
;; Reset to line-mode
(,(kbd "s-R") . exwm-reset)
;; Switch windows
(,(kbd "s-<left>"). windmove-left)
(,(kbd "s-<right>") . windmove-right)
(,(kbd "s-<up>") . windmove-up)
(,(kbd "s-<down>") . windmove-down)
(,(kbd "s-h"). windmove-left)
(,(kbd "s-l") . windmove-right)
(,(kbd "s-k") . windmove-up)
(,(kbd "s-j") . windmove-down)
;; Moving windows
(,(kbd "s-H") . (lambda () (interactive) (my/exwm-move-window 'left)))
(,(kbd "s-L") . (lambda () (interactive) (my/exwm-move-window 'right)))
(,(kbd "s-K") . (lambda () (interactive) (my/exwm-move-window 'up)))
(,(kbd "s-J") . (lambda () (interactive) (my/exwm-move-window 'down)))
;; Fullscreen
(,(kbd "s-f") . exwm-layout-toggle-fullscreen)
;; Quit
(,(kbd "s-Q") . evil-quit)
;; Split windows
(,(kbd "s-s") . evil-window-vsplit)
(,(kbd "s-v") . evil-window-hsplit)
;; Switch perspectives
(,(kbd "s-,") . persp-prev)
(,(kbd "s-.") . persp-next)
;; Switch buffers
(,(kbd "s-e") . persp-ivy-switch-buffer)
;; Resize windows
(,(kbd "s-r") . my/exwm-resize-hydra/body)
;; Apps & stuff
(,(kbd "s-p") . ,(my/app-command "rofi -modi drun,run -show drun"))
(,(kbd "s-;") . my/exwm-apps)
(,(kbd "s--") . ,(my/app-command "rofi-pass"))
(,(kbd "s-=") . ,(my/app-command "rofimoji"))
;; Basic controls
(,(kbd "<XF86AudioRaiseVolume>") . ,(my/app-command "ponymix increase 5 --max-volume 150"))
(,(kbd "<XF86AudioLowerVolume>") . ,(my/app-command "ponymix decrease 5 --max-volume 150"))
(,(kbd "<XF86AudioMute>") . ,(my/app-command "ponymix toggle"))
(,(kbd "<XF86AudioPlay>") . ,(my/app-command "mpc toggle"))
(,(kbd "<XF86AudioPause>") . ,(my/app-command "mpc pause"))
(,(kbd "<print>") . ,(my/app-command "flameshot gui"))
;; Switch workspace
(,(kbd "s-q") . my/exwm-switch-to-other-monitor)
(,(kbd "s-w") . exwm-workspace-switch)
(,(kbd "s-W") . exwm-workspace-move-window)
(,(kbd "s-<tab>") . my/exwm-workspace-switch-monitor)
;; Cycle EXWM windows in the current perspective
(,(kbd "s-[") . (lambda () (interactive) (my/cycle-persp-exwm-buffers 'backward)))
(,(kbd "s-]") . (lambda () (interactive) (my/cycle-persp-exwm-buffers 'forward)))
(,(kbd "s-o") . ,(my/app-command "rofi -show window"))
;; 's-N': Switch to certain workspace with Super (Win) plus a number key (0 - 9)
,@(mapcar (lambda (i)
`(,(kbd (format "s-%d" i)) .
(lambda ()
(interactive)
(exwm-workspace-switch-create ,i))))
(number-sequence 0 9))))
```
### Pinentry {#pinentry}
The GUI pinentry doesn't work too well with EXWM because of issues with popup windows, so we will use the Emacs one.
```emacs-lisp
(use-package pinentry
:straight t
:after (exwm)
:config
(setenv "GPG_AGENT_INFO" nil) ;; use emacs pinentry
(setq auth-source-debug t)
(setq epg-gpg-program "gpg2") ;; not necessary
(require 'epa-file)
(epa-file-enable)
(setq epa-pinentry-mode 'loopback)
(setq epg-pinentry-mode 'loopback)
(pinentry-start)
(my/run-in-background "gpgconf --reload gpg-agent"))
```
```vim
default-cache-ttl 3600
max-cache-ttl 3600
allow-emacs-pinentry
allow-loopback-pinentry
```
### Modeline {#modeline}
Show current workspace in the modeline.
```emacs-lisp
(defvar my/exwm-mode-line-info "")
(add-to-list 'mode-line-misc-info
'(:eval my/exwm-mode-line-info))
(defun my/exwm-mode-line-info-update ()
(setq my/exwm-mode-line-info
(concat
"["
(propertize (funcall exwm-workspace-index-map exwm-workspace-current-index)
'face
`(foreground-color . ,(doom-color 'yellow)))
"]"))
(force-mode-line-update))
(add-hook 'exwm-workspace-switch-hook #'my/exwm-mode-line-info-update)
```
### EXWM config {#exwm-config}
And the EXWM config itself.
```emacs-lisp
(defun my/exwm-init ()
(exwm-workspace-switch 1)
(my/exwm-run-polybar)
(my/exwm-set-wallpaper)
(my/exwm-run-shepherd)
;; (with-eval-after-load 'perspective
;; (my/exwm-setup-perspectives))
)
(defun my/exwm-update-class ()
(exwm-workspace-rename-buffer (format "EXWM :: %s" exwm-class-name)))
(use-package exwm
:straight t
:config
(setq exwm-workspace-number 5)
(add-hook 'exwm-init-hook #'my/exwm-init)
(add-hook 'exwm-update-class-hook #'my/exwm-update-class)
(require 'exwm-randr)
(exwm-randr-enable)
(start-process-shell-command "xrandr" nil "~/bin/scripts/screen-layout")
(when (string= (system-name) "indigo")
(setq my/exwm-another-monitor "DVI-D-0")
(setq exwm-randr-workspace-monitor-plist `(2 ,my/exwm-another-monitor 3 ,my/exwm-another-monitor)))
(setq exwm-workspace-warp-cursor t)
(setq mouse-autoselect-window t)
(setq focus-follows-mouse t)
<<exwm-monitor-config>>
<<exwm-keybindings>>
<<exwm-mode-line-config>>
(set-frame-parameter (selected-frame) 'alpha '(90 . 90))
(add-to-list 'default-frame-alist '(alpha . (90 . 90)))
(exwm-enable))
```
## i3wm {#i3wm}
| Guix dependency | Disabled |
@ -688,7 +1246,8 @@ Keybindings to launch [rofi](https://github.com/davatorium/rofi). For more detai
```vim
bindsym $mod+d exec "rofi -modi 'drun,run' -show drun"
bindsym $mod+b exec --no-startup-id rofi-buku-mine
bindsym $mod+minus exec rofi-pass; mode default
bindsym $mod+minus exec rofi-pass
bindsym $mod+equal exec rofimoji
bindsym $mod+apostrophe mode "rofi"
@ -894,9 +1453,9 @@ exec "xmodmap ~/.Xmodmap"
## Polybar {#polybar}
| Guix dependency | Description |
|-----------------|-------------|
| polybar | statusbar |
| Category | Guix dependency | Description |
|-----------------|-----------------|-------------|
| desktop-polybar | polybar | statusbar |
[Polybar](https://github.com/polybar/polybar) is a nice-looking, WM-agnostic statusbar program.
@ -956,13 +1515,13 @@ declare -A BLOCKS=(
["eDP"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP battery SEP sun aw-afk date TSEP"
["eDP-1"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP battery SEP sun aw-afk date TSEP"
["DVI-D-0"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP sun aw-afk date TSEP"
["HDMI-A-0"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP sun aw-afk date TSEP"
["HDMI-A-0"]="pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP pomm sun aw-afk date TSEP"
)
# Geolocation for some modules
export LOC="SPB"
export IPSTACK_API_KEY=$(pass show My_Online/APIs/ipstack | head -n 1)
# export IPSTACK_API_KEY=$(pass show My_Online/APIs/ipstack | head -n 1)
pkill polybar
for m in $(xrandr --query | grep " connected" | cut -d" " -f1); do
@ -1090,11 +1649,11 @@ If you want to copy something, you can go to the [bin/polybar](bin/polybar/) fol
#### ipstack-vpn {#ipstack-vpn}
| Guix dependency | Description |
|-----------------|-------------------------|
| bind:utils | Provides dig |
| curl | |
| jq | util to work with JSONs |
| Category | Guix dependency | Description |
|-----------------|-----------------|-------------------------|
| desktop-polybar | bind:utils | Provides dig |
| desktop-polybar | curl | |
| desktop-polybar | jq | util to work with JSONs |
A module to get a country of the current IP and openvpn status. Uses [ipstack](https://ipstack.com/) API.
@ -1164,9 +1723,9 @@ interval = 1200
Prints out a current uptime and non-AFK time from [ActivityWatch](https://github.com/ActivityWatch) server
| Guix dependency |
|-----------------|
| dateutils |
| Category | Guix dependency |
|-----------------|-----------------|
| desktop-polybar | dateutils |
```bash
afk_event=$(curl -s -X GET "http://localhost:5600/api/0/buckets/aw-watcher-afk_$(hostname)/events?limit=1" -H "accept: application/json")
@ -1190,11 +1749,30 @@ interval = 60
```
#### pomm {#pomm}
Pomodoro module.
```bash
if ps -e | grep emacs >> /dev/null; then
emacsclient --eval "(if (boundp 'pomm-current-mode-line-string) pomm-current-mode-line-string \"\") " | xargs echo -e
fi
```
```ini
[module/pomm]
type = custom/script
exec = /home/pavel/bin/polybar/pomm.sh
interval = 1
format-underline = ${colors.green-lighter}
```
#### sun {#sun}
| Guix dependency |
|-----------------|
| sunwait |
| Category | Guix dependency |
|-----------------|-----------------|
| desktop-polybar | sunwait |
Prints out the time of sunrise/sunset. Uses [sunwait](https://github.com/risacher/sunwait)
@ -1520,9 +2098,9 @@ ramp-capacity-4 = 
## Rofi {#rofi}
| Guix dependency |
|-----------------|
| rofi |
| Category | Guix dependency |
|--------------|-----------------|
| desktop-rofi | rofi |
[rofi](https://github.com/davatorium/rofi) is another dynamic menu generator. It can act as dmenu replacement but offers a superset of dmenu's features.
@ -1741,12 +2319,19 @@ fi
```
#### Emojis {#emojis}
| Category | Guix dependency |
|--------------|-----------------|
| desktop-rofi | python-rofimoji |
#### pass {#pass}
| Guix dependency |
|-----------------|
| rofi-pass |
| xset |
| Category | Guix dependency |
|--------------|-----------------|
| desktop-rofi | rofi-pass |
| desktop-rofi | xset |
A nice [pass frontend for Rofi](https://github.com/carnager/rofi-pass), which is even packaged for Guix.
@ -1758,13 +2343,6 @@ clip=both
```
#### emojis {#emojis}
| Guix dependency |
|-----------------|
| rofi-emoji |
## Flameshot {#flameshot}
| Guix dependency |
@ -2331,12 +2909,12 @@ wintypes:
## Zathura {#zathura}
| Guix dependency |
|---------------------|
| zathura |
| zathura-ps |
| zathura-pdf-poppler |
| zathura-djvu |
| Category | Guix dependency |
|----------|-------------------|
| office | zathura |
| office | zathura-ps |
| office | zathura-pdf-mupdf |
| office | zathura-djvu |
[Zathura](https://pwmt.org/projects/zathura/) is a pdf viewer with vim-like keybindings. One of my favorite features is an ability to invert the document colors.
@ -2352,6 +2930,26 @@ map <C-r> set recolor false
map <C-R> set recolor true
```
For some reason zathura doesn't pick up the plugin directory, so I make a wrapper that sets the directory up:
```bash
zathura -p ~/.guix-extra-profiles/office/office/lib/zathura $@
```
```conf-desktop
[Desktop Entry]
Version=1.0
Type=Application
Name=Zathura
Exec=/home/pavel/bin/zathura-wrapper %U
```
Add the following like to the `mimeapps.list`
```text
application/pdf=zathura-wrapper.desktop
```
## Various software {#various-software}
@ -2459,6 +3057,30 @@ LaTeX
<<packages("latex")>>))
```
Desktop Misc
```scheme
(specifications->manifest
'(
<<packages("desktop-misc")>>))
```
Desktop polybar
```scheme
(specifications->manifest
'(
<<packages("desktop-polybar")>>))
```
Desktop rofi
```scheme
(specifications->manifest
'(
<<packages("desktop-rofi")>>))
```
### Flatpak {#flatpak}
@ -2661,6 +3283,18 @@ aw-watcher-window
```
### nm-applet {#nm-applet}
```scheme
(define nm-applet
(make <service>
#:provides '(nm-applet)
#:respawn? #t
#:start (make-forkexec-constructor '("nm-applet"))
#:stop (make-kill-destructor)))
```
### Discord rich presence {#discord-rich-presence}
References:
@ -2687,7 +3321,7 @@ Launch an authentication agent. Necessary for stuff like `pkexec`. I suspect I'm
(make <service>
#:provides '(polkit-gnome)
#:respawn? #t
#:start (make-forkexec-constructor '("/home/pavel/.guix-extra-profiles/desktop/desktop/libexec/polkit-gnome-authentication-agent-1"))
#:start (make-forkexec-constructor '("/home/pavel/.guix-extra-profiles/desktop-misc/desktop-misc/libexec/polkit-gnome-authentication-agent-1"))
#:stop (make-kill-destructor)))
```
@ -2747,7 +3381,8 @@ Register services
polkit-gnome
vpn
davmail
xmodmap)
xmodmap
nm-applet)
```
Daemonize shepherd
@ -2759,7 +3394,7 @@ Daemonize shepherd
Run services
```scheme
(for-each start '(mpd mpd-watcher mcron aw-server aw-watcher-afk aw-watcher-window pulseeffects xsettingsd discord-rich-presence polkit-gnome davmail xmodmap))
(for-each start '(mpd mpd-watcher mcron aw-server aw-watcher-afk aw-watcher-window pulseeffects xsettingsd discord-rich-presence polkit-gnome davmail xmodmap nm-applet))
```
@ -2774,29 +3409,28 @@ Run services
Other desktop programs I use are listed below.
| Guix dependency | Description |
|------------------------|-------------------------------------------|
| xprop | Tool to display properties of X windows |
| arandr | GUI to xrandr |
| light | Control screen brightness |
| ponymix | Control PulseAudio CLI |
| pavucontrol | Control PulseAudio GUI |
| network-manager-applet | Applet to manage network connections |
| feh | Image viewer. Used to set background |
| copyq | Clipboard manager |
| xmodmap | Program to modify keybindings on X server |
| thunar | My preferred GUI file manager |
| keepassxc | My preferred password manager |
| telegram-desktop | telegram client |
| xdg-utils | gives xdg-open and stuff |
| gnome-font-viewer | view fonts |
| qbittorrent | torrent client |
| fontconfig | |
| polkit-gnome | Polkit authentication agent |
| anydesk | Remote desktop software |
| gnome-disk-utility | Manage disks |
| gparted | Manage partitions |
| xev | Test input |
| Category | Guix dependency | Description |
|--------------|------------------------|-------------------------------------------|
| desktop-misc | xprop | Tool to display properties of X windows |
| desktop-misc | arandr | GUI to xrandr |
| desktop-misc | light | Control screen brightness |
| desktop-misc | ponymix | Control PulseAudio CLI |
| desktop-misc | pavucontrol | Control PulseAudio GUI |
| desktop-misc | network-manager-applet | Applet to manage network connections |
| desktop-misc | xmodmap | Program to modify keybindings on X server |
| desktop-misc | fontconfig | |
| desktop-misc | polkit-gnome | Polkit authentication agent |
| desktop-misc | feh | Image viewer. Used to set background |
| desktop-misc | copyq | Clipboard manager |
| desktop-misc | thunar | My preferred GUI file manager |
| desktop-misc | telegram-desktop | telegram client |
| desktop-misc | xdg-utils | gives xdg-open and stuff |
| desktop-misc | gnome-font-viewer | view fonts |
| desktop-misc | qbittorrent | torrent client |
| desktop-misc | anydesk | Remote desktop software |
| desktop-misc | gnome-disk-utility | Manage disks |
| desktop-misc | gparted | Manage partitions |
| desktop-misc | xev | Test input |
<a id="code-snippet--packages"></a>
```emacs-lisp

View file

@ -69,6 +69,7 @@ Parts prefixed with (OFF) are not used, but kept for historic purposes. For some
- [Buku bookmarks](#buku-bookmarks)
- [Man pages](#man-pages)
- [pass](#pass)
- [emojis](#emojis)
- [Flameshot](#flameshot)
- [dunst](#dunst)
- [keynav](#keynav)
@ -1107,9 +1108,13 @@ if [[ -z $ip || $ip == *"timed out"* ]]; then
fi
ip_info=$(curl -s http://api.ipstack.com/${ip}?access_key=${API_KEY})
# emoji=$(echo $ip_info | jq -r '.location.country_flag_emoji')
code=$(echo $ip_info | jq -r '.country_code')
code=$(echo $ip_info | jq -r '.country_code' 2> /dev/null)
vpn=$(pgrep -a openvpn$ | head -n 1 | awk '{print $NF }' | cut -d '.' -f 1)
if [[ -z $code ]]; then
code="??"
fi
if [ -n "$vpn" ]; then
echo "%{u<<get-color(name="blue")>>}%{+u}  $code %{u-}"
else
@ -1753,6 +1758,13 @@ clip=both
```
#### emojis {#emojis}
| Guix dependency |
|-----------------|
| rofi-emoji |
## Flameshot {#flameshot}
| Guix dependency |
@ -2395,6 +2407,9 @@ This section generates manifests for various desktop software that I'm using.
| dev | hugo-extended |
| dev | make |
| dev | sbcl |
| dev | git-lfs |
| dev | mysql |
| dev | gource |
### Manifests {#manifests}

View file

@ -67,7 +67,6 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [ivy-rich](#ivy-rich)
- [prescient](#prescient)
- [Keybindings](#keybindings)
- [<span class="org-todo done OFF">OFF</span> (OFF) Helm](#off--helm)
- [Treemacs](#treemacs)
- [Helper functions](#helper-functions)
- [Custom icons](#custom-icons)
@ -92,7 +91,6 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [My title](#my-title)
- [Modeline](#modeline)
- [Font stuff](#font-stuff)
- [Emojis](#emojis)
- [Ligatures](#ligatures)
- [Icons](#icons)
- [Highlight todo](#highlight-todo)
@ -172,7 +170,12 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [Keybindings](#keybindings)
- [Flycheck](#flycheck)
- [Tree Sitter](#tree-sitter)
- [<span class="org-todo done OFF">OFF</span> (OFF) DAP](#off--dap)
- [DAP](#dap)
- [Controls](#controls)
- [UI Fixes](#ui-fixes)
- [Helper functions](#helper-functions)
- [Improved stack frame switching](#improved-stack-frame-switching)
- [Debug templates](#debug-templates)
- [<span class="org-todo done OFF">OFF</span> (OFF) TabNine](#off--tabnine)
- [<span class="org-todo done OFF">OFF</span> (OFF) Code Compass](#off--code-compass)
- [Dependencies](#dependencies)
@ -277,11 +280,9 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [proced](#proced)
- [Guix](#guix)
- [Productivity](#productivity)
- [Pomidor](#pomidor)
- [pomm](#pomm)
- [<span class="org-todo done OFF">OFF</span> (OFF) Pomidor](#off--pomidor)
- [Calendar](#calendar)
- [<span class="org-todo done OFF">OFF</span> (OFF) EAF](#off--eaf)
- [Installation](#installation)
- [Config](#config)
- [Fun](#fun)
- [Discord integration](#discord-integration)
- [Snow](#snow)
@ -719,6 +720,7 @@ Basic evil configuration.
pass
calendar
dired
ivy
debug
guix
calc
@ -805,7 +807,12 @@ Using the `SPC` key as a leader key, like in Doom Emacs or Spacemacs.
:prefix "SPC"
:states '(normal motion emacs))
(general-def :states '(normal motion emacs) "SPC" nil)
(general-def :states '(normal motion emacs)
"SPC" nil
"M-SPC" (general-key "SPC"))
(general-def :states '(insert)
"M-SPC" (general-key "SPC" :state 'normal))
(my-leader-def "?" 'which-key-show-top-level)
(my-leader-def "E" 'eval-expression)
@ -1028,7 +1035,7 @@ So here is a simple predicate which checks whether there is space in the given d
```emacs-lisp
(defun my/emacs-i3-direction-exists-p (dir)
(some (lambda (dir)
(cl-some (lambda (dir)
(let ((win (windmove-find-other-window dir)))
(and win (not (window-minibuffer-p win)))))
(pcase dir
@ -1388,6 +1395,10 @@ References:
;; ivy-resume
;; ivy--restore-session
lsp-ivy-workspace-symbol
dap-switch-stack-frame
my/dap-switch-stack-frame
dap-switch-session
dap-switch-thread
counsel-grep
;; counsel-find-file
counsel-git-grep
@ -1439,69 +1450,12 @@ References:
```
### <span class="org-todo done OFF">OFF</span> (OFF) Helm {#off--helm}
Config for the Helm incremental completion framework. I switched to Ivy some time ago, but keep the configuration just in case.
```emacs-lisp
(use-package helm
:init
(require 'helm-config)
(setq helm-split-window-in-side-p t)
(setq helm-move-to-line-cycle-in-source t)
:straight t
:config
(helm-mode 1)
(helm-autoresize-mode 1))
(use-package helm-ag
:straight t)
(use-package helm-rg
:straight t)
(general-nmap
:keymaps 'helm-ag-mode-map
"RET" 'helm-ag-mode-jump
"M-RET" 'helm-ag-mode-jump-other-window)
(general-nmap
:keymaps 'helm-occur-mode-map
"RET" 'helm-occur-mode-goto-line
"M-RET" 'helm-occur-mode-goto-line-ow)
(general-define-key "M-x" 'helm-M-x)
(my-leader-def
"fb" 'helm-buffers-list
"fs" 'helm-lsp-workspace-symbol
"fw" 'helm-lsp-global-workspace-symbol
"fc" 'helm-show-kill-ring
;; "fa" 'helm-do-ag-project-root
"fm" 'helm-bookmarks
"ff" 'project-find-file
"fe" 'conda-env-activate)
(my-leader-def "s" 'helm-occur)
(my-leader-def "SPC" 'helm-resume)
(general-define-key
:keymaps 'helm-map
"C-j" 'helm-next-line
"C-k" 'helm-previous-line)
(general-define-key
:keymaps '(helm-find-files-map helm-locate-map)
"C-h" 'helm-find-files-up-one-level
"C-l" 'helm-execute-persistent-action)
(general-imap
"C-y" 'helm-show-kill-ring)
;; (general-nmap "C-p" 'project-find-file)
```
### Treemacs {#treemacs}
| Type | Note |
|------|--------------------------------------------------------|
| TODO | Enable modeline only for particular treemacs instances |
[Treemacs](https://github.com/Alexander-Miller/treemacs) calls itself a tree layout file explorer, but looks more like a project and workspace management system.
Integrates with evil, magit, projectile and perspective. The latter is particularly great - each perspective can have its own treemacs workspace!
@ -2154,21 +2108,6 @@ References:
### Font stuff {#font-stuff}
#### Emojis {#emojis}
| Note | Type |
|------|-----------------------------------------------------------|
| TODO | Figure out how to display emojis without prettify symbols |
```emacs-lisp
(use-package emojify
:straight t
:if (and (display-graphic-p) (not (or my/lowpower my/is-termux)))
:disabled
:hook (after-init . global-emojify-mode))
```
#### Ligatures {#ligatures}
Ligature setup for the JetBrainsMono font.
@ -2761,6 +2700,10 @@ Use the built-in org mode.
(add-hook 'org-mode-hook
(lambda ()
(rainbow-delimiters-mode -1)))
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("sq" . "src sql"))
<<org-crypt-setup>>
(unless my/is-termux
<<org-lang-setup>>)
@ -3179,6 +3122,12 @@ Refile targets
Settings for Org capture mode. The goal here is to have a non-disruptive process to capture various ideas.
```emacs-lisp
(defun my/generate-inbox-note-name ()
(format
"%s/inbox-notes/%s.org"
org-directory
(format-time-string "%Y%m%d%H%M%S")))
(setq org-capture-templates
`(("i" "Inbox" entry (file "inbox.org")
,(concat "* TODO %?\n"
@ -3191,7 +3140,10 @@ Settings for Org capture mode. The goal here is to have a non-disruptive process
("f" "elfeed" entry (file "inbox.org")
,(concat "* TODO %:elfeed-entry-title\n"
"/Entered on/ %U\n"
"%a\n"))))
"%a\n"))
("n" "note" entry (file my/generate-inbox-note-name)
,(concat "* %?\n"
"/Entered on/ %U"))))
```
Effort estimation
@ -3640,7 +3592,7 @@ References:
(my-leader-def
:infix "or"
"r" '(:which-key "org-roam")
"" '(:which-key "org-roam")
"i" 'org-roam-node-insert
"r" 'org-roam-node-find
"g" 'org-roam-graph
@ -3729,8 +3681,9 @@ As of now, this package loads Helm on start. To avoid this, I have to exclude He
(general-define-key
:keymaps 'bibtex-mode-map
"M-RET" 'org-ref-bibtex-hydra/body)
(add-to-list 'orhc-candidate-formats
'("online" . " |${=key=}| ${title} ${url}")))
;; (add-to-list 'orhc-candidate-formats
;; '("online" . " |${=key=}| ${title} ${url}"))
)
```
@ -4322,6 +4275,7 @@ References:
:if (not (or my/slow-ssh my/is-termux my/remote-server))
:hook (
(typescript-mode . lsp)
(js-mode . lsp)
(vue-mode . lsp)
(go-mode . lsp)
(svelte-mode . lsp)
@ -4462,11 +4416,11 @@ References:
```
#### <span class="org-todo done OFF">OFF</span> (OFF) DAP {#off--dap}
#### DAP {#dap}
An Emacs client for Debugger Adapter Protocol.
I don't use it now, because there are debuggers I like more for the technologies I'm currently using.
As of time of this writing, I mostly debug TypeScript, so the main competitor is Chrome Inspector for node.js.
References:
@ -4477,12 +4431,13 @@ References:
```emacs-lisp
(use-package dap-mode
:straight t
:defer t
:commands (dap-debug)
:init
(setq lsp-enable-dap-auto-configure nil)
:config
(setq dap-ui-variable-length 100)
(setq dap-auto-show-output nil)
(require 'dap-node)
(dap-node-setup)
@ -4494,30 +4449,251 @@ References:
(dap-mode 1)
(dap-ui-mode 1)
(dap-tooltip-mode 1)
(tooltip-mode 1)
(dap-ui-controls-mode 1))
(tooltip-mode 1))
```
(my-leader-def
:infix "d"
"d" 'dap-debug
"b" 'dap-breakpoint-toggle
"c" 'dap-breakpoint-condition
"wl" 'dap-ui-locals
"wb" 'dap-ui-breakpoints
"wr" 'dap-ui-repl
"ws" 'dap-ui-sessions
"we" 'dap-ui-expressions)
(my-leader-def
:infix "d"
:keymaps 'dap-mode-map
"h" 'dap-hydra)
##### Controls {#controls}
I don't like some keybindings in the built-in hydra, and there seems to be no easy way to modify the existing hydra, so I create my own. I tried to use transient, but the transient buffer seems to conflict with special buffers of DAP, and hydra does not.
Also, I want the hydra to toggle UI windows instead of just opening them, so here is macro that defines such functions:
```emacs-lisp
(with-eval-after-load 'dap-mode
(defmacro my/define-dap-ui-window-toggler (name)
`(defun ,(intern (concat "my/dap-ui-toggle-" name)) ()
,(concat "Toggle DAP " name "buffer")
(interactive)
(if-let (window (get-buffer-window ,(intern (concat "dap-ui--" name "-buffer"))))
(quit-window nil window)
(,(intern (concat "dap-ui-" name))))))
(my/define-dap-ui-window-toggler "locals")
(my/define-dap-ui-window-toggler "expressions")
(my/define-dap-ui-window-toggler "sessions")
(my/define-dap-ui-window-toggler "breakpoints")
(my/define-dap-ui-window-toggler "repl"))
```
And here is the hydra:
```emacs-lisp
(defhydra my/dap-hydra (:color pink :hint nil :foreign-keys run)
"
^Stepping^ ^UI^ ^Switch^ ^Breakpoints^ ^Debug^ ^Expressions
^^^^^^^^------------------------------------------------------------------------------------------------------------------------------------------
_n_: Next _uc_: Controls _ss_: Session _bb_: Toggle _dd_: Debug _ee_: Eval
_i_: Step in _ue_: Expressions _st_: Thread _bd_: Delete _dr_: Debug recent _er_: Eval region
_o_: Step out _ul_: Locals _sf_: Stack frame _ba_: Add _dl_: Debug last _es_: Eval thing at point
_c_: Continue _ur_: REPL _su_: Up stack frame _bc_: Set condition _de_: Edit debug template _ea_: Add expression
_r_: Restart frame _uo_: Output _sd_: Down stack frame _bh_: Set hit count _Q_: Disconnect _ed_: Remove expression
_us_: Sessions _sF_: Stack frame filtered _bl_: Set log message _eu_: Refresh expressions
_ub_: Breakpoints "
("n" dap-next)
("i" dap-step-in)
("o" dap-step-out)
("c" dap-continue)
("r" dap-restart-frame)
("uc" dap-ui-controls-mode)
("ue" my/dap-ui-toggle-expressions)
("ul" my/dap-ui-toggle-locals)
("ur" my/dap-ui-toggle-repl)
("uo" dap-ui-go-to-output-buffer)
("us" my/dap-ui-toggle-sessions)
("ub" my/dap-ui-toggle-breakpoints)
("ss" dap-switch-session)
("st" dap-switch-thread)
("sf" dap-switch-stack-frame)
("sF" my/dap-switch-stack-frame)
("su" dap-up-stack-frame)
("sd" dap-down-stack-frame)
("bb" dap-breakpoint-toggle)
("ba" dap-breakpoint-add)
("bd" dap-breakpoint-delete)
("bc" dap-breakpoint-condition)
("bh" dap-breakpoint-hit-condition)
("bl" dap-breakpoint-log-message)
("dd" dap-debug)
("dr" dap-debug-recent)
("dl" dap-debug-last)
("de" dap-debug-edit-template)
("ee" dap-eval)
("ea" dap-ui-expressions-add)
("er" dap-eval-region)
("es" dap-eval-thing-at-point)
("ed" dap-ui-expressions-remove)
("eu" dap-ui-expressions-refresh)
("q" nil "quit" :color blue)
("Q" dap-disconnect :color red))
(my-leader-def "d" #'my/dap-hydra/body)
```
##### UI Fixes {#ui-fixes}
There are some problems with DAP UI in my setup.
First, DAP uses Treemacs buffers quite extensively, and they hide the doom modeline for some reason, so I can't tell which buffer is active and can't see borders between buffers.
Second, lines are truncated in some strange way, but calling `toggle-truncate-lines` seems to fix that.
So I define a macro that creates a function that I can further use in an advice.
```emacs-lisp
(defvar my/dap-mode-buffer-fixed nil)
(with-eval-after-load 'dap-mode
(defmacro my/define-dap-tree-buffer-fixer (buffer-var buffer-name)
`(defun ,(intern (concat "my/fix-dap-ui-" buffer-name "-buffer")) (&rest _)
(with-current-buffer ,buffer-var
(unless my/dap-mode-buffer-fixed
(toggle-truncate-lines 1)
(doom-modeline-set-modeline 'info)
(setq-local my/dap-mode-buffer-fixed t)))))
(my/define-dap-tree-buffer-fixer dap-ui--locals-buffer "locals")
(my/define-dap-tree-buffer-fixer dap-ui--expressions-buffer "expressions")
(my/define-dap-tree-buffer-fixer dap-ui--sessions-buffer "sessions")
(my/define-dap-tree-buffer-fixer dap-ui--breakpoints-buffer "breakpoints")
(advice-add 'dap-ui-locals :after #'my/fix-dap-ui-locals-buffer)
(advice-add 'dap-ui-expressions :after #'my/fix-dap-ui-expressions-buffer)
(advice-add 'dap-ui-sessions :after #'my/fix-dap-ui-sessions-buffer)
(advice-add 'dap-ui-breakpoints :after #'my/fix-dap-ui-breakpoints-buffer))
```
##### Helper functions {#helper-functions}
Some helper functions that make debugging with DAP easier.
DAP seems to mess with window parameters from time to time. This function clears "bad" window parameters.
```emacs-lisp
(defun my/clear-bad-window-parameters ()
"Clear window parameters that interrupt my workflow."
(interactive)
(let ((window (get-buffer-window (current-buffer))))
(set-window-parameter window 'no-delete-other-windows nil)))
```
A function to kill a value from a treemacs node.
```emacs-lisp
(defun my/dap-yank-value-at-point (node)
(interactive (list (treemacs-node-at-point)))
(kill-new (message (plist-get (button-get node :item) :value))))
```
A function to open a value from a treemacs node in a new buffer.
```emacs-lisp
(defun my/dap-display-value (node)
(interactive (list (treemacs-node-at-point)))
(let ((value (plist-get (button-get node :item) :value)))
(when value
(let ((buffer (generate-new-buffer "dap-value")))
(with-current-buffer buffer
(insert value))
(select-window (display-buffer buffer))))))
```
##### Improved stack frame switching {#improved-stack-frame-switching}
One significant improvement over Chrome Inspector for my particular stack is an ability to filter the stack frame list, for instance to see only frames that relate to my current project.
So, here are functions that customize the filters:
```emacs-lisp
(with-eval-after-load 'dap-mode
(setq my/dap-stack-frame-filters
`(("node_modules,node:internal" . ,(rx (or "node_modules" "node:internal")))
("node_modules" . ,(rx (or "node_modules")))
("node:internal" . ,(rx (or "node:internal")))))
(setq my/dap-stack-frame-current-filter (cdar my/dap-stack-frame-filters))
(defun my/dap-stack-frame-filter-set ()
(interactive)
(setq my/dap-stack-frame-current-filter
(cdr
(assoc
(completing-read "Filter: " my/dap-stack-frame-filters)
my/dap-stack-frame-filters))))
(defun my/dap-stack-frame-filter (frame)
(when-let (path (dap--get-path-for-frame frame))
(not (string-match my/dap-stack-frame-current-filter path)))))
```
And here is a version of `dap-switch-stack-frame` that uses the said filter.
```emacs-lisp
(defun my/dap-switch-stack-frame ()
"Switch stackframe by selecting another stackframe stackframes from current thread."
(interactive)
(when (not (dap--cur-session))
(error "There is no active session"))
(-if-let (thread-id (dap--debug-session-thread-id (dap--cur-session)))
(-if-let (stack-frames
(gethash
thread-id
(dap--debug-session-thread-stack-frames (dap--cur-session))))
(let* ((index 0)
(stack-framces-filtered
(-filter
#'my/dap-stack-frame-filter
stack-frames))
(new-stack-frame
(dap--completing-read
"Select active frame: "
stack-framces-filtered
(-lambda ((frame &as &hash "name"))
(if-let (frame-path (dap--get-path-for-frame frame))
(format "%s: %s (in %s)"
(cl-incf index) name frame-path)
(format "%s: %s" (cl-incf index) name)))
nil
t)))
(dap--go-to-stack-frame (dap--cur-session) new-stack-frame))
(->> (dap--cur-session)
dap--debug-session-name
(format "Current session %s is not stopped")
error))
(error "No thread is currently active %s" (dap--debug-session-name (dap--cur-session)))))
```
##### Debug templates {#debug-templates}
Some debug templates I frequently use.
```emacs-lisp
(with-eval-after-load 'dap-mode
(dap-register-debug-template
"Node::Nest.js"
(list :type "node"
:request "attach"
:name "Node::Attach"
:port 9229
:outFiles ["${workspaceFolder}/dist/**/*.js"]
:sourceMaps t
:program "${workspaceFolder}/src/app.ts"))
(dap-register-debug-template
"Node::Babel"
(list :type "node"
:request "attach"
:name "Node::Attach"
:port 9229
:program "${workspaceFolder}/dist/bin/www.js")))
```
#### <span class="org-todo done OFF">OFF</span> (OFF) TabNine {#off--tabnine}
@ -6078,6 +6254,25 @@ Setting up custom faces for certain tags to make the feed look a bit nicer.
(unread elfeed-search-unread-title-face))))
```
Also a function to automatically adjust these colors with the Doom theme.
```emacs-lisp
(defun my/update-my-theme-elfeed (&rest _)
(custom-theme-set-faces
'my-theme
`(elfeed-videos-entry ((t :foreground ,(doom-color 'red))))
`(elfeed-twitter-entry ((t :foreground ,(doom-color 'blue))))
`(elfeed-emacs-entry ((t :foreground ,(doom-color 'magenta))))
`(elfeed-music-entry ((t :foreground ,(doom-color 'green))))
`(elfeed-podcasts-entry ((t :foreground ,(doom-color 'yellow))))
`(elfeed-blogs-entry ((t :foreground ,(doom-color 'orange)))))
(enable-theme 'my-theme))
(advice-add 'load-theme :after #'my/update-my-theme-elfeed)
(when (fboundp 'doom-color)
(my/update-my-theme-elfeed))
```
##### elfeed-score {#elfeed-score}
@ -6263,7 +6458,7 @@ script-opts=ytdl_hook-ytdl_path=yt-dlp
It seems a bit strange to keep the MPV config in this file, but I don't use the program outside Emacs.
```emacs-lisp
(add-to-list 'emms-player-list 'emms-player-mpv t)
(add-to-list 'emms-player-list 'emms-player-mpv)
```
Also a custom regex. My demands for MPV include running `yt-dlp`, so there is a regex that matches youtube.com or some of the video formats.
@ -6753,7 +6948,7 @@ The actual service definitions are in the `~/.emacs.d/prodigy.org`, which tangle
:straight t
:commands (prodigy)
:init
(my-leader-def "ap" 'prodigy)
(my-leader-def "aP" 'prodigy)
:config
(when (not (boundp 'my/docker-directories))
(load (concat user-emacs-directory "prodigy-config")))
@ -6811,7 +7006,7 @@ Tecosaur's plugin to make beautiful code screenshots.
```emacs-lisp
(use-package screenshot
:straight (:repo "tecosaur/screenshot" :host github :files ("screenshot.el"))
:straight (:repo "tecosaur/screenshot" :host github :files ("screenshot.el") :commit "f8204e82dc0c1158c401735d36a143e6f6d24cf5")
:if (display-graphic-p)
:commands (screenshot)
:init
@ -6849,13 +7044,33 @@ An Emacs package to help managing GNU Guix.
### Productivity {#productivity}
#### Pomidor {#pomidor}
#### pomm {#pomm}
My package for doing Pomodoro timer.
```emacs-lisp
(use-package pomm
:straight (:host github :repo "SqrtMinusOne/pomm.el" :files (:defaults "resources"))
;; :straight (:local-repo "~/Code/Emacs/pomm" :files (:defaults "resources"))
:init
(my-leader-def "ap" #'pomm)
:config
(setq alert-default-style 'libnotify)
(add-hook 'pomm-on-tick-hook 'pomm-update-mode-line-string)
(add-hook 'pomm-on-status-changed-hook 'pomm-update-mode-line-string))
```
#### <span class="org-todo done OFF">OFF</span> (OFF) Pomidor {#off--pomidor}
A simple pomodoro technique timer.
Disabled it in favour of my own package.
```emacs-lisp
(use-package pomidor
:straight t
:disabled
:commands (pomidor)
:init
(my-leader-def "aP" #'pomidor)
@ -6889,37 +7104,6 @@ Emacs' built-in calendar. Can even calculate sunrise and sunset times.
```
### <span class="org-todo done OFF">OFF</span> (OFF) EAF {#off--eaf}
[Emacs Application Framework](https://github.com/manateelazycat/emacs-application-framework) provides a way to integrate PyQt applications with Emacs.
I've made it work, but don't find any uses cases for me at the moment
#### Installation {#installation}
Requirements: Node >= 14
```bash
pip install qtconsole markdown qrcode[pil] PyQt5 PyQtWebEngine
```
#### Config {#config}
```emacs-lisp
(use-package eaf
:straight (:host github :repo "manateelazycat/emacs-application-framework" :files ("*"))
:init
(use-package epc :defer t :straight t)
(use-package ctable :defer t :straight t)
(use-package deferred :defer t :straight t)
:config
(require 'eaf-evil)
(setq eaf-evil-leader-key "SPC"))
```
### Fun {#fun}
@ -6929,6 +7113,28 @@ Integration with Discord. Shows which file is being edited in Emacs.
In order for this to work in Guix, a service is necessary - [Discord rich presence]({{< relref "Desktop" >}}).
Some functions to override the displayed message:
```emacs-lisp
(defun my/elcord-mask-buffer-name (name)
(cond
((string-match-p (rx bos (? "CAPTURE-") (= 14 num) "-" (* not-newline) ".org" eos) name)
"<ORG-ROAM>")
((string-match-p (rx bos (+ num) "-" (+ num) "-" (+ num) ".org" eos) name)
"<ORG-JOURNAL>")
((string-match-p (rx bos "EXWM") name)
"<EXWM>")
(t name)))
(defun my/elcord-buffer-details-format-functions ()
(format "Editing %s" (my/elcord-mask-buffer-name (buffer-name))))
(defun my/elcord-update-presence-mask-advice (r)
(list (my/elcord-mask-buffer-name (nth 0 r)) (nth 1 r)))
```
And the package configuration:
```emacs-lisp
(use-package elcord
:straight t
@ -6938,11 +7144,9 @@ In order for this to work in Guix, a service is necessary - [Discord rich presen
(not my/slow-ssh)
(not my/remote-server))
:config
(elcord-mode)
(add-to-list 'elcord-boring-buffers-regexp-list
(rx bos (+ num) "-" (+ num) "-" (+ num) ".org" eos))
(add-to-list 'elcord-boring-buffers-regexp-list
(rx bos (= 14 num) "-" (* not-newline) ".org" eos)))
(setq elcord-buffer-details-format-function #'my/elcord-buffer-details-format-functions)
(advice-add 'elcord--try-update-presence :filter-args #'my/elcord-update-presence-mask-advice)
(elcord-mode))
```

View file

@ -19,7 +19,7 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [Measure startup speed](#measure-startup-speed)
- [straight.el](#straight-dot-el)
- [use-package](#use-package)
- [config variants & environment](#config-variants-and-environment)
- [Config variants & environment](#config-variants-and-environment)
- [Performance](#performance)
- [Garbage collection](#garbage-collection)
- [Run garbage collection when Emacs is unfocused](#run-garbage-collection-when-emacs-is-unfocused)
@ -124,10 +124,12 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [Managing Jupyter kernels](#managing-jupyter-kernels)
- [Do not wrap the output in emacs-jupyter](#do-not-wrap-the-output-in-emacs-jupyter)
- [Wrap source code output](#wrap-source-code-output)
- [Managing a literate programming project](#managing-a-literate-programming-project)
- [Productivity & Knowledge management](#productivity-and-knowledge-management)
- [Capture templates & various settings](#capture-templates-and-various-settings)
- [Custom agendas](#custom-agendas)
- [Trello sync](#trello-sync)
- [org-ql](#org-ql)
- [Custom agendas](#custom-agendas)
- [Review workflow](#review-workflow)
- [Data from git & org-roam](#data-from-git-and-org-roam)
- [Data from org-journal](#data-from-org-journal)
@ -139,6 +141,7 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [org-roam-protocol](#org-roam-protocol)
- [org-ref](#org-ref)
- [org-roam-bibtex](#org-roam-bibtex)
- [Managing tables](#managing-tables)
- [UI](#ui)
- [<span class="org-todo done OFF">OFF</span> (OFF) Instant equations preview](#off--instant-equations-preview)
- [LaTeX fragments](#latex-fragments)
@ -152,6 +155,7 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [LaTeX](#latex)
- [Keybindings & stuff](#keybindings-and-stuff)
- [Copy a link](#copy-a-link)
- [Open a file from `org-directory`](#open-a-file-from-org-directory)
- [Presentations](#presentations)
- [Tools](#tools)
- [TOC](#toc)
@ -160,9 +164,6 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [Tables for Guix Dependencies](#tables-for-guix-dependencies)
- [Noweb evaluations](#noweb-evaluations)
- [yadm hook](#yadm-hook)
- [<span class="org-todo done OFF">OFF</span> (OFF) EAF](#off--eaf)
- [Installation](#installation)
- [Config](#config)
- [Programming](#programming)
- [General setup](#general-setup)
- [LSP](#lsp)
@ -240,6 +241,7 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [CSV](#csv)
- [<span class="org-todo done OFF">OFF</span> (OFF) PDF](#off--pdf)
- [Docker](#docker)
- [crontab](#crontab)
- [Apps & Misc](#apps-and-misc)
- [Managing dotfiles](#managing-dotfiles)
- [Open Emacs config](#open-emacs-config)
@ -249,6 +251,8 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [Notmuch](#notmuch)
- [Elfeed](#elfeed)
- [Some additions](#some-additions)
- [Custom faces](#custom-faces)
- [elfeed-score](#elfeed-score)
- [YouTube & EMMS](#youtube-and-emms)
- [EMMS](#emms)
- [MPD](#mpd)
@ -275,6 +279,9 @@ As with other files in the repo, parts prefixed with (OFF) are not used but kept
- [Productivity](#productivity)
- [Pomidor](#pomidor)
- [Calendar](#calendar)
- [<span class="org-todo done OFF">OFF</span> (OFF) EAF](#off--eaf)
- [Installation](#installation)
- [Config](#config)
- [Fun](#fun)
- [Discord integration](#discord-integration)
- [Snow](#snow)
@ -300,7 +307,11 @@ A small function to print out the loading time and number of GCs during the load
(float-time
(time-subtract after-init-time before-init-time)))
gcs-done)))
```
Set the following to `t` to print debug information during the startup. This will include the order in which the packages are loaded and the loading time of individual packages.
```emacs-lisp
;; (setq use-package-verbose t)
```
@ -348,11 +359,12 @@ References:
```emacs-lisp
(straight-use-package 'use-package)
(eval-when-compile (require 'use-package))
;; (setq use-package-verbose t)
```
### config variants & environment {#config-variants-and-environment}
### Config variants & environment {#config-variants-and-environment}
This section is about optionating the Emacs config.
The following variable is true when my machine is not powerful enough for some resource-heavy packages.
@ -360,7 +372,7 @@ The following variable is true when my machine is not powerful enough for some r
(setq my/lowpower (string= (system-name) "azure"))
```
The following is true if Emacs is meant to be used with TRAMP over slow ssh.
The following is true if Emacs is meant to be used with TRAMP over slow ssh. Take a look at the [TRAMP](#tramp) section for more details.
```emacs-lisp
(setq my/slow-ssh
@ -435,7 +447,7 @@ Some time has passed, and I still don't know if there is any quantifiable advant
#### Native compilation {#native-compilation}
Set number of jobs to 1 on low-power machines
Set the number of native compilation jobs to 1 on low-power machines.
```emacs-lisp
(when my/lowpower
@ -445,11 +457,11 @@ Set number of jobs to 1 on low-power machines
### Anaconda {#anaconda}
[Anaconda](https://www.anaconda.com/) is a free package and environment manager. I currently use it to manage multiple versions of Python and Node.js
[Anaconda](https://www.anaconda.com/) is a free package and environment manager. I currently use it to manage multiple versions of Python and Node.js. Take a look at [the corresponding entry]({{< relref "Guix" >}}) in the Guix config for details about using it on Guix.
The following code uses the conda package to activate the base environment on startup if Emacs is launched outside the environment.
Also, some strange things are happening if vterm is launched with conda activated from Emacs, so I advise `conda-env-activate` to set an auxililary environment variable.
Also, some strange things are happening if vterm is launched with conda activated from Emacs, so I advise `conda-env-activate` to set an auxililary environment variable. This variable is used in the [shell config]({{< relref "Console" >}}).
References:
@ -476,7 +488,7 @@ References:
### Custom file location {#custom-file-location}
By default, custom writes stuff to `init.el`, which is somewhat annoying. The following makes a separate file `custom.el`
By default, custom writes stuff to `init.el`, which is somewhat annoying. The following makes it write to a separate file `custom.el`
```emacs-lisp
(setq custom-file (concat user-emacs-directory "custom.el"))
@ -497,7 +509,7 @@ I have some variables which I don't commit to the repo, e.g. my current location
### No littering {#no-littering}
By default emacs and its packages create a lot files in `.emacs.d` and in other places. [no-littering](https://github.com/emacscollective/no-littering) is a collective effort to redirect all of this to two folders in `user-emacs-directory`.
By default Mmacs and its packages create a lot files in `.emacs.d` and in other places. [no-littering](https://github.com/emacscollective/no-littering) is a collective effort to redirect all of that to two folders in `user-emacs-directory`.
```emacs-lisp
(use-package no-littering
@ -540,9 +552,7 @@ References:
#### which-key {#which-key}
A package that displays the available keybindings in a popup.
Pretty useful, as Emacs seems to have more keybindings than I can remember at any given point.
A package that displays the available keybindings in a popup. The package is pretty useful, as Emacs seems to have more keybindings than I can remember at any given point.
References:
@ -594,7 +604,7 @@ A function to dump keybindings starting with a prefix to a buffer in tree-like f
### Evil mode {#evil-mode}
A whole ecosystem of packages that emulates the main features of Vim. Probably the best vim emulator out there.
An entire ecosystem of packages that emulates the main features of Vim. Probably the best vim emulator out there.
The only problem is that the package name makes it hard to google anything by just typing "evil".
@ -615,15 +625,13 @@ Basic evil configuration.
(setq evil-want-integration t)
(setq evil-want-C-u-scroll t)
(setq evil-want-keybinding nil)
:config
(evil-mode 1)
(setq evil-search-module 'evil-search)
(setq evil-split-window-below t)
(setq evil-vsplit-window-right t)
:config
(evil-mode 1)
;; (setq evil-respect-visual-line-mode t)
(evil-set-undo-system 'undo-tree)
;; (add-to-list 'evil-emacs-state-modes 'dired-mode)
)
(evil-set-undo-system 'undo-tree))
```
@ -639,7 +647,7 @@ Basic evil configuration.
(global-evil-surround-mode 1))
```
[evil-commentary](https://github.com/linktohack/evil-commentary) emulates commentary.vim.
[evil-commentary](https://github.com/linktohack/evil-commentary) emulates commentary.vim. It gives actions for quick insertion and deletion of comments.
```emacs-lisp
(use-package evil-commentary
@ -684,7 +692,7 @@ Basic evil configuration.
(evil-lion-mode))
```
[evil-matchit](https://github.com/redguardtoo/evil-matchit) makes "%" to match things like tags.
[evil-matchit](https://github.com/redguardtoo/evil-matchit) makes "%" to match things like tags. It doesn't work perfectly, so I occasionally turn it off.
```emacs-lisp
(use-package evil-matchit
@ -696,9 +704,7 @@ Basic evil configuration.
#### evil-collection {#evil-collection}
[evil-collection](https://github.com/emacs-evil/evil-collection) is a package that provides evil bindings for a lot of different packages. One can see the whole list in the [modes](https://github.com/emacs-evil/evil-collection/tree/master/modes) folder.
I don't enable the entire package, just the modes I need.
[evil-collection](https://github.com/emacs-evil/evil-collection) is a package that provides evil bindings for a lot of different packages. One can see the complete list in the [modes](https://github.com/emacs-evil/evil-collection/tree/master/modes) folder.
```emacs-lisp
(use-package evil-collection
@ -805,7 +811,7 @@ Using the `SPC` key as a leader key, like in Doom Emacs or Spacemacs.
(my-leader-def "E" 'eval-expression)
```
`general.el` has a nice integration with which-key, so I use this fact to show more descriptive annotations for certain groups of keybindings (the default one is `prefix`).
`general.el` has a nice integration with which-key, so I use that to show more descriptive annotations for certain groups of keybindings (the default annotation is just `prefix`).
```emacs-lisp
(my-leader-def
@ -844,7 +850,7 @@ The built-in profiler is a magnificent tool to troubleshoot performance issues.
#### Buffer switching {#buffer-switching}
Some keybindings I used in vim to switch buffers and can't let go of.
Some keybindings I used in vim to switch buffers and can't let go of. But I think I started to use these less since I made an attempt in [i3 integration](#i3-integration).
```emacs-lisp
(general-define-key
@ -866,7 +872,9 @@ Some keybindings I used in vim to switch buffers and can't let go of.
"d" 'kill-current-buffer)
```
And winner-mode to keep the history of window states.
`winner-mode` to keep the history of window states.
It doesn't play too well with perspective.el, that is it has a single history list for all of the perspectives. But it is still quite usable.
```emacs-lisp
(winner-mode 1)
@ -918,7 +926,7 @@ There are multiple ways to fold text in Emacs.
The most versatile is the built-in `hs-minor-mode`, which seems to work out of the box for Lisps, C-like languages and Python. `outline-minor-mode` works for org-mode, LaTeX and the like. There is a 3rd-party solution [origami.el](https://github.com/elp-revive/origami.el), but I don't use it at the moment.
Evil does a pretty good job of uniting these two in the set of vim-like keybindings. I was using `SPC` in vim, but as now this isn't an option, I set `TAB` to toggle folding.
Evil does a pretty good job of abstracting the first two with a set of vim-like keybindings. I was using `SPC` in vim, but as now this isn't an option, I set `TAB` to toggle folding.
```emacs-lisp
(general-nmap :keymaps '(hs-minor-mode-map outline-minor-mode-map)
@ -1139,7 +1147,7 @@ References:
A package to keep the code intended.
Doesn't work too well with js ecosystem, because the LSP-based indentation is rather slow but nice for Lisps.
Doesn't work too well with many ecosystems because the LSP-based indentation is rather slow, but nice for Lisps.
References:
@ -2156,6 +2164,7 @@ References:
(use-package emojify
:straight t
:if (and (display-graphic-p) (not (or my/lowpower my/is-termux)))
:disabled
:hook (after-init . global-emojify-mode))
```
@ -2313,7 +2322,7 @@ My config mostly follows ranger's and vifm's keybindings which I'm used to.
### Addons {#addons}
I used to use [dired+](https://www.emacswiki.org/emacs/DiredPlus), which provides a lot of extensions for dired functionality, but it also creates some new problems, so I opt out of it. Fortunately, the one feature I want from this package - adding more colors to dired buffers - is available as a separate package
I used to use [dired+](https://www.emacswiki.org/emacs/DiredPlus), which provides a lot of extensions for dired functionality, but it also creates some new problems, so I opt out of it. Fortunately, the one feature I want from this package - adding more colors to dired buffers - is available as a separate package.
```emacs-lisp
(use-package diredfl
@ -2475,7 +2484,7 @@ Also, here is a hack to make TRAMP find `ls` on Guix:
A simple bookmark list for Dired, mainly to use with TRAMP. I may look into a proper bookmarking system later.
Bookmarks are listed in the [dired-bookmarks.el](.emacs.d/dired-bookmarks.el) file, which looks like this:
Bookmarks are listed in the [private.el](.emacs.d/private.el) file, which has an expression like this:
```text
(setq my/dired-bookmarks
@ -2487,8 +2496,6 @@ The file itself is encrypted with yadm.
```emacs-lisp
(defun my/dired-bookmark-open ()
(interactive)
(unless (boundp 'my/dired-bookmarks)
(load (concat user-emacs-directory "dired-bookmarks")))
(let ((bookmarks
(mapcar
(lambda (el) (cons (format "%-30s %s" (car el) (cdr el)) (cdr el)))
@ -2739,6 +2746,8 @@ Use the built-in org mode.
:straight t
:if (not my/remote-server)
:defer t
:init
(setq org-directory (expand-file-name "~/Documents/org-mode"))
:config
(setq org-startup-indented t)
(setq org-return-follows-link t)
@ -3098,6 +3107,32 @@ Example usage:
```
#### Managing a literate programming project {#managing-a-literate-programming-project}
A few tricks to do literate programming.
I prefer to put the org files to a separate directory (e.g. `org`). So I've come up with the following solution to avoid manually prefixing the `:tangle` arguments.
Set up the following argument with the path to the project root:
```text
#+PROPERTY: PRJ-DIR ..
```
A function to do the prefixing:
```emacs-lisp
(defun my/org-prj-dir (path)
(expand-file-name path (org-entry-get nil "PRJ-DIR" t)))
```
Example usage is as follows:
```text
:tangle (my/org-prj-dir "sqrt_data/api/__init__.py")
```
### Productivity & Knowledge management {#productivity-and-knowledge-management}
My ongoing effort to get a productivity setup in Org.
@ -3112,7 +3147,6 @@ Some inspiration:
Used files
```emacs-lisp
(setq org-directory (expand-file-name "~/Documents/org-mode"))
(setq org-agenda-files '("inbox.org" "projects.org" "work.org" "sem-11.org" "life.org"))
;; (setq org-default-notes-file (concat org-directory "/notes.org"))
```
@ -3174,8 +3208,64 @@ Log DONE time
```
#### Trello sync {#trello-sync}
Some of the projects I'm participating in are managed via Trello, so I use [org-trello](http://org-trello.github.io/) to keep track of them. The package has a remarkably awkward keybindings setup, so my effort to call `my-leader-def` to set keybindings I like is no less awkward.
Also, trello files are huge and have a lot of information and tasks which do not concern me, so I don't add them to `org-agenda-files`.
```emacs-lisp
(setq org-trello-files
(thread-last (concat org-directory "/trello")
(directory-files)
(seq-filter
(lambda (f) (string-match-p (rx ".org" eos) f)))
(mapcar
(lambda (f) (concat org-directory "/trello/" f)))))
```
```emacs-lisp
(use-package org-trello
:straight (:build (:not native-compile))
:commands (org-trello-mode)
:init
(setq org-trello-current-prefix-keybinding "C-c o")
(setq org-trello-add-tags nil)
(add-hook 'org-mode-hook
(lambda ()
(when (string-match-p (rx "trello") (or (buffer-file-name) ""))
(org-trello-mode))))
:config
(eval
`(my-leader-def
:infix "o t"
:keymaps '(org-trello-mode-map)
"" '(:which-key "trello")
,@(mapcan
(lambda (b) (list (nth 1 b) (macroexp-quote (nth 0 b))))
org-trello-interactive-command-binding-couples))))
```
#### org-ql {#org-ql}
[org-ql](https://github.com/alphapapa/org-ql) is a package to query the org files. I'm using it in my review workflow and for custom agenda views.
```emacs-lisp
(use-package org-ql
:straight (:fetcher github
:repo "alphapapa/org-ql"
:files (:defaults (:exclude "helm-org-ql.el"))))
```
#### Custom agendas {#custom-agendas}
Some custom agendas to fit my workflow.
Despite the fact that I don't add `org-trello-files` to `org-agenda-files` I still want to see them in agenda, so I use `org-ql-block` from `org-ql`.
```emacs-lisp
(defun my/org-scheduled-get-time ()
(let ((scheduled (org-get-scheduled-time (point))))
@ -3189,6 +3279,13 @@ Log DONE time
(todo "NEXT"
((org-agenda-prefix-format " %i %-12:c [%e] ")
(org-agenda-overriding-header "Next tasks")))
(org-ql-block
`(and
(regexp ,(rx ":orgtrello_users:" (* nonl) "sqrtminusone"))
(todo)
(deadline))
((org-agenda-files ',org-trello-files)
(org-ql-block-header "Trello assigned")))
(tags-todo "inbox"
((org-agenda-overriding-header "Inbox")
(org-agenda-prefix-format " %i %-12:c")
@ -3203,18 +3300,6 @@ Log DONE time
```
#### org-ql {#org-ql}
[org-ql](https://github.com/alphapapa/org-ql) is a package to query the org files. I'm using it in my review workflow, perhaps later I'll find another usecases.
```emacs-lisp
(use-package org-ql
:straight (:fetcher github
:repo "alphapapa/org-ql"
:files (:defaults (:exclude "helm-org-ql.el"))))
```
#### Review workflow {#review-workflow}
My take on a review workflow. As a baseline, I want to have a template that lists the important changes since the last review and other basic information. I'm doing reviews regularly, but the time intervals still may vary, hence this flexibility.
@ -3665,6 +3750,27 @@ There are some problems with org roam v2, so I disabled it as of now. I will pro
```
#### Managing tables {#managing-tables}
I use Org to manage some small tables which I want to process further. So here is a function that saves each table to a CSV file.
```emacs-lisp
(defun my/export-org-tables-to-csv ()
(interactive)
(org-table-map-tables
(lambda ()
(when-let
(name
(plist-get (cadr (org-element-at-point)) :name))
(org-table-export
(concat
(file-name-directory
(buffer-file-name))
name ".csv")
"orgtbl-to-csv")))))
```
### UI {#ui}
@ -3746,12 +3852,36 @@ Also, LaTeX fragments preview tends to break whenever the are custom `#+LATEX_HE
#### Better headers {#better-headers}
[org-superstar-mode](https://github.com/integral-dw/org-superstar-mode) is package that makes Org heading lines look a bit prettier.
Disabled it for now because of overlapping functionality with org-bars.
```emacs-lisp
(use-package org-superstar
:straight t
:disabled
:hook (org-mode . org-superstar-mode))
```
[org-bars](https://github.com/tonyaldon/org-bars) highlights Org indentation with bars.
```emacs-lisp
(use-package org-bars
:straight (:repo "tonyaldon/org-bars" :host github)
:if (display-graphic-p)
:hook (org-mode . org-bars-mode))
```
Remove the elipsis at the end of folded headlines. The elipsis seems unnecesary with org-bars.
```emacs-lisp
(defun my/org-no-ellipsis-in-headlines ()
(remove-from-invisibility-spec '(outline . t))
(add-to-invisibility-spec 'outline))
(add-hook 'org-mode-hook #'my/org-no-ellipsis-in-headlines)
```
#### Org Agenda Icons {#org-agenda-icons}
@ -3911,6 +4041,29 @@ Add a custom LaTeX template without default packages. Packages are indented to b
```
#### Open a file from `org-directory` {#open-a-file-from-org-directory}
A function to open a file from `org-directory`, excluding a few directories like `roam` and `journal`.
```emacs-lisp
(defun my/org-file-open ()
(interactive)
(let* ((default-directory org-directory)
(project-files
(seq-filter
(lambda (f)
(and
(string-match-p (rx (* nonl) ".org" eos) f)
(not (string-match-p (rx (| "journal" "roam" "review" "archive")) f))))
(projectile-current-project-files))))
(find-file
(concat org-directory "/" (completing-read "Org file: " project-files)))))
(my-leader-def
"o o" 'my/org-file-open)
```
### Presentations {#presentations}
Doing presentations with [org-present](https://github.com/rlister/org-present).
@ -4146,37 +4299,6 @@ emacs -Q --batch -l run-tangle.el
I have added this line to yadm's `post_alt` hook, so tangle is run after `yadm alt`
## <span class="org-todo done OFF">OFF</span> (OFF) EAF {#off--eaf}
[Emacs Application Framework](https://github.com/manateelazycat/emacs-application-framework) provides a way to integrate PyQt applications with Emacs.
I've made it work, but don't find any uses cases for me at the moment
### Installation {#installation}
Requirements: Node >= 14
```bash
pip install qtconsole markdown qrcode[pil] PyQt5 PyQtWebEngine
```
### Config {#config}
```emacs-lisp
(use-package eaf
:straight (:host github :repo "manateelazycat/emacs-application-framework" :files ("*"))
:init
(use-package epc :defer t :straight t)
(use-package ctable :defer t :straight t)
(use-package deferred :defer t :straight t)
:config
(require 'eaf-evil)
(setq eaf-evil-leader-key "SPC"))
```
## Programming {#programming}
@ -5671,7 +5793,7 @@ So far I didn't find a nice SQL client for Emacs, but I occasionally run SQL que
(reformatter-define sqlformat
:program (executable-find "sql-formatter")
:args `("-l" ,my/sqlformatter-dialect))
:args `("-l" ,my/sqlformatter-dialect, "-u"))
(my-leader-def
:keymaps '(sql-mode-map)
@ -5738,6 +5860,14 @@ References:
```
### crontab {#crontab}
```emacs-lisp
(use-package crontab-mode
:straight t)
```
## Apps & Misc {#apps-and-misc}
@ -5871,7 +6001,7 @@ Using my own fork until the modifications are merged into master.
:straight t
:after (elfeed)
:config
(setq rmh-elfeed-org-files '("~/.emacs.d/elfeed.org"))
(setq rmh-elfeed-org-files '("~/.emacs.d/private.org"))
(elfeed-org))
```
@ -5908,6 +6038,79 @@ Open a URL with eww.
```
##### Custom faces {#custom-faces}
Setting up custom faces for certain tags to make the feed look a bit nicer.
```emacs-lisp
(defface elfeed-videos-entry
`((t :foreground ,(doom-color 'red)))
"Face for the elfeed entries with tag \"videos\"")
(defface elfeed-twitter-entry
`((t :foreground ,(doom-color 'blue)))
"Face for the elfeed entries with tah \"twitter\"")
(defface elfeed-emacs-entry
`((t :foreground ,(doom-color 'magenta)))
"Face for the elfeed entries with tah \"emacs\"")
(defface elfeed-music-entry
`((t :foreground ,(doom-color 'green)))
"Face for the elfeed entries with tah \"music\"")
(defface elfeed-podcasts-entry
`((t :foreground ,(doom-color 'yellow)))
"Face for the elfeed entries with tag \"podcasts\"")
(defface elfeed-blogs-entry
`((t :foreground ,(doom-color 'orange)))
"Face for the elfeed entries with tag \"blogs\"")
(with-eval-after-load 'elfeed
(setq elfeed-search-face-alist
'((twitter elfeed-twitter-entry)
(podcasts elfeed-podcasts-entry)
(music elfeed-music-entry)
(videos elfeed-videos-entry)
(emacs elfeed-emacs-entry)
(blogs elfeed-blogs-entry)
(unread elfeed-search-unread-title-face))))
```
##### elfeed-score {#elfeed-score}
[elfeed-score](https://github.com/sp1ff/elfeed-score) is a package that implements scoring for the elfeed entries. Entries are scored by a set of rules for tags/title/content/etc and sorted by that score.
```emacs-lisp
(defun my/elfeed-toggle-score-sort ()
(interactive)
(setq elfeed-search-sort-function
(if elfeed-search-sort-function
nil
#'elfeed-score-sort))
(message "Sorting by score: %S" (if elfeed-search-sort-function "ON" "OFF"))
(elfeed-search-update--force))
(use-package elfeed-score
:straight t
:after (elfeed)
:init
(setq elfeed-score-serde-score-file "~/.emacs.d/elfeed.score")
:config
(elfeed-score-enable)
(setq elfeed-search-print-entry-function #'elfeed-score-print-entry)
(general-define-key
:states '(normal)
:keymaps '(elfeed-search-mode-map)
"=" elfeed-score-map)
(general-define-key
:keymaps '(elfeed-score-map)
"=" #'my/elfeed-toggle-score-sort))
```
##### YouTube & EMMS {#youtube-and-emms}
Previously this block was opening MPV with `start-process`, but now I've managed to hook up MPV with EMMS. So there is the EMMS+elfeed "integration".
@ -6047,15 +6250,23 @@ After all this is done, run `M-x emms-cache-set-from-mpd-all` to set cache from
| Guix dependency |
|-----------------|
| mpv |
| youtube-dl |
| yt-dlp |
[mpv](https://mpv.io/) is a decent media player, which has found a place in this configuration because it integrates with youtube-dl.
[mpv](https://mpv.io/) is a decent media player, which has found a place in this configuration because it integrates with ~~youtube-dl~~ yt-dlp.
It looks like YouTube has started to throttle youtube-dl, and yt-dlp has a workaround for that particular case. Just don't forget to add the following like to the mpv config:
```ini
script-opts=ytdl_hook-ytdl_path=yt-dlp
```
It seems a bit strange to keep the MPV config in this file, but I don't use the program outside Emacs.
```emacs-lisp
(add-to-list 'emms-player-list 'emms-player-mpv t)
```
Also a custom regex. My demands for MPV include running `youtube-dl`, so there is a regex that matches youtube.com or some of the video formats.
Also a custom regex. My demands for MPV include running `yt-dlp`, so there is a regex that matches youtube.com or some of the video formats.
```emacs-lisp
(emms-player-set emms-player-mpv
@ -6064,7 +6275,7 @@ Also a custom regex. My demands for MPV include running `youtube-dl`, so there i
(+ (? (or "https://" "http://"))
(* nonl)
(regexp (eval (emms-player-simple-regexp
"mp4" "mov" "wmv" "webm" "flv" "avi" "mkv")))))))
"mp4" "mov" "wmv" "webm" "flv" "avi" "mkv")))))))
```
By default MPV plays the video in the best possible quality, which may be pretty high, even too high with limited bandwidth. So here is the logic to choose the quality.
@ -6678,6 +6889,37 @@ Emacs' built-in calendar. Can even calculate sunrise and sunset times.
```
### <span class="org-todo done OFF">OFF</span> (OFF) EAF {#off--eaf}
[Emacs Application Framework](https://github.com/manateelazycat/emacs-application-framework) provides a way to integrate PyQt applications with Emacs.
I've made it work, but don't find any uses cases for me at the moment
#### Installation {#installation}
Requirements: Node >= 14
```bash
pip install qtconsole markdown qrcode[pil] PyQt5 PyQtWebEngine
```
#### Config {#config}
```emacs-lisp
(use-package eaf
:straight (:host github :repo "manateelazycat/emacs-application-framework" :files ("*"))
:init
(use-package epc :defer t :straight t)
(use-package ctable :defer t :straight t)
(use-package deferred :defer t :straight t)
:config
(require 'eaf-evil)
(setq eaf-evil-leader-key "SPC"))
```
### Fun {#fun}
@ -6732,6 +6974,17 @@ In order for this to work in Guix, a service is necessary - [Discord rich presen
(zone))))
```
Also, a function to copy a URL to the video under cursor.
```emacs-lisp
(defun my/ytel-kill-url ()
(interactive)
(kill-new
(concat
"https://www.youtube.com/watch?v="
(ytel-video-id (ytel-get-current-video)))))
```
## Guix settings {#guix-settings}

View file

@ -107,8 +107,7 @@ Uses yadm's `post_alt` hook to create symlinks
Mail/thexcloud/.credentials.gmailieer.json
Mail/progin6304/.credentials.gmailieer.json
.emacs.d/dired-bookmarks.el
.emacs.d/elfeed.org
.emacs.d/private.org
.emacs.d/prodigy-config.el
.emacs.d/private.el
.emacs.d/.trello/sqrtminusone.el
```

View file

@ -105,8 +105,8 @@ export QT_AUTO_SCREEN_SCALE_FACTOR<span style="color:#f92672">=</span><span styl
. /run/current-system/profile/etc/profile.d/nix.sh
<span style="color:#66d9ef">fi</span>
</code></pre></div><p>Use Guix fontconfig. Necessary for nix apps</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -d <span style="color:#e6db74">&#34;</span>$HOME<span style="color:#e6db74">/.guix-extra-profiles/desktop&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
export FONTCONFIG_PATH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$HOME<span style="color:#e6db74">/.guix-extra-profiles/desktop/desktop/etc/fonts&#34;</span>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -d <span style="color:#e6db74">&#34;</span>$HOME<span style="color:#e6db74">/.guix-extra-profiles/desktop-misc&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
export FONTCONFIG_PATH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$HOME<span style="color:#e6db74">/.guix-extra-profiles/desktop-misc/desktop-misc/etc/fonts&#34;</span>
<span style="color:#66d9ef">fi</span>
</code></pre></div><p>Make nix apps visible to launchers:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> -d <span style="color:#e6db74">&#34;</span>$HOME<span style="color:#e6db74">/.nix-profile&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>

View file

@ -78,6 +78,25 @@
<li><a href="#device-specific-settings">Device-specific settings</a></li>
</ul>
</li>
<li><a href="#exwm">EXWM</a>
<ul>
<li><a href="#xsession">Xsession</a></li>
<li><a href="#startup-apps">Startup apps</a></li>
<li><a href="#moving-windows">Moving windows</a></li>
<li><a href="#resizing-windows">Resizing windows</a></li>
<li><a href="#app-shortcuts">App shortcuts</a></li>
<li><a href="#move-workspace-to-another-monitor">Move workspace to another monitor</a></li>
<li><a href="#switch-to-the-opposite-monitor">Switch to the opposite monitor</a></li>
<li><a href="#switching-buffers">Switching buffers</a></li>
<li><a href="#add-all-exwm-buffers-to-current-perspective">Add all EXWM buffers to current perspective</a></li>
<li><a href="#revive-perspectives">Revive perspectives</a></li>
<li><a href="#locking-up">Locking up</a></li>
<li><a href="#keybindings">Keybindings</a></li>
<li><a href="#pinentry">Pinentry</a></li>
<li><a href="#modeline">Modeline</a></li>
<li><a href="#exwm-config">EXWM config</a></li>
</ul>
</li>
<li><a href="#i3wm">i3wm</a>
<ul>
<li><a href="#general-settings">General settings</a></li>
@ -125,6 +144,7 @@
<li><a href="#ipstack-vpn">ipstack-vpn</a></li>
<li><a href="#weather">weather</a></li>
<li><a href="#aw-afk">aw-afk</a></li>
<li><a href="#pomm">pomm</a></li>
<li><a href="#sun">sun</a></li>
<li><a href="#sep">SEP</a></li>
<li><a href="#tsep">TSEP</a></li>
@ -149,8 +169,8 @@
<ul>
<li><a href="#buku-bookmarks">Buku bookmarks</a></li>
<li><a href="#man-pages">Man pages</a></li>
<li><a href="#emojis">Emojis</a></li>
<li><a href="#pass">pass</a></li>
<li><a href="#emojis">emojis</a></li>
</ul>
</li>
</ul>
@ -190,6 +210,7 @@
<li><a href="#activitywatch">ActivityWatch</a></li>
<li><a href="#pulseeffects">PulseEffects</a></li>
<li><a href="#xsettingsd">xsettingsd</a></li>
<li><a href="#nm-applet">nm-applet</a></li>
<li><a href="#discord-rich-presence">Discord rich presence</a></li>
<li><a href="#polkit-authentication-agent">Polkit Authentication agent</a></li>
<li><a href="#xmodmap">Xmodmap</a></li>
@ -398,6 +419,425 @@
<span style="color:#66d9ef">elif</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$hostname<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;eminence&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
xgamma -gamma 1.25
<span style="color:#66d9ef">fi</span>
</code></pre></div><h2 id="exwm">EXWM</h2>
<p>Settings for <a href="https://github.com/ch11ng/exwm">Emacs X Window Manager</a>, a tiling WM implemented in Emacs Lisp.</p>
<p>References:</p>
<ul>
<li><a href="https://github.com/ch11ng/exwm/wiki">EXWM Wiki</a></li>
<li><a href="https://github.com/daviwil/emacs-from-scratch/blob/master/Desktop.org">Emacs From Scratch config</a></li>
</ul>
<h3 id="xsession">Xsession</h3>
<p>First things first, Emacs has to be launched as a window manager. On a more conventional system, I&rsquo;d create a .desktop file in some system folder that can be seen by a login manager, but in the case of Guix, it&rsquo;s a bit more complicated, because all such folders are not meant to be changed manually.</p>
<p>However, GDM, the login manager that seems to default on Guix, launches <code>~/.xsession</code> on the startup if it&rsquo;s present, which is just fine for my purposes.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#75715e"># Source .profile</span>
. ~/.profile
<span style="color:#75715e"># Disable access control for the current user</span>
xhost +SI:localuser:$USER
<span style="color:#75715e"># Fix for Java applications</span>
export _JAVA_AWT_WM_NONREPARENTING<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
<span style="color:#75715e"># Apply XResourses</span>
xrdb -merge ~/.Xresources
<span style="color:#75715e"># Turn off the system bell</span>
xset -b
<span style="color:#75715e"># Use i3lock as a screen locker</span>
xss-lock -- i3lock &amp;
<span style="color:#75715e"># Some apps that have to be launched only once.</span>
picom &amp;
<span style="color:#75715e"># nm-applet &amp;</span>
dunst &amp;
copyq &amp;
<span style="color:#75715e"># Run the Emacs startup script as a session.</span>
<span style="color:#75715e"># exec dbus-launch --exit-with-session ~/.emacs.d/run-exwm.sh</span>
exec dbus-launch --exit-with-session emacs -mm --debug-init -l ~/.emacs.d/desktop.el
</code></pre></div><h3 id="startup-apps">Startup apps</h3>
<p>Now that Emacs is launched, it is necessary to set up the EXWM-specific parts of config.</p>
<p>I want to launch some apps from EXWM instead of the Xsession file for two purposes:</p>
<ul>
<li>the app may need to have the entire desktop environment set up</li>
<li>or it may need to be restarted if Emacs is killed.</li>
</ul>
<p>As of now, these are polybar, feh and, shepherd:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/exwm-run-polybar ()
(<span style="color:#a6e22e">call-process</span> <span style="color:#e6db74">&#34;~/bin/polybar.sh&#34;</span>))
(defun my/exwm-set-wallpaper ()
(call-process-shell-command <span style="color:#e6db74">&#34;feh --bg-fill ~/Pictures/wallpaper.jpg&#34;</span>))
(defun my/exwm-run-shepherd ()
(when (string-empty-p (shell-command-to-string <span style="color:#e6db74">&#34;pgrep -u pavel shepherd&#34;</span>))
(<span style="color:#a6e22e">call-process</span> <span style="color:#e6db74">&#34;shepherd&#34;</span>)))
</code></pre></div><h3 id="moving-windows">Moving windows</h3>
<p>My functions for managing windows. I initially wrote these to mimic the i3 behavior for my Emacs + i3 integration, but I want to try to keep them for the EXWM config as well to make the transition less painful.</p>
<p>A predicate which checks whether there is space in the given direction:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/exwm-direction-exists-p (dir)
(cl-some (lambda (dir)
(let ((win (windmove-find-other-window dir)))
(and win (not (<span style="color:#a6e22e">window-minibuffer-p</span> win)))))
(pcase dir
(<span style="color:#e6db74">&#39;width</span> <span style="color:#f92672">&#39;</span>(left right))
(<span style="color:#e6db74">&#39;height</span> <span style="color:#f92672">&#39;</span>(up down)))))
</code></pre></div><p>And a function to move windows with the following behavior:</p>
<ul>
<li>if there is space in the required direction, move the Emacs window there;</li>
<li>if there is no space in the required direction, but space in two orthogonal directions, move the Emacs window so that there is no more space in the orthogonal directions;</li>
</ul>
<!--listend-->
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/exwm-move-window (dir)
(let ((other-window (windmove-find-other-window dir))
(other-direction (my/exwm-direction-exists-p
(pcase dir
(<span style="color:#e6db74">&#39;up</span> <span style="color:#e6db74">&#39;width</span>)
(<span style="color:#e6db74">&#39;down</span> <span style="color:#e6db74">&#39;width</span>)
(<span style="color:#e6db74">&#39;left</span> <span style="color:#e6db74">&#39;height</span>)
(<span style="color:#e6db74">&#39;right</span> <span style="color:#e6db74">&#39;height</span>)))))
(cond
((and other-window (not (<span style="color:#a6e22e">window-minibuffer-p</span> other-window)))
(window-swap-states (<span style="color:#a6e22e">selected-window</span>) other-window))
(other-direction
(evil-move-window dir)))))
</code></pre></div><h3 id="resizing-windows">Resizing windows</h3>
<p>Something like this also goes for resizing windows. I&rsquo;m used to the i3 &ldquo;mode&rdquo; for this functionality, and this seems to be a sensible approach.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package transient
:straight <span style="color:#66d9ef">t</span>)
(setq my/exwm-resize-value <span style="color:#ae81ff">5</span>)
(defun my/exwm-resize-window (dir kind <span style="color:#66d9ef">&amp;optional</span> value)
(unless value
(setq value my/exwm-resize-value))
(pcase kind
(<span style="color:#e6db74">&#39;shrink</span>
(pcase dir
(<span style="color:#e6db74">&#39;width</span>
(evil-window-decrease-width value))
(<span style="color:#e6db74">&#39;height</span>
(evil-window-decrease-height value))))
(<span style="color:#e6db74">&#39;grow</span>
(pcase dir
(<span style="color:#e6db74">&#39;width</span>
(evil-window-increase-width value))
(<span style="color:#e6db74">&#39;height</span>
(evil-window-increase-height value))))))
(defhydra my/exwm-resize-hydra (:color pink :hint <span style="color:#66d9ef">nil</span> :foreign-keys run)
<span style="color:#e6db74">&#34;
</span><span style="color:#e6db74">^Resize^
</span><span style="color:#e6db74">_l_: Increase width _h_: Decrease width _j_: Increase height _k_: Decrease height
</span><span style="color:#e6db74">
</span><span style="color:#e6db74">_=_: Balance &#34;</span>
(<span style="color:#e6db74">&#34;h&#34;</span> (lambda () (interactive) (my/exwm-resize-window <span style="color:#e6db74">&#39;width</span> <span style="color:#e6db74">&#39;shrink</span>)))
(<span style="color:#e6db74">&#34;j&#34;</span> (lambda () (interactive) (my/exwm-resize-window <span style="color:#e6db74">&#39;height</span> <span style="color:#e6db74">&#39;grow</span>)))
(<span style="color:#e6db74">&#34;k&#34;</span> (lambda () (interactive) (my/exwm-resize-window <span style="color:#e6db74">&#39;height</span> <span style="color:#e6db74">&#39;shrink</span>)))
(<span style="color:#e6db74">&#34;l&#34;</span> (lambda () (interactive) (my/exwm-resize-window <span style="color:#e6db74">&#39;width</span> <span style="color:#e6db74">&#39;grow</span>)))
(<span style="color:#e6db74">&#34;=&#34;</span> balance-windows)
(<span style="color:#e6db74">&#34;q&#34;</span> <span style="color:#66d9ef">nil</span> <span style="color:#e6db74">&#34;quit&#34;</span> :color blue))
</code></pre></div><h3 id="app-shortcuts">App shortcuts</h3>
<p>Also, a transient for shortcuts for the most frequent apps.</p>
<p>I wanted to make the interactive lambda a macro, but this doesn&rsquo;t seem to work the way I expect, so the code has a bit of duplication.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/run-in-background (command)
(let ((command-parts (split-string command <span style="color:#e6db74">&#34;[ ]+&#34;</span>)))
(<span style="color:#a6e22e">apply</span> <span style="color:#a6e22e">#&#39;call-process</span> <span style="color:#f92672">`</span>(<span style="color:#f92672">,</span>(<span style="color:#a6e22e">car</span> command-parts) <span style="color:#66d9ef">nil</span> <span style="color:#ae81ff">0</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">,@</span>(<span style="color:#a6e22e">cdr</span> command-parts)))))
(transient-define-prefix my/exwm-apps ()
[<span style="color:#e6db74">&#34;Apps&#34;</span>
(<span style="color:#e6db74">&#34;t&#34;</span> <span style="color:#e6db74">&#34;Termnial (Alacritty)&#34;</span> (lambda () (interactive) (my/run-in-background <span style="color:#e6db74">&#34;alacritty&#34;</span>)))
(<span style="color:#e6db74">&#34;b&#34;</span> <span style="color:#e6db74">&#34;Browser (Firefox)&#34;</span> (lambda () (interactive) (my/run-in-background <span style="color:#e6db74">&#34;firefox&#34;</span>)))
(<span style="color:#e6db74">&#34;v&#34;</span> <span style="color:#e6db74">&#34;VK&#34;</span> (lambda () (interactive) (my/run-in-background <span style="color:#e6db74">&#34;vk&#34;</span>)))
(<span style="color:#e6db74">&#34;s&#34;</span> <span style="color:#e6db74">&#34;Slack&#34;</span> (lambda () (interactive) (my/run-in-background <span style="color:#e6db74">&#34;slack-wrapper&#34;</span>)))
(<span style="color:#e6db74">&#34;d&#34;</span> <span style="color:#e6db74">&#34;Discord&#34;</span> (lambda () (interactive) (my/run-in-background <span style="color:#e6db74">&#34;flatpak run com.discordapp.Discord&#34;</span>)))
(<span style="color:#e6db74">&#34;q&#34;</span> <span style="color:#e6db74">&#34;Quit&#34;</span> transient-quit-one)])
</code></pre></div><h3 id="move-workspace-to-another-monitor">Move workspace to another monitor</h3>
<p>A function to move the current workspace to another monitor.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/exwm-workspace-switch-monitor ()
(interactive)
(if (<span style="color:#a6e22e">plist-get</span> exwm-randr-workspace-monitor-plist exwm-workspace-current-index)
(setq exwm-randr-workspace-monitor-plist
(map-delete exwm-randr-workspace-monitor-plist exwm-workspace-current-index))
(setq exwm-randr-workspace-monitor-plist
(<span style="color:#a6e22e">plist-put</span> exwm-randr-workspace-monitor-plist
exwm-workspace-current-index
my/exwm-another-monitor)))
(exwm-randr-refresh))
</code></pre></div><h3 id="switch-to-the-opposite-monitor">Switch to the opposite monitor</h3>
<p>Store the information about which workspace is available on which monitor.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(setq my/exwm-monitor-workspace <span style="color:#f92672">&#39;</span>())
(defun my/exwm-get-current-monitor ()
(let* ((info (shell-command-to-string <span style="color:#e6db74">&#34;xdotool getmouselocation --shell | head -n 1&#34;</span>))
(coord (<span style="color:#a6e22e">string-to-number</span> (<span style="color:#a6e22e">substring</span> info <span style="color:#ae81ff">2</span>))))
(if (<span style="color:#a6e22e">&gt;</span> coord <span style="color:#ae81ff">1920</span>) <span style="color:#ae81ff">1</span> <span style="color:#ae81ff">0</span>)))
(defun my/exwm-update-current-monitor ()
(setf (alist-get (my/exwm-get-current-monitor) my/exwm-monitor-workspace)
exwm-workspace-current-index))
(add-hook <span style="color:#e6db74">&#39;exwm-workspace-switch-hook</span>
<span style="color:#a6e22e">#&#39;</span>my/exwm-update-current-monitor)
</code></pre></div><p>Switch to the opposite monitor.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/exwm-switch-to-other-monitor ()
(interactive)
(let* ((current (my/exwm-get-current-monitor))
(other (seq-some
(lambda (m)
(and (not (<span style="color:#a6e22e">=</span> (<span style="color:#a6e22e">car</span> m) current)) (<span style="color:#a6e22e">cdr</span> m)))
my/exwm-monitor-workspace)))
(exwm-workspace-switch other)))
</code></pre></div><h3 id="switching-buffers">Switching buffers</h3>
<p>A single perspective usually has only a handful of EXWM buffers, so here is a function to cycle them.</p>
<p>Those buffers that are visible in another window are highlighted blue and skipped. The current buffer is highlighted yellow.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/cycle-persp-exwm-buffers (dir)
(let* ((current (<span style="color:#a6e22e">current-buffer</span>))
(ignore-rx (persp--make-ignore-buffer-rx))
(visible-buffers <span style="color:#f92672">&#39;</span>())
(exwm-data
(cl-loop for buf in (persp-current-buffers)
for is-another <span style="color:#a6e22e">=</span> (and (<span style="color:#a6e22e">get-buffer-window</span> buf) (not (<span style="color:#a6e22e">eq</span> current buf)))
if (and (<span style="color:#a6e22e">buffer-live-p</span> buf)
(<span style="color:#a6e22e">eq</span> <span style="color:#e6db74">&#39;exwm-mode</span> (<span style="color:#a6e22e">buffer-local-value</span> <span style="color:#e6db74">&#39;major-mode</span> buf))
(not (string-match-p ignore-rx (<span style="color:#a6e22e">buffer-name</span> buf))))
collect buf into all-buffers
and if (not is-another) collect buf into cycle-buffers
finally (return (<span style="color:#a6e22e">list</span> all-buffers cycle-buffers))))
(all-buffers (<span style="color:#a6e22e">nth</span> <span style="color:#ae81ff">0</span> exwm-data))
(cycle-buffers (<span style="color:#a6e22e">nth</span> <span style="color:#ae81ff">1</span> exwm-data))
(current-pos (or (cl-position current cycle-buffers) <span style="color:#ae81ff">-1</span>)))
(if (seq-empty-p cycle-buffers)
(<span style="color:#a6e22e">message</span> <span style="color:#e6db74">&#34;No EXWM buffers to cycle!&#34;</span>)
(let* ((next-pos (<span style="color:#a6e22e">%</span> (<span style="color:#a6e22e">+</span> current-pos (<span style="color:#a6e22e">length</span> cycle-buffers)
(if (<span style="color:#a6e22e">eq</span> dir <span style="color:#e6db74">&#39;forward</span>) <span style="color:#ae81ff">1</span> <span style="color:#ae81ff">-1</span>))
(<span style="color:#a6e22e">length</span> cycle-buffers)))
(next-buffer (<span style="color:#a6e22e">nth</span> next-pos cycle-buffers)))
(switch-to-buffer next-buffer)
(<span style="color:#a6e22e">message</span>
<span style="color:#e6db74">&#34;%s&#34;</span>
(<span style="color:#a6e22e">mapconcat</span>
(lambda (buf)
(let ((name (string-replace <span style="color:#e6db74">&#34;EXWM :: &#34;</span> <span style="color:#e6db74">&#34;&#34;</span> (<span style="color:#a6e22e">buffer-name</span> buf))))
(cond
((<span style="color:#a6e22e">eq</span> (<span style="color:#a6e22e">current-buffer</span>) buf)
(<span style="color:#a6e22e">concat</span>
<span style="color:#e6db74">&#34;[&#34;</span>
(<span style="color:#a6e22e">propertize</span> name <span style="color:#e6db74">&#39;face</span> <span style="color:#f92672">`</span>(foreground-color <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(doom-color <span style="color:#e6db74">&#39;yellow</span>)))
<span style="color:#e6db74">&#34;]&#34;</span>))
((not (<span style="color:#a6e22e">member</span> buf cycle-buffers))
(<span style="color:#a6e22e">concat</span>
<span style="color:#e6db74">&#34;[&#34;</span>
(<span style="color:#a6e22e">propertize</span> name <span style="color:#e6db74">&#39;face</span> <span style="color:#f92672">`</span>(foreground-color <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(doom-color <span style="color:#e6db74">&#39;blue</span>)))
<span style="color:#e6db74">&#34;]&#34;</span>))
(<span style="color:#66d9ef">t</span> (<span style="color:#a6e22e">format</span> <span style="color:#e6db74">&#34; %s &#34;</span> name)))))
all-buffers
<span style="color:#e6db74">&#34; &#34;</span>))))))
</code></pre></div><h3 id="add-all-exwm-buffers-to-current-perspective">Add all EXWM buffers to current perspective</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/add-exwm-buffers-to-current-perspective ()
(interactive)
(let ((ignore-rx (persp--make-ignore-buffer-rx)))
(cl-loop for buf in (<span style="color:#a6e22e">buffer-list</span>)
if (and (<span style="color:#a6e22e">buffer-live-p</span> buf)
(<span style="color:#a6e22e">eq</span> <span style="color:#e6db74">&#39;exwm-mode</span> (<span style="color:#a6e22e">buffer-local-value</span> <span style="color:#e6db74">&#39;major-mode</span> buf))
(not (string-match-p ignore-rx (<span style="color:#a6e22e">buffer-name</span> buf))))
do (persp-add-buffer (<span style="color:#a6e22e">buffer-name</span> buf)))))
</code></pre></div><h3 id="revive-perspectives">Revive perspectives</h3>
<p>Occasionally the current perspective gets screwed up after a popup. This function attempts to fix it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/exwm-revive-perspectives ()
<span style="color:#e6db74">&#34;Make perspectives in the current frame not killed.&#34;</span>
(interactive)
(let ((to-switch <span style="color:#66d9ef">nil</span>))
(<span style="color:#a6e22e">maphash</span>
(lambda (_ v)
(setf (persp-killed v) <span style="color:#66d9ef">nil</span>)
(unless to-switch
(setq to-switch v)))
(<span style="color:#a6e22e">frame-parameter</span> <span style="color:#66d9ef">nil</span> <span style="color:#e6db74">&#39;persp--hash</span>))
(when to-switch
(persp-switch (persp-name to-switch)))))
</code></pre></div><h3 id="locking-up">Locking up</h3>
<p>Run i3lock.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/exwm-lock ()
(interactive)
(my/run-in-background <span style="color:#e6db74">&#34;i3lock -f -i /home/pavel/Pictures/lock-wallpaper.png&#34;</span>))
</code></pre></div><h3 id="keybindings">Keybindings</h3>
<p>Setting keybindings for EXWM. This actually has to be in the <code>:config</code> block of the <code>use-package</code> form, that is it has to be run after EXWM is loaded, so I use noweb to put this block in the correct place.</p>
<p>First, some prefixes for keybindings that are always passed to EXWM instead of the X application in <code>line-mode</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(setq exwm-input-prefix-keys
<span style="color:#f92672">`</span>(<span style="color:#e6db74">?\C</span>-x
<span style="color:#e6db74">?\C</span>-w
<span style="color:#e6db74">?\M</span>-x
<span style="color:#e6db74">?\M</span>-u))
</code></pre></div><p>Also other local keybindings, that are also available only in <code>line-mode</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defmacro my/app-command (command)
<span style="color:#f92672">`</span>(lambda () (interactive) (my/run-in-background <span style="color:#f92672">,</span>command)))
(general-define-key
:keymaps <span style="color:#f92672">&#39;</span>(exwm-mode-map)
<span style="color:#e6db74">&#34;C-q&#34;</span> <span style="color:#e6db74">&#39;exwm-input-send-next-key</span>
<span style="color:#e6db74">&#34;&lt;print&gt;&#34;</span> (my/app-command <span style="color:#e6db74">&#34;flameshot gui&#34;</span>)
<span style="color:#e6db74">&#34;M-x&#34;</span> <span style="color:#e6db74">&#39;counsel-M-x</span>
<span style="color:#e6db74">&#34;M-SPC&#34;</span> (general-key <span style="color:#e6db74">&#34;SPC&#34;</span>))
</code></pre></div><p>Simulation keys.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(setq exwm-input-simulation-keys <span style="color:#f92672">`</span>((<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;M-w&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;C-w&#34;</span>))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;M-c&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;C-c&#34;</span>))))
</code></pre></div><p>And keybindings that are available in both <code>char-mode</code> and <code>line-mode</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(setq exwm-input-global-keys
<span style="color:#f92672">`</span>(
<span style="color:#75715e">;; Reset to line-mode</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-R&#34;</span>) <span style="color:#f92672">.</span> exwm-reset)
<span style="color:#75715e">;; Switch windows</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-&lt;left&gt;&#34;</span>)<span style="color:#f92672">.</span> windmove-left)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-&lt;right&gt;&#34;</span>) <span style="color:#f92672">.</span> windmove-right)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-&lt;up&gt;&#34;</span>) <span style="color:#f92672">.</span> windmove-up)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-&lt;down&gt;&#34;</span>) <span style="color:#f92672">.</span> windmove-down)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-h&#34;</span>)<span style="color:#f92672">.</span> windmove-left)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-l&#34;</span>) <span style="color:#f92672">.</span> windmove-right)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-k&#34;</span>) <span style="color:#f92672">.</span> windmove-up)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-j&#34;</span>) <span style="color:#f92672">.</span> windmove-down)
<span style="color:#75715e">;; Moving windows</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-H&#34;</span>) <span style="color:#f92672">.</span> (lambda () (interactive) (my/exwm-move-window <span style="color:#e6db74">&#39;left</span>)))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-L&#34;</span>) <span style="color:#f92672">.</span> (lambda () (interactive) (my/exwm-move-window <span style="color:#e6db74">&#39;right</span>)))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-K&#34;</span>) <span style="color:#f92672">.</span> (lambda () (interactive) (my/exwm-move-window <span style="color:#e6db74">&#39;up</span>)))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-J&#34;</span>) <span style="color:#f92672">.</span> (lambda () (interactive) (my/exwm-move-window <span style="color:#e6db74">&#39;down</span>)))
<span style="color:#75715e">;; Fullscreen</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-f&#34;</span>) <span style="color:#f92672">.</span> exwm-layout-toggle-fullscreen)
<span style="color:#75715e">;; Quit</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-Q&#34;</span>) <span style="color:#f92672">.</span> evil-quit)
<span style="color:#75715e">;; Split windows</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-s&#34;</span>) <span style="color:#f92672">.</span> evil-window-vsplit)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-v&#34;</span>) <span style="color:#f92672">.</span> evil-window-hsplit)
<span style="color:#75715e">;; Switch perspectives</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-,&#34;</span>) <span style="color:#f92672">.</span> persp-prev)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-.&#34;</span>) <span style="color:#f92672">.</span> persp-next)
<span style="color:#75715e">;; Switch buffers</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-e&#34;</span>) <span style="color:#f92672">.</span> persp-ivy-switch-buffer)
<span style="color:#75715e">;; Resize windows</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-r&#34;</span>) <span style="color:#f92672">.</span> my/exwm-resize-hydra/body)
<span style="color:#75715e">;; Apps &amp; stuff</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-p&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;rofi -modi drun,run -show drun&#34;</span>))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-;&#34;</span>) <span style="color:#f92672">.</span> my/exwm-apps)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s--&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;rofi-pass&#34;</span>))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-=&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;rofimoji&#34;</span>))
<span style="color:#75715e">;; Basic controls</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;&lt;XF86AudioRaiseVolume&gt;&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;ponymix increase 5 --max-volume 150&#34;</span>))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;&lt;XF86AudioLowerVolume&gt;&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;ponymix decrease 5 --max-volume 150&#34;</span>))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;&lt;XF86AudioMute&gt;&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;ponymix toggle&#34;</span>))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;&lt;XF86AudioPlay&gt;&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;mpc toggle&#34;</span>))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;&lt;XF86AudioPause&gt;&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;mpc pause&#34;</span>))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;&lt;print&gt;&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;flameshot gui&#34;</span>))
<span style="color:#75715e">;; Switch workspace</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-q&#34;</span>) <span style="color:#f92672">.</span> my/exwm-switch-to-other-monitor)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-w&#34;</span>) <span style="color:#f92672">.</span> exwm-workspace-switch)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-W&#34;</span>) <span style="color:#f92672">.</span> exwm-workspace-move-window)
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-&lt;tab&gt;&#34;</span>) <span style="color:#f92672">.</span> my/exwm-workspace-switch-monitor)
<span style="color:#75715e">;; Cycle EXWM windows in the current perspective</span>
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-[&#34;</span>) <span style="color:#f92672">.</span> (lambda () (interactive) (my/cycle-persp-exwm-buffers <span style="color:#e6db74">&#39;backward</span>)))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-]&#34;</span>) <span style="color:#f92672">.</span> (lambda () (interactive) (my/cycle-persp-exwm-buffers <span style="color:#e6db74">&#39;forward</span>)))
(<span style="color:#f92672">,</span>(kbd <span style="color:#e6db74">&#34;s-o&#34;</span>) <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(my/app-command <span style="color:#e6db74">&#34;rofi -show window&#34;</span>))
<span style="color:#75715e">;; &#39;s-N&#39;: Switch to certain workspace with Super (Win) plus a number key (0 - 9)</span>
<span style="color:#f92672">,@</span>(<span style="color:#a6e22e">mapcar</span> (lambda (i)
<span style="color:#f92672">`</span>(<span style="color:#f92672">,</span>(kbd (<span style="color:#a6e22e">format</span> <span style="color:#e6db74">&#34;s-%d&#34;</span> i)) <span style="color:#f92672">.</span>
(lambda ()
(interactive)
(exwm-workspace-switch-create <span style="color:#f92672">,</span>i))))
(number-sequence <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">9</span>))))
</code></pre></div><h3 id="pinentry">Pinentry</h3>
<p>The GUI pinentry doesn&rsquo;t work too well with EXWM because of issues with popup windows, so we will use the Emacs one.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package pinentry
:straight <span style="color:#66d9ef">t</span>
:after (exwm)
:config
(setenv <span style="color:#e6db74">&#34;GPG_AGENT_INFO&#34;</span> <span style="color:#66d9ef">nil</span>) <span style="color:#75715e">;; use emacs pinentry</span>
(setq auth-source-debug <span style="color:#66d9ef">t</span>)
(setq epg-gpg-program <span style="color:#e6db74">&#34;gpg2&#34;</span>) <span style="color:#75715e">;; not necessary</span>
(require <span style="color:#e6db74">&#39;epa-file</span>)
(epa-file-enable)
(setq epa-pinentry-mode <span style="color:#e6db74">&#39;loopback</span>)
(setq epg-pinentry-mode <span style="color:#e6db74">&#39;loopback</span>)
(pinentry-start)
(my/run-in-background <span style="color:#e6db74">&#34;gpgconf --reload gpg-agent&#34;</span>))
</code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#a6e22e">default</span>-<span style="color:#a6e22e">cache</span>-<span style="color:#a6e22e">ttl</span> <span style="color:#ae81ff">3600</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">max</span>-<span style="color:#a6e22e">cache</span>-<span style="color:#a6e22e">ttl</span> <span style="color:#ae81ff">3600</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">allow</span>-<span style="color:#a6e22e">emacs</span>-<span style="color:#a6e22e">pinentry</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">allow</span>-<span style="color:#a6e22e">loopback</span>-<span style="color:#a6e22e">pinentry</span><span style="color:#960050;background-color:#1e0010">
</span></code></pre></div><h3 id="modeline">Modeline</h3>
<p>Show current workspace in the modeline.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defvar my/exwm-mode-line-info <span style="color:#e6db74">&#34;&#34;</span>)
(add-to-list <span style="color:#e6db74">&#39;mode-line-misc-info</span>
<span style="color:#f92672">&#39;</span>(:eval my/exwm-mode-line-info))
(defun my/exwm-mode-line-info-update ()
(setq my/exwm-mode-line-info
(<span style="color:#a6e22e">concat</span>
<span style="color:#e6db74">&#34;[&#34;</span>
(<span style="color:#a6e22e">propertize</span> (<span style="color:#a6e22e">funcall</span> exwm-workspace-index-map exwm-workspace-current-index)
<span style="color:#e6db74">&#39;face</span>
<span style="color:#f92672">`</span>(foreground-color <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(doom-color <span style="color:#e6db74">&#39;yellow</span>)))
<span style="color:#e6db74">&#34;]&#34;</span>))
(<span style="color:#a6e22e">force-mode-line-update</span>))
(add-hook <span style="color:#e6db74">&#39;exwm-workspace-switch-hook</span> <span style="color:#a6e22e">#&#39;</span>my/exwm-mode-line-info-update)
</code></pre></div><h3 id="exwm-config">EXWM config</h3>
<p>And the EXWM config itself.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/exwm-init ()
(exwm-workspace-switch <span style="color:#ae81ff">1</span>)
(my/exwm-run-polybar)
(my/exwm-set-wallpaper)
(my/exwm-run-shepherd)
<span style="color:#75715e">;; (with-eval-after-load &#39;perspective</span>
<span style="color:#75715e">;; (my/exwm-setup-perspectives))</span>
)
(defun my/exwm-update-class ()
(exwm-workspace-rename-buffer (<span style="color:#a6e22e">format</span> <span style="color:#e6db74">&#34;EXWM :: %s&#34;</span> exwm-class-name)))
(use-package exwm
:straight <span style="color:#66d9ef">t</span>
:config
(setq exwm-workspace-number <span style="color:#ae81ff">5</span>)
(add-hook <span style="color:#e6db74">&#39;exwm-init-hook</span> <span style="color:#a6e22e">#&#39;</span>my/exwm-init)
(add-hook <span style="color:#e6db74">&#39;exwm-update-class-hook</span> <span style="color:#a6e22e">#&#39;</span>my/exwm-update-class)
(require <span style="color:#e6db74">&#39;exwm-randr</span>)
(exwm-randr-enable)
(start-process-shell-command <span style="color:#e6db74">&#34;xrandr&#34;</span> <span style="color:#66d9ef">nil</span> <span style="color:#e6db74">&#34;~/bin/scripts/screen-layout&#34;</span>)
(when (string= (<span style="color:#a6e22e">system-name</span>) <span style="color:#e6db74">&#34;indigo&#34;</span>)
(setq my/exwm-another-monitor <span style="color:#e6db74">&#34;DVI-D-0&#34;</span>)
(setq exwm-randr-workspace-monitor-plist <span style="color:#f92672">`</span>(<span style="color:#ae81ff">2</span> <span style="color:#f92672">,</span>my/exwm-another-monitor <span style="color:#ae81ff">3</span> <span style="color:#f92672">,</span>my/exwm-another-monitor)))
(setq exwm-workspace-warp-cursor <span style="color:#66d9ef">t</span>)
(setq mouse-autoselect-window <span style="color:#66d9ef">t</span>)
(setq focus-follows-mouse <span style="color:#66d9ef">t</span>)
&lt;&lt;exwm-monitor-config&gt;&gt;
&lt;&lt;exwm-keybindings&gt;&gt;
&lt;&lt;exwm-mode-line-config&gt;&gt;
(set-frame-parameter (<span style="color:#a6e22e">selected-frame</span>) <span style="color:#e6db74">&#39;alpha</span> <span style="color:#f92672">&#39;</span>(<span style="color:#ae81ff">90</span> <span style="color:#f92672">.</span> <span style="color:#ae81ff">90</span>))
(add-to-list <span style="color:#e6db74">&#39;default-frame-alist</span> <span style="color:#f92672">&#39;</span>(alpha <span style="color:#f92672">.</span> (<span style="color:#ae81ff">90</span> <span style="color:#f92672">.</span> <span style="color:#ae81ff">90</span>)))
(exwm-enable))
</code></pre></div><h2 id="i3wm">i3wm</h2>
<table>
<thead>
@ -743,7 +1183,8 @@ i3_balance_workspace
<p>Keybindings to launch <a href="https://github.com/davatorium/rofi">rofi</a>. For more detail, look the <a href="#rofi">Rofi</a> section.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#a6e22e">bindsym</span> $<span style="color:#a6e22e">mod</span>+<span style="color:#a6e22e">d</span> <span style="color:#a6e22e">exec</span> <span style="color:#e6db74">&#34;rofi -modi &#39;drun,run&#39; -show drun&#34;</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">bindsym</span> $<span style="color:#a6e22e">mod</span>+<span style="color:#a6e22e">b</span> <span style="color:#a6e22e">exec</span> --<span style="color:#a6e22e">no</span>-<span style="color:#a6e22e">startup</span>-<span style="color:#a6e22e">id</span> <span style="color:#a6e22e">rofi</span>-<span style="color:#a6e22e">buku</span>-<span style="color:#a6e22e">mine</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">bindsym</span> $<span style="color:#a6e22e">mod</span>+<span style="color:#a6e22e">minus</span> <span style="color:#a6e22e">exec</span> <span style="color:#a6e22e">rofi</span>-<span style="color:#a6e22e">pass</span>; <span style="color:#a6e22e">mode</span> <span style="color:#a6e22e">default</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">bindsym</span> $<span style="color:#a6e22e">mod</span>+<span style="color:#a6e22e">minus</span> <span style="color:#a6e22e">exec</span> <span style="color:#a6e22e">rofi</span>-<span style="color:#a6e22e">pass</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">bindsym</span> $<span style="color:#a6e22e">mod</span>+<span style="color:#a6e22e">equal</span> <span style="color:#a6e22e">exec</span> <span style="color:#a6e22e">rofimoji</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">bindsym</span> $<span style="color:#a6e22e">mod</span>+<span style="color:#a6e22e">apostrophe</span> <span style="color:#a6e22e">mode</span> <span style="color:#e6db74">&#34;rofi&#34;</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010">
@ -899,12 +1340,14 @@ setxkbmap -model pc105 -option <span style="color:#e6db74">&#39;grp:win_space_to
<table>
<thead>
<tr>
<th>Category</th>
<th>Guix dependency</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>desktop-polybar</td>
<td>polybar</td>
<td>statusbar</td>
</tr>
@ -961,13 +1404,13 @@ declare -A BLOCKS<span style="color:#f92672">=(</span>
<span style="color:#f92672">[</span><span style="color:#e6db74">&#34;eDP&#34;</span><span style="color:#f92672">]=</span><span style="color:#e6db74">&#34;pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP battery SEP sun aw-afk date TSEP&#34;</span>
<span style="color:#f92672">[</span><span style="color:#e6db74">&#34;eDP-1&#34;</span><span style="color:#f92672">]=</span><span style="color:#e6db74">&#34;pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP battery SEP sun aw-afk date TSEP&#34;</span>
<span style="color:#f92672">[</span><span style="color:#e6db74">&#34;DVI-D-0&#34;</span><span style="color:#f92672">]=</span><span style="color:#e6db74">&#34;pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP sun aw-afk date TSEP&#34;</span>
<span style="color:#f92672">[</span><span style="color:#e6db74">&#34;HDMI-A-0&#34;</span><span style="color:#f92672">]=</span><span style="color:#e6db74">&#34;pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP sun aw-afk date TSEP&#34;</span>
<span style="color:#f92672">[</span><span style="color:#e6db74">&#34;HDMI-A-0&#34;</span><span style="color:#f92672">]=</span><span style="color:#e6db74">&#34;pulseaudio mpd SEP cpu ram-memory swap-memory SEP network ipstack-vpn SEP xkeyboard SEP weather SEP pomm sun aw-afk date TSEP&#34;</span>
<span style="color:#f92672">)</span>
<span style="color:#75715e"># Geolocation for some modules</span>
export LOC<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;SPB&#34;</span>
export IPSTACK_API_KEY<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>pass show My_Online/APIs/ipstack | head -n 1<span style="color:#66d9ef">)</span>
<span style="color:#75715e"># export IPSTACK_API_KEY=$(pass show My_Online/APIs/ipstack | head -n 1)</span>
pkill polybar
<span style="color:#66d9ef">for</span> m in <span style="color:#66d9ef">$(</span>xrandr --query | grep <span style="color:#e6db74">&#34; connected&#34;</span> | cut -d<span style="color:#e6db74">&#34; &#34;</span> -f1<span style="color:#66d9ef">)</span>; <span style="color:#66d9ef">do</span>
@ -1078,20 +1521,24 @@ pkill polybar
<table>
<thead>
<tr>
<th>Category</th>
<th>Guix dependency</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>desktop-polybar</td>
<td>bind:utils</td>
<td>Provides dig</td>
</tr>
<tr>
<td>desktop-polybar</td>
<td>curl</td>
<td></td>
</tr>
<tr>
<td>desktop-polybar</td>
<td>jq</td>
<td>util to work with JSONs</td>
</tr>
@ -1149,11 +1596,13 @@ bar_weather<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</s
<table>
<thead>
<tr>
<th>Category</th>
<th>Guix dependency</th>
</tr>
</thead>
<tbody>
<tr>
<td>desktop-polybar</td>
<td>dateutils</td>
</tr>
</tbody>
@ -1173,15 +1622,27 @@ res<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><
<span style="color:#a6e22e">type</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">custom/script</span>
<span style="color:#a6e22e">exec</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">/home/pavel/bin/polybar/aw_afk.sh</span>
<span style="color:#a6e22e">interval</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">60</span>
</code></pre></div><h4 id="pomm">pomm</h4>
<p>Pomodoro module.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash"><span style="color:#66d9ef">if</span> ps -e | grep emacs &gt;&gt; /dev/null; <span style="color:#66d9ef">then</span>
emacsclient --eval <span style="color:#e6db74">&#34;(if (boundp &#39;pomm-current-mode-line-string) pomm-current-mode-line-string \&#34;\&#34;) &#34;</span> | xargs echo -e
<span style="color:#66d9ef">fi</span>
</code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#66d9ef">[module/pomm]</span>
<span style="color:#a6e22e">type</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">custom/script</span>
<span style="color:#a6e22e">exec</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">/home/pavel/bin/polybar/pomm.sh</span>
<span style="color:#a6e22e">interval</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">1</span>
<span style="color:#a6e22e">format-underline</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">${colors.green-lighter}</span>
</code></pre></div><h4 id="sun">sun</h4>
<table>
<thead>
<tr>
<th>Category</th>
<th>Guix dependency</th>
</tr>
</thead>
<tbody>
<tr>
<td>desktop-polybar</td>
<td>sunwait</td>
</tr>
</tbody>
@ -1430,11 +1891,13 @@ time<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>sun
<table>
<thead>
<tr>
<th>Category</th>
<th>Guix dependency</th>
</tr>
</thead>
<tbody>
<tr>
<td>desktop-rofi</td>
<td>rofi</td>
</tr>
</tbody>
@ -1630,18 +2093,36 @@ $BUKU -f <span style="color:#ae81ff">4</span> -p | awk -F<span style="color:#e6d
<span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> ! -z $SELECTED <span style="color:#f92672">]]</span>; <span style="color:#66d9ef">then</span>
man -Tpdf $SELECTED | zathura -
<span style="color:#66d9ef">fi</span>
</code></pre></div><h4 id="pass">pass</h4>
</code></pre></div><h4 id="emojis">Emojis</h4>
<table>
<thead>
<tr>
<th>Category</th>
<th>Guix dependency</th>
</tr>
</thead>
<tbody>
<tr>
<td>desktop-rofi</td>
<td>python-rofimoji</td>
</tr>
</tbody>
</table>
<h4 id="pass">pass</h4>
<table>
<thead>
<tr>
<th>Category</th>
<th>Guix dependency</th>
</tr>
</thead>
<tbody>
<tr>
<td>desktop-rofi</td>
<td>rofi-pass</td>
</tr>
<tr>
<td>desktop-rofi</td>
<td>xset</td>
</tr>
</tbody>
@ -1651,20 +2132,7 @@ $BUKU -f <span style="color:#ae81ff">4</span> -p | awk -F<span style="color:#e6d
EDITOR<span style="color:#f92672">=</span>vim
default_autotype<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;username :tab pass&#39;</span>
clip<span style="color:#f92672">=</span>both
</code></pre></div><h4 id="emojis">emojis</h4>
<table>
<thead>
<tr>
<th>Guix dependency</th>
</tr>
</thead>
<tbody>
<tr>
<td>rofi-emoji</td>
</tr>
</tbody>
</table>
<h2 id="flameshot">Flameshot</h2>
</code></pre></div><h2 id="flameshot">Flameshot</h2>
<table>
<thead>
<tr>
@ -2226,20 +2694,25 @@ clip<span style="color:#f92672">=</span>both
<table>
<thead>
<tr>
<th>Category</th>
<th>Guix dependency</th>
</tr>
</thead>
<tbody>
<tr>
<td>office</td>
<td>zathura</td>
</tr>
<tr>
<td>office</td>
<td>zathura-ps</td>
</tr>
<tr>
<td>zathura-pdf-poppler</td>
<td>office</td>
<td>zathura-pdf-mupdf</td>
</tr>
<tr>
<td>office</td>
<td>zathura-djvu</td>
</tr>
</tbody>
@ -2254,7 +2727,16 @@ clip<span style="color:#f92672">=</span>both
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">set</span> <span style="color:#a6e22e">recolor</span> <span style="color:#a6e22e">true</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">map</span> &lt;<span style="color:#a6e22e">C</span>-<span style="color:#a6e22e">r</span>&gt; <span style="color:#a6e22e">set</span> <span style="color:#a6e22e">recolor</span> <span style="color:#a6e22e">false</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">map</span> &lt;<span style="color:#a6e22e">C</span>-<span style="color:#a6e22e">R</span>&gt; <span style="color:#a6e22e">set</span> <span style="color:#a6e22e">recolor</span> <span style="color:#a6e22e">true</span><span style="color:#960050;background-color:#1e0010">
</span></code></pre></div><h2 id="various-software">Various software</h2>
</span></code></pre></div><p>For some reason zathura doesn&rsquo;t pick up the plugin directory, so I make a wrapper that sets the directory up:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">zathura -p ~/.guix-extra-profiles/office/office/lib/zathura $@
</code></pre></div><pre><code class="language-conf-desktop" data-lang="conf-desktop">[Desktop Entry]
Version=1.0
Type=Application
Name=Zathura
Exec=/home/pavel/bin/zathura-wrapper %U
</code></pre><p>Add the following like to the <code>mimeapps.list</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">application/pdf=zathura-wrapper.desktop
</code></pre></div><h2 id="various-software">Various software</h2>
<p>This section generates manifests for various desktop software that I&rsquo;m using.</p>
<h3 id="browsers">Browsers</h3>
<table>
@ -2443,6 +2925,18 @@ clip<span style="color:#f92672">=</span>both
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-scheme" data-lang="scheme">(<span style="color:#a6e22e">specifications-&gt;manifest</span>
<span style="color:#f92672">&#39;</span>(
&lt;&lt;packages(<span style="color:#e6db74">&#34;latex&#34;</span>)&gt;&gt;))
</code></pre></div><p>Desktop Misc</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-scheme" data-lang="scheme">(<span style="color:#a6e22e">specifications-&gt;manifest</span>
<span style="color:#f92672">&#39;</span>(
&lt;&lt;packages(<span style="color:#e6db74">&#34;desktop-misc&#34;</span>)&gt;&gt;))
</code></pre></div><p>Desktop polybar</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-scheme" data-lang="scheme">(<span style="color:#a6e22e">specifications-&gt;manifest</span>
<span style="color:#f92672">&#39;</span>(
&lt;&lt;packages(<span style="color:#e6db74">&#34;desktop-polybar&#34;</span>)&gt;&gt;))
</code></pre></div><p>Desktop rofi</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-scheme" data-lang="scheme">(<span style="color:#a6e22e">specifications-&gt;manifest</span>
<span style="color:#f92672">&#39;</span>(
&lt;&lt;packages(<span style="color:#e6db74">&#34;desktop-rofi&#34;</span>)&gt;&gt;))
</code></pre></div><h3 id="flatpak">Flatpak</h3>
<p>A lot of proprietary desktop applications can be installed most easily with flatpak &amp; flathub.</p>
<table>
@ -2642,6 +3136,13 @@ aw-watcher-afk
<span style="color:#f92672">#</span>:respawn? <span style="color:#66d9ef">#t</span>
<span style="color:#f92672">#</span>:start (<span style="color:#a6e22e">make-forkexec-constructor</span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;xsettingsd&#34;</span>))
<span style="color:#f92672">#</span>:stop (<span style="color:#a6e22e">make-kill-destructor</span>)))
</code></pre></div><h3 id="nm-applet">nm-applet</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-scheme" data-lang="scheme">(<span style="color:#66d9ef">define </span>nm-applet
(<span style="color:#a6e22e">make</span> &lt;service&gt;
<span style="color:#f92672">#</span>:provides <span style="color:#f92672">&#39;</span>(nm-applet)
<span style="color:#f92672">#</span>:respawn? <span style="color:#66d9ef">#t</span>
<span style="color:#f92672">#</span>:start (<span style="color:#a6e22e">make-forkexec-constructor</span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;nm-applet&#34;</span>))
<span style="color:#f92672">#</span>:stop (<span style="color:#a6e22e">make-kill-destructor</span>)))
</code></pre></div><h3 id="discord-rich-presence">Discord rich presence</h3>
<p>References:</p>
<ul>
@ -2659,7 +3160,7 @@ aw-watcher-afk
(<span style="color:#a6e22e">make</span> &lt;service&gt;
<span style="color:#f92672">#</span>:provides <span style="color:#f92672">&#39;</span>(polkit-gnome)
<span style="color:#f92672">#</span>:respawn? <span style="color:#66d9ef">#t</span>
<span style="color:#f92672">#</span>:start (<span style="color:#a6e22e">make-forkexec-constructor</span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;/home/pavel/.guix-extra-profiles/desktop/desktop/libexec/polkit-gnome-authentication-agent-1&#34;</span>))
<span style="color:#f92672">#</span>:start (<span style="color:#a6e22e">make-forkexec-constructor</span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;/home/pavel/.guix-extra-profiles/desktop-misc/desktop-misc/libexec/polkit-gnome-authentication-agent-1&#34;</span>))
<span style="color:#f92672">#</span>:stop (<span style="color:#a6e22e">make-kill-destructor</span>)))
</code></pre></div><h3 id="xmodmap">Xmodmap</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-scheme" data-lang="scheme">(<span style="color:#66d9ef">define </span>xmodmap
@ -2697,11 +3198,12 @@ aw-watcher-afk
polkit-gnome
vpn
davmail
xmodmap)
xmodmap
nm-applet)
</code></pre></div><p>Daemonize shepherd</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-scheme" data-lang="scheme">(<span style="color:#a6e22e">action</span> <span style="color:#e6db74">&#39;shepherd</span> <span style="color:#e6db74">&#39;daemonize</span>)
</code></pre></div><p>Run services</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-scheme" data-lang="scheme">(for-each start <span style="color:#f92672">&#39;</span>(mpd mpd-watcher mcron aw-server aw-watcher-afk aw-watcher-window pulseeffects xsettingsd discord-rich-presence polkit-gnome davmail xmodmap))
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-scheme" data-lang="scheme">(for-each start <span style="color:#f92672">&#39;</span>(mpd mpd-watcher mcron aw-server aw-watcher-afk aw-watcher-window pulseeffects xsettingsd discord-rich-presence polkit-gnome davmail xmodmap nm-applet))
</code></pre></div><h3 id="sync">Sync</h3>
<table>
<thead>
@ -2720,92 +3222,109 @@ aw-watcher-afk
<table>
<thead>
<tr>
<th>Category</th>
<th>Guix dependency</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>desktop-misc</td>
<td>xprop</td>
<td>Tool to display properties of X windows</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>arandr</td>
<td>GUI to xrandr</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>light</td>
<td>Control screen brightness</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>ponymix</td>
<td>Control PulseAudio CLI</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>pavucontrol</td>
<td>Control PulseAudio GUI</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>network-manager-applet</td>
<td>Applet to manage network connections</td>
</tr>
<tr>
<td>feh</td>
<td>Image viewer. Used to set background</td>
</tr>
<tr>
<td>copyq</td>
<td>Clipboard manager</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>xmodmap</td>
<td>Program to modify keybindings on X server</td>
</tr>
<tr>
<td>thunar</td>
<td>My preferred GUI file manager</td>
</tr>
<tr>
<td>keepassxc</td>
<td>My preferred password manager</td>
</tr>
<tr>
<td>telegram-desktop</td>
<td>telegram client</td>
</tr>
<tr>
<td>xdg-utils</td>
<td>gives xdg-open and stuff</td>
</tr>
<tr>
<td>gnome-font-viewer</td>
<td>view fonts</td>
</tr>
<tr>
<td>qbittorrent</td>
<td>torrent client</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>fontconfig</td>
<td></td>
</tr>
<tr>
<td>desktop-misc</td>
<td>polkit-gnome</td>
<td>Polkit authentication agent</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>feh</td>
<td>Image viewer. Used to set background</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>copyq</td>
<td>Clipboard manager</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>thunar</td>
<td>My preferred GUI file manager</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>telegram-desktop</td>
<td>telegram client</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>xdg-utils</td>
<td>gives xdg-open and stuff</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>gnome-font-viewer</td>
<td>view fonts</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>qbittorrent</td>
<td>torrent client</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>anydesk</td>
<td>Remote desktop software</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>gnome-disk-utility</td>
<td>Manage disks</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>gparted</td>
<td>Manage partitions</td>
</tr>
<tr>
<td>desktop-misc</td>
<td>xev</td>
<td>Test input</td>
</tr>

View file

@ -148,7 +148,6 @@
<li><a href="#keybindings">Keybindings</a></li>
</ul>
</li>
<li><a href="#off--helm"><span class="org-todo done OFF">OFF</span> (OFF) Helm</a></li>
<li><a href="#treemacs">Treemacs</a>
<ul>
<li><a href="#helper-functions">Helper functions</a></li>
@ -192,7 +191,6 @@
<li><a href="#modeline">Modeline</a></li>
<li><a href="#font-stuff">Font stuff</a>
<ul>
<li><a href="#emojis">Emojis</a></li>
<li><a href="#ligatures">Ligatures</a></li>
<li><a href="#icons">Icons</a></li>
<li><a href="#highlight-todo">Highlight todo</a></li>
@ -323,7 +321,15 @@
</li>
<li><a href="#flycheck">Flycheck</a></li>
<li><a href="#tree-sitter">Tree Sitter</a></li>
<li><a href="#off--dap"><span class="org-todo done OFF">OFF</span> (OFF) DAP</a></li>
<li><a href="#dap">DAP</a>
<ul>
<li><a href="#controls">Controls</a></li>
<li><a href="#ui-fixes">UI Fixes</a></li>
<li><a href="#helper-functions">Helper functions</a></li>
<li><a href="#improved-stack-frame-switching">Improved stack frame switching</a></li>
<li><a href="#debug-templates">Debug templates</a></li>
</ul>
</li>
<li><a href="#off--tabnine"><span class="org-todo done OFF">OFF</span> (OFF) TabNine</a></li>
<li><a href="#off--code-compass"><span class="org-todo done OFF">OFF</span> (OFF) Code Compass</a>
<ul>
@ -488,16 +494,11 @@
</li>
<li><a href="#productivity">Productivity</a>
<ul>
<li><a href="#pomidor">Pomidor</a></li>
<li><a href="#pomm">pomm</a></li>
<li><a href="#off--pomidor"><span class="org-todo done OFF">OFF</span> (OFF) Pomidor</a></li>
<li><a href="#calendar">Calendar</a></li>
</ul>
</li>
<li><a href="#off--eaf"><span class="org-todo done OFF">OFF</span> (OFF) EAF</a>
<ul>
<li><a href="#installation">Installation</a></li>
<li><a href="#config">Config</a></li>
</ul>
</li>
<li><a href="#fun">Fun</a>
<ul>
<li><a href="#discord-integration">Discord integration</a></li>
@ -762,6 +763,7 @@
pass
calendar
dired
ivy
debug
guix
calc
@ -827,7 +829,12 @@
:prefix <span style="color:#e6db74">&#34;SPC&#34;</span>
:states <span style="color:#f92672">&#39;</span>(normal motion emacs))
(general-def :states <span style="color:#f92672">&#39;</span>(normal motion emacs) <span style="color:#e6db74">&#34;SPC&#34;</span> <span style="color:#66d9ef">nil</span>)
(general-def :states <span style="color:#f92672">&#39;</span>(normal motion emacs)
<span style="color:#e6db74">&#34;SPC&#34;</span> <span style="color:#66d9ef">nil</span>
<span style="color:#e6db74">&#34;M-SPC&#34;</span> (general-key <span style="color:#e6db74">&#34;SPC&#34;</span>))
(general-def :states <span style="color:#f92672">&#39;</span>(<span style="color:#a6e22e">insert</span>)
<span style="color:#e6db74">&#34;M-SPC&#34;</span> (general-key <span style="color:#e6db74">&#34;SPC&#34;</span> :state <span style="color:#e6db74">&#39;normal</span>))
(my-leader-def <span style="color:#e6db74">&#34;?&#34;</span> <span style="color:#e6db74">&#39;which-key-show-top-level</span>)
(my-leader-def <span style="color:#e6db74">&#34;E&#34;</span> <span style="color:#e6db74">&#39;eval-expression</span>)
@ -965,7 +972,7 @@
<p><code>evil-move-window</code> works well for the second part. By itself it doesn&rsquo;t behave quite like i3, for instance, <code>(evil-move-window 'right)</code> in a three-column split would move the window from the far left side to the far right side (bypassing center). Hence the combination as described here.</p>
<p>So here is a simple predicate which checks whether there is space in the given direction.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/emacs-i3-direction-exists-p (dir)
(some (lambda (dir)
(cl-some (lambda (dir)
(let ((win (windmove-find-other-window dir)))
(and win (not (<span style="color:#a6e22e">window-minibuffer-p</span> win)))))
(pcase dir
@ -1215,6 +1222,10 @@
<span style="color:#75715e">;; ivy-resume</span>
<span style="color:#75715e">;; ivy--restore-session</span>
lsp-ivy-workspace-symbol
dap-switch-stack-frame
my/dap-switch-stack-frame
dap-switch-session
dap-switch-thread
counsel-grep
<span style="color:#75715e">;; counsel-find-file</span>
counsel-git-grep
@ -1258,62 +1269,21 @@
<span style="color:#e6db74">&#34;&lt;C-return&gt;&#34;</span> <span style="color:#e6db74">&#39;ivy-call</span>
<span style="color:#e6db74">&#34;M-RET&#34;</span> <span style="color:#e6db74">&#39;ivy-immediate-done</span>
[escape] <span style="color:#e6db74">&#39;minibuffer-keyboard-quit</span>)
</code></pre></div><h3 id="off--helm"><span class="org-todo done OFF">OFF</span> (OFF) Helm</h3>
<p>Config for the Helm incremental completion framework. I switched to Ivy some time ago, but keep the configuration just in case.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package helm
:init
(require <span style="color:#e6db74">&#39;helm-config</span>)
(setq helm-split-window-in-side-p <span style="color:#66d9ef">t</span>)
(setq helm-move-to-line-cycle-in-source <span style="color:#66d9ef">t</span>)
:straight <span style="color:#66d9ef">t</span>
:config
(helm-mode <span style="color:#ae81ff">1</span>)
(helm-autoresize-mode <span style="color:#ae81ff">1</span>))
(use-package helm-ag
:straight <span style="color:#66d9ef">t</span>)
(use-package helm-rg
:straight <span style="color:#66d9ef">t</span>)
(general-nmap
:keymaps <span style="color:#e6db74">&#39;helm-ag-mode-map</span>
<span style="color:#e6db74">&#34;RET&#34;</span> <span style="color:#e6db74">&#39;helm-ag-mode-jump</span>
<span style="color:#e6db74">&#34;M-RET&#34;</span> <span style="color:#e6db74">&#39;helm-ag-mode-jump-other-window</span>)
(general-nmap
:keymaps <span style="color:#e6db74">&#39;helm-occur-mode-map</span>
<span style="color:#e6db74">&#34;RET&#34;</span> <span style="color:#e6db74">&#39;helm-occur-mode-goto-line</span>
<span style="color:#e6db74">&#34;M-RET&#34;</span> <span style="color:#e6db74">&#39;helm-occur-mode-goto-line-ow</span>)
(general-define-key <span style="color:#e6db74">&#34;M-x&#34;</span> <span style="color:#e6db74">&#39;helm-M-x</span>)
(my-leader-def
<span style="color:#e6db74">&#34;fb&#34;</span> <span style="color:#e6db74">&#39;helm-buffers-list</span>
<span style="color:#e6db74">&#34;fs&#34;</span> <span style="color:#e6db74">&#39;helm-lsp-workspace-symbol</span>
<span style="color:#e6db74">&#34;fw&#34;</span> <span style="color:#e6db74">&#39;helm-lsp-global-workspace-symbol</span>
<span style="color:#e6db74">&#34;fc&#34;</span> <span style="color:#e6db74">&#39;helm-show-kill-ring</span>
<span style="color:#75715e">;; &#34;fa&#34; &#39;helm-do-ag-project-root</span>
<span style="color:#e6db74">&#34;fm&#34;</span> <span style="color:#e6db74">&#39;helm-bookmarks</span>
<span style="color:#e6db74">&#34;ff&#34;</span> <span style="color:#e6db74">&#39;project-find-file</span>
<span style="color:#e6db74">&#34;fe&#34;</span> <span style="color:#e6db74">&#39;conda-env-activate</span>)
(my-leader-def <span style="color:#e6db74">&#34;s&#34;</span> <span style="color:#e6db74">&#39;helm-occur</span>)
(my-leader-def <span style="color:#e6db74">&#34;SPC&#34;</span> <span style="color:#e6db74">&#39;helm-resume</span>)
(general-define-key
:keymaps <span style="color:#e6db74">&#39;helm-map</span>
<span style="color:#e6db74">&#34;C-j&#34;</span> <span style="color:#e6db74">&#39;helm-next-line</span>
<span style="color:#e6db74">&#34;C-k&#34;</span> <span style="color:#e6db74">&#39;helm-previous-line</span>)
(general-define-key
:keymaps <span style="color:#f92672">&#39;</span>(helm-find-files-map helm-locate-map)
<span style="color:#e6db74">&#34;C-h&#34;</span> <span style="color:#e6db74">&#39;helm-find-files-up-one-level</span>
<span style="color:#e6db74">&#34;C-l&#34;</span> <span style="color:#e6db74">&#39;helm-execute-persistent-action</span>)
(general-imap
<span style="color:#e6db74">&#34;C-y&#34;</span> <span style="color:#e6db74">&#39;helm-show-kill-ring</span>)
<span style="color:#75715e">;; (general-nmap &#34;C-p&#34; &#39;project-find-file)</span>
</code></pre></div><h3 id="treemacs">Treemacs</h3>
<table>
<thead>
<tr>
<th>Type</th>
<th>Note</th>
</tr>
</thead>
<tbody>
<tr>
<td>TODO</td>
<td>Enable modeline only for particular treemacs instances</td>
</tr>
</tbody>
</table>
<p><a href="https://github.com/Alexander-Miller/treemacs">Treemacs</a> calls itself a tree layout file explorer, but looks more like a project and workspace management system.</p>
<p>Integrates with evil, magit, projectile and perspective. The latter is particularly great - each perspective can have its own treemacs workspace!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package treemacs
@ -1767,27 +1737,7 @@
(setq doom-modeline-minor-modes <span style="color:#66d9ef">nil</span>)
(setq doom-modeline-buffer-state-icon <span style="color:#66d9ef">nil</span>))
</code></pre></div><h3 id="font-stuff">Font stuff</h3>
<h4 id="emojis">Emojis</h4>
<table>
<thead>
<tr>
<th>Note</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>TODO</td>
<td>Figure out how to display emojis without prettify symbols</td>
</tr>
</tbody>
</table>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package emojify
:straight <span style="color:#66d9ef">t</span>
:if (and (display-graphic-p) (not (or my/lowpower my/is-termux)))
:disabled
:hook (after-init <span style="color:#f92672">.</span> global-emojify-mode))
</code></pre></div><h4 id="ligatures">Ligatures</h4>
<h4 id="ligatures">Ligatures</h4>
<p>Ligature setup for the JetBrainsMono font.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package ligature
:straight (:host github :repo <span style="color:#e6db74">&#34;mickeynp/ligature.el&#34;</span>)
@ -2265,6 +2215,10 @@
(add-hook <span style="color:#e6db74">&#39;org-mode-hook</span>
(lambda ()
(rainbow-delimiters-mode <span style="color:#ae81ff">-1</span>)))
(require <span style="color:#e6db74">&#39;org-tempo</span>)
(add-to-list <span style="color:#e6db74">&#39;org-structure-template-alist</span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;el&#34;</span> <span style="color:#f92672">.</span> <span style="color:#e6db74">&#34;src emacs-lisp&#34;</span>))
(add-to-list <span style="color:#e6db74">&#39;org-structure-template-alist</span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;py&#34;</span> <span style="color:#f92672">.</span> <span style="color:#e6db74">&#34;src python&#34;</span>))
(add-to-list <span style="color:#e6db74">&#39;org-structure-template-alist</span> <span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;sq&#34;</span> <span style="color:#f92672">.</span> <span style="color:#e6db74">&#34;src sql&#34;</span>))
&lt;&lt;org-crypt-setup&gt;&gt;
(unless my/is-termux
&lt;&lt;org-lang-setup&gt;&gt;)
@ -2536,7 +2490,13 @@
(setq org-outline-path-complete-in-steps <span style="color:#66d9ef">nil</span>)
</code></pre></div><h4 id="capture-templates-and-various-settings">Capture templates &amp; various settings</h4>
<p>Settings for Org capture mode. The goal here is to have a non-disruptive process to capture various ideas.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(setq org-capture-templates
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/generate-inbox-note-name ()
(<span style="color:#a6e22e">format</span>
<span style="color:#e6db74">&#34;%s/inbox-notes/%s.org&#34;</span>
org-directory
(<span style="color:#a6e22e">format-time-string</span> <span style="color:#e6db74">&#34;%Y%m%d%H%M%S&#34;</span>)))
(setq org-capture-templates
<span style="color:#f92672">`</span>((<span style="color:#e6db74">&#34;i&#34;</span> <span style="color:#e6db74">&#34;Inbox&#34;</span> entry (file <span style="color:#e6db74">&#34;inbox.org&#34;</span>)
<span style="color:#f92672">,</span>(<span style="color:#a6e22e">concat</span> <span style="color:#e6db74">&#34;* TODO %?\n&#34;</span>
<span style="color:#e6db74">&#34;/Entered on/ %U&#34;</span>))
@ -2548,7 +2508,10 @@
(<span style="color:#e6db74">&#34;f&#34;</span> <span style="color:#e6db74">&#34;elfeed&#34;</span> entry (file <span style="color:#e6db74">&#34;inbox.org&#34;</span>)
<span style="color:#f92672">,</span>(<span style="color:#a6e22e">concat</span> <span style="color:#e6db74">&#34;* TODO %:elfeed-entry-title\n&#34;</span>
<span style="color:#e6db74">&#34;/Entered on/ %U\n&#34;</span>
<span style="color:#e6db74">&#34;%a\n&#34;</span>))))
<span style="color:#e6db74">&#34;%a\n&#34;</span>))
(<span style="color:#e6db74">&#34;n&#34;</span> <span style="color:#e6db74">&#34;note&#34;</span> entry (file my/generate-inbox-note-name)
<span style="color:#f92672">,</span>(<span style="color:#a6e22e">concat</span> <span style="color:#e6db74">&#34;* %?\n&#34;</span>
<span style="color:#e6db74">&#34;/Entered on/ %U&#34;</span>))))
</code></pre></div><p>Effort estimation</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(add-to-list <span style="color:#e6db74">&#39;org-global-properties</span>
<span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;Effort_ALL&#34;</span> <span style="color:#f92672">.</span> <span style="color:#e6db74">&#34;0 0:05 0:10 0:15 0:30 0:45 1:00 2:00 4:00&#34;</span>))
@ -2900,7 +2863,7 @@
(my-leader-def
:infix <span style="color:#e6db74">&#34;or&#34;</span>
<span style="color:#e6db74">&#34;r&#34;</span> <span style="color:#f92672">&#39;</span>(:which-key <span style="color:#e6db74">&#34;org-roam&#34;</span>)
<span style="color:#e6db74">&#34;&#34;</span> <span style="color:#f92672">&#39;</span>(:which-key <span style="color:#e6db74">&#34;org-roam&#34;</span>)
<span style="color:#e6db74">&#34;i&#34;</span> <span style="color:#e6db74">&#39;org-roam-node-insert</span>
<span style="color:#e6db74">&#34;r&#34;</span> <span style="color:#e6db74">&#39;org-roam-node-find</span>
<span style="color:#e6db74">&#34;g&#34;</span> <span style="color:#e6db74">&#39;org-roam-graph</span>
@ -2975,8 +2938,9 @@ MimeType=x-scheme-handler/org-protocol
(general-define-key
:keymaps <span style="color:#e6db74">&#39;bibtex-mode-map</span>
<span style="color:#e6db74">&#34;M-RET&#34;</span> <span style="color:#e6db74">&#39;org-ref-bibtex-hydra/body</span>)
(add-to-list <span style="color:#e6db74">&#39;orhc-candidate-formats</span>
<span style="color:#f92672">&#39;</span>(<span style="color:#e6db74">&#34;online&#34;</span> <span style="color:#f92672">.</span> <span style="color:#e6db74">&#34; |${=key=}| ${title} ${url}&#34;</span>)))
<span style="color:#75715e">;; (add-to-list &#39;orhc-candidate-formats</span>
<span style="color:#75715e">;; &#39;(&#34;online&#34; . &#34; |${=key=}| ${title} ${url}&#34;))</span>
)
</code></pre></div><h4 id="org-roam-bibtex">org-roam-bibtex</h4>
<p>Integration with bibtex and org-ref.</p>
<p>There are some problems with org roam v2, so I disabled it as of now. I will probably use another way of managing bibliography notes anyway.</p>
@ -3402,6 +3366,7 @@ MimeType=x-scheme-handler/org-protocol
:if (not (or my/slow-ssh my/is-termux my/remote-server))
:hook (
(typescript-mode <span style="color:#f92672">.</span> lsp)
(js-mode <span style="color:#f92672">.</span> lsp)
(vue-mode <span style="color:#f92672">.</span> lsp)
(go-mode <span style="color:#f92672">.</span> lsp)
(svelte-mode <span style="color:#f92672">.</span> lsp)
@ -3511,9 +3476,9 @@ MimeType=x-scheme-handler/org-protocol
(use-package tree-sitter-langs
:straight <span style="color:#66d9ef">t</span>
:after tree-sitter)
</code></pre></div><h4 id="off--dap"><span class="org-todo done OFF">OFF</span> (OFF) DAP</h4>
</code></pre></div><h4 id="dap">DAP</h4>
<p>An Emacs client for Debugger Adapter Protocol.</p>
<p>I don&rsquo;t use it now, because there are debuggers I like more for the technologies I&rsquo;m currently using.</p>
<p>As of time of this writing, I mostly debug TypeScript, so the main competitor is Chrome Inspector for node.js.</p>
<p>References:</p>
<ul>
<li><a href="https://emacs-lsp.github.io/dap-mode/">dap-mode homepage</a></li>
@ -3521,12 +3486,13 @@ MimeType=x-scheme-handler/org-protocol
<!--listend-->
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package dap-mode
:straight <span style="color:#66d9ef">t</span>
:defer <span style="color:#66d9ef">t</span>
:commands (dap-debug)
:init
(setq lsp-enable-dap-auto-configure <span style="color:#66d9ef">nil</span>)
:config
(setq dap-ui-variable-length <span style="color:#ae81ff">100</span>)
(setq dap-auto-show-output <span style="color:#66d9ef">nil</span>)
(require <span style="color:#e6db74">&#39;dap-node</span>)
(dap-node-setup)
@ -3538,28 +3504,197 @@ MimeType=x-scheme-handler/org-protocol
(dap-mode <span style="color:#ae81ff">1</span>)
(dap-ui-mode <span style="color:#ae81ff">1</span>)
(dap-tooltip-mode <span style="color:#ae81ff">1</span>)
(tooltip-mode <span style="color:#ae81ff">1</span>)
(dap-ui-controls-mode <span style="color:#ae81ff">1</span>))
(tooltip-mode <span style="color:#ae81ff">1</span>))
</code></pre></div><h5 id="controls">Controls</h5>
<p>I don&rsquo;t like some keybindings in the built-in hydra, and there seems to be no easy way to modify the existing hydra, so I create my own. I tried to use transient, but the transient buffer seems to conflict with special buffers of DAP, and hydra does not.</p>
<p>Also, I want the hydra to toggle UI windows instead of just opening them, so here is macro that defines such functions:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(with-eval-after-load <span style="color:#e6db74">&#39;dap-mode</span>
(defmacro my/define-dap-ui-window-toggler (name)
<span style="color:#f92672">`</span>(defun <span style="color:#f92672">,</span>(<span style="color:#a6e22e">intern</span> (<span style="color:#a6e22e">concat</span> <span style="color:#e6db74">&#34;my/dap-ui-toggle-&#34;</span> name)) ()
<span style="color:#f92672">,</span>(<span style="color:#a6e22e">concat</span> <span style="color:#e6db74">&#34;Toggle DAP &#34;</span> name <span style="color:#e6db74">&#34;buffer&#34;</span>)
(interactive)
(if-let (window (<span style="color:#a6e22e">get-buffer-window</span> <span style="color:#f92672">,</span>(<span style="color:#a6e22e">intern</span> (<span style="color:#a6e22e">concat</span> <span style="color:#e6db74">&#34;dap-ui--&#34;</span> name <span style="color:#e6db74">&#34;-buffer&#34;</span>))))
(quit-window <span style="color:#66d9ef">nil</span> window)
(<span style="color:#f92672">,</span>(<span style="color:#a6e22e">intern</span> (<span style="color:#a6e22e">concat</span> <span style="color:#e6db74">&#34;dap-ui-&#34;</span> name))))))
(my-leader-def
:infix <span style="color:#e6db74">&#34;d&#34;</span>
<span style="color:#e6db74">&#34;d&#34;</span> <span style="color:#e6db74">&#39;dap-debug</span>
<span style="color:#e6db74">&#34;b&#34;</span> <span style="color:#e6db74">&#39;dap-breakpoint-toggle</span>
<span style="color:#e6db74">&#34;c&#34;</span> <span style="color:#e6db74">&#39;dap-breakpoint-condition</span>
<span style="color:#e6db74">&#34;wl&#34;</span> <span style="color:#e6db74">&#39;dap-ui-locals</span>
<span style="color:#e6db74">&#34;wb&#34;</span> <span style="color:#e6db74">&#39;dap-ui-breakpoints</span>
<span style="color:#e6db74">&#34;wr&#34;</span> <span style="color:#e6db74">&#39;dap-ui-repl</span>
<span style="color:#e6db74">&#34;ws&#34;</span> <span style="color:#e6db74">&#39;dap-ui-sessions</span>
<span style="color:#e6db74">&#34;we&#34;</span> <span style="color:#e6db74">&#39;dap-ui-expressions</span>)
(my/define-dap-ui-window-toggler <span style="color:#e6db74">&#34;locals&#34;</span>)
(my/define-dap-ui-window-toggler <span style="color:#e6db74">&#34;expressions&#34;</span>)
(my/define-dap-ui-window-toggler <span style="color:#e6db74">&#34;sessions&#34;</span>)
(my/define-dap-ui-window-toggler <span style="color:#e6db74">&#34;breakpoints&#34;</span>)
(my/define-dap-ui-window-toggler <span style="color:#e6db74">&#34;repl&#34;</span>))
</code></pre></div><p>And here is the hydra:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defhydra my/dap-hydra (:color pink :hint <span style="color:#66d9ef">nil</span> :foreign-keys run)
<span style="color:#e6db74">&#34;
</span><span style="color:#e6db74">^Stepping^ ^UI^ ^Switch^ ^Breakpoints^ ^Debug^ ^Expressions
</span><span style="color:#e6db74">^^^^^^^^------------------------------------------------------------------------------------------------------------------------------------------
</span><span style="color:#e6db74">_n_: Next _uc_: Controls _ss_: Session _bb_: Toggle _dd_: Debug _ee_: Eval
</span><span style="color:#e6db74">_i_: Step in _ue_: Expressions _st_: Thread _bd_: Delete _dr_: Debug recent _er_: Eval region
</span><span style="color:#e6db74">_o_: Step out _ul_: Locals _sf_: Stack frame _ba_: Add _dl_: Debug last _es_: Eval thing at point
</span><span style="color:#e6db74">_c_: Continue _ur_: REPL _su_: Up stack frame _bc_: Set condition _de_: Edit debug template _ea_: Add expression
</span><span style="color:#e6db74">_r_: Restart frame _uo_: Output _sd_: Down stack frame _bh_: Set hit count _Q_: Disconnect _ed_: Remove expression
</span><span style="color:#e6db74"> _us_: Sessions _sF_: Stack frame filtered _bl_: Set log message _eu_: Refresh expressions
</span><span style="color:#e6db74"> _ub_: Breakpoints &#34;</span>
(my-leader-def
:infix <span style="color:#e6db74">&#34;d&#34;</span>
:keymaps <span style="color:#e6db74">&#39;dap-mode-map</span>
<span style="color:#e6db74">&#34;h&#34;</span> <span style="color:#e6db74">&#39;dap-hydra</span>)
(<span style="color:#e6db74">&#34;n&#34;</span> dap-next)
(<span style="color:#e6db74">&#34;i&#34;</span> dap-step-in)
(<span style="color:#e6db74">&#34;o&#34;</span> dap-step-out)
(<span style="color:#e6db74">&#34;c&#34;</span> dap-continue)
(<span style="color:#e6db74">&#34;r&#34;</span> dap-restart-frame)
(<span style="color:#e6db74">&#34;uc&#34;</span> dap-ui-controls-mode)
(<span style="color:#e6db74">&#34;ue&#34;</span> my/dap-ui-toggle-expressions)
(<span style="color:#e6db74">&#34;ul&#34;</span> my/dap-ui-toggle-locals)
(<span style="color:#e6db74">&#34;ur&#34;</span> my/dap-ui-toggle-repl)
(<span style="color:#e6db74">&#34;uo&#34;</span> dap-ui-go-to-output-buffer)
(<span style="color:#e6db74">&#34;us&#34;</span> my/dap-ui-toggle-sessions)
(<span style="color:#e6db74">&#34;ub&#34;</span> my/dap-ui-toggle-breakpoints)
(<span style="color:#e6db74">&#34;ss&#34;</span> dap-switch-session)
(<span style="color:#e6db74">&#34;st&#34;</span> dap-switch-thread)
(<span style="color:#e6db74">&#34;sf&#34;</span> dap-switch-stack-frame)
(<span style="color:#e6db74">&#34;sF&#34;</span> my/dap-switch-stack-frame)
(<span style="color:#e6db74">&#34;su&#34;</span> dap-up-stack-frame)
(<span style="color:#e6db74">&#34;sd&#34;</span> dap-down-stack-frame)
(<span style="color:#e6db74">&#34;bb&#34;</span> dap-breakpoint-toggle)
(<span style="color:#e6db74">&#34;ba&#34;</span> dap-breakpoint-add)
(<span style="color:#e6db74">&#34;bd&#34;</span> dap-breakpoint-delete)
(<span style="color:#e6db74">&#34;bc&#34;</span> dap-breakpoint-condition)
(<span style="color:#e6db74">&#34;bh&#34;</span> dap-breakpoint-hit-condition)
(<span style="color:#e6db74">&#34;bl&#34;</span> dap-breakpoint-log-message)
(<span style="color:#e6db74">&#34;dd&#34;</span> dap-debug)
(<span style="color:#e6db74">&#34;dr&#34;</span> dap-debug-recent)
(<span style="color:#e6db74">&#34;dl&#34;</span> dap-debug-last)
(<span style="color:#e6db74">&#34;de&#34;</span> dap-debug-edit-template)
(<span style="color:#e6db74">&#34;ee&#34;</span> dap-eval)
(<span style="color:#e6db74">&#34;ea&#34;</span> dap-ui-expressions-add)
(<span style="color:#e6db74">&#34;er&#34;</span> dap-eval-region)
(<span style="color:#e6db74">&#34;es&#34;</span> dap-eval-thing-at-point)
(<span style="color:#e6db74">&#34;ed&#34;</span> dap-ui-expressions-remove)
(<span style="color:#e6db74">&#34;eu&#34;</span> dap-ui-expressions-refresh)
(<span style="color:#e6db74">&#34;q&#34;</span> <span style="color:#66d9ef">nil</span> <span style="color:#e6db74">&#34;quit&#34;</span> :color blue)
(<span style="color:#e6db74">&#34;Q&#34;</span> dap-disconnect :color red))
(defun my/dap-yank-value-at-point (node)
(my-leader-def <span style="color:#e6db74">&#34;d&#34;</span> <span style="color:#a6e22e">#&#39;</span>my/dap-hydra/body)
</code></pre></div><h5 id="ui-fixes">UI Fixes</h5>
<p>There are some problems with DAP UI in my setup.</p>
<p>First, DAP uses Treemacs buffers quite extensively, and they hide the doom modeline for some reason, so I can&rsquo;t tell which buffer is active and can&rsquo;t see borders between buffers.</p>
<p>Second, lines are truncated in some strange way, but calling <code>toggle-truncate-lines</code> seems to fix that.</p>
<p>So I define a macro that creates a function that I can further use in an advice.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defvar my/dap-mode-buffer-fixed <span style="color:#66d9ef">nil</span>)
(with-eval-after-load <span style="color:#e6db74">&#39;dap-mode</span>
(defmacro my/define-dap-tree-buffer-fixer (buffer-var <span style="color:#a6e22e">buffer-name</span>)
<span style="color:#f92672">`</span>(defun <span style="color:#f92672">,</span>(<span style="color:#a6e22e">intern</span> (<span style="color:#a6e22e">concat</span> <span style="color:#e6db74">&#34;my/fix-dap-ui-&#34;</span> <span style="color:#a6e22e">buffer-name</span> <span style="color:#e6db74">&#34;-buffer&#34;</span>)) (<span style="color:#66d9ef">&amp;rest</span> _)
(with-current-buffer <span style="color:#f92672">,</span>buffer-var
(unless my/dap-mode-buffer-fixed
(toggle-truncate-lines <span style="color:#ae81ff">1</span>)
(doom-modeline-set-modeline <span style="color:#e6db74">&#39;info</span>)
(setq-local my/dap-mode-buffer-fixed <span style="color:#66d9ef">t</span>)))))
(my/define-dap-tree-buffer-fixer dap-ui--locals-buffer <span style="color:#e6db74">&#34;locals&#34;</span>)
(my/define-dap-tree-buffer-fixer dap-ui--expressions-buffer <span style="color:#e6db74">&#34;expressions&#34;</span>)
(my/define-dap-tree-buffer-fixer dap-ui--sessions-buffer <span style="color:#e6db74">&#34;sessions&#34;</span>)
(my/define-dap-tree-buffer-fixer dap-ui--breakpoints-buffer <span style="color:#e6db74">&#34;breakpoints&#34;</span>)
(advice-add <span style="color:#e6db74">&#39;dap-ui-locals</span> :after <span style="color:#a6e22e">#&#39;</span>my/fix-dap-ui-locals-buffer)
(advice-add <span style="color:#e6db74">&#39;dap-ui-expressions</span> :after <span style="color:#a6e22e">#&#39;</span>my/fix-dap-ui-expressions-buffer)
(advice-add <span style="color:#e6db74">&#39;dap-ui-sessions</span> :after <span style="color:#a6e22e">#&#39;</span>my/fix-dap-ui-sessions-buffer)
(advice-add <span style="color:#e6db74">&#39;dap-ui-breakpoints</span> :after <span style="color:#a6e22e">#&#39;</span>my/fix-dap-ui-breakpoints-buffer))
</code></pre></div><h5 id="helper-functions">Helper functions</h5>
<p>Some helper functions that make debugging with DAP easier.</p>
<p>DAP seems to mess with window parameters from time to time. This function clears &ldquo;bad&rdquo; window parameters.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/clear-bad-window-parameters ()
<span style="color:#e6db74">&#34;Clear window parameters that interrupt my workflow.&#34;</span>
(interactive)
(let ((window (<span style="color:#a6e22e">get-buffer-window</span> (<span style="color:#a6e22e">current-buffer</span>))))
(<span style="color:#a6e22e">set-window-parameter</span> window <span style="color:#e6db74">&#39;no-delete-other-windows</span> <span style="color:#66d9ef">nil</span>)))
</code></pre></div><p>A function to kill a value from a treemacs node.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/dap-yank-value-at-point (node)
(interactive (<span style="color:#a6e22e">list</span> (treemacs-node-at-point)))
(kill-new (<span style="color:#a6e22e">message</span> (<span style="color:#a6e22e">plist-get</span> (button-get node :item) :value))))
</code></pre></div><p>A function to open a value from a treemacs node in a new buffer.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/dap-display-value (node)
(interactive (<span style="color:#a6e22e">list</span> (treemacs-node-at-point)))
(let ((value (<span style="color:#a6e22e">plist-get</span> (button-get node :item) :value)))
(when value
(let ((buffer (generate-new-buffer <span style="color:#e6db74">&#34;dap-value&#34;</span>)))
(with-current-buffer buffer
(<span style="color:#a6e22e">insert</span> value))
(<span style="color:#a6e22e">select-window</span> (display-buffer buffer))))))
</code></pre></div><h5 id="improved-stack-frame-switching">Improved stack frame switching</h5>
<p>One significant improvement over Chrome Inspector for my particular stack is an ability to filter the stack frame list, for instance to see only frames that relate to my current project.</p>
<p>So, here are functions that customize the filters:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(with-eval-after-load <span style="color:#e6db74">&#39;dap-mode</span>
(setq my/dap-stack-frame-filters
<span style="color:#f92672">`</span>((<span style="color:#e6db74">&#34;node_modules,node:internal&#34;</span> <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(rx (or <span style="color:#e6db74">&#34;node_modules&#34;</span> <span style="color:#e6db74">&#34;node:internal&#34;</span>)))
(<span style="color:#e6db74">&#34;node_modules&#34;</span> <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(rx (or <span style="color:#e6db74">&#34;node_modules&#34;</span>)))
(<span style="color:#e6db74">&#34;node:internal&#34;</span> <span style="color:#f92672">.</span> <span style="color:#f92672">,</span>(rx (or <span style="color:#e6db74">&#34;node:internal&#34;</span>)))))
(setq my/dap-stack-frame-current-filter (cdar my/dap-stack-frame-filters))
(defun my/dap-stack-frame-filter-set ()
(interactive)
(setq my/dap-stack-frame-current-filter
(<span style="color:#a6e22e">cdr</span>
(<span style="color:#a6e22e">assoc</span>
(<span style="color:#a6e22e">completing-read</span> <span style="color:#e6db74">&#34;Filter: &#34;</span> my/dap-stack-frame-filters)
my/dap-stack-frame-filters))))
(defun my/dap-stack-frame-filter (frame)
(when-let (path (dap--get-path-for-frame frame))
(not (<span style="color:#a6e22e">string-match</span> my/dap-stack-frame-current-filter path)))))
</code></pre></div><p>And here is a version of <code>dap-switch-stack-frame</code> that uses the said filter.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/dap-switch-stack-frame ()
<span style="color:#e6db74">&#34;Switch stackframe by selecting another stackframe stackframes from current thread.&#34;</span>
(interactive)
(when (not (dap--cur-session))
(<span style="color:#a6e22e">error</span> <span style="color:#e6db74">&#34;There is no active session&#34;</span>))
(-if-let (thread-id (dap--debug-session-thread-id (dap--cur-session)))
(-if-let (stack-frames
(<span style="color:#a6e22e">gethash</span>
thread-id
(dap--debug-session-thread-stack-frames (dap--cur-session))))
(let* ((index <span style="color:#ae81ff">0</span>)
(stack-framces-filtered
(-filter
<span style="color:#a6e22e">#&#39;</span>my/dap-stack-frame-filter
stack-frames))
(new-stack-frame
(dap--completing-read
<span style="color:#e6db74">&#34;Select active frame: &#34;</span>
stack-framces-filtered
(-lambda ((frame &amp;as &amp;hash <span style="color:#e6db74">&#34;name&#34;</span>))
(if-let (frame-path (dap--get-path-for-frame frame))
(<span style="color:#a6e22e">format</span> <span style="color:#e6db74">&#34;%s: %s (in %s)&#34;</span>
(cl-incf index) name frame-path)
(<span style="color:#a6e22e">format</span> <span style="color:#e6db74">&#34;%s: %s&#34;</span> (cl-incf index) name)))
<span style="color:#66d9ef">nil</span>
<span style="color:#66d9ef">t</span>)))
(dap--go-to-stack-frame (dap--cur-session) new-stack-frame))
(-&gt;&gt; (dap--cur-session)
dap--debug-session-name
(<span style="color:#a6e22e">format</span> <span style="color:#e6db74">&#34;Current session %s is not stopped&#34;</span>)
<span style="color:#a6e22e">error</span>))
(<span style="color:#a6e22e">error</span> <span style="color:#e6db74">&#34;No thread is currently active %s&#34;</span> (dap--debug-session-name (dap--cur-session)))))
</code></pre></div><h5 id="debug-templates">Debug templates</h5>
<p>Some debug templates I frequently use.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(with-eval-after-load <span style="color:#e6db74">&#39;dap-mode</span>
(dap-register-debug-template
<span style="color:#e6db74">&#34;Node::Nest.js&#34;</span>
(<span style="color:#a6e22e">list</span> :type <span style="color:#e6db74">&#34;node&#34;</span>
:request <span style="color:#e6db74">&#34;attach&#34;</span>
:name <span style="color:#e6db74">&#34;Node::Attach&#34;</span>
:port <span style="color:#ae81ff">9229</span>
:outFiles [<span style="color:#e6db74">&#34;${workspaceFolder}/dist/**/*.js&#34;</span>]
:sourceMaps <span style="color:#66d9ef">t</span>
:program <span style="color:#e6db74">&#34;${workspaceFolder}/src/app.ts&#34;</span>))
(dap-register-debug-template
<span style="color:#e6db74">&#34;Node::Babel&#34;</span>
(<span style="color:#a6e22e">list</span> :type <span style="color:#e6db74">&#34;node&#34;</span>
:request <span style="color:#e6db74">&#34;attach&#34;</span>
:name <span style="color:#e6db74">&#34;Node::Attach&#34;</span>
:port <span style="color:#ae81ff">9229</span>
:program <span style="color:#e6db74">&#34;${workspaceFolder}/dist/bin/www.js&#34;</span>)))
</code></pre></div><h4 id="off--tabnine"><span class="org-todo done OFF">OFF</span> (OFF) TabNine</h4>
<p>A ML-based autocompletion system.</p>
<p>More often than not gives really good results, but is slow as hell &amp; consumes a lot of RAM. Also, LSP-provided completions were more useful in my experience.</p>
@ -4731,6 +4866,21 @@ MimeType=x-scheme-handler/org-protocol
(emacs elfeed-emacs-entry)
(blogs elfeed-blogs-entry)
(unread elfeed-search-unread-title-face))))
</code></pre></div><p>Also a function to automatically adjust these colors with the Doom theme.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/update-my-theme-elfeed (<span style="color:#66d9ef">&amp;rest</span> _)
(custom-theme-set-faces
<span style="color:#e6db74">&#39;my-theme</span>
<span style="color:#f92672">`</span>(elfeed-videos-entry ((<span style="color:#66d9ef">t</span> :foreground <span style="color:#f92672">,</span>(doom-color <span style="color:#e6db74">&#39;red</span>))))
<span style="color:#f92672">`</span>(elfeed-twitter-entry ((<span style="color:#66d9ef">t</span> :foreground <span style="color:#f92672">,</span>(doom-color <span style="color:#e6db74">&#39;blue</span>))))
<span style="color:#f92672">`</span>(elfeed-emacs-entry ((<span style="color:#66d9ef">t</span> :foreground <span style="color:#f92672">,</span>(doom-color <span style="color:#e6db74">&#39;magenta</span>))))
<span style="color:#f92672">`</span>(elfeed-music-entry ((<span style="color:#66d9ef">t</span> :foreground <span style="color:#f92672">,</span>(doom-color <span style="color:#e6db74">&#39;green</span>))))
<span style="color:#f92672">`</span>(elfeed-podcasts-entry ((<span style="color:#66d9ef">t</span> :foreground <span style="color:#f92672">,</span>(doom-color <span style="color:#e6db74">&#39;yellow</span>))))
<span style="color:#f92672">`</span>(elfeed-blogs-entry ((<span style="color:#66d9ef">t</span> :foreground <span style="color:#f92672">,</span>(doom-color <span style="color:#e6db74">&#39;orange</span>)))))
(enable-theme <span style="color:#e6db74">&#39;my-theme</span>))
(advice-add <span style="color:#e6db74">&#39;load-theme</span> :after <span style="color:#a6e22e">#&#39;</span>my/update-my-theme-elfeed)
(when (<span style="color:#a6e22e">fboundp</span> <span style="color:#e6db74">&#39;doom-color</span>)
(my/update-my-theme-elfeed))
</code></pre></div><h5 id="elfeed-score">elfeed-score</h5>
<p><a href="https://github.com/sp1ff/elfeed-score">elfeed-score</a> is a package that implements scoring for the elfeed entries. Entries are scored by a set of rules for tags/title/content/etc and sorted by that score.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/elfeed-toggle-score-sort ()
@ -4874,7 +5024,7 @@ MimeType=x-scheme-handler/org-protocol
<p>It looks like YouTube has started to throttle youtube-dl, and yt-dlp has a workaround for that particular case. Just don&rsquo;t forget to add the following like to the mpv config:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#a6e22e">script-opts</span><span style="color:#f92672">=</span><span style="color:#e6db74">ytdl_hook-ytdl_path=yt-dlp</span>
</code></pre></div><p>It seems a bit strange to keep the MPV config in this file, but I don&rsquo;t use the program outside Emacs.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(add-to-list <span style="color:#e6db74">&#39;emms-player-list</span> <span style="color:#e6db74">&#39;emms-player-mpv</span> <span style="color:#66d9ef">t</span>)
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(add-to-list <span style="color:#e6db74">&#39;emms-player-list</span> <span style="color:#e6db74">&#39;emms-player-mpv</span>)
</code></pre></div><p>Also a custom regex. My demands for MPV include running <code>yt-dlp</code>, so there is a regex that matches youtube.com or some of the video formats.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(emms-player-set emms-player-mpv
<span style="color:#e6db74">&#39;regex</span>
@ -5218,7 +5368,7 @@ tag2: value2&#39;
:straight <span style="color:#66d9ef">t</span>
:commands (prodigy)
:init
(my-leader-def <span style="color:#e6db74">&#34;ap&#34;</span> <span style="color:#e6db74">&#39;prodigy</span>)
(my-leader-def <span style="color:#e6db74">&#34;aP&#34;</span> <span style="color:#e6db74">&#39;prodigy</span>)
:config
(when (not (<span style="color:#a6e22e">boundp</span> <span style="color:#e6db74">&#39;my/docker-directories</span>))
(<span style="color:#a6e22e">load</span> (<span style="color:#a6e22e">concat</span> user-emacs-directory <span style="color:#e6db74">&#34;prodigy-config&#34;</span>)))
@ -5274,7 +5424,7 @@ tag2: value2&#39;
</tbody>
</table>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package screenshot
:straight (:repo <span style="color:#e6db74">&#34;tecosaur/screenshot&#34;</span> :host github :files (<span style="color:#e6db74">&#34;screenshot.el&#34;</span>))
:straight (:repo <span style="color:#e6db74">&#34;tecosaur/screenshot&#34;</span> :host github :files (<span style="color:#e6db74">&#34;screenshot.el&#34;</span>) :commit <span style="color:#e6db74">&#34;f8204e82dc0c1158c401735d36a143e6f6d24cf5&#34;</span>)
:if (display-graphic-p)
:commands (screenshot)
:init
@ -5295,10 +5445,23 @@ tag2: value2&#39;
:init
(my-leader-def <span style="color:#e6db74">&#34;ag&#34;</span> <span style="color:#e6db74">&#39;guix</span>))
</code></pre></div><h3 id="productivity">Productivity</h3>
<h4 id="pomidor">Pomidor</h4>
<h4 id="pomm">pomm</h4>
<p>My package for doing Pomodoro timer.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package pomm
:straight (:host github :repo <span style="color:#e6db74">&#34;SqrtMinusOne/pomm.el&#34;</span> :files (:defaults <span style="color:#e6db74">&#34;resources&#34;</span>))
<span style="color:#75715e">;; :straight (:local-repo &#34;~/Code/Emacs/pomm&#34; :files (:defaults &#34;resources&#34;))</span>
:init
(my-leader-def <span style="color:#e6db74">&#34;ap&#34;</span> <span style="color:#a6e22e">#&#39;</span>pomm)
:config
(setq alert-default-style <span style="color:#e6db74">&#39;libnotify</span>)
(add-hook <span style="color:#e6db74">&#39;pomm-on-tick-hook</span> <span style="color:#e6db74">&#39;pomm-update-mode-line-string</span>)
(add-hook <span style="color:#e6db74">&#39;pomm-on-status-changed-hook</span> <span style="color:#e6db74">&#39;pomm-update-mode-line-string</span>))
</code></pre></div><h4 id="off--pomidor"><span class="org-todo done OFF">OFF</span> (OFF) Pomidor</h4>
<p>A simple pomodoro technique timer.</p>
<p>Disabled it in favour of my own package.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package pomidor
:straight <span style="color:#66d9ef">t</span>
:disabled
:commands (pomidor)
:init
(my-leader-def <span style="color:#e6db74">&#34;aP&#34;</span> <span style="color:#a6e22e">#&#39;</span>pomidor)
@ -5323,26 +5486,27 @@ tag2: value2&#39;
(setq calendar-latitude <span style="color:#ae81ff">59.9375</span>)
(setq calendar-longitude <span style="color:#ae81ff">30.308611</span>)
</code></pre></div><h3 id="off--eaf"><span class="org-todo done OFF">OFF</span> (OFF) EAF</h3>
<p><a href="https://github.com/manateelazycat/emacs-application-framework">Emacs Application Framework</a> provides a way to integrate PyQt applications with Emacs.</p>
<p>I&rsquo;ve made it work, but don&rsquo;t find any uses cases for me at the moment</p>
<h4 id="installation">Installation</h4>
<p>Requirements: Node &gt;= 14</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">pip install qtconsole markdown qrcode<span style="color:#f92672">[</span>pil<span style="color:#f92672">]</span> PyQt5 PyQtWebEngine
</code></pre></div><h4 id="config">Config</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package eaf
:straight (:host github :repo <span style="color:#e6db74">&#34;manateelazycat/emacs-application-framework&#34;</span> :files (<span style="color:#e6db74">&#34;*&#34;</span>))
:init
(use-package epc :defer <span style="color:#66d9ef">t</span> :straight <span style="color:#66d9ef">t</span>)
(use-package ctable :defer <span style="color:#66d9ef">t</span> :straight <span style="color:#66d9ef">t</span>)
(use-package deferred :defer <span style="color:#66d9ef">t</span> :straight <span style="color:#66d9ef">t</span>)
:config
(require <span style="color:#e6db74">&#39;eaf-evil</span>)
(setq eaf-evil-leader-key <span style="color:#e6db74">&#34;SPC&#34;</span>))
</code></pre></div><h3 id="fun">Fun</h3>
<h4 id="discord-integration">Discord integration</h4>
<p>Integration with Discord. Shows which file is being edited in Emacs.</p>
<p>In order for this to work in Guix, a service is necessary - <a href="/configs/desktop/">Discord rich presence</a>.</p>
<p>Some functions to override the displayed message:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(defun my/elcord-mask-buffer-name (name)
(cond
((string-match-p (rx bos (<span style="color:#e6db74">? </span><span style="color:#e6db74">&#34;CAPTURE-&#34;</span>) (<span style="color:#a6e22e">=</span> <span style="color:#ae81ff">14</span> num) <span style="color:#e6db74">&#34;-&#34;</span> (<span style="color:#a6e22e">*</span> not-newline) <span style="color:#e6db74">&#34;.org&#34;</span> eos) name)
<span style="color:#e6db74">&#34;&lt;ORG-ROAM&gt;&#34;</span>)
((string-match-p (rx bos (<span style="color:#a6e22e">+</span> num) <span style="color:#e6db74">&#34;-&#34;</span> (<span style="color:#a6e22e">+</span> num) <span style="color:#e6db74">&#34;-&#34;</span> (<span style="color:#a6e22e">+</span> num) <span style="color:#e6db74">&#34;.org&#34;</span> eos) name)
<span style="color:#e6db74">&#34;&lt;ORG-JOURNAL&gt;&#34;</span>)
((string-match-p (rx bos <span style="color:#e6db74">&#34;EXWM&#34;</span>) name)
<span style="color:#e6db74">&#34;&lt;EXWM&gt;&#34;</span>)
(<span style="color:#66d9ef">t</span> name)))
(defun my/elcord-buffer-details-format-functions ()
(<span style="color:#a6e22e">format</span> <span style="color:#e6db74">&#34;Editing %s&#34;</span> (my/elcord-mask-buffer-name (<span style="color:#a6e22e">buffer-name</span>))))
(defun my/elcord-update-presence-mask-advice (r)
(<span style="color:#a6e22e">list</span> (my/elcord-mask-buffer-name (<span style="color:#a6e22e">nth</span> <span style="color:#ae81ff">0</span> r)) (<span style="color:#a6e22e">nth</span> <span style="color:#ae81ff">1</span> r)))
</code></pre></div><p>And the package configuration:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package elcord
:straight <span style="color:#66d9ef">t</span>
:if (and (or
@ -5351,11 +5515,9 @@ tag2: value2&#39;
(not my/slow-ssh)
(not my/remote-server))
:config
(elcord-mode)
(add-to-list <span style="color:#e6db74">&#39;elcord-boring-buffers-regexp-list</span>
(rx bos (<span style="color:#a6e22e">+</span> num) <span style="color:#e6db74">&#34;-&#34;</span> (<span style="color:#a6e22e">+</span> num) <span style="color:#e6db74">&#34;-&#34;</span> (<span style="color:#a6e22e">+</span> num) <span style="color:#e6db74">&#34;.org&#34;</span> eos))
(add-to-list <span style="color:#e6db74">&#39;elcord-boring-buffers-regexp-list</span>
(rx bos (<span style="color:#a6e22e">=</span> <span style="color:#ae81ff">14</span> num) <span style="color:#e6db74">&#34;-&#34;</span> (<span style="color:#a6e22e">*</span> not-newline) <span style="color:#e6db74">&#34;.org&#34;</span> eos)))
(setq elcord-buffer-details-format-function <span style="color:#a6e22e">#&#39;</span>my/elcord-buffer-details-format-functions)
(advice-add <span style="color:#e6db74">&#39;elcord--try-update-presence</span> :filter-args <span style="color:#a6e22e">#&#39;</span>my/elcord-update-presence-mask-advice)
(elcord-mode))
</code></pre></div><h4 id="snow">Snow</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-emacs-lisp" data-lang="emacs-lisp">(use-package snow
:straight (:repo <span style="color:#e6db74">&#34;alphapapa/snow.el&#34;</span> :host github)

View file

@ -27,7 +27,7 @@ if [ -z &amp;#34;$IS_ANDROID&amp;#34; ]; then GUIX_EXTRA_PROFILES=$HOME/.guix-ex
<guid>https://sqrtminusone.xyz/configs/desktop/</guid>
<description>My general desktop environment configuration.
Parts prefixed with (OFF) are not used, but kept for historic purposes. For some reason GitHub&amp;rsquo;s org renderer ignores TODO status, hence such a prefix. Round brackets instead of square ones to prevent GitHub&amp;rsquo;s org renderer from screwing up.
Table of Contents Global customization Colors Xresources Colors in Xresources Fonts Themes Device-specific settings i3wm General settings Managing windows Workspaces Rules Scratchpad Launch script i3 config Gaps &amp;amp; borders Keybindings Move &amp;amp; resize windows OFF (OFF) Intergration with dmenu Integration with rofi Launching apps &amp;amp; misc keybindings Apps Media controls &amp;amp; brightness Screenshots Colors OFF (OFF) i3blocks Keyboard Layout Autostart Polybar Launching General settings Colors Bar config Modules ipstack-vpn weather aw-afk sun SEP TSEP i3 xkeyboard mpd pulseaudio cpu ram-memory swap-memory network date battery Rofi Theme Scripts Buku bookmarks Man pages pass emojis Flameshot dunst keynav Config Using with picom Picom Shadows Fading Opacity General settings Zathura Various software Browsers Office &amp;amp; Multimedia LaTeX Dev Manifests Flatpak Nix Services Music GNU Mcron ActivityWatch PulseEffects xsettingsd Discord rich presence Polkit Authentication agent Xmodmap VPN Davmail Shepherd config Sync Guix settings Global customization Colors Most of the colors are from the Palenight theme.</description>
Table of Contents Global customization Colors Xresources Colors in Xresources Fonts Themes Device-specific settings EXWM Xsession Startup apps Moving windows Resizing windows App shortcuts Move workspace to another monitor Switch to the opposite monitor Switching buffers Add all EXWM buffers to current perspective Revive perspectives Locking up Keybindings Pinentry Modeline EXWM config i3wm General settings Managing windows Workspaces Rules Scratchpad Launch script i3 config Gaps &amp;amp; borders Keybindings Move &amp;amp; resize windows OFF (OFF) Intergration with dmenu Integration with rofi Launching apps &amp;amp; misc keybindings Apps Media controls &amp;amp; brightness Screenshots Colors OFF (OFF) i3blocks Keyboard Layout Autostart Polybar Launching General settings Colors Bar config Modules ipstack-vpn weather aw-afk pomm sun SEP TSEP i3 xkeyboard mpd pulseaudio cpu ram-memory swap-memory network date battery Rofi Theme Scripts Buku bookmarks Man pages Emojis pass Flameshot dunst keynav Config Using with picom Picom Shadows Fading Opacity General settings Zathura Various software Browsers Office &amp;amp; Multimedia LaTeX Dev Manifests Flatpak Nix Services Music GNU Mcron ActivityWatch PulseEffects xsettingsd nm-applet Discord rich presence Polkit Authentication agent Xmodmap VPN Davmail Shepherd config Sync Guix settings Global customization Colors Most of the colors are from the Palenight theme.</description>
</item>
<item>