Compare commits

...

3 commits

Author SHA1 Message Date
2715390f16 *: update README 2025-11-23 21:57:40 +03:00
2e64d77ba8 emacs: some updates 2025-11-23 21:52:49 +03:00
6c489b4a32 arch: add violet 2025-11-23 21:52:41 +03:00
12 changed files with 204 additions and 60 deletions

View file

@ -3,6 +3,7 @@ enabled_backends = ["arch"]
hostname_groups_enabled = true hostname_groups_enabled = true
[hostname_groups] [hostname_groups]
violet = ["system","office","nvidia","music","mail","latex","emacs","dev","desktop-rofi","desktop-polybar","desktop-misc","desktop","console","browsers"]
weiss = ["system","office","music","mail","latex","emacs","dev","desktop-rofi","desktop-polybar","desktop-misc","desktop","console","browsers"] weiss = ["system","office","music","mail","latex","emacs","dev","desktop-rofi","desktop-polybar","desktop-misc","desktop","console","browsers"]
archlinux = ["system","office","music","mail","latex","emacs","dev","desktop-rofi","desktop-polybar","desktop-misc","desktop","console","browsers"] archlinux = ["system","office","music","mail","latex","emacs","dev","desktop-rofi","desktop-polybar","desktop-misc","desktop","console","browsers"]

View file

@ -1,4 +1,5 @@
arch = [ arch = [
"veracrypt",
"android-file-transfer", "android-file-transfer",
"remmina", "remmina",
"noto-fonts-emoji", "noto-fonts-emoji",

View file

@ -2,7 +2,6 @@ arch = [
"xf86-video-ati", "xf86-video-ati",
"xf86-video-amdgpu", "xf86-video-amdgpu",
"vulkan-radeon", "vulkan-radeon",
"nvidia-utils",
"vulkan-intel", "vulkan-intel",
"intel-media-driver", "intel-media-driver",
"libva-intel-driver", "libva-intel-driver",

View file

@ -1,5 +1,5 @@
[Unit] [Unit]
Description=Run notmuch new every 5 minutes Description=Run notmuch sync script every 5 minutes
[Timer] [Timer]
OnBootSec=1min OnBootSec=1min

View file

@ -381,14 +381,14 @@ DIR is either 'left or 'right."
_t_: Terminal (Alacritty) _t_: Terminal (Alacritty)
_b_: Browser (Firefox) _b_: Browser (Firefox)
_s_: Rocket.Chat _s_: Rocket.Chat
_e_: Element _d_: DBeaver
_d_: Discord _c_: Chromium
" "
("t" (lambda () (interactive) (my/run-in-background "alacritty"))) ("t" (lambda () (interactive) (my/run-in-background "alacritty")))
("b" (lambda () (interactive) (my/run-in-background "firefox"))) ("b" (lambda () (interactive) (my/run-in-background "firefox")))
("s" (lambda () (interactive) (my/run-in-background "flatpak run chat.rocket.RocketChat"))) ("s" (lambda () (interactive) (my/run-in-background "rocketchat-desktop")))
("e" (lambda () (interactive) (my/run-in-background "flatpak run im.riot.Riot"))) ("d" (lambda () (interactive) (my/run-in-background "dbeaver")))
("d" (lambda () (interactive) (my/run-in-background "flatpak run com.discordapp.Discord")))) ("c" (lambda () (interactive) (my/run-in-background "chromium"))))
(defun my/exwm-lock () (defun my/exwm-lock ()
(interactive) (interactive)
@ -594,10 +594,10 @@ _d_: Discord
(my/exwm-set-wallpaper) (my/exwm-set-wallpaper)
(my/exwm-run-shepherd) (my/exwm-run-shepherd)
(my/exwm-run-systemd)
(my/run-in-background "gpgconf --reload gpg-agent") (my/run-in-background "gpgconf --reload gpg-agent")
(my/exwm-run-polybar) (my/exwm-run-polybar)
(setenv "DBUS_SESSION_BUS_ADDRESS" "unix:path=/run/user/1000/bus") (setenv "DBUS_SESSION_BUS_ADDRESS" "unix:path=/run/user/1000/bus")
(my/exwm-run-systemd)
(when (my/is-arch) (when (my/is-arch)
(my/run-in-background "set_layout"))) (my/run-in-background "set_layout")))

View file

@ -82,6 +82,8 @@
;; I have everything I need in polybar ;; I have everything I need in polybar
(emms-mode-line-mode -1) (emms-mode-line-mode -1)
(emms-playing-time-display-mode -1) (emms-playing-time-display-mode -1)
(delq 'emms-mark-mode evil-emacs-state-modes)
(delq 'emms-browser-mode evil-emacs-state-modes)
(defun emms-info-mpd-process (track info) (defun emms-info-mpd-process (track info)
(dolist (data info) (dolist (data info)
(let ((name (car data)) (let ((name (car data))

View file

@ -375,8 +375,11 @@ REMOTE = '<rclone-remote>'
FOLDERS = json.loads('<rclone-folders-json>') FOLDERS = json.loads('<rclone-folders-json>')
OPTIONS = json.loads('<rclone-options>') OPTIONS = json.loads('<rclone-options>')
for folder, i in zip(FOLDERS, range(len(FOLDERS))):
folder['id'] = i
def rclone_make_command(local_path, remote_path, remote):
def rclone_make_command(local_path, remote_path, remote, extra_args=[]):
return [ return [
'rclone', 'rclone',
'bisync', 'bisync',
@ -390,7 +393,8 @@ def rclone_make_command(local_path, remote_path, remote):
'NEVER', 'NEVER',
'--use-json-log', '--use-json-log',
'--stats', '--stats',
'9999m' '9999m',
*extra_args
] ]
@ -418,15 +422,26 @@ def process_output(output):
except Exception: except Exception:
print(line) print(line)
def rclone_run(folder): def process_command_for_print(command):
res = []
for c in command:
if ' ' in c:
res.append(f'\\'{c}\\'')
else:
res.append(c)
return ' '.join(res)
def rclone_run(folder, extra_args=[]):
command = rclone_make_command( command = rclone_make_command(
folder['local-path'], folder['remote-path'], folder['remote'] folder['local-path'], folder['remote-path'], folder['remote'], extra_args
) )
try: try:
print(str(folder['id']) + '. ' + process_command_for_print(command))
result = subprocess.run(command, check=True, capture_output=True, text=True) result = subprocess.run(command, check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print(f'=== Error syncing {folder['local-path']} ===') print(f'=== Error syncing {folder['local-path']} ===')
print(f'Command: {' '.join(command)}') print(f'Command: {process_command_for_print(command)}')
print(f'--- STDOUT ---') print(f'--- STDOUT ---')
process_output(e.stdout) process_output(e.stdout)
print(f'--- STDERR ---') print(f'--- STDERR ---')
@ -434,7 +449,6 @@ def rclone_run(folder):
return {'success': False, 'stats': {}} return {'success': False, 'stats': {}}
return {'success': True, 'stats': parse_rclone_stats(result.stderr)} return {'success': True, 'stats': parse_rclone_stats(result.stderr)}
def notify(summary, body, level='normal', expire_time=5000): def notify(summary, body, level='normal', expire_time=5000):
subprocess.run(['notify-send', '-u', level, '-t', str(expire_time), summary, body]) subprocess.run(['notify-send', '-u', level, '-t', str(expire_time), summary, body])
@ -447,17 +461,16 @@ def sizeof_fmt(num, suffix='B'):
return f'{num:.1f}Yi{suffix}' return f'{num:.1f}Yi{suffix}'
def rclone_run_all(folders): def rclone_run_all(folders, extra_args=[]):
error_folders = [] error_folders = []
total_bytes = 0 total_bytes = 0
total_transfers = 0 total_transfers = 0
total_deleted = 0 total_deleted = 0
total_renamed = 0 total_renamed = 0
for folder in folders: for folder in folders:
print(f'Running rclone for {folder}') res = rclone_run(folder, extra_args)
res = rclone_run(folder)
if not res['success']: if not res['success']:
error_folders.append(folder['local-path']) error_folders.append(folder)
else: else:
total_bytes += res.get('stats', {}).get('bytes', 0) total_bytes += res.get('stats', {}).get('bytes', 0)
total_transfers += res.get('stats', {}).get('transfers', 0) total_transfers += res.get('stats', {}).get('transfers', 0)
@ -469,21 +482,44 @@ def rclone_run_all(folders):
if total_transfers > 0: if total_transfers > 0:
msg += f'''Transferred {total_transfers} files ({sizeof_fmt(total_bytes)})\n''' msg += f'''Transferred {total_transfers} files ({sizeof_fmt(total_bytes)})\n'''
if total_deleted > 0: if total_deleted > 0:
msg += f'''Deleted {total_transfers} files\n''' msg += f'''Deleted {total_deleted} files\n'''
if total_renamed > 0: if total_renamed > 0:
msg += f'''Renamed {total_renamed} files\n''' msg += f'''Renamed {total_renamed} files\n'''
if len(error_folders) > 0: if len(error_folders) > 0:
msg += '''\nSync errors for the following folders:''' msg += '''\nSync errors for the following folders:'''
for folder in error_folders: for folder in error_folders:
msg += '''\n- ''' + folder msg += '''\n- ''' + str(folder['id']) + '. ' + folder['local-path']
level = 'critical' level = 'critical'
if len(msg) > 0: if len(msg) > 0:
notify(f'rclone sync {REMOTE}', msg, level=level) notify(f'rclone sync {REMOTE}', msg, level=level)
def parse_arguments():
if len(sys.argv) < 2:
return None, []
id_arg = sys.argv[1]
folder_ids = [int(x.strip()) for x in id_arg.split(',')]
extra_args = sys.argv[2:]
return folder_ids, extra_args
if __name__ == '__main__': if __name__ == '__main__':
rclone_run_all(FOLDERS) folder_ids, extra_args = parse_arguments()
if folder_ids is None:
selected_folders = FOLDERS
else:
selected_folders = [f for f in FOLDERS if f['id'] in folder_ids]
found_ids = {f['id'] for f in selected_folders}
missing_ids = set(folder_ids) - found_ids
if missing_ids:
print(f'Warning: folder IDs not found: {sorted(missing_ids)}')
rclone_run_all(selected_folders, extra_args)
")) "))
(setq script (setq script
(thread-last script (thread-last script
@ -562,6 +598,23 @@ The return value is a list of commands as defined by
commands)) commands))
(nreverse commands))) (nreverse commands)))
(defun my/index-rclone-reset ()
"Delete all rclone test files."
(interactive)
(let* ((tree (my/index--tree-retrive))
(folders (my/index--rclone-get-folders tree))
files-to-delete)
(dolist (folder folders)
(let ((test-file-path
(concat
(alist-get :local-path folder)
(format ".rclone-test-%s" (alist-get :remote folder)))))
(when (file-exists-p test-file-path)
(push test-file-path files-to-delete))))
(when (y-or-n-p (format "Delete %d files" (seq-length files-to-delete)))
(dolist (file files-to-delete)
(delete-file file)))))
(defun my/index--git-commands (tree) (defun my/index--git-commands (tree)
"Get commands to clone the yet uncloned git repos in TREE. "Get commands to clone the yet uncloned git repos in TREE.

View file

@ -70,6 +70,12 @@ Host *
AddKeysToAgent yes AddKeysToAgent yes
#+end_src #+end_src
And run:
#+begin_src bash
systemctl enable --user --now ssh-agent
#+end_src
It looks like it is necessary to run at least once.
Then, clone the dotfiles repo with =yadm=: Then, clone the dotfiles repo with =yadm=:
#+begin_src bash #+begin_src bash
yadm clone git@github.com:SqrtMinusOne/dotfiles.git yadm clone git@github.com:SqrtMinusOne/dotfiles.git
@ -134,6 +140,8 @@ sudo systemctl disable --now systemd-networkd
#+end_src #+end_src
And reboot. After the reboot, =NetworkManager= should run using =wpa_supplicant= as backend for Wi-Fi. And reboot. After the reboot, =NetworkManager= should run using =wpa_supplicant= as backend for Wi-Fi.
Don't forget to sync mail and enable the sync timer.
* Metapac configuration * Metapac configuration
[[https://github.com/ripytide/metapac][metapac]] is a declarative wrapper around different package managers, including [[https://wiki.archlinux.org/title/Pacman][pacman]] and [[https://github.com/Morganamilo/paru][paru]]. This means the required packages can be listed in configuration files and checked into version control. [[https://github.com/ripytide/metapac][metapac]] is a declarative wrapper around different package managers, including [[https://wiki.archlinux.org/title/Pacman][pacman]] and [[https://github.com/Morganamilo/paru][paru]]. This means the required packages can be listed in configuration files and checked into version control.
@ -143,20 +151,21 @@ In =metapac=, packages are listed in "groups", each group being a TOML file stat
Below is the table enabling different groups on different hostnames: Below is the table enabling different groups on different hostnames:
#+NAME: metapac-groups #+NAME: metapac-groups
| Profile | archlinux | weiss | | Profile | archlinux | weiss | violet |
| browsers | + | + | | browsers | + | + | + |
| console | + | + | | console | + | + | + |
| desktop | + | + | | desktop | + | + | + |
| desktop-misc | + | + | | desktop-misc | + | + | + |
| desktop-polybar | + | + | | desktop-polybar | + | + | + |
| desktop-rofi | + | + | | desktop-rofi | + | + | + |
| dev | + | + | | dev | + | + | + |
| emacs | + | + | | emacs | + | + | + |
| latex | + | + | | latex | + | + | + |
| mail | + | + | | mail | + | + | + |
| music | + | + | | music | + | + | + |
| office | + | + | | nvidia | | | + |
| system | + | + | | office | + | + | + |
| system | + | + | + |
And the code to format it as TOML: And the code to format it as TOML:
#+NAME: metapac-groups-format #+NAME: metapac-groups-format
@ -231,16 +240,26 @@ Various drivers, I'm not sure which I actually need, so...
| libva-intel-driver | | libva-intel-driver |
| intel-media-driver | | intel-media-driver |
| vulkan-intel | | vulkan-intel |
| nvidia-utils |
| vulkan-radeon | | vulkan-radeon |
| xf86-video-amdgpu | | xf86-video-amdgpu |
| xf86-video-ati | | xf86-video-ati |
NVIDIA drivers for violet
| Category | Arch dependency |
|----------+-----------------|
| nvidia | cuda |
| nvidia | nvidia-utils |
| nvidia | nvidia |
#+NAME: packages #+NAME: packages
#+begin_src emacs-lisp :tangle no :var category="" #+begin_src emacs-lisp :tangle no :var category=""
(my/format-arch-dependencies category) (my/format-arch-dependencies category)
#+end_src #+end_src
#+begin_src scheme :tangle .config/metapac/groups/nvidia.toml :noweb yes
<<packages("nvidia")>>
#+end_src
#+begin_src scheme :tangle .config/metapac/groups/system.toml :noweb yes #+begin_src scheme :tangle .config/metapac/groups/system.toml :noweb yes
<<packages()>> <<packages()>>
#+end_src #+end_src

View file

@ -965,14 +965,14 @@ A +transient+ hydra for shortcuts for the most frequent apps.
_t_: Terminal (Alacritty) _t_: Terminal (Alacritty)
_b_: Browser (Firefox) _b_: Browser (Firefox)
_s_: Rocket.Chat _s_: Rocket.Chat
_e_: Element _d_: DBeaver
_d_: Discord _c_: Chromium
" "
("t" (lambda () (interactive) (my/run-in-background "alacritty"))) ("t" (lambda () (interactive) (my/run-in-background "alacritty")))
("b" (lambda () (interactive) (my/run-in-background "firefox"))) ("b" (lambda () (interactive) (my/run-in-background "firefox")))
("s" (lambda () (interactive) (my/run-in-background "flatpak run chat.rocket.RocketChat"))) ("s" (lambda () (interactive) (my/run-in-background "rocketchat-desktop")))
("e" (lambda () (interactive) (my/run-in-background "flatpak run im.riot.Riot"))) ("d" (lambda () (interactive) (my/run-in-background "dbeaver")))
("d" (lambda () (interactive) (my/run-in-background "flatpak run com.discordapp.Discord")))) ("c" (lambda () (interactive) (my/run-in-background "chromium"))))
#+end_src #+end_src
*** Locking up *** Locking up
Run i3lock. Run i3lock.
@ -1219,10 +1219,10 @@ And the EXWM config itself.
(my/exwm-set-wallpaper) (my/exwm-set-wallpaper)
(my/exwm-run-shepherd) (my/exwm-run-shepherd)
(my/exwm-run-systemd)
(my/run-in-background "gpgconf --reload gpg-agent") (my/run-in-background "gpgconf --reload gpg-agent")
(my/exwm-run-polybar) (my/exwm-run-polybar)
(setenv "DBUS_SESSION_BUS_ADDRESS" "unix:path=/run/user/1000/bus") (setenv "DBUS_SESSION_BUS_ADDRESS" "unix:path=/run/user/1000/bus")
(my/exwm-run-systemd)
(when (my/is-arch) (when (my/is-arch)
(my/run-in-background "set_layout"))) (my/run-in-background "set_layout")))
@ -4239,6 +4239,7 @@ This section generates manifests for various desktop software that I'm using.
| office | okular | | office | okular |
| office | obs-studio | | office | obs-studio |
| office | rocketchat-desktop | | office | rocketchat-desktop |
** LaTeX ** LaTeX
| Category | Arch dependency | Disabled | | Category | Arch dependency | Disabled |
|----------+--------------------------+----------| |----------+--------------------------+----------|
@ -4540,6 +4541,7 @@ Other desktop programs I use are listed below.
| desktop-misc | noto-fonts-emoji | | | desktop-misc | noto-fonts-emoji | |
| desktop-misc | remmina | | | desktop-misc | remmina | |
| desktop-misc | android-file-transfer | | | desktop-misc | android-file-transfer | |
| desktop-misc | veracrypt | |
#+NAME: packages #+NAME: packages
#+begin_src emacs-lisp :tangle no #+begin_src emacs-lisp :tangle no

View file

@ -10433,6 +10433,8 @@ References:
;; I have everything I need in polybar ;; I have everything I need in polybar
(emms-mode-line-mode -1) (emms-mode-line-mode -1)
(emms-playing-time-display-mode -1) (emms-playing-time-display-mode -1)
(delq 'emms-mark-mode evil-emacs-state-modes)
(delq 'emms-browser-mode evil-emacs-state-modes)
<<emms-fixes>>) <<emms-fixes>>)
#+end_src #+end_src
**** MPD **** MPD
@ -12870,8 +12872,11 @@ REMOTE = '<rclone-remote>'
FOLDERS = json.loads('<rclone-folders-json>') FOLDERS = json.loads('<rclone-folders-json>')
OPTIONS = json.loads('<rclone-options>') OPTIONS = json.loads('<rclone-options>')
for folder, i in zip(FOLDERS, range(len(FOLDERS))):
folder['id'] = i
def rclone_make_command(local_path, remote_path, remote):
def rclone_make_command(local_path, remote_path, remote, extra_args=[]):
return [ return [
'rclone', 'rclone',
'bisync', 'bisync',
@ -12885,7 +12890,8 @@ def rclone_make_command(local_path, remote_path, remote):
'NEVER', 'NEVER',
'--use-json-log', '--use-json-log',
'--stats', '--stats',
'9999m' '9999m',
,*extra_args
] ]
@ -12913,15 +12919,26 @@ def process_output(output):
except Exception: except Exception:
print(line) print(line)
def rclone_run(folder): def process_command_for_print(command):
res = []
for c in command:
if ' ' in c:
res.append(f'\\'{c}\\'')
else:
res.append(c)
return ' '.join(res)
def rclone_run(folder, extra_args=[]):
command = rclone_make_command( command = rclone_make_command(
folder['local-path'], folder['remote-path'], folder['remote'] folder['local-path'], folder['remote-path'], folder['remote'], extra_args
) )
try: try:
print(str(folder['id']) + '. ' + process_command_for_print(command))
result = subprocess.run(command, check=True, capture_output=True, text=True) result = subprocess.run(command, check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print(f'=== Error syncing {folder['local-path']} ===') print(f'=== Error syncing {folder['local-path']} ===')
print(f'Command: {' '.join(command)}') print(f'Command: {process_command_for_print(command)}')
print(f'--- STDOUT ---') print(f'--- STDOUT ---')
process_output(e.stdout) process_output(e.stdout)
print(f'--- STDERR ---') print(f'--- STDERR ---')
@ -12929,7 +12946,6 @@ def rclone_run(folder):
return {'success': False, 'stats': {}} return {'success': False, 'stats': {}}
return {'success': True, 'stats': parse_rclone_stats(result.stderr)} return {'success': True, 'stats': parse_rclone_stats(result.stderr)}
def notify(summary, body, level='normal', expire_time=5000): def notify(summary, body, level='normal', expire_time=5000):
subprocess.run(['notify-send', '-u', level, '-t', str(expire_time), summary, body]) subprocess.run(['notify-send', '-u', level, '-t', str(expire_time), summary, body])
@ -12942,17 +12958,16 @@ def sizeof_fmt(num, suffix='B'):
return f'{num:.1f}Yi{suffix}' return f'{num:.1f}Yi{suffix}'
def rclone_run_all(folders): def rclone_run_all(folders, extra_args=[]):
error_folders = [] error_folders = []
total_bytes = 0 total_bytes = 0
total_transfers = 0 total_transfers = 0
total_deleted = 0 total_deleted = 0
total_renamed = 0 total_renamed = 0
for folder in folders: for folder in folders:
print(f'Running rclone for {folder}') res = rclone_run(folder, extra_args)
res = rclone_run(folder)
if not res['success']: if not res['success']:
error_folders.append(folder['local-path']) error_folders.append(folder)
else: else:
total_bytes += res.get('stats', {}).get('bytes', 0) total_bytes += res.get('stats', {}).get('bytes', 0)
total_transfers += res.get('stats', {}).get('transfers', 0) total_transfers += res.get('stats', {}).get('transfers', 0)
@ -12964,21 +12979,44 @@ def rclone_run_all(folders):
if total_transfers > 0: if total_transfers > 0:
msg += f'''Transferred {total_transfers} files ({sizeof_fmt(total_bytes)})\n''' msg += f'''Transferred {total_transfers} files ({sizeof_fmt(total_bytes)})\n'''
if total_deleted > 0: if total_deleted > 0:
msg += f'''Deleted {total_transfers} files\n''' msg += f'''Deleted {total_deleted} files\n'''
if total_renamed > 0: if total_renamed > 0:
msg += f'''Renamed {total_renamed} files\n''' msg += f'''Renamed {total_renamed} files\n'''
if len(error_folders) > 0: if len(error_folders) > 0:
msg += '''\nSync errors for the following folders:''' msg += '''\nSync errors for the following folders:'''
for folder in error_folders: for folder in error_folders:
msg += '''\n- ''' + folder msg += '''\n- ''' + str(folder['id']) + '. ' + folder['local-path']
level = 'critical' level = 'critical'
if len(msg) > 0: if len(msg) > 0:
notify(f'rclone sync {REMOTE}', msg, level=level) notify(f'rclone sync {REMOTE}', msg, level=level)
def parse_arguments():
if len(sys.argv) < 2:
return None, []
id_arg = sys.argv[1]
folder_ids = [int(x.strip()) for x in id_arg.split(',')]
extra_args = sys.argv[2:]
return folder_ids, extra_args
if __name__ == '__main__': if __name__ == '__main__':
rclone_run_all(FOLDERS) folder_ids, extra_args = parse_arguments()
if folder_ids is None:
selected_folders = FOLDERS
else:
selected_folders = [f for f in FOLDERS if f['id'] in folder_ids]
found_ids = {f['id'] for f in selected_folders}
missing_ids = set(folder_ids) - found_ids
if missing_ids:
print(f'Warning: folder IDs not found: {sorted(missing_ids)}')
rclone_run_all(selected_folders, extra_args)
#+end_src #+end_src
A function that templates the script above: A function that templates the script above:
@ -13073,6 +13111,26 @@ The return value is a list of commands as defined by
(nreverse commands))) (nreverse commands)))
#+end_src #+end_src
Also, a command to remove all =.rclone-test-*= files. This is necessary, e.g. after a change in the filter file.
#+begin_src emacs-lisp
(defun my/index-rclone-reset ()
"Delete all rclone test files."
(interactive)
(let* ((tree (my/index--tree-retrive))
(folders (my/index--rclone-get-folders tree))
files-to-delete)
(dolist (folder folders)
(let ((test-file-path
(concat
(alist-get :local-path folder)
(format ".rclone-test-%s" (alist-get :remote folder)))))
(when (file-exists-p test-file-path)
(push test-file-path files-to-delete))))
(when (y-or-n-p (format "Delete %d files" (seq-length files-to-delete)))
(dolist (file files-to-delete)
(delete-file file)))))
#+end_src
**** Git repos **** Git repos
To sync git, we just need to clone the required git repos. Removing the repos is handled by the folder sync commands. To sync git, we just need to clone the required git repos. Removing the repos is handled by the folder sync commands.

View file

@ -9,7 +9,7 @@ I use the [[https://leanpub.com/lit-config/read][literate configuration]] strate
The files themselves are managed and deployed via [[https://yadm.io/][yadm]], although I use Org Mode for things like config templating. The files themselves are managed and deployed via [[https://yadm.io/][yadm]], although I use Org Mode for things like config templating.
My current GNU/Linux distribution is [[https://guix.gnu.org/][GNU Guix]]. I like Guix because, among other things, it allows [[https://guix.gnu.org/cookbook/en/html_node/Advanced-package-management.html#Advanced-package-management][to declare the required software]] in configuration files, so I can have the same set of programs across multiple machines (look for tables with "Guix dependency" in the header). My current GNU/Linux distribution is [[https://guix.gnu.org/][Arch Linux]], managed declaratively with [[https://github.com/ripytide/metapac][metapac]] (look for tables with "Arch dependency" in the header). I used to use Guix for the same purpose for 4.5 years; I keep the config now for archival purposes.
The central program to all of that is, of course, [[https://www.gnu.org/software/emacs/][GNU Emacs]]. At the time of this writing, it takes ~50% of my screen time and has the largest share of configuration here. The central program to all of that is, of course, [[https://www.gnu.org/software/emacs/][GNU Emacs]]. At the time of this writing, it takes ~50% of my screen time and has the largest share of configuration here.
@ -22,15 +22,14 @@ Table of contents and software:
- [[file:Console.org][Console.org]] - [[file:Console.org][Console.org]]
- /Active/: [[file:Console.org::*=.profile=][.profile]], [[file:Console.org::*Bash][Bash]], [[file:Console.org::*Fish][Fish]], [[file:Console.org::*Starship prompt][Starship]], [[file:Console.org::*Tmux][Tmux]], [[file:Console.org::*Alacritty][Alacritty]] - /Active/: [[file:Console.org::*=.profile=][.profile]], [[file:Console.org::*Bash][Bash]], [[file:Console.org::*Fish][Fish]], [[file:Console.org::*Starship prompt][Starship]], [[file:Console.org::*Tmux][Tmux]], [[file:Console.org::*Alacritty][Alacritty]]
- /In Limbo/: [[file:Console.org::*Nushell][Nushell]] - /In Limbo/: [[file:Console.org::*Nushell][Nushell]]
- [[file:Guix.org][Guix.org]] - [[file:Arch.org][Arch.org]]
- [[file:Mail.org][Mail.org]] - [[file:Mail.org][Mail.org]]
- /Active/: [[file:Mail.org::*Lieer][Lieer]], [[file:Mail.org::*DavMail][DavMail]], [[file:Mail.org::*OfflineIMAP][OfflineIMAP]], [[file:Mail.org::*Notmuch][Notmuch]] - /Active/: [[file:Mail.org::*Lieer][Lieer]], [[file:Mail.org::*DavMail][DavMail]], [[file:Mail.org::*OfflineIMAP][OfflineIMAP]], [[file:Mail.org::*Notmuch][Notmuch]]
- [[file:Guix.org][Guix.org]] (archive)
(/Apparently, links on the second level work only in Emacs 🙁/) (/Apparently, links on the second level work only in Emacs 🙁/)
A few other repositories I may consider a part of my config: A few other repositories I may consider a part of my config:
- [[https://github.com/SqrtMinusOne/channel-q][channel-q]] is my Guix channel
- [[https://github.com/SqrtMinusOne/sqrt-data][sqrt-data]] is a home for my statistics gathering effort
- [[https://sqrtminusone.xyz/emacs-packages/][My Emacs Packages]], some of which originated in my Emacs config - [[https://sqrtminusone.xyz/emacs-packages/][My Emacs Packages]], some of which originated in my Emacs config
See also [[https://sqrtminusone.xyz/posts/][my blog posts]]. See also [[https://sqrtminusone.xyz/posts/][my blog posts]].

View file

@ -2,11 +2,21 @@
{ {
"title": "OS/Distro", "title": "OS/Distro",
"elements": [ "elements": [
{
"name": "Arch Linux",
"states": [
{
"startDate": "2025-11-23"
}
],
"color": "y"
},
{ {
"name": "GNU Guix", "name": "GNU Guix",
"states": [ "states": [
{ {
"startDate": "2021-06-11" "startDate": "2021-06-11",
"endDate": "2025-11-23"
} }
], ],
"color": "y" "color": "y"