├── .ansible-lint
├── README.md
├── bashrc.bash
├── dotfiles
├── aichat
│ └── .config
│ │ └── aichat
│ │ ├── config.yaml
│ │ ├── dark.tmTheme
│ │ └── roles
│ │ └── technical-writer.md
├── autostart
│ └── .config
│ │ └── autostart
│ │ ├── kitty.desktop
│ │ ├── org.gnome.Calendar.desktop
│ │ └── org.keepassxc.KeePassXC.desktop
├── config
│ └── .config
│ │ └── mimeapps.list
├── helix
│ └── .config
│ │ └── helix
│ │ ├── config.toml
│ │ └── languages.toml
├── keepassxc
│ └── .config
│ │ └── keepassxc
│ │ └── keepassxc.ini
├── kitty
│ └── .config
│ │ └── kitty
│ │ └── kitty.conf
├── lazygit
│ └── .config
│ │ └── lazygit
│ │ └── config.yml
├── marksman
│ └── .config
│ │ └── marksman
│ │ └── config.toml
├── mpv
│ └── .config
│ │ └── mpv
│ │ ├── input.conf
│ │ └── mpv.conf
├── pandoc
│ └── .local
│ │ └── share
│ │ └── pandoc
│ │ └── filters
│ │ ├── diagram-generator.lua
│ │ ├── include-code-files.lua
│ │ ├── include-files.lua
│ │ ├── pagebreak.lua
│ │ └── wordcount.lua
├── shell
│ ├── .gitconfig
│ ├── .zprofile
│ └── .zshrc
└── sidplayfp
│ └── .local
│ └── share
│ └── sidplayfp
│ ├── basic
│ └── kernal
├── extras
├── README.md
├── _aichat
├── compile-helix-playbook.yml
├── install-blender-playbook.yml
├── nasa-Q1p7bh3SHj8-unsplash.jpg
├── nnn_4.9-1_amd64.deb
└── showmethekey-1.12.0-compiled.zip
├── images
├── debian_logo.svg
└── sources.png
├── install-playbook.yml
├── packages.yml
├── profile.sh
└── tasks
├── configure_system_settings.yml
├── install_github_packages.yml
├── install_python_packages.yml
├── install_repo_packages.yml
├── setup-gnome.yml
├── setup_pipewire.yml
├── stow_dotfiles.yml
└── update_bashrc.yml
/.ansible-lint:
--------------------------------------------------------------------------------
1 | skip_list:
2 | - yaml[indentation]
3 | - risky-file-permissions
4 | - '403'
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Developer Workstation Setup Script Debian Edition
2 |
3 | 
4 |
5 | This guide provides instructions for setting up a developer workstation using Debian 12 "Bookworm" or 13 "Trixie" (currently unreleased, but in hard freeze). The Ansible playbook automates the installation of software and configurations. Your version of Debian is detected, and the best package options are chosen for you.
6 |
7 | While the software and setup choices are mainly aimed towards developers, it is also suitable for general use.
8 |
9 | ## Installation
10 |
11 | Before running the playbook, follow these steps to install Debian:
12 |
13 | ### Installing Debian 12 Bookworm or 13 Trixie Testing
14 |
15 | You can use the testing installer until Trixie is released this summer:
16 |
17 | https://cdimage.debian.org/images/daily-builds/daily/current/amd64/iso-cd/debian-testing-amd64-netinst.iso
18 |
19 | > [!NOTE]
20 | > - Do not provide any details for the root account, your user account will then have administrative rights.
21 | > - Leave Gnome as the default desktop environment.
22 | > - If you installed from a DVD ISO use the Software & Updates application or the terminal to remove `cdrom` from `/etc/apt/sources.list`. Look in Other Software:
23 | > 
24 |
25 | > [!NOTE]
26 | > There is a bug in the Debian 12 installer, if you use the default guided partitioner, you will get a swap partition of only 1 GB regardless of how much RAM you have. To get an uncapped swap partition size, in the grub menu before the Debian installer runs, follow these steps:
27 | >
28 | > 1. Press "e" to edit the default installation option.
29 | > 2. In the line that says `linux /install.amd/vmlinuz vga=788 --- quiet`, add the following separated by a space after `vmlinuz`:
30 | >
31 | > ```sh
32 | > partman-auto/cap-ram=n
33 | > ```
34 | >
35 | > 3. Press Ctrl-x or F10 to continue.
36 |
37 | ## Setting up Debian
38 |
39 | 1. Open the terminal and run the following command to install Ansible, git, and Flatpak:
40 | ```sh
41 | sudo apt install ansible git flatpak
42 | ```
43 |
44 | 2. Clone this repository and navigate to it:
45 | ```sh
46 | git clone https://github.com/David-Else/developer-workstation-setup-script-debian
47 | cd developer-workstation-setup-script-debian
48 | ```
49 |
50 | 3. Customize the software selection by modifying `packages.yml` according to your preferences.
51 |
52 | 4. Run the main installation playbook:
53 | > [!NOTE]
54 | > When prompted for the `BECOME` password in Ansible, enter your user password. Your account must have administrative privileges.
55 | >
56 | > You can add `--check` for a test run or `--diff, -vv` to see more info.
57 |
58 | ```sh
59 | ansible-playbook ./install-playbook.yml -K
60 | ```
61 |
62 | 5. To enable the preview feature in the `nnn` file manager, run it once with the `-a` flag to create the FIFO file. Install the plugins with `sh -c "$(curl -Ls https://raw.githubusercontent.com/jarun/nnn/master/plugins/getplugs)"`.
63 |
64 | 6. Install showmethekey:
65 |
66 | ```sh
67 | cd extras
68 | unzip showmethekey-1.12.0-compiled.zip
69 | cd showmethekey-1.12.0
70 | sudo ./install-show-me-the-key.sh
71 | ```
72 |
73 | 7. Install Firefox extensions:
74 |
75 | ```sh
76 | firefox https://addons.mozilla.org/en-GB/firefox/addon/ublock-origin/ \
77 | https://addons.mozilla.org/en-US/firefox/addon/surfingkeys_ff/ \
78 | https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/ &
79 | ```
80 |
81 | 8. Compile tt terminal typing test from source:
82 |
83 | ```sh
84 | git clone https://github.com/lemnos/tt
85 | cd tt
86 | make && sudo make install
87 | ```
88 |
89 | 9. Downgrade the MPV config file for Debian 12 if needed:
90 |
91 | ```sh
92 | profile=gpu-hq
93 | hwdec=auto-safe
94 | fullscreen=yes
95 | input-gamepad=yes
96 | osd-font-size=25
97 | ```
98 |
99 | 10. Change the visudo editor to vim: `sudo update-alternatives --config editor`
100 |
101 | 11. Install Rust and AIChat:
102 |
103 | ```sh
104 | set -o pipefail &&
105 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y &&
106 | . "$HOME/.cargo/env" &&
107 | rustup component add rust-analyzer &&
108 | cargo install aichat --version 0.29.0
109 | sudo cp ./extras/_aichat /usr/share/zsh/vendor-completions/
110 | ```
111 |
112 | 12. `sudo reboot`
113 |
114 | ## Optional Tweaks
115 |
116 | Depending on your software selection, hardware, and personal preferences, you may want to make the following changes:
117 |
118 | ### Audio
119 |
120 | You can confirm the allowed sample rate settings were changed by the playbook with `pw-metadata -n settings` and watch the sample rates change per application running `pw-top`.
121 |
122 | > [!NOTE]
123 | > More info can be found at: [docs.pipewire.org configuration-file-pipewireconf](https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PipeWire#configuration-file-pipewireconf)
124 |
125 | ### General
126 |
127 | To perform general tweaks, follow these steps:
128 |
129 | - Set Helix to open in Kitty `sudoedit /usr/share/applications/Helix.desktop`:
130 |
131 | ```sh
132 | Exec=kitty --single-instance hx %F
133 | Terminal=false
134 | ```
135 |
136 | - Configure Git email and name:
137 | ```sh
138 | git config --global user.email "you@example.com"
139 | git config --global user.name "Your Name"
140 | ```
141 | Enable GPG signing for commits:
142 | ```sh
143 | git config --global user.signingkey key
144 | git config --global commit.gpgsign true
145 | ```
146 |
147 | - Install extras:
148 | ```sh
149 | gh extension install yusukebe/gh-markdown-preview
150 | gh extension install dlvhdr/gh-dash
151 | hx ~/.config/gh-dash/config.yml # diff: "delta"
152 | ```
153 | - `sudo apt install v4l2loopback-dkms v4l2loopback-utils` for virtual video devices
154 |
155 | ## FAQ
156 |
157 | If you would like to use Code for things that Helix still struggles with (like debugging), and still use all the modal keyboard shortcuts, I suggest installing `silverquark.dancehelix` or `asvetliakov.vscode-neovim` and using these settings:
158 | ```jsonc
159 | {
160 | // font size
161 | "editor.fontSize": 15,
162 | "markdown.preview.fontSize": 15,
163 | "terminal.integrated.fontSize": 15,
164 | // asvetliakov.vscode-neovim
165 | "editor.scrollBeyondLastLine": false,
166 | "vscode-neovim.neovimExecutablePaths.linux": "/usr/local/bin/nvim", // for el9 clones, or "/usr/bin/nvim" for Fedora
167 | "workbench.list.automaticKeyboardNavigation": false,
168 | // various
169 | "window.titleBarStyle": "custom", // adjust the appearance of the window title bar for linux
170 | "editor.minimap.enabled": false, // controls whether the minimap is shown
171 | "workbench.activityBar.visible": false, // controls the visibility of the activity bar in the workbench
172 | "window.menuBarVisibility": "hidden", // control the visibility of the menu bar
173 | "files.restoreUndoStack": false, // don't restore the undo stack when a file is reopened
174 | "editor.dragAndDrop": false, // controls whether the editor should allow moving selections via drag and drop
175 | "telemetry.enableTelemetry": false, // disable diagnostic data collection
176 | }
177 | ```
178 | You might also like to install `ms-vscode.live-server` for live debugging in Code or the browser.
179 |
180 | If you get no bootable device found after installing Debian, try https://itsfoss.com/no-bootable-device-found-ubuntu/. Basically, add `shimx64.efi` as a trusted EFI file to be executed.
181 | > [!NOTE]
182 | > Bonus: If you are using Debian 12 as a VM don't forget to install `spice-vdagent` AND restart to get copy and paste working. It should be installed by default on a Debian 13 guest. You can check it is running with `sudo systemctl status spice-vdagent` and enable at boot if needed with `sudo systemctl enable spice-vdagent`.
183 |
184 | ### Updating from Bookworm to Trixie
185 |
186 | If you already have a clean installation of Bookworm and want to update to Trixie before using this playbook:
187 |
188 | 1. Check you have about 5 gig free disk space with `df -h`
189 | 2. `sudo apt-get update && sudo apt-get dist-upgrade --autoremove -y`
190 | 3. `sudo sed -i 's/bookworm/trixie/g' /etc/apt/sources.list`
191 | 4. `sudo apt-get update && sudo apt-get dist-upgrade --autoremove -y`
192 |
193 |
--------------------------------------------------------------------------------
/bashrc.bash:
--------------------------------------------------------------------------------
1 | # Aliases
2 | alias ls="ls -ltha --color --group-directories-first --hyperlink=auto"
3 | alias tree="tree -Catr --noreport --dirsfirst --filelimit 100"
4 | alias ebrc='xdg-open ~/.bashrc && source ~/.bashrc'
5 | alias ai="aichat"
6 | alias n="nnn"
7 |
8 | # Functions
9 | md() {
10 | filename="${1##*/}"
11 | pandoc --self-contained --metadata title="Preview" "$1" -o /tmp/"$filename".html
12 | xdg-open /tmp/"$filename".html
13 | }
14 |
15 | ghpr() { GH_FORCE_TTY=100% gh pr list --limit 300 |
16 | fzf --ansi --preview 'GH_FORCE_TTY=100% gh pr view {1}' --preview-window 'down,70%' --header-lines 3 |
17 | awk '{print $1}' |
18 | xargs gh pr checkout; }
19 |
20 | wordcount() { pandoc --lua-filter wordcount.lua "$@"; }
21 |
22 | # nnn
23 | [ -n "$NNNLVL" ] && PS1="N$NNNLVL $PS1" # prompt you are within a shell that will return you to nnn
24 |
25 | # fzf
26 | source /usr/share/doc/fzf/examples/key-bindings.bash
27 |
28 | # zoxide
29 | eval "$(zoxide init bash)"
30 |
31 | # aichat and aider
32 | export OPENAI_API_KEY="xxx"
33 | export TOGETHERAI_API_KEY="xxx"
34 | export TOGETHER_API_KEY="xxx"
35 |
36 | stty -ixon # disable terminal flow control
37 |
--------------------------------------------------------------------------------
/dotfiles/aichat/.config/aichat/config.yaml:
--------------------------------------------------------------------------------
1 | # model: openai:gpt-4o
2 | model: together:meta-llama/Llama-3.3-70B-Instruct-Turbo-Free
3 | keybindings: vi
4 | clients:
5 | # - type: openai
6 | - type: openai-compatible
7 | name: together
8 | api_base: https://api.together.xyz/v1
9 | models:
10 | - name: meta-llama/Llama-3.3-70B-Instruct-Turbo-Free
11 | max_input_tokens: 131072
12 | input_price: 0
13 | output_price: 0
14 | supports_function_calling: true
15 | - name: deepseek-ai/DeepSeek-V3
16 | max_input_tokens: 131072
17 | input_price: 1.25
18 | output_price: 1.25
19 | - name: deepseek-ai/DeepSeek-R1
20 | max_input_tokens: 163840
21 | input_price: 3
22 | output_price: 7
23 | - name: Qwen/Qwen3-235B-A22B-fp8-tput
24 | max_input_tokens: 131072
25 | input_price: 0.2
26 | output_price: 0.6
27 | patch:
28 | body:
29 | chat_template_kwargs: { "enable_thinking": false }
30 |
--------------------------------------------------------------------------------
/dotfiles/aichat/.config/aichat/dark.tmTheme:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Visual Studio Dark+
7 | author
8 | vidann1
9 | settings
10 |
11 |
12 | settings
13 |
14 | background
15 | #1E1E1E
16 | caret
17 | #DCDCDC
18 | foreground
19 | #DCDCDC
20 | invisibles
21 | #FFFFFF40
22 | lineHighlight
23 | #0F0F0F
24 | selection
25 | #264F78
26 |
27 |
28 |
29 | name
30 | Comment
31 | scope
32 | comment
33 | settings
34 |
35 | fontStyle
36 |
37 | foreground
38 | #608B4E
39 |
40 |
41 |
42 | name
43 | Variable
44 | scope
45 | variable
46 | settings
47 |
48 | fontStyle
49 |
50 | foreground
51 | #9CDCFE
52 |
53 |
54 |
55 | name
56 | Keyword
57 | scope
58 | keyword
59 | settings
60 |
61 | fontStyle
62 |
63 | foreground
64 | #C586C0
65 |
66 |
67 |
68 | name
69 | Comparision Operator
70 | scope
71 | keyword.operator.comparison
72 | settings
73 |
74 | fontStyle
75 |
76 | foreground
77 | #DCDCDC
78 |
79 |
80 |
81 | name
82 | Assignment Operator
83 | scope
84 | keyword.operator.assignment
85 | settings
86 |
87 | fontStyle
88 |
89 | foreground
90 | #DCDCDC
91 |
92 |
93 |
94 | name
95 | Arithmetic Operator
96 | scope
97 | keyword.operator.arithmetic
98 | settings
99 |
100 | fontStyle
101 |
102 | foreground
103 | #DCDCDC
104 |
105 |
106 |
107 | name
108 | Number
109 | scope
110 | constant.numeric
111 | settings
112 |
113 | fontStyle
114 |
115 | foreground
116 | #B5CEA8
117 |
118 |
119 |
120 | name
121 | User-defined constant
122 | scope
123 | constant
124 | settings
125 |
126 | fontStyle
127 |
128 | foreground
129 | #B4CEA8
130 |
131 |
132 |
133 | name
134 | Built-in constant
135 | scope
136 | constant.language
137 | settings
138 |
139 | fontStyle
140 |
141 | foreground
142 | #569CD6
143 |
144 |
145 |
146 | name
147 | Boolean
148 | scope
149 | constant.language.boolean
150 | settings
151 |
152 | fontStyle
153 |
154 | foreground
155 | #569CD6
156 |
157 |
158 |
159 | name
160 | String
161 | scope
162 | string
163 | settings
164 |
165 | fontStyle
166 |
167 | foreground
168 | #D69D85
169 |
170 |
171 |
172 | name
173 | String interpolation
174 | scope
175 | constant.character.escape, string source
176 | settings
177 |
178 | fontStyle
179 |
180 | foreground
181 | #E3BBAB
182 |
183 |
184 |
185 | name
186 | Preprocessor line
187 | scope
188 | meta.preprocessor
189 | settings
190 |
191 | fontStyle
192 |
193 | foreground
194 | #9B9B9B
195 |
196 |
197 |
198 | name
199 | Preprocessor directive
200 | scope
201 | keyword.control.import
202 | settings
203 |
204 | fontStyle
205 |
206 | foreground
207 | #C586C0
208 |
209 |
210 |
211 | name
212 | Function name
213 | scope
214 | entity.name.function, keyword.other.name-of-parameter.objc
215 | settings
216 |
217 | fontStyle
218 |
219 | foreground
220 | #DCDCAA
221 |
222 |
223 |
224 | name
225 | Class name
226 | scope
227 | entity.name.type
228 | settings
229 |
230 | fontStyle
231 |
232 | foreground
233 | #4EC9B0
234 |
235 |
236 |
237 | name
238 | Type name
239 | scope
240 | storage.type
241 | settings
242 |
243 | fontStyle
244 |
245 | foreground
246 | #569CD6
247 |
248 |
249 |
250 | name
251 | Type modifier
252 | scope
253 | storage.modifier
254 | settings
255 |
256 | fontStyle
257 |
258 | foreground
259 | #569CD6
260 |
261 |
262 |
263 | name
264 | Inherited class name
265 | scope
266 | entity.other.inherited-class
267 | settings
268 |
269 | fontStyle
270 |
271 | foreground
272 | #4EC9B0
273 |
274 |
275 |
276 | name
277 | Function parameter
278 | scope
279 | variable.parameter
280 | settings
281 |
282 | fontStyle
283 |
284 |
285 |
286 |
287 | name
288 | Function argument and result types
289 | scope
290 | storage.type.method
291 | settings
292 |
293 | fontStyle
294 |
295 | foreground
296 | #70727E
297 |
298 |
299 |
300 | name
301 | Section
302 | scope
303 | meta.section entity.name.section, declaration.section entity.name.section
304 | settings
305 |
306 | fontStyle
307 |
308 |
309 |
310 |
311 | name
312 | Library function
313 | scope
314 | support.function
315 | settings
316 |
317 | fontStyle
318 |
319 | foreground
320 | #DCDCDC
321 |
322 |
323 |
324 | name
325 | Library object
326 | scope
327 | support.class, support.type
328 | settings
329 |
330 | fontStyle
331 |
332 | foreground
333 | #DCDCDC
334 |
335 |
336 |
337 | name
338 | Library constant
339 | scope
340 | support.constant
341 | settings
342 |
343 | fontStyle
344 |
345 | foreground
346 | #B5CEA8
347 |
348 |
349 |
350 | name
351 | Library variable
352 | scope
353 | support.variable
354 | settings
355 |
356 | fontStyle
357 |
358 | foreground
359 | #DCDCDC
360 |
361 |
362 |
363 | name
364 | JS: Operator
365 | scope
366 | keyword.operator.js
367 | settings
368 |
369 | foreground
370 | #687687
371 |
372 |
373 |
374 | name
375 | Invalid
376 | scope
377 | invalid
378 | settings
379 |
380 | foreground
381 | #DCDCAA
382 |
383 |
384 |
385 | name
386 | Invalid trailing whitespace
387 | scope
388 | invalid.deprecated.trailing-whitespace
389 | settings
390 |
391 | background
392 | #ff3333
393 |
394 |
395 |
396 | name
397 | Embedded source
398 | scope
399 | text source, string.unquoted
400 | settings
401 |
402 | background
403 | #282828
404 |
405 |
406 |
407 | name
408 | Markup XML declaration
409 | scope
410 | meta.xml-processing, declaration.xml-processing
411 | settings
412 |
413 | fontStyle
414 |
415 | foreground
416 | #68685B
417 |
418 |
419 |
420 | name
421 | Markup DOCTYPE
422 | scope
423 | meta.doctype, declaration.doctype
424 | settings
425 |
426 | fontStyle
427 |
428 | foreground
429 | #808080
430 |
431 |
432 |
433 | name
434 | Markup DTD
435 | scope
436 | meta.doctype.DTD, declaration.doctype.DTD
437 | settings
438 |
439 | fontStyle
440 |
441 |
442 |
443 |
444 | name
445 | Markup tag
446 | scope
447 | meta.tag, declaration.tag
448 | settings
449 |
450 | fontStyle
451 |
452 | foreground
453 | #808080
454 |
455 |
456 |
457 | name
458 | Markup name of tag
459 | scope
460 | entity.name.tag
461 | settings
462 |
463 | fontStyle
464 |
465 | foreground
466 | #569CD6
467 |
468 |
469 |
470 | name
471 | Markup tag attribute
472 | scope
473 | entity.other.attribute-name
474 | settings
475 |
476 | fontStyle
477 |
478 | foreground
479 | #92CAF4
480 |
481 |
482 |
483 | name
484 | Markup: Attribute Value
485 | scope
486 | string.quoted.double.xml, string.quoted.double.html
487 | settings
488 |
489 | fontStyle
490 |
491 | foreground
492 | #C8C8C8
493 |
494 |
495 |
496 | name
497 | Markup: Heading
498 | scope
499 | markup.heading
500 | settings
501 |
502 | fontStyle
503 |
504 | foreground
505 | #569CD6
506 |
507 |
508 |
509 | name
510 | Markup: Quote
511 | scope
512 | markup.quote
513 | settings
514 |
515 | fontStyle
516 |
517 | foreground
518 | #DCDCDC
519 |
520 |
521 |
522 | name
523 | Markup: List
524 | scope
525 | markup.list
526 | settings
527 |
528 | foreground
529 | #DCDCDC
530 |
531 |
532 |
533 | name
534 | § css tag-name
535 | scope
536 | meta.selector.css entity.name.tag
537 | settings
538 |
539 | foreground
540 | #D7BA7D
541 |
542 |
543 |
544 | name
545 | § css:pseudo-class
546 | scope
547 | meta.selector.css entity.other.attribute-name.tag.pseudo-class
548 | settings
549 |
550 | foreground
551 | #D7BA7D
552 |
553 |
554 |
555 | name
556 | § css#id
557 | scope
558 | meta.selector.css entity.other.attribute-name.id
559 | settings
560 |
561 | foreground
562 | #D7BA7D
563 |
564 |
565 |
566 | name
567 | § css.class
568 | scope
569 | meta.selector.css entity.other.attribute-name.class
570 | settings
571 |
572 | foreground
573 | #D7BA7D
574 |
575 |
576 |
577 | name
578 | § css property-name:
579 | scope
580 | support.type.property-name.css
581 | settings
582 |
583 | foreground
584 | #9CDCFE
585 |
586 |
587 |
588 | name
589 | § css property-value;
590 | scope
591 | meta.property-group support.constant.property-value.css, meta.property-value support.constant.property-value.css
592 | settings
593 |
594 | foreground
595 | #C8C8C8
596 |
597 |
598 |
599 | name
600 | § css @at-rule
601 | scope
602 | meta.preprocessor.at-rule keyword.control.at-rule
603 | settings
604 |
605 | foreground
606 | #87CEFA
607 |
608 |
609 |
610 | name
611 | C#: XML Comment Tags
612 | scope
613 | source.cs comment.block.documentation.source.cs meta.tag.xml, source.cs comment.block.documentation.source.cs meta.tag.xml entity.name.tag.localname.xml, source.cs comment.block.documentation.source.cs meta.tag.xml entity.other.attribute-name
614 | settings
615 |
616 | foreground
617 | #608B4E
618 |
619 |
620 |
621 | name
622 | GitGutter deleted
623 | scope
624 | markup.deleted.git_gutter
625 | settings
626 |
627 | foreground
628 | #F92672
629 |
630 |
631 |
632 | name
633 | GitGutter inserted
634 | scope
635 | markup.inserted.git_gutter
636 | settings
637 |
638 | foreground
639 | #A6E22E
640 |
641 |
642 |
643 | name
644 | GitGutter changed
645 | scope
646 | markup.changed.git_gutter
647 | settings
648 |
649 | foreground
650 | #967EFB
651 |
652 |
653 |
654 | name
655 | GitGutter ignored
656 | scope
657 | markup.ignored.git_gutter
658 | settings
659 |
660 | foreground
661 | #565656
662 |
663 |
664 |
665 | name
666 | GitGutter untracked
667 | scope
668 | markup.untracked.git_gutter
669 | settings
670 |
671 | foreground
672 | #565656
673 |
674 |
675 |
676 | name
677 | Git Modified Line
678 | scope
679 | git.changes.x
680 | settings
681 |
682 | background
683 | #272852
684 |
685 |
686 |
687 | name
688 | Git Added Line
689 | scope
690 | git.changes.+
691 | settings
692 |
693 | background
694 | #275822
695 |
696 |
697 |
698 | name
699 | Git Remove Line
700 | scope
701 | git.changes.-
702 | settings
703 |
704 | background
705 | #A72822
706 |
707 |
708 |
709 | uuid
710 | 2fd1a8f9-ddfd-11e2-a28f-0800200c9a66
711 |
712 |
713 |
--------------------------------------------------------------------------------
/dotfiles/aichat/.config/aichat/roles/technical-writer.md:
--------------------------------------------------------------------------------
1 | Assume the role of a professional technical writer.
2 | Correct all spelling and grammar errors and improve readability.
3 |
--------------------------------------------------------------------------------
/dotfiles/autostart/.config/autostart/kitty.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Version=1.0
3 | Type=Application
4 | Name=kitty
5 | GenericName=Terminal emulator
6 | Comment=Fast, feature-rich, GPU based terminal
7 | TryExec=kitty
8 | StartupNotify=true
9 | Exec=kitty
10 | Icon=kitty
11 | Categories=System;TerminalEmulator;
12 |
--------------------------------------------------------------------------------
/dotfiles/autostart/.config/autostart/org.gnome.Calendar.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name[af]=Kalender
3 | Name[an]=Calandario
4 | Name[ar]=التقويم
5 | Name[be]=Каляндар
6 | Name[be@latin]=Kalandar
7 | Name[bg]=Календар
8 | Name[bs]=Kalendar
9 | Name[ca]=Calendari
10 | Name[ca@valencia]=Calendari
11 | Name[ckb]=ڕۆژژمێر
12 | Name[cs]=Kalendář
13 | Name[da]=Kalender
14 | Name[de]=Kalender
15 | Name[el]=Ημερολόγιο
16 | Name[en_GB]=Calendar
17 | Name[eo]=Kalendaro
18 | Name[es]=Calendario
19 | Name[et]=Kalender
20 | Name[eu]=Egutegia
21 | Name[fa]=تقویم
22 | Name[fi]=Kalenteri
23 | Name[fr]=Agenda
24 | Name[fur]=Calendari
25 | Name[fy]=Kalinder
26 | Name[ga]=Féilire
27 | Name[gd]=Am mìosachan
28 | Name[gl]=Calendario
29 | Name[he]=לוח שנה
30 | Name[hi]=कैलेंडर
31 | Name[hr]=Kalendar
32 | Name[hu]=Naptár
33 | Name[id]=Kalender
34 | Name[is]=Dagatal
35 | Name[it]=Calendario
36 | Name[ja]=カレンダー
37 | Name[ka]=კალენდარი
38 | Name[kab]=Awitay
39 | Name[kk]=Күнтізбе
40 | Name[ko]=달력
41 | Name[lt]=Kalendorius
42 | Name[lv]=Kalendārs
43 | Name[mjw]=Calendar
44 | Name[ml]=കലണ്ടർ
45 | Name[ms]=Kalendar
46 | Name[my]=ပြက္ခဒိန်
47 | Name[nb]=Kalender
48 | Name[ne]=पात्रो
49 | Name[nl]=Agenda
50 | Name[oc]=Agenda
51 | Name[pa]=ਕੈਲੰਡਰ
52 | Name[pl]=Kalendarz
53 | Name[pt]=Calendário
54 | Name[pt_BR]=Calendário
55 | Name[ro]=Calendar
56 | Name[ru]=Календарь
57 | Name[sk]=Kalendár
58 | Name[sl]=Koledar
59 | Name[sr]=Календар
60 | Name[sr@latin]=Kalendar
61 | Name[sv]=Kalender
62 | Name[ta]=நாள்காட்டி
63 | Name[tg]=Тақвим
64 | Name[th]=ปฏิทิน
65 | Name[tr]=Takvim
66 | Name[uk]=Календар
67 | Name[vi]=Lịch
68 | Name[zh_CN]=日历
69 | Name[zh_HK]=行事曆
70 | Name[zh_TW]=行事曆
71 | Name=Calendar
72 | Comment[af]=Kry toegang tot en bestuur jou kalenders
73 | Comment[ar]=انفذ إلى تقاويمك و أدرها
74 | Comment[be]=Доступ і кіраванне календарамі
75 | Comment[be@latin]=Dostup i kiravannie kalendarami
76 | Comment[bg]=Достъп и управление на календари
77 | Comment[ca]=Accedeix i gestiona els calendaris
78 | Comment[ca@valencia]=Accedeix i gestiona els calendaris
79 | Comment[ckb]=بچۆناوەو و ڕۆژژمێرەکەت ڕێکبخە
80 | Comment[cs]=Zobrazte si a spravujte své kalendáře
81 | Comment[da]=Tilgå og håndtér dine kalendere
82 | Comment[de]=Auf Ihre Kalender zugreifen und verwalten
83 | Comment[el]=Πρόσβαση και διαχείριση του ημερολογίου σας
84 | Comment[en_GB]=Access and manage your calendars
85 | Comment[eo]=Aliri kaj viajn kalendarojn
86 | Comment[es]=Acceder y gestionar sus calendarios
87 | Comment[et]=Isiklike kalendrite vaatamine ja haldamine
88 | Comment[eu]=Atzitu eta kudeatu zure egutegiak
89 | Comment[fa]=نمایش و مدیریت تقویمهایتان
90 | Comment[fi]=Hallitse aikatauluasi kalenterin avulla
91 | Comment[fr]=Ouvrir et gérer vos agendas
92 | Comment[fur]=Jentre e ministre i tiei calendaris
93 | Comment[fy]=Krij tagong ta en besjoch jo kalinders
94 | Comment[gd]=Inntrig is stiùirich na mìosachain agad
95 | Comment[gl]=Acceder e xestionar un calendario
96 | Comment[he]=גישה וניהול לוחות שנה
97 | Comment[hi]=अपने कैलेंडर तक पहुंचें और प्रबंधित करें
98 | Comment[hr]=Pristupite i upravljajte svojim kalendarom
99 | Comment[hu]=Naptárak elérése és kezelése
100 | Comment[id]=Akses dan kelola kalender Anda
101 | Comment[is]=Skoða og sýsla með dagatöl
102 | Comment[it]=Accede e gestisce i propri calendari
103 | Comment[ja]=カレンダーへのアクセスと管理
104 | Comment[ka]=კალენდრების მართვა
105 | Comment[kab]=Kcem, tesferkeḍ iwitayen-ik
106 | Comment[kk]=Күнтізбелеріңізге қатынау және басқару
107 | Comment[ko]=달력에 접근하고 관리합니다
108 | Comment[lt]=Prieikite ir tvarkykite savo kalendorius
109 | Comment[lv]=Piekļūstiet un pārvaldiet savus kalendārus
110 | Comment[ml]=താങ്കളുടെ കലണ്ടറുകൾ കാണുകയും നിയന്ത്രിക്കുകയും ചെയ്യുക
111 | Comment[ms]=Capai dan urus kalendar anda
112 | Comment[my]=သင့်ပြက္ခဒိန်များကို ဝင်ရောက် စီမံပါ
113 | Comment[nb]=Hold styr på livet ditt
114 | Comment[ne]=पात्रो पहुच र ब्यवस्थापन गर्नुहोस
115 | Comment[nl]=Beheer en gebruik uw agenda’s
116 | Comment[oc]=Dobrir e gerir vòstres agendas
117 | Comment[pa]=ਆਪਣੇ ਕੈਲੰਡਰਾਂ ਨੂੰ ਵਰਤੋਂ ਅਤੇ ਬੰਦੋਬਸਤ ਕਰੋ
118 | Comment[pl]=Wyświetlanie i zarządzanie kalendarzem
119 | Comment[pt]=Aceda e gira os seus calendários
120 | Comment[pt_BR]=Acesse e gerencie seus calendários
121 | Comment[ro]=Accesați și administrați calendarele
122 | Comment[ru]=Доступ и управление календарями
123 | Comment[sk]=Zobrazujte a spravujte svoje kalendáre
124 | Comment[sl]=Upravljanje in urejanje koledarjev
125 | Comment[sr]=Приступите и управљајте календаром
126 | Comment[sr@latin]=Pristupite i upravljajte kalendarom
127 | Comment[sv]=Kom åt och hantera dina kalendrar
128 | Comment[th]=เข้าถึงและจัดการปฏิทินต่างๆ ของคุณ
129 | Comment[tr]=Takvimlerinize erişin ve yönetin
130 | Comment[uk]=Доступ та організування календарів
131 | Comment[vi]=Truy cập và quản lý lịch của mình
132 | Comment[zh_CN]=访问并管理日历
133 | Comment[zh_TW]=存取及管理您的行事曆
134 | Comment=Access and manage your calendars
135 | Exec=gnome-calendar %U
136 | # Translators: Do NOT translate or transliterate this text (this is an icon file name)!
137 | Icon=org.gnome.Calendar
138 | Terminal=false
139 | Type=Application
140 | StartupNotify=true
141 | Categories=GNOME;GTK;Office;Calendar;Core;
142 | # Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
143 | Keywords[af]=kalender;geleentheid;aanmanings;
144 | Keywords[an]=Calandario;Evento;Recordatorio;
145 | Keywords[ar]=Calendar;Event;Reminder;تقويم;حدث;تذكير;
146 | Keywords[be]=Calendar;Event;Reminder;Каляндар;Падзея;Напамін;
147 | Keywords[be@latin]=Calendar;Event;Reminder;Kalandar;Padzieja;Napamin;
148 | Keywords[bg]=calendar;event;reminder;календар;събития;напомняне;разписание;
149 | Keywords[bs]=Kalendar;Događaj;Podsjetnik;
150 | Keywords[ca]=Calendari;Cita;Recordatori;
151 | Keywords[ca@valencia]=Calendari;Cita;Recordatori;
152 | Keywords[ckb]=Calendar;Event;Reminder;
153 | Keywords[cs]=kalendář;událost;upomínka;připomenutí;
154 | Keywords[da]=Kalender;Begivenhed;Påmindelse;
155 | Keywords[de]=Calendar;Event;Reminder;Kalender;Termin;Erinnerung;
156 | Keywords[el]=Ημερολόγιο;Συμβάν;Υπενθύμιση;Calendar;Event;Reminder;
157 | Keywords[en_GB]=Calendar;Event;Reminder;
158 | Keywords[eo]=Kalendaro;Evento;Memorigilo;
159 | Keywords[es]=Calendario;Evento;Recordatorio;
160 | Keywords[et]=Calendar;Event;Reminder;Kalender;Sündmused;Meeldetuletused;Päevakava;
161 | Keywords[eu]=Egutegia;Gertaera;Oroigarria;
162 | Keywords[fa]=Calendar;Event;Reminder;تقویم;رویداد;یادآوری;
163 | Keywords[fi]=Calendar;Event;Reminder;Kalenteri;Tapahtuma;Muistutus;
164 | Keywords[fr]=Agenda;Évènement;Rappel;
165 | Keywords[fur]=Calendari;Lunari;Event;Events;Promemorie;
166 | Keywords[fy]=Kalinder;Evenemint;Oantinkens;
167 | Keywords[gd]=Calendar;Event;Reminder;mìosachan;tachartas;cuimhneachan;
168 | Keywords[gl]=Calendario;Evento;Recordatorio;
169 | Keywords[he]=לוח שנה;יומן;אירוע;תזכיר;מזכיר;תזכורת;מזכר;
170 | Keywords[hi]=कैलेंडर;कार्यक्रम;अनुस्मारक;
171 | Keywords[hr]=Kalendar;Događaj;Podsjetnik;
172 | Keywords[hu]=Naptár;Esemény;Emlékeztető;
173 | Keywords[id]=Kalender;Acara;Pengingat;
174 | Keywords[is]=dagatal;viðburður;atburður;áminning;
175 | Keywords[it]=Calendario;Evento;Eventi;Promemoria;
176 | Keywords[ja]=Calendar;Event;Reminder;カレンダー;イベント;リマインダー;
177 | Keywords[ka]=Calendar;Event;Reminder;
178 | Keywords[kab]=Awitay;Tadyant;Asmekti;
179 | Keywords[kk]=Calendar;Event;Reminder;Күнтізбе;Оқиға;Естелік;
180 | Keywords[ko]=Calendar;달력;캘린더;Event;행사;이벤트;Reminder;알림;
181 | Keywords[lt]=Kalendorius;Įvykis;Priminimas;
182 | Keywords[lv]=Kalendārs;Notikums;Atgādinājums;
183 | Keywords[mjw]=Calendar;Event;Reminder;
184 | Keywords[ml]=Calendar;Event;Reminder;
185 | Keywords[ms]=Kalendar;Peristiwa;Pemberitahuan;
186 | Keywords[my]=ပြက္ခဒိန်;အစီအစဉ်;သတိပေးချက်;
187 | Keywords[nb]=Kalender;Hendelser;Påminnelser;Timeplan;Tidsskjema;Ukeplan;Aktiviteter;Planlegger;
188 | Keywords[ne]=भित्तेपात्रो; नतिजा; स्मरणपत्र;
189 | Keywords[nl]=Calendar;Agenda;Kalender;Event;Afspraak;Evenement;Gebeurtenis;Reminder;Herinnering;
190 | Keywords[oc]=Agenda;Eveniment;Rapèl;
191 | Keywords[pa]=ਕੈਲੰਡਰ;ਈਵੈਂਟ;ਰੀਮਾਈਡਰ;
192 | Keywords[pl]=Kalendarz;Wydarzenie;Zdarzenie;Przypomnienie;Przypominanie;
193 | Keywords[pt]=Calendário;Evento;Lembrete;
194 | Keywords[pt_BR]=Calendário;Agenda;Evento;Lembrete;
195 | Keywords[ro]=Calendar;Event;Reminder;Eveniment;Memento;
196 | Keywords[ru]=Календарь;Событие;Напоминание;
197 | Keywords[sk]=kalendár;udalosť;pripomienka;pripomenutie;
198 | Keywords[sl]=koledar;dogodki;dogodek;opomnik;opomniki;datum;calendar;task;reminder;date;
199 | Keywords[sr]=Calendar;Event;Reminder;Календар;Догађај;Подсетник;Kalendar;Događaj;Podsetnik;Dogadjaj;
200 | Keywords[sr@latin]=Calendar;Event;Reminder;Kalendar;Događaj;Podsetnik;Kalendar;Događaj;Podsetnik;Dogadjaj;
201 | Keywords[sv]=Kalender;Händelse;Påminnelse;
202 | Keywords[tg]=Тақвим;Рӯйдод;Ёдрасон;
203 | Keywords[th]=ปฏิทิน;งานกิจกรรม;ปลุกเตือน;
204 | Keywords[tr]=Calendar;Event;Reminder;Takvim;Olay;Etkinlik;Anımsatıcı;Hatırlatıcı;
205 | Keywords[uk]=Calendar;Event;Reminder;Календар;Подія;Нагадування;
206 | Keywords[vi]=Calendar;Event;Reminder;Lịch;Lich;Sự kiện;Su kien;Nhắc;Nhac;
207 | Keywords[zh_CN]=Calendar;Event;Reminder;日历;事件;提醒;
208 | Keywords[zh_TW]=Calendar;Event;Reminder;行事曆;事件;事件;活動;提醒;日曆;
209 | Keywords=Calendar;Event;Reminder;
210 | MimeType=text/calendar;
211 | DBusActivatable=true
212 |
--------------------------------------------------------------------------------
/dotfiles/autostart/.config/autostart/org.keepassxc.KeePassXC.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=KeePassXC
3 | GenericName=Password Manager
4 | GenericName[ar]=مدير كلمات المرور
5 | GenericName[bg]=Мениджър на пароли
6 | GenericName[ca]=Gestor de contrasenyes
7 | GenericName[cs]=Aplikace pro správu hesel
8 | GenericName[da]=Adgangskodehåndtering
9 | GenericName[de]=Passwortverwaltung
10 | GenericName[es]=Gestor de contraseñas
11 | GenericName[et]=Paroolihaldur
12 | GenericName[fi]=Salasanamanageri
13 | GenericName[fr]=Gestionnaire de mot de passe
14 | GenericName[hu]=Jelszókezelő
15 | GenericName[id]=Pengelola Sandi
16 | GenericName[it]=Gestione password
17 | GenericName[ja]=パスワードマネージャー
18 | GenericName[ko]=암호 관리자
19 | GenericName[lt]=Slaptažodžių tvarkytuvė
20 | GenericName[nb]=Passordhåndterer
21 | GenericName[nl]=Wachtwoordbeheer
22 | GenericName[pl]=Menedżer haseł
23 | GenericName[pt_BR]=Gerenciador de Senhas
24 | GenericName[pt]=Gestor de palavras-passe
25 | GenericName[ro]=Manager de parole
26 | GenericName[ru]=Менеджер паролей
27 | GenericName[sk]=Správca hesiel
28 | GenericName[sv]=Lösenordshanterare
29 | GenericName[th]=แอพจัดการรหัสผ่าน
30 | GenericName[tr]=Parola yöneticisi
31 | GenericName[uk]=Розпорядник паролів
32 | GenericName[zh_CN]=密码管理器
33 | GenericName[zh_TW]=密碼管理員
34 | Comment=Community-driven port of the Windows application “KeePass Password Safe”
35 | Comment[da]=Fællesskabsdrevet port af Windows-programmet “KeePass Password Safe”
36 | Comment[et]=Kogukonna arendatav port Windowsi programmist KeePass Password Safe
37 | Comment[ru]=Разработанный сообществом порт Windows-приложения KeePass Password Safe
38 | Exec=keepassxc %f
39 | TryExec=keepassxc
40 | Icon=keepassxc
41 | StartupWMClass=keepassxc
42 | StartupNotify=true
43 | Terminal=false
44 | Type=Application
45 | Version=1.5
46 | Categories=Utility;Security;Qt;
47 | MimeType=application/x-keepass2;
48 | SingleMainWindow=true
49 | X-GNOME-SingleWindow=true
50 | Keywords=security;privacy;password-manager;yubikey;password;keepass;
51 | Keywords[de]=sicherheit;privatsphäre;passwort-manager;yubikey;passwort;keepass;
52 |
--------------------------------------------------------------------------------
/dotfiles/config/.config/mimeapps.list:
--------------------------------------------------------------------------------
1 | [Default Applications]
2 | video/x-matroska=mpv.desktop
3 | video/mp4=mpv.desktop
4 | audio/x-opus+ogg=mpv.desktop
5 | text/vnd.trolltech.linguist=helix.desktop
6 | application/toml=helix.desktop
7 | text/plain=helix.desktop
8 | text/x-python=helix.desktop
9 | application/json=helix.desktop
10 | application/javascript=helix.desktop
11 | audio/flac=mpv.desktop
12 | application/x-shellscript=helix.desktop
13 | audio/prs.sid=sidplayfp.desktop
14 | text/csv=libreoffice-calc.desktop
15 | video/mpeg=mpv.desktop
16 |
17 | [Added Associations]
18 | video/x-matroska=mpv.desktop;
19 | video/mp4=mpv.desktop;
20 | audio/x-opus+ogg=mpv.desktop;
21 | text/vnd.trolltech.linguist=helix.desktop;
22 | application/toml=helix.desktop;
23 | text/plain=helix.desktop;
24 | text/x-python=helix.desktop;
25 | application/json=helix.desktop;
26 | application/javascript=helix.desktop;
27 | audio/flac=mpv.desktop;
28 | application/x-shellscript=helix.desktop;
29 | audio/prs.sid=sidplayfp.desktop;
30 | text/csv=libreoffice-calc.desktop;
31 | video/mpeg=mpv.desktop;
32 |
--------------------------------------------------------------------------------
/dotfiles/helix/.config/helix/config.toml:
--------------------------------------------------------------------------------
1 | theme = "dark_plus"
2 |
3 | [keys.normal]
4 | C-j = "page_down"
5 | C-k = ["page_up", "goto_window_top"]
6 | G = "goto_file_end"
7 | C-l = "goto_next_buffer"
8 | C-h = "goto_previous_buffer"
9 | "tab" = "expand_selection"
10 | "S-tab" = "shrink_selection"
11 | "F5" = ":reload"
12 | "@" = ["select_all", ":pipe sort -t@ -k2,2r"]
13 | "+" = ["select_all", ":pipe sort -t+ -k2,2r"]
14 | Z = { Z = ":wq", Q = ":q!" }
15 |
16 | [keys.select]
17 | G = "goto_file_end"
18 |
19 | [keys.normal.space]
20 | w = ":write"
21 | q = ":quit"
22 | l = ":sh kitty @ launch --no-response --cwd=current --type=overlay --copy-env lazygit"
23 |
24 | [keys.normal.space.t]
25 | f = ":toggle auto-format"
26 | "." = ":toggle file-picker.hidden" # toggles ignoring hidden files
27 | i = ":toggle lsp.display-inlay-hints"
28 | s = ":toggle soft-wrap.enable"
29 | z = ":toggle gutters.line-numbers.min-width 52 3"
30 | b = ":toggle bufferline multiple never"
31 |
32 | [keys.normal.C-space]
33 | n = "@:o %"
34 | x = "@:sh rm %"
35 | r = "@:sh mv % %"
36 | g = [":pipe-to cat > /tmp/helix-gpt", ":append-output cat /tmp/helix-gpt | aichat --role technical-writer"]
37 | p = "@:sh pandoc --resource-path % --self-contained --metadata title='Preview' % -o /tmp/md-preview.html && xdg-open /tmp/md-preview.html"
38 | d = ":pipe echo -n $(date +%d-%m-%Y)"
39 | t = ":sh kitty @ focus-window --match 'title:terminal and state:parent_active' || kitty @ launch --no-response --keep-focus --cwd=current --title=terminal"
40 | a = ":sh kitty @ launch --no-response --title=aichat aichat --role technical-writer"
41 | i = ":sh kitty @ signal-child --match 'title:terminal and state:parent_active' SIGINT"
42 | m = { r = ":sh kitty @ send-text --match 'title:terminal and state:parent_active' 'make run\n'", b = ":sh kitty @ send-text --match 'title:terminal and state:parent_active' 'make build\n'", t = ":sh kitty @ send-text --match 'title:terminal and state:parent_active' 'clear\nmake test\n'"}
43 | s = ":pipe-to xargs -I {} kitty @ send-text --match title:terminal and state:parent_active '{}\n'"
44 |
45 | [editor]
46 | color-modes = true
47 | end-of-line-diagnostics = "hint"
48 | bufferline = "multiple"
49 | default-yank-register = "+"
50 |
51 | [editor.whitespace.render]
52 | newline = "all"
53 |
54 | [editor.cursor-shape]
55 | insert = "bar"
56 |
57 | [editor.file-picker]
58 | follow-symlinks = false
59 | hidden = false # don't ignore hidden files
60 |
61 | [editor.statusline]
62 | center = ["version-control"]
63 |
64 | [editor.soft-wrap]
65 | enable = true
66 | wrap-at-text-width = true
67 |
68 | [editor.inline-diagnostics]
69 | cursor-line = "warning"
70 |
--------------------------------------------------------------------------------
/dotfiles/helix/.config/helix/languages.toml:
--------------------------------------------------------------------------------
1 | [language-server.rust-analyzer.config]
2 | check.command = "clippy"
3 |
4 | [language-server.ltex-ls-plus.config]
5 | ltex.diagnosticSeverity = "warning"
6 | ltex.disabledRules = { "en-US" = ["PROFANITY"], "en-GB" = ["PROFANITY"] }
7 | ltex.dictionary = { "en-US" = ["builtin"], "en-GB" = ["builtin"] }
8 |
9 | [[language]]
10 | name = "markdown"
11 | text-width = 80
12 | soft-wrap = { wrap-at-text-width = true }
13 | language-servers = ["marksman", "ltex-ls-plus"]
14 | formatter = { command = 'prettier', args = [
15 | "--parser",
16 | "markdown",
17 | "--prose-wrap",
18 | "never", #
19 | ] }
20 | # auto-format = true
21 |
22 | [[language]]
23 | name = "html"
24 | language-servers = [ "vscode-html-language-server", "tailwindcss-ls" ]
25 | formatter = { command = 'prettier', args = ["--parser", "html"] }
26 |
27 | [[language]]
28 | name = "json"
29 | formatter = { command = 'prettier', args = ["--parser", "json"] }
30 |
31 | [[language]]
32 | name = "css"
33 | language-servers = [ "vscode-css-language-server", "tailwindcss-ls" ]
34 | formatter = { command = 'prettier', args = ["--parser", "css"] }
35 |
36 | [[language]]
37 | name = "yaml"
38 | formatter = { command = 'prettier', args = ["--parser", "yaml"] }
39 | auto-format = true
40 |
41 | [[language]]
42 | name = "javascript"
43 | formatter = { command = 'prettier', args = ["--parser", "typescript"] }
44 | auto-format = true
45 |
46 | [[language]]
47 | name = "typescript"
48 | formatter = { command = 'prettier', args = ["--parser", "typescript"] }
49 | auto-format = true
50 |
51 | [[language]]
52 | name = "bash"
53 | formatter = { command = 'shfmt', args = ["-i", "4"] }
54 | auto-format = true
55 |
56 | [[language]]
57 | name = "git-commit"
58 | language-servers = ["ltex-ls-plus"]
59 |
60 | [[language]]
61 | name = "python"
62 | formatter = { command = "black", args = ["--quiet", "-"] }
63 | auto-format = true
64 | language-servers = ["pyright"]
65 | # pyproject.toml
66 | # [tool.pyright]
67 | # typeCheckingMode = "strict"
68 |
--------------------------------------------------------------------------------
/dotfiles/keepassxc/.config/keepassxc/keepassxc.ini:
--------------------------------------------------------------------------------
1 | [Browser]
2 | CustomProxyLocation=
3 | Enabled=true
4 |
5 | [SSHAgent]
6 | Enabled=true
7 |
8 | [Security]
9 | LockDatabaseScreenLock=false
10 |
--------------------------------------------------------------------------------
/dotfiles/kitty/.config/kitty/kitty.conf:
--------------------------------------------------------------------------------
1 | font_size 12.0
2 | hide_window_decorations yes
3 | enabled_layouts tall,stack
4 | enable_audio_bell no
5 | wayland_enable_ime no
6 | copy_on_select yes
7 |
8 | tab_bar_edge top
9 | tab_bar_style separator
10 | tab_separator " | "
11 |
12 | allow_remote_control yes
13 | listen_on unix:/tmp/kitty
14 |
15 | map ctrl+= change_font_size all 22.0
16 | map ctrl+enter launch --cwd=current
17 | map ctrl+t new_tab
18 | map ctrl+k scroll_line_up
19 | map ctrl+j scroll_line_down
20 | map ctrl+] next_window
21 | map ctrl+[ previous_window
22 | map alt+l next_layout
23 | # map alt+s launch --cwd=current --type background bash -c 'random=$RANDOM && gnome-screenshot -f "./screenshot_$random.png" && krita "./screenshot_$random.png"'
24 |
25 | # use script with `cat - | ansi2html > path/to/screenshot.html`
26 | # map alt+s launch --type background --stdin-source=@screen --stdin-add-formatting sh path/to/terminal-screen-shot.sh
27 |
--------------------------------------------------------------------------------
/dotfiles/lazygit/.config/lazygit/config.yml:
--------------------------------------------------------------------------------
1 | git:
2 | paging:
3 | colorArg: always
4 | pager: delta --paging=never --side-by-side
5 |
6 | gui:
7 | nerdFontsVersion: "3"
8 | screenMode: half
9 | enlargedSideViewLocation: top
10 | showCommandLog: false
11 |
12 | keybinding:
13 | universal:
14 | scrollUpMain-alt1:
15 | scrollDownMain-alt1:
16 |
17 | promptToReturnFromSubprocess: false
18 |
--------------------------------------------------------------------------------
/dotfiles/marksman/.config/marksman/config.toml:
--------------------------------------------------------------------------------
1 | [code_action]
2 | # Enable/disable "Table of Contents" code action
3 | toc.enable = false
4 |
--------------------------------------------------------------------------------
/dotfiles/mpv/.config/mpv/input.conf:
--------------------------------------------------------------------------------
1 | l seek +5
2 | h seek -5
3 | ctrl+l playlist-next
4 | ctrl+h playlist-prev
5 | ctrl+p show-text ${playlist} 2000
6 |
7 | GAMEPAD_ACTION_DOWN cycle pause
8 | GAMEPAD_ACTION_RIGHT add chapter 1
9 | GAMEPAD_ACTION_LEFT add chapter -1
10 | GAMEPAD_MENU quit
11 | GAMEPAD_RIGHT_STICK_RIGHT seek +5
12 | GAMEPAD_RIGHT_STICK_LEFT seek -5
13 | GAMEPAD_DPAD_UP add volume 2
14 | GAMEPAD_DPAD_DOWN add volume -2
15 | GAMEPAD_DPAD_LEFT cycle audio
16 | GAMEPAD_DPAD_RIGHT cycle sub
17 | GAMEPAD_START script_binding file_browser/browse-files
18 | GAMEPAD_BACK show-text ${playlist} 3000
19 |
--------------------------------------------------------------------------------
/dotfiles/mpv/.config/mpv/mpv.conf:
--------------------------------------------------------------------------------
1 | profile=high-quality
2 | hwdec=auto-safe
3 | fullscreen=yes
4 | input-gamepad=yes
5 | osd-font-size=25
6 |
7 | autocreate-playlist=filter
8 | directory-mode=ignore
9 | directory-filter-types=video,audio
10 |
--------------------------------------------------------------------------------
/dotfiles/pandoc/.local/share/pandoc/filters/diagram-generator.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | diagram-generator – create images and figures from code blocks.
3 |
4 | This Lua filter is used to create images with or without captions
5 | from code blocks. Currently PlantUML, GraphViz, Tikz, and Python
6 | can be processed. For further details, see README.md.
7 |
8 | Copyright: © 2018-2021 John MacFarlane ,
9 | 2018 Florian Schätzig ,
10 | 2019 Thorsten Sommer ,
11 | 2019-2021 Albert Krewinkel
12 | License: MIT – see LICENSE file for details
13 | ]]
14 | -- Module pandoc.system is required and was added in version 2.7.3
15 | PANDOC_VERSION:must_be_at_least '2.7.3'
16 |
17 | local system = require 'pandoc.system'
18 | local utils = require 'pandoc.utils'
19 | local stringify = function (s)
20 | return type(s) == 'string' and s or utils.stringify(s)
21 | end
22 | local with_temporary_directory = system.with_temporary_directory
23 | local with_working_directory = system.with_working_directory
24 |
25 | -- The PlantUML path. If set, uses the environment variable PLANTUML or the
26 | -- value "plantuml.jar" (local PlantUML version). In order to define a
27 | -- PlantUML version per pandoc document, use the meta data to define the key
28 | -- "plantuml_path".
29 | local plantuml_path = os.getenv("PLANTUML") or "plantuml.jar"
30 |
31 | -- The Inkscape path. In order to define an Inkscape version per pandoc
32 | -- document, use the meta data to define the key "inkscape_path".
33 | local inkscape_path = os.getenv("INKSCAPE") or "inkscape"
34 |
35 | -- The Python path. In order to define a Python version per pandoc document,
36 | -- use the meta data to define the key "python_path".
37 | local python_path = os.getenv("PYTHON") or "python"
38 |
39 | -- The Python environment's activate script. Can be set on a per document
40 | -- basis by using the meta data key "activatePythonPath".
41 | local python_activate_path = os.getenv("PYTHON_ACTIVATE")
42 |
43 | -- The Java path. In order to define a Java version per pandoc document,
44 | -- use the meta data to define the key "java_path".
45 | local java_path = os.getenv("JAVA_HOME")
46 | if java_path then
47 | java_path = java_path .. package.config:sub(1,1) .. "bin"
48 | .. package.config:sub(1,1) .. "java"
49 | else
50 | java_path = "java"
51 | end
52 |
53 | -- The dot (Graphviz) path. In order to define a dot version per pandoc
54 | -- document, use the meta data to define the key "dot_path".
55 | local dot_path = os.getenv("DOT") or "dot"
56 |
57 | -- The pdflatex path. In order to define a pdflatex version per pandoc
58 | -- document, use the meta data to define the key "pdflatex_path".
59 | local pdflatex_path = os.getenv("PDFLATEX") or "pdflatex"
60 |
61 | -- The asymptote path. There is also the metadata variable
62 | -- "asymptote_path".
63 | local asymptote_path = os.getenv ("ASYMPTOTE") or "asy"
64 |
65 | -- The default format is SVG i.e. vector graphics:
66 | local filetype = "svg"
67 | local mimetype = "image/svg+xml"
68 |
69 | -- Check for output formats that potentially cannot use SVG
70 | -- vector graphics. In these cases, we use a different format
71 | -- such as PNG:
72 | if FORMAT == "docx" then
73 | filetype = "png"
74 | mimetype = "image/png"
75 | elseif FORMAT == "pptx" then
76 | filetype = "png"
77 | mimetype = "image/png"
78 | elseif FORMAT == "rtf" then
79 | filetype = "png"
80 | mimetype = "image/png"
81 | end
82 |
83 | -- Execute the meta data table to determine the paths. This function
84 | -- must be called first to get the desired path. If one of these
85 | -- meta options was set, it gets used instead of the corresponding
86 | -- environment variable:
87 | function Meta(meta)
88 | plantuml_path = stringify(
89 | meta.plantuml_path or meta.plantumlPath or plantuml_path
90 | )
91 | inkscape_path = stringify(
92 | meta.inkscape_path or meta.inkscapePath or inkscape_path
93 | )
94 | python_path = stringify(
95 | meta.python_path or meta.pythonPath or python_path
96 | )
97 | python_activate_path =
98 | meta.activate_python_path or meta.activatePythonPath or python_activate_path
99 | python_activate_path = python_activate_path and stringify(python_activate_path)
100 | java_path = stringify(
101 | meta.java_path or meta.javaPath or java_path
102 | )
103 | dot_path = stringify(
104 | meta.path_dot or meta.dotPath or dot_path
105 | )
106 | pdflatex_path = stringify(
107 | meta.pdflatex_path or meta.pdflatexPath or pdflatex_path
108 | )
109 | asymptote_path = stringify(
110 | meta.asymptote_path or meta.asymptotePath or asymptote_path
111 | )
112 | end
113 |
114 | -- Call plantuml.jar with some parameters (cf. PlantUML help):
115 | local function plantuml(puml, filetype)
116 | return pandoc.pipe(
117 | java_path,
118 | {"-jar", plantuml_path, "-t" .. filetype, "-pipe", "-charset", "UTF8"},
119 | puml
120 | )
121 | end
122 |
123 | -- Call dot (GraphViz) in order to generate the image
124 | -- (thanks @muxueqz for this code):
125 | local function graphviz(code, filetype)
126 | return pandoc.pipe(dot_path, {"-T" .. filetype}, code)
127 | end
128 |
129 | --
130 | -- TikZ
131 | --
132 |
133 | --- LaTeX template used to compile TikZ images. Takes additional
134 | --- packages as the first, and the actual TikZ code as the second
135 | --- argument.
136 | local tikz_template = [[
137 | \documentclass{standalone}
138 | \usepackage{tikz}
139 | %% begin: additional packages
140 | %s
141 | %% end: additional packages
142 | \begin{document}
143 | %s
144 | \end{document}
145 | ]]
146 |
147 | -- Returns a function which takes the filename of a PDF or SVG file
148 | -- and a target filename, and writes the input as the given format.
149 | -- Returns `nil` if conversion into the target format is not possible.
150 | local function convert_with_inkscape(filetype)
151 | -- Build the basic Inkscape command for the conversion
152 | local inkscape_output_args
153 |
154 | -- Check inksape version.
155 | -- TODO: this can be removed if supporting older Inkscape is not important.
156 | local inkscape_v_string = io.popen(inkscape_path .. " --version"):read()
157 | local inkscape_v_major = inkscape_v_string:gmatch("([0-9]*)%.")()
158 | local isv1 = tonumber(inkscape_v_major) >= 1
159 |
160 | local cmd_arg = isv1 and '"%s" "%s" -o "%s" ' or '"%s" --without-gui --file="%s" '
161 |
162 | if filetype == 'png' then
163 | local png_arg = isv1 and '--export-type=png' or '--export-png="%s"'
164 | output_args = png_arg .. '--export-dpi=300'
165 | elseif filetype == 'svg' then
166 | output_args = isv1 and '--export-type=svg --export-plain-svg' or '--export-plain-svg="%s"'
167 | else
168 | return nil
169 | end
170 |
171 | return function (pdf_file, outfile)
172 | local inkscape_command = string.format(
173 | cmd_arg .. output_args,
174 | inkscape_path,
175 | pdf_file,
176 | outfile
177 | )
178 | local command_output = io.popen(inkscape_command)
179 | -- TODO: print output when debugging.
180 | command_output:close()
181 | end
182 | end
183 |
184 | --- Compile LaTeX with Tikz code to an image
185 | local function tikz2image(src, filetype, additional_packages)
186 | local convert = convert_with_inkscape(filetype)
187 | -- Bail if there is now known way from PDF to the target format.
188 | if not convert then
189 | error(string.format("Don't know how to convert pdf to %s.", filetype))
190 | end
191 | return with_temporary_directory("tikz2image", function (tmpdir)
192 | return with_working_directory(tmpdir, function ()
193 | -- Define file names:
194 | local file_template = "%s/tikz-image.%s"
195 | local tikz_file = file_template:format(tmpdir, "tex")
196 | local pdf_file = file_template:format(tmpdir, "pdf")
197 | local outfile = file_template:format(tmpdir, filetype)
198 |
199 | -- Build and write the LaTeX document:
200 | local f = io.open(tikz_file, 'w')
201 | f:write(tikz_template:format(additional_packages or '', src))
202 | f:close()
203 |
204 | -- Execute the LaTeX compiler:
205 | pandoc.pipe(pdflatex_path, {'-output-directory', tmpdir, tikz_file}, '')
206 |
207 | convert(pdf_file, outfile)
208 |
209 | -- Try to open and read the image:
210 | local img_data
211 | local r = io.open(outfile, 'rb')
212 | if r then
213 | img_data = r:read("*all")
214 | r:close()
215 | else
216 | -- TODO: print warning
217 | end
218 |
219 | return img_data
220 | end)
221 | end)
222 | end
223 |
224 | -- Run Python to generate an image:
225 | local function py2image(code, filetype)
226 |
227 | -- Define the temp files:
228 | local outfile = string.format('%s.%s', os.tmpname(), filetype)
229 | local pyfile = os.tmpname()
230 |
231 | -- Replace the desired destination's file type in the Python code:
232 | local extendedCode = string.gsub(code, "%$FORMAT%$", filetype)
233 |
234 | -- Replace the desired destination's path in the Python code:
235 | extendedCode = string.gsub(extendedCode, "%$DESTINATION%$", outfile)
236 |
237 | -- Write the Python code:
238 | local f = io.open(pyfile, 'w')
239 | f:write(extendedCode)
240 | f:close()
241 |
242 | -- Execute Python in the desired environment:
243 | local pycmd = python_path .. ' ' .. pyfile
244 | local command = python_activate_path
245 | and python_activate_path .. ' && ' .. pycmd
246 | or pycmd
247 | os.execute(command)
248 |
249 | -- Try to open the written image:
250 | local r = io.open(outfile, 'rb')
251 | local imgData = nil
252 |
253 | -- When the image exist, read it:
254 | if r then
255 | imgData = r:read("*all")
256 | r:close()
257 | else
258 | io.stderr:write(string.format("File '%s' could not be opened", outfile))
259 | error 'Could not create image from python code.'
260 | end
261 |
262 | -- Delete the tmp files:
263 | os.remove(pyfile)
264 | os.remove(outfile)
265 |
266 | return imgData
267 | end
268 |
269 | --
270 | -- Asymptote
271 | --
272 |
273 | local function asymptote(code, filetype)
274 | local convert
275 | if filetype ~= 'svg' and filetype ~= 'png' then
276 | error(string.format("Conversion to %s not implemented", filetype))
277 | end
278 | return with_temporary_directory(
279 | "asymptote",
280 | function(tmpdir)
281 | return with_working_directory(
282 | tmpdir,
283 | function ()
284 | local asy_file = "pandoc_diagram.asy"
285 | local svg_file = "pandoc_diagram.svg"
286 | local f = io.open(asy_file, 'w')
287 | f:write(code)
288 | f:close()
289 |
290 | pandoc.pipe(asymptote_path, {"-f", "svg", "-o", "pandoc_diagram", asy_file}, "")
291 |
292 | local r
293 | if filetype == 'svg' then
294 | r = io.open(svg_file, 'rb')
295 | else
296 | local png_file = "pandoc_diagram.png"
297 | convert_with_inkscape("png")(svg_file, png_file)
298 | r = io.open(png_file, 'rb')
299 | end
300 |
301 | local img_data
302 | if r then
303 | img_data = r:read("*all")
304 | r:close()
305 | else
306 | error("could not read asymptote result file")
307 | end
308 | return img_data
309 | end)
310 | end)
311 | end
312 |
313 | -- Executes each document's code block to find matching code blocks:
314 | function CodeBlock(block)
315 | -- Using a table with all known generators i.e. converters:
316 | local converters = {
317 | plantuml = plantuml,
318 | graphviz = graphviz,
319 | tikz = tikz2image,
320 | py2image = py2image,
321 | asymptote = asymptote,
322 | }
323 |
324 | -- Check if a converter exists for this block. If not, return the block
325 | -- unchanged.
326 | local img_converter = converters[block.classes[1]]
327 | if not img_converter then
328 | return nil
329 | end
330 |
331 | -- Call the correct converter which belongs to the used class:
332 | local success, img = pcall(img_converter, block.text,
333 | filetype, block.attributes["additionalPackages"] or nil)
334 |
335 | -- Bail if an error occured; img contains the error message when that
336 | -- happens.
337 | if not (success and img) then
338 | io.stderr:write(tostring(img or "no image data has been returned."))
339 | io.stderr:write('\n')
340 | error 'Image conversion failed. Aborting.'
341 | end
342 |
343 | -- If we got here, then the transformation went ok and `img` contains
344 | -- the image data.
345 |
346 | -- Create figure name by hashing the image content
347 | local fname = pandoc.sha1(img) .. "." .. filetype
348 |
349 | -- Store the data in the media bag:
350 | pandoc.mediabag.insert(fname, mimetype, img)
351 |
352 | local enable_caption = nil
353 |
354 | -- If the user defines a caption, read it as Markdown.
355 | local caption = block.attributes.caption
356 | and pandoc.read(block.attributes.caption).blocks[1].content
357 | or {}
358 |
359 | -- A non-empty caption means that this image is a figure. We have to
360 | -- set the image title to "fig:" for pandoc to treat it as such.
361 | local title = #caption > 0 and "fig:" or ""
362 |
363 | -- Transfer identifier and other relevant attributes from the code
364 | -- block to the image. The `name` is kept as an attribute.
365 | -- This allows a figure block starting with:
366 | --
367 | -- ```{#fig:example .plantuml caption="Image created by **PlantUML**."}
368 | --
369 | -- to be referenced as @fig:example outside of the figure when used
370 | -- with `pandoc-crossref`.
371 | local img_attr = {
372 | id = block.identifier,
373 | name = block.attributes.name,
374 | width = block.attributes.width,
375 | height = block.attributes.height
376 | }
377 |
378 | -- Create a new image for the document's structure. Attach the user's
379 | -- caption. Also use a hack (fig:) to enforce pandoc to create a
380 | -- figure i.e. attach a caption to the image.
381 | local img_obj = pandoc.Image(caption, fname, title, img_attr)
382 |
383 | -- Finally, put the image inside an empty paragraph. By returning the
384 | -- resulting paragraph object, the source code block gets replaced by
385 | -- the image:
386 | return pandoc.Para{ img_obj }
387 | end
388 |
389 | -- Normally, pandoc will run the function in the built-in order Inlines ->
390 | -- Blocks -> Meta -> Pandoc. We instead want Meta -> Blocks. Thus, we must
391 | -- define our custom order:
392 | return {
393 | {Meta = Meta},
394 | {CodeBlock = CodeBlock},
395 | }
396 |
--------------------------------------------------------------------------------
/dotfiles/pandoc/.local/share/pandoc/filters/include-code-files.lua:
--------------------------------------------------------------------------------
1 | --- include-code-files.lua – filter to include code from source files
2 | ---
3 | --- Copyright: © 2020 Bruno BEAUFILS
4 | --- License: MIT – see LICENSE file for details
5 |
6 | --- Dedent a line
7 | local function dedent (line, n)
8 | return line:sub(1,n):gsub(" ","") .. line:sub(n+1)
9 | end
10 |
11 | --- Filter function for code blocks
12 | local function transclude (cb)
13 | if cb.attributes.include then
14 | local content = ""
15 | local fh = io.open(cb.attributes.include)
16 | if not fh then
17 | io.stderr:write("Cannot open file " .. cb.attributes.include .. " | Skipping includes\n")
18 | else
19 | local number = 1
20 | local start = 1
21 |
22 | -- change hyphenated attributes to PascalCase
23 | for i,pascal in pairs({"startLine", "endLine"})
24 | do
25 | local hyphen = pascal:gsub("%u", "-%0"):lower()
26 | if cb.attributes[hyphen] then
27 | cb.attributes[pascal] = cb.attributes[hyphen]
28 | cb.attributes[hyphen] = nil
29 | end
30 | end
31 |
32 | if cb.attributes.startLine then
33 | cb.attributes.startFrom = cb.attributes.startLine
34 | start = tonumber(cb.attributes.startLine)
35 | end
36 | for line in fh:lines ("L")
37 | do
38 | if cb.attributes.dedent then
39 | line = dedent(line, cb.attributes.dedent)
40 | end
41 | if number >= start then
42 | if not cb.attributes.endLine or number <= tonumber(cb.attributes.endLine) then
43 | content = content .. line
44 | end
45 | end
46 | number = number + 1
47 | end
48 | fh:close()
49 | end
50 | -- remove key-value pair for used keys
51 | cb.attributes.include = nil
52 | cb.attributes.startLine = nil
53 | cb.attributes.endLine = nil
54 | cb.attributes.dedent = nil
55 | -- return final code block
56 | return pandoc.CodeBlock(content, cb.attr)
57 | end
58 | end
59 |
60 | return {
61 | { CodeBlock = transclude }
62 | }
63 |
--------------------------------------------------------------------------------
/dotfiles/pandoc/.local/share/pandoc/filters/include-files.lua:
--------------------------------------------------------------------------------
1 | --- include-files.lua – filter to include Markdown files
2 | ---
3 | --- Copyright: © 2019–2021 Albert Krewinkel
4 | --- License: MIT – see LICENSE file for details
5 |
6 | -- Module pandoc.path is required and was added in version 2.12
7 | PANDOC_VERSION:must_be_at_least '2.12'
8 |
9 | local List = require 'pandoc.List'
10 | local path = require 'pandoc.path'
11 | local system = require 'pandoc.system'
12 |
13 | --- Get include auto mode
14 | local include_auto = false
15 | function get_vars (meta)
16 | if meta['include-auto'] then
17 | include_auto = true
18 | end
19 | end
20 |
21 | --- Keep last heading level found
22 | local last_heading_level = 0
23 | function update_last_level(header)
24 | last_heading_level = header.level
25 | end
26 |
27 | --- Update contents of included file
28 | local function update_contents(blocks, shift_by, include_path)
29 | local update_contents_filter = {
30 | -- Shift headings in block list by given number
31 | Header = function (header)
32 | if shift_by then
33 | header.level = header.level + shift_by
34 | end
35 | return header
36 | end,
37 | -- If image paths are relative then prepend include file path
38 | Image = function (image)
39 | if path.is_relative(image.src) then
40 | image.src = path.normalize(path.join({include_path, image.src}))
41 | end
42 | return image
43 | end,
44 | -- Update path for include-code-files.lua filter style CodeBlocks
45 | CodeBlock = function (cb)
46 | if cb.attributes.include and path.is_relative(cb.attributes.include) then
47 | cb.attributes.include =
48 | path.normalize(path.join({include_path, cb.attributes.include}))
49 | end
50 | return cb
51 | end
52 | }
53 |
54 | return pandoc.walk_block(pandoc.Div(blocks), update_contents_filter).content
55 | end
56 |
57 | --- Filter function for code blocks
58 | local transclude
59 | function transclude (cb)
60 | -- ignore code blocks which are not of class "include".
61 | if not cb.classes:includes 'include' then
62 | return
63 | end
64 |
65 | -- Markdown is used if this is nil.
66 | local format = cb.attributes['format']
67 |
68 | -- Attributes shift headings
69 | local shift_heading_level_by = 0
70 | local shift_input = cb.attributes['shift-heading-level-by']
71 | if shift_input then
72 | shift_heading_level_by = tonumber(shift_input)
73 | else
74 | if include_auto then
75 | -- Auto shift headings
76 | shift_heading_level_by = last_heading_level
77 | end
78 | end
79 |
80 | --- keep track of level before recusion
81 | local buffer_last_heading_level = last_heading_level
82 |
83 | local blocks = List:new()
84 | for line in cb.text:gmatch('[^\n]+') do
85 | if line:sub(1,2) ~= '//' then
86 | local fh = io.open(line)
87 | if not fh then
88 | io.stderr:write("Cannot open file " .. line .. " | Skipping includes\n")
89 | else
90 | -- read file as the given format with global reader options
91 | local contents = pandoc.read(
92 | fh:read '*a',
93 | format,
94 | PANDOC_READER_OPTIONS
95 | ).blocks
96 | last_heading_level = 0
97 | -- recursive transclusion
98 | contents = system.with_working_directory(
99 | path.directory(line),
100 | function ()
101 | return pandoc.walk_block(
102 | pandoc.Div(contents),
103 | { Header = update_last_level, CodeBlock = transclude }
104 | )
105 | end).content
106 | --- reset to level before recursion
107 | last_heading_level = buffer_last_heading_level
108 | blocks:extend(update_contents(contents, shift_heading_level_by,
109 | path.directory(line)))
110 | fh:close()
111 | end
112 | end
113 | end
114 | return blocks
115 | end
116 |
117 | return {
118 | { Meta = get_vars },
119 | { Header = update_last_level, CodeBlock = transclude }
120 | }
121 |
--------------------------------------------------------------------------------
/dotfiles/pandoc/.local/share/pandoc/filters/pagebreak.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | pagebreak – convert raw LaTeX page breaks to other formats
3 |
4 | Copyright © 2017-2021 Benct Philip Jonsson, Albert Krewinkel
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted, provided that the above
8 | copyright notice and this permission notice appear in all copies.
9 |
10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 | ]]
18 | local stringify_orig = (require 'pandoc.utils').stringify
19 |
20 | local function stringify(x)
21 | return type(x) == 'string' and x or stringify_orig(x)
22 | end
23 |
24 | --- configs – these are populated in the Meta filter.
25 | local pagebreak = {
26 | asciidoc = '<<<\n\n',
27 | context = '\\page',
28 | epub = '
',
29 | html = '',
30 | latex = '\\newpage{}',
31 | ms = '.bp',
32 | ooxml = '',
33 | odt = ''
34 | }
35 |
36 | local function pagebreaks_from_config (meta)
37 | local html_class =
38 | (meta.newpage_html_class and stringify(meta.newpage_html_class))
39 | or os.getenv 'PANDOC_NEWPAGE_HTML_CLASS'
40 | if html_class and html_class ~= '' then
41 | pagebreak.html = string.format('', html_class)
42 | end
43 |
44 | local odt_style =
45 | (meta.newpage_odt_style and stringify(meta.newpage_odt_style))
46 | or os.getenv 'PANDOC_NEWPAGE_ODT_STYLE'
47 | if odt_style and odt_style ~= '' then
48 | pagebreak.odt = string.format('', odt_style)
49 | end
50 | end
51 |
52 | --- Return a block element causing a page break in the given format.
53 | local function newpage(format)
54 | if format:match 'asciidoc' then
55 | return pandoc.RawBlock('asciidoc', pagebreak.asciidoc)
56 | elseif format == 'context' then
57 | return pandoc.RawBlock('context', pagebreak.context)
58 | elseif format == 'docx' then
59 | return pandoc.RawBlock('openxml', pagebreak.ooxml)
60 | elseif format:match 'epub' then
61 | return pandoc.RawBlock('html', pagebreak.epub)
62 | elseif format:match 'html.*' then
63 | return pandoc.RawBlock('html', pagebreak.html)
64 | elseif format:match 'latex' then
65 | return pandoc.RawBlock('tex', pagebreak.latex)
66 | elseif format:match 'ms' then
67 | return pandoc.RawBlock('ms', pagebreak.ms)
68 | elseif format:match 'odt' then
69 | return pandoc.RawBlock('opendocument', pagebreak.odt)
70 | else
71 | -- fall back to insert a form feed character
72 | return pandoc.Para{pandoc.Str '\f'}
73 | end
74 | end
75 |
76 | local function is_newpage_command(command)
77 | return command:match '^\\newpage%{?%}?$'
78 | or command:match '^\\pagebreak%{?%}?$'
79 | end
80 |
81 | -- Filter function called on each RawBlock element.
82 | function RawBlock (el)
83 | -- Don't do anything if the output is TeX
84 | if FORMAT:match 'tex$' then
85 | return nil
86 | end
87 | -- check that the block is TeX or LaTeX and contains only
88 | -- \newpage or \pagebreak.
89 | if el.format:match 'tex' and is_newpage_command(el.text) then
90 | -- use format-specific pagebreak marker. FORMAT is set by pandoc to
91 | -- the targeted output format.
92 | return newpage(FORMAT)
93 | end
94 | -- otherwise, leave the block unchanged
95 | return nil
96 | end
97 |
98 | -- Turning paragraphs which contain nothing but a form feed
99 | -- characters into line breaks.
100 | function Para (el)
101 | if #el.content == 1 and el.content[1].text == '\f' then
102 | return newpage(FORMAT)
103 | end
104 | end
105 |
106 | return {
107 | {Meta = pagebreaks_from_config},
108 | {RawBlock = RawBlock, Para = Para}
109 | }
110 |
--------------------------------------------------------------------------------
/dotfiles/pandoc/.local/share/pandoc/filters/wordcount.lua:
--------------------------------------------------------------------------------
1 | -- counts words in a document
2 |
3 | words = 0
4 | characters = 0
5 | characters_and_spaces = 0
6 | process_anyway = false
7 |
8 | wordcount = {
9 | Str = function(el)
10 | -- we don't count a word if it's entirely punctuation:
11 | if el.text:match("%P") then
12 | words = words + 1
13 | end
14 | characters = characters + utf8.len(el.text)
15 | characters_and_spaces = characters_and_spaces + utf8.len(el.text)
16 | end,
17 |
18 | Space = function(el)
19 | characters_and_spaces = characters_and_spaces + 1
20 | end,
21 |
22 | Code = function(el)
23 | _,n = el.text:gsub("%S+","")
24 | words = words + n
25 | text_nospace = el.text:gsub("%s", "")
26 | characters = characters + utf8.len(text_nospace)
27 | characters_and_spaces = characters_and_spaces + utf8.len(el.text)
28 | end,
29 |
30 | CodeBlock = function(el)
31 | _,n = el.text:gsub("%S+","")
32 | words = words + n
33 | text_nospace = el.text:gsub("%s", "")
34 | characters = characters + utf8.len(text_nospace)
35 | characters_and_spaces = characters_and_spaces + utf8.len(el.text)
36 | end
37 | }
38 |
39 | -- check if the `wordcount` variable is set to `process-anyway`
40 | function Meta(meta)
41 | if meta.wordcount and (meta.wordcount=="process-anyway"
42 | or meta.wordcount=="process" or meta.wordcount=="convert") then
43 | process_anyway = true
44 | end
45 | end
46 |
47 | function Pandoc(el)
48 | -- skip metadata, just count body:
49 | pandoc.walk_block(pandoc.Div(el.blocks), wordcount)
50 | print(words .. " words in body")
51 | print(characters .. " characters in body")
52 | print(characters_and_spaces .. " characters in body (including spaces)")
53 | if not process_anyway then
54 | os.exit(0)
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/dotfiles/shell/.gitconfig:
--------------------------------------------------------------------------------
1 | [core]
2 | pager = delta
3 |
4 | [delta]
5 | syntax-theme = "Visual Studio Dark+"
6 | side-by-side = true
7 | wrap-max-lines = "unlimited"
8 |
9 | [commit]
10 | gpgsign = true
11 |
--------------------------------------------------------------------------------
/dotfiles/shell/.zprofile:
--------------------------------------------------------------------------------
1 | . "$HOME/.profile"
2 |
--------------------------------------------------------------------------------
/dotfiles/shell/.zshrc:
--------------------------------------------------------------------------------
1 | # History configuration
2 | HISTFILE=~/.histfile
3 | HISTSIZE=10000
4 | SAVEHIST=10000
5 |
6 | # Shell options
7 | unsetopt autocd beep
8 | bindkey -v
9 | setopt PROMPT_SUBST
10 |
11 | # Load and configure VCS (Version Control System) information
12 | autoload -Uz vcs_info
13 |
14 | # Configure VCS info style for Git repositories
15 | zstyle ':vcs_info:git:*' formats '%F{#888888} (%F{#888888} %b)%f'
16 |
17 | # Function to set VCS information before each prompt
18 | precmd() { vcs_info }
19 |
20 | # Custom prompt including VCS information
21 | PROMPT='%n@%m:%~${vcs_info_msg_0_}%(!.#.$) '
22 |
23 | # Completion system initialization
24 | autoload -Uz compinit
25 | compinit
26 |
27 | # Autosuggestions configuration
28 | ZSH_AUTOSUGGEST_STRATEGY=(history completion)
29 | source /usr/share/zsh-autosuggestions/zsh-autosuggestions.zsh
30 |
31 | # Key bindings:
32 | bindkey '^ ' autosuggest-accept
33 | bindkey '^P' history-beginning-search-backward
34 | bindkey '^N' history-beginning-search-forward
35 |
36 | # Redo operation in Vi command mode (using Helix redo shortcut)
37 | bindkey -M vicmd 'U' redo
38 |
39 | # Aliases
40 | alias ls="ls -ltha --color --group-directories-first --hyperlink=auto"
41 | alias tree="tree -Catr --noreport --dirsfirst --filelimit 100"
42 | alias ezrc='hx ~/.zshrc && source ~/.zshrc'
43 | alias ai="aichat"
44 | alias n="nnn"
45 |
46 | # Functions
47 | md() {
48 | filename="${1##*/}"
49 | pandoc --self-contained --metadata title="Preview" "$1" -o /tmp/"$filename".html
50 | xdg-open /tmp/"$filename".html
51 | }
52 |
53 | ghpr() { GH_FORCE_TTY=100% gh pr list --limit 300 |
54 | fzf --ansi --preview 'GH_FORCE_TTY=100% gh pr view {1}' --preview-window 'down,70%' --header-lines 3 |
55 | awk '{print $1}' |
56 | xargs gh pr checkout; }
57 |
58 | wordcount() { pandoc --lua-filter wordcount.lua "$@"; }
59 |
60 | # nnn
61 | [ -n "$NNNLVL" ] && PS1="N$NNNLVL $PS1" # prompt you are within a shell that will return you to nnn
62 |
63 | # fzf
64 | source /usr/share/doc/fzf/examples/key-bindings.zsh
65 |
66 | # zoxide
67 | eval "$(zoxide init zsh)"
68 |
69 | # aichat and aider
70 | export OPENAI_API_KEY="xxx"
71 | export TOGETHERAI_API_KEY="xxx"
72 | export TOGETHER_API_KEY="xxx"
73 |
74 | stty -ixon # disable terminal flow control
75 |
--------------------------------------------------------------------------------
/dotfiles/sidplayfp/.local/share/sidplayfp/basic:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/David-Else/developer-workstation-setup-script-debian/0e160829dfb03526517787e8f84dbbd282a226ae/dotfiles/sidplayfp/.local/share/sidplayfp/basic
--------------------------------------------------------------------------------
/dotfiles/sidplayfp/.local/share/sidplayfp/kernal:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/David-Else/developer-workstation-setup-script-debian/0e160829dfb03526517787e8f84dbbd282a226ae/dotfiles/sidplayfp/.local/share/sidplayfp/kernal
--------------------------------------------------------------------------------
/extras/README.md:
--------------------------------------------------------------------------------
1 | To re-create the `nnn` deb file, follow these steps:
2 |
3 | 1. Download the following files:
4 | - [nnn_4.9.orig.tar.gz](http://deb.debian.org/debian/pool/main/n/nnn/nnn_4.9.orig.tar.gz)
5 | - [nnn_4.9-1.debian.tar.xz](http://deb.debian.org/debian/pool/main/n/nnn/nnn_4.9-1.debian.tar.xz)
6 |
7 | 2. Extract the contents of both files.
8 |
9 | 3. Copy the `debian` folder from the extracted `nnn_4.9-1.debian.tar.xz` file into the `nnn-4.9` folder inside the `nnn_4.9.orig`.folder.
10 |
11 | 4. Add a new rule to the `rules` file inside the `debian` folder:
12 |
13 | ```makefile
14 | #!/usr/bin/make -f
15 |
16 | export DEB_BUILD_MAINT_OPTIONS = hardening=+all
17 |
18 | %:
19 | dh $@
20 |
21 | override_dh_auto_install:
22 |
23 | override_dh_auto_build:
24 | make -j8 "INSTALL=install --strip-program=true" O_NERD=1
25 |
26 | override_dh_missing:
27 | dh_missing --fail-missing
28 | ```
29 |
30 | 5. Open the terminal and navigate to the `nnn-4.9` folder.
31 |
32 | 6. Run the command `dpkg-buildpackage -b` to build the `nnn` deb file in the parent folder.
33 |
34 |
--------------------------------------------------------------------------------
/extras/_aichat:
--------------------------------------------------------------------------------
1 | #compdef aichat
2 |
3 | autoload -U is-at-least
4 |
5 | _aichat() {
6 | typeset -A opt_args
7 | typeset -a _arguments_options
8 | local ret=1
9 |
10 | if is-at-least 5.2; then
11 | _arguments_options=(-s -S -C)
12 | else
13 | _arguments_options=(-s -C)
14 | fi
15 |
16 | local context curcontext="$curcontext" state line
17 | local common=(
18 | '-m[Select a LLM model]:MODEL:->models' \
19 | '--model[Select a LLM model]:MODEL:->models' \
20 | '--prompt[Use the system prompt]:PROMPT: ' \
21 | '-r[Select a role]:ROLE:->roles' \
22 | '--role[Select a role]:ROLE:->roles' \
23 | '-s[Start or join a session]:SESSION:->sessions' \
24 | '--session[Start or join a session]:SESSION:->sessions' \
25 | '--empty-session[Ensure the session is empty]' \
26 | '--save-session[Ensure the new conversation is saved to the session]' \
27 | '-a[Start a agent]:AGENT:->agents' \
28 | '--agent[Start a agent]:AGENT:->agents' \
29 | '--agent-variable[Set agent variables]' \
30 | '--rag[Start a RAG]:RAG:->rags' \
31 | '--rebuild-rag[Rebuild the RAG to sync document changes]' \
32 | '--macro[Execute a macro]:MACRO:->macros' \
33 | '--serve[Serve the LLM API and WebAPP]' \
34 | '-e[Execute commands in natural language]' \
35 | '--execute[Execute commands in natural language]' \
36 | '-c[Output code only]' \
37 | '--code[Output code only]' \
38 | '*-f[Include files, directories, or URLs]:FILE:_files' \
39 | '*--file[Include files, directories, or URLs]:FILE:_files' \
40 | '-S[Turn off stream mode]' \
41 | '--no-stream[Turn off stream mode]' \
42 | '--dry-run[Display the message without sending it]' \
43 | '--info[Display information]' \
44 | '--sync-models[Sync models updates]' \
45 | '--list-models[List all available chat models]' \
46 | '--list-roles[List all roles]' \
47 | '--list-sessions[List all sessions]' \
48 | '--list-agents[List all agents]' \
49 | '--list-rags[List all RAGs]' \
50 | '--list-macros[List all macros]' \
51 | '-h[Print help]' \
52 | '--help[Print help]' \
53 | '-V[Print version]' \
54 | '--version[Print version]' \
55 | '*::text -- Input text:' \
56 | )
57 |
58 |
59 | _arguments "${_arguments_options[@]}" $common \
60 | && ret=0
61 | case $state in
62 | models|roles|sessions|agents|rags|macros)
63 | local -a values expl
64 | values=( ${(f)"$(_call_program values aichat --list-$state)"} )
65 | _wanted values expl $state compadd -a values && ret=0
66 | ;;
67 | esac
68 | return ret
69 | }
70 |
71 | (( $+functions[_aichat_commands] )) ||
72 | _aichat_commands() {
73 | local commands; commands=()
74 | _describe -t commands 'aichat commands' commands "$@"
75 | }
76 |
77 | if [ "$funcstack[1]" = "_aichat" ]; then
78 | _aichat "$@"
79 | else
80 | compdef _aichat aichat
81 | fi
82 |
--------------------------------------------------------------------------------
/extras/compile-helix-playbook.yml:
--------------------------------------------------------------------------------
1 | - name: Install Helix
2 | hosts: localhost
3 | vars:
4 | helix_src_folder: "{{ ansible_env.HOME }}/src/helix"
5 | helix_config_folder: "{{ ansible_env.HOME }}/.config/helix"
6 | helix_git_version: "e7ac2fcdecfdbf43a4f772e7f7c163b43b3d0b9b" # 25.01.1
7 | tasks:
8 | - name: Clone Helix editor from GitHub
9 | ansible.builtin.git:
10 | repo: https://github.com/helix-editor/helix
11 | dest: "{{ helix_src_folder }}"
12 | version: "{{ helix_git_version }}"
13 | clone: true
14 | update: false
15 | register: helix_cloned
16 |
17 | - name: Install and setup Helix
18 | when: helix_cloned.changed
19 | block:
20 | - name: Install Helix
21 | ansible.builtin.shell: >
22 | cargo install --locked --path "{{ helix_src_folder }}/helix-term"
23 |
24 | - name: Create Helix editor config symlink
25 | ansible.builtin.file:
26 | src: "{{ helix_src_folder }}/runtime"
27 | dest: "{{ helix_config_folder }}/runtime"
28 | state: link
29 |
30 | - name: Ensure the icons directory exists
31 | ansible.builtin.file:
32 | path: "{{ ansible_env.HOME }}/.icons"
33 | state: directory
34 |
35 | - name: Copy Helix editor icons
36 | ansible.builtin.copy:
37 | src: "{{ helix_src_folder }}/contrib/helix.png"
38 | dest: "{{ ansible_env.HOME }}/.icons/helix.png"
39 |
40 | - name: Create Helix .desktop file
41 | ansible.builtin.copy:
42 | dest: "{{ ansible_env.HOME }}/.local/share/applications/helix.desktop"
43 | content: |
44 | [Desktop Entry]
45 | Version=1.0
46 | Type=Application
47 | Terminal=false
48 | Exec={{ ansible_env['HOME'] }}/.local/kitty.app/bin/kitty --single-instance {{ ansible_env['HOME'] }}/.cargo/bin/hx %F
49 | Name=Helix
50 | Comment=Open in Helix using the Kitty terminal
51 | Icon={{ ansible_env.HOME }}/.icons/helix.png
52 | Categories=Utility;TerminalEmulator;
53 | MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;text/html;application/toml;text/x-python;application/json;application/javascript;
54 |
55 | - name: Update the desktop database
56 | ansible.builtin.command: update-desktop-database "{{ ansible_env.HOME }}/.local/share/applications"
57 | changed_when: false
58 |
--------------------------------------------------------------------------------
/extras/install-blender-playbook.yml:
--------------------------------------------------------------------------------
1 | - name: Install Blender
2 | hosts: localhost
3 | become: false
4 | vars:
5 | bin_install_dir: /usr/local/bin
6 | blender_version: 4.3.2
7 | blender_url: "https://download.blender.org/release/Blender4.3/blender-{{ blender_version }}-linux-x64.tar.xz"
8 |
9 | tasks:
10 | - name: Create directory for Blender
11 | become: true
12 | ansible.builtin.file:
13 | path: "{{ bin_install_dir }}/blender-bin"
14 | state: directory
15 |
16 | - name: Download and extract Blender
17 | become: true
18 | ansible.builtin.unarchive:
19 | src: "{{ blender_url }}"
20 | dest: "{{ bin_install_dir }}/blender-bin"
21 | remote_src: true
22 | creates: "{{ bin_install_dir }}/blender-bin/blender"
23 | extra_opts:
24 | - "--strip-components=1"
25 |
26 | - name: Create symlink to Blender binary
27 | become: true
28 | ansible.builtin.file:
29 | src: "{{ bin_install_dir }}/blender-bin/blender"
30 | dest: "{{ bin_install_dir }}/blender"
31 | state: link
32 |
33 | - name: Configure Blender desktop file
34 | block:
35 | - name: Copy Blender desktop file
36 | ansible.builtin.copy:
37 | src: "{{ bin_install_dir }}/blender-bin/blender.desktop"
38 | dest: "{{ lookup('ansible.builtin.env', 'HOME') }}/.local/share/applications/blender.desktop"
39 |
40 | - name: Create ~/.icons directory
41 | ansible.builtin.file:
42 | path: "{{ lookup('ansible.builtin.env', 'HOME') }}/.icons"
43 | state: directory
44 |
45 | - name: Copy Blender icon
46 | ansible.builtin.copy:
47 | src: "{{ bin_install_dir }}/blender-bin/blender.svg"
48 | dest: "{{ lookup('ansible.builtin.env', 'HOME') }}/.icons/blender.svg"
49 |
--------------------------------------------------------------------------------
/extras/nasa-Q1p7bh3SHj8-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/David-Else/developer-workstation-setup-script-debian/0e160829dfb03526517787e8f84dbbd282a226ae/extras/nasa-Q1p7bh3SHj8-unsplash.jpg
--------------------------------------------------------------------------------
/extras/nnn_4.9-1_amd64.deb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/David-Else/developer-workstation-setup-script-debian/0e160829dfb03526517787e8f84dbbd282a226ae/extras/nnn_4.9-1_amd64.deb
--------------------------------------------------------------------------------
/extras/showmethekey-1.12.0-compiled.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/David-Else/developer-workstation-setup-script-debian/0e160829dfb03526517787e8f84dbbd282a226ae/extras/showmethekey-1.12.0-compiled.zip
--------------------------------------------------------------------------------
/images/debian_logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
18 |
--------------------------------------------------------------------------------
/images/sources.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/David-Else/developer-workstation-setup-script-debian/0e160829dfb03526517787e8f84dbbd282a226ae/images/sources.png
--------------------------------------------------------------------------------
/install-playbook.yml:
--------------------------------------------------------------------------------
1 | - name: Install packages and configure Debian 12/13
2 | hosts: localhost
3 | vars_files:
4 | - packages.yml
5 | tasks:
6 | - name: System configuration
7 | become: true
8 | block:
9 | - name: Install and remove repository packages
10 | ansible.builtin.import_tasks: tasks/install_repo_packages.yml
11 | - name: Install GitHub packages
12 | ansible.builtin.import_tasks: tasks/install_github_packages.yml
13 | - name: Configure system settings and user environment
14 | ansible.builtin.import_tasks: tasks/configure_system_settings.yml
15 |
16 | - name: User configuration
17 | become: false
18 | block:
19 | - name: Install Python packages
20 | ansible.builtin.import_tasks: tasks/install_python_packages.yml
21 | - name: Stow dotfiles
22 | ansible.builtin.import_tasks: tasks/stow_dotfiles.yml
23 | - name: Configure Pipewire
24 | ansible.builtin.import_tasks: tasks/setup_pipewire.yml
25 | - name: Update .bashrc and .profile
26 | ansible.builtin.import_tasks: tasks/update_bashrc.yml
27 | - name: Setup Gnome
28 | ansible.builtin.import_tasks: tasks/setup-gnome.yml
29 | - name: Download and install yabridge
30 | ansible.builtin.unarchive:
31 | src: "https://github.com/robbert-vdh/yabridge/releases/download/{{ yabridge_version }}/yabridge-{{ yabridge_version }}.tar.gz"
32 | dest: "{{ ansible_env.HOME }}/.local/share"
33 | remote_src: true
34 |
--------------------------------------------------------------------------------
/packages.yml:
--------------------------------------------------------------------------------
1 | bin_install_dir: /usr/local/bin
2 | pipewire_config_dir: "{{ ansible_env['HOME'] }}/.config/pipewire/"
3 | rclone_version: "1.69.2"
4 | hugo_version: "0.147.2"
5 | helix_version: "25.01.1"
6 | marksman_version: "2024-12-18"
7 | marksman_shasum: "b9cb666c643dfd9b699811fdfc445ed4c56be65c1d878c21d46847f0d7b0e475"
8 | ltex_ls_plus_version: "18.5.1"
9 | yabridge_version: "5.0.5"
10 | delta_version: "0.18.2"
11 | keyd_git_version: "v2.5.0"
12 |
13 | packages_to_remove:
14 | - cheese
15 | - evolution
16 | - gnome-games
17 | - gnome-music
18 | - gnome-software
19 | - gnome-text-editor
20 | - gnome-sound-recorder
21 | - gnome-weather
22 | - rhythmbox
23 | - totem
24 |
25 | debian_packages:
26 | - adb
27 | - android-sdk-platform-tools-common
28 | - ansible-lint
29 | - bat
30 | - borgbackup
31 | - build-essential
32 | - curl
33 | - ffmpeg
34 | - fzf
35 | - gdb
36 | - gh
37 | - gnome-boxes
38 | - gnome-shell-extension-autohidetopbar
39 | - gnome-shell-extension-auto-move-windows
40 | - gnome-tweaks
41 | - golang
42 | - handbrake
43 | - heif-gdk-pixbuf
44 | - heif-thumbnailer
45 | - imagemagick
46 | - jq
47 | - kitty
48 | - krita
49 | # - libvirt-daemon-system # dependency for gnome-boxes at least in Debian 12
50 | - lldb-19 # to supply lldb-dap-19 for Helix debugging
51 | - lshw
52 | - mediainfo
53 | - mpv
54 | - nodejs
55 | - npm
56 | - pandoc
57 | - pipx
58 | - qpwgraph
59 | - ripgrep
60 | - shellcheck
61 | - sidplayfp
62 | - shfmt
63 | - stow
64 | - trash-cli
65 | - wl-clipboard
66 | - xdg-desktop-portal-gnome
67 | - zathura
68 | - zoxide
69 | - zsh
70 | - zsh-autosuggestions
71 |
72 | debian_13_packages:
73 | - alsa-scarlett-gui
74 | - flatseal
75 | - git-delta
76 | - keepassxc-full
77 | - keyd
78 | - lazygit
79 |
80 | flatpak_packages:
81 | - com.github.polymeilex.neothesia
82 | - com.obsproject.Studio # TODO in trixie
83 | - com.obsproject.Studio.Plugin.DroidCam # TODO in trixie
84 | - io.github.flattool.Warehouse
85 | - org.signal.Signal
86 |
87 | npm_packages:
88 | - "@ansible/ansible-language-server@1.2.3"
89 | - "@tailwindcss/language-server@0.14.16"
90 | - bash-language-server@5.4.3
91 | - prettier@3.5.3
92 | - typescript-language-server@4.3.3
93 | - typescript@5.7.3
94 | - vscode-langservers-extracted@4.8.0
95 | - yaml-language-server@1.15.0
96 |
97 | python_packages:
98 | - ansi2html
99 | # - gdbgui doesn't seem to work on trixie
100 | - visidata
101 | - yt-dlp
102 |
--------------------------------------------------------------------------------
/profile.sh:
--------------------------------------------------------------------------------
1 | PATH="$HOME/Documents/scripts:$HOME/go/bin:$PATH"
2 | export PATH
3 | export NNN_PLUG='i:-!|mediainfo $nnn;d:dragdrop;f:fzcd;p:preview-tui;m:mtpmount;j:autojump'
4 | export NNN_BMS="d:~/Documents;p:~/Pictures;v:~/Videos;m:~/Music;h:~/;u:/media/$USERNAME;D:~/Downloads;M:${XDG_CONFIG_HOME:-$HOME/.config}/nnn/mounts;a:/run/user/$UID/gvfs"
5 | export NNN_TRASH=1 # use trash-cli: https://pypi.org/project/trash-cli/
6 | export NNN_FIFO=/tmp/nnn.fifo
7 | export NNN_BATTHEME="Visual Studio Dark+"
8 | export NNN_BATSTYLE="plain"
9 | export NNN_RCLONE='rclone mount --vfs-cache-mode writes'
10 | export BAT_THEME="Visual Studio Dark+"
11 | export FZF_DEFAULT_COMMAND='rg --files --hidden --follow --no-ignore-vcs -g "!{node_modules,.git,.wine}"'
12 | export EDITOR="hx"
13 | export SUDO_EDITOR="/usr/bin/hx"
14 |
--------------------------------------------------------------------------------
/tasks/configure_system_settings.yml:
--------------------------------------------------------------------------------
1 | - name: Create symlinks
2 | block:
3 | - name: Gather the package facts
4 | ansible.builtin.package_facts:
5 | manager: auto
6 |
7 | - name: Create symlink for lldb-dap-19 as lldb-dap
8 | ansible.builtin.file:
9 | src: /usr/bin/lldb-dap-19
10 | dest: /usr/bin/lldb-dap
11 | state: link
12 | when: "'lldb-19' in ansible_facts.packages"
13 |
14 | - name: Create symlink for batcat as bat
15 | ansible.builtin.file:
16 | src: /usr/bin/batcat
17 | dest: /usr/local/bin/bat
18 | state: link
19 | when: "'bat' in ansible_facts.packages"
20 |
21 | - name: Create Hugo Zsh completions
22 | block:
23 | - name: Generate Hugo completion for zsh
24 | ansible.builtin.command: hugo completion zsh
25 | register: hugo_completion
26 | changed_when: false
27 |
28 | - name: Write Hugo completion to file
29 | ansible.builtin.copy:
30 | content: "{{ hugo_completion.stdout }}"
31 | dest: /usr/share/zsh/vendor-completions/_hugo
32 |
33 | - name: Switch to Zsh for the default shell
34 | ansible.builtin.user:
35 | name: "{{ lookup('ansible.builtin.env', 'USER') }}"
36 | shell: /usr/bin/zsh
37 |
38 | - name: Create default.conf for keyd
39 | ansible.builtin.copy:
40 | content: |
41 | [ids]
42 | *
43 |
44 | [main]
45 | # Maps capslock to escape when pressed and control when held.
46 | capslock = overload(control, esc)
47 | dest: /etc/keyd/default.conf
48 |
49 | - name: Add user to the pipewire group to get realtime privileges from /etc/security/limits.d/25-pw-rlimits.conf
50 | ansible.builtin.user:
51 | name: "{{ lookup('ansible.builtin.env', 'USER') }}"
52 | groups: pipewire
53 | append: true
54 |
--------------------------------------------------------------------------------
/tasks/install_github_packages.yml:
--------------------------------------------------------------------------------
1 | - name: Debian 12 specific tasks
2 | when: ansible_distribution == "Debian" and ansible_distribution_major_version == "12"
3 | block:
4 | - name: Install delta
5 | ansible.builtin.apt:
6 | deb: https://github.com/dandavison/delta/releases/download/{{ delta_version }}/git-delta_{{ delta_version }}_amd64.deb
7 |
8 | - name: Install keyd from source
9 | block:
10 | - name: Clone keyd from GitHub
11 | ansible.builtin.git:
12 | repo: https://github.com/rvaiya/keyd
13 | dest: /tmp/keyd
14 | version: "{{ keyd_git_version }}"
15 | update: false
16 |
17 | - name: Ensure the keyd directory exists
18 | ansible.builtin.file:
19 | path: /etc/keyd/
20 | state: directory
21 |
22 | - name: Build keyd
23 | community.general.make:
24 | chdir: /tmp/keyd
25 |
26 | - name: Install keyd
27 | community.general.make:
28 | chdir: /tmp/keyd
29 | target: install
30 |
31 | - name: Enable and start keyd service
32 | ansible.builtin.systemd:
33 | name: keyd
34 | enabled: true
35 | state: started
36 |
37 | - name: Clean up temporary directory
38 | ansible.builtin.file:
39 | path: "/tmp/keyd"
40 | state: absent
41 |
42 | - name: Install ltex-ls-plus with JDK
43 | block:
44 | - name: Create versioned installation directory for ltex-ls-plus
45 | ansible.builtin.file:
46 | path: "{{ bin_install_dir }}/ltex-ls-plus-{{ ltex_ls_plus_version }}"
47 | state: directory
48 |
49 | - name: Extract ltex-ls-plus
50 | ansible.builtin.unarchive:
51 | src: "https://github.com/ltex-plus/ltex-ls-plus/releases/download/{{ ltex_ls_plus_version }}/ltex-ls-plus-{{ ltex_ls_plus_version }}-linux-x64.tar.gz"
52 | dest: "{{ bin_install_dir }}/ltex-ls-plus-{{ ltex_ls_plus_version }}"
53 | remote_src: true
54 | extra_opts:
55 | - "--strip-components=2" # removes /./ltex-ls-plus-18.4.0/
56 | - "--wildcards"
57 | - "*/bin/*" # */ is needed to deal with strange /./ structure
58 | - "*/lib/*"
59 | - "*/jdk-*/*"
60 | creates: "{{ bin_install_dir }}/ltex-ls-plus-{{ ltex_ls_plus_version }}/bin/ltex-ls-plus"
61 |
62 | - name: Create symbolic links to versioned binary
63 | ansible.builtin.file:
64 | src: "{{ bin_install_dir }}/ltex-ls-plus-{{ ltex_ls_plus_version }}/bin/ltex-ls-plus"
65 | dest: "{{ bin_install_dir }}/ltex-ls-plus"
66 | state: link
67 | force: true
68 |
69 | - name: Install executables
70 | block:
71 | - name: Install marksman
72 | ansible.builtin.get_url:
73 | url: "https://github.com/artempyanykh/marksman/releases/download/{{ marksman_version }}/marksman-linux-x64"
74 | dest: "{{ bin_install_dir }}/marksman"
75 | checksum: "sha256:{{ marksman_shasum }}"
76 |
77 | - name: Install .deb packages
78 | ansible.builtin.apt:
79 | deb: "{{ item.url }}"
80 | loop:
81 | - name: rclone
82 | url: "https://github.com/rclone/rclone/releases/download/v{{ rclone_version }}/rclone-v{{ rclone_version }}-linux-amd64.deb"
83 | - name: hugo
84 | url: "https://github.com/gohugoio/hugo/releases/download/v{{ hugo_version }}/hugo_extended_{{ hugo_version }}_linux-amd64.deb"
85 | - name: helix
86 | url: "https://github.com/helix-editor/helix/releases/download/{{ helix_version }}/helix_25.1.1-1_amd64.deb"
87 |
--------------------------------------------------------------------------------
/tasks/install_python_packages.yml:
--------------------------------------------------------------------------------
1 | - name: Install packages with pipx
2 | ansible.builtin.command: pipx install {{ item }}
3 | loop: "{{ python_packages }}"
4 | args:
5 | creates: "{{ ansible_env.HOME }}/.local/pipx/venvs/{{ item }}"
6 |
7 | - name: Run pipx ensurepath
8 | ansible.builtin.command: pipx ensurepath
9 | changed_when: false
10 |
--------------------------------------------------------------------------------
/tasks/install_repo_packages.yml:
--------------------------------------------------------------------------------
1 | - name: Remove unwanted desktop apps
2 | ansible.builtin.apt:
3 | name: "{{ packages_to_remove }}"
4 | state: absent
5 | autoremove: true
6 | purge: true
7 |
8 | - name: Add Flathub repository
9 | community.general.flatpak_remote:
10 | name: flathub
11 | flatpakrepo_url: https://flathub.org/repo/flathub.flatpakrepo
12 |
13 | - name: Update and upgrade all Debian packages
14 | ansible.builtin.apt:
15 | upgrade: dist
16 | update_cache: true
17 |
18 | - name: Install packages
19 | block:
20 | - name: Install Debian packages (exclude Debian 13 packages on Debian 12)
21 | ansible.builtin.apt:
22 | name: >-
23 | {{
24 | (ansible_distribution == 'Debian' and ansible_distribution_major_version == '12')
25 | | ternary(
26 | debian_packages,
27 | debian_packages + debian_13_packages
28 | )
29 | }}
30 |
31 | - name: Install Flatpak packages
32 | community.general.flatpak:
33 | name: "{{ flatpak_packages }}"
34 |
35 | - name: Install NPM global packages
36 | loop: "{{ npm_packages }}"
37 | community.general.npm:
38 | name: "{{ item }}"
39 | global: true
40 |
41 | - name: Install pipewire backport for Debian 12
42 | when: ansible_distribution == "Debian" and ansible_distribution_major_version == "12"
43 | block:
44 | - name: Add bookworm backports apt repository
45 | ansible.builtin.apt_repository:
46 | repo: deb http://deb.debian.org/debian bookworm-backports main
47 |
48 | - name: Install backports pipewire
49 | ansible.builtin.apt:
50 | name: pipewire
51 | state: latest
52 | default_release: bookworm-backports
53 |
--------------------------------------------------------------------------------
/tasks/setup-gnome.yml:
--------------------------------------------------------------------------------
1 | - name: Enable GNOME Night Light
2 | community.general.dconf:
3 | key: "/org/gnome/settings-daemon/plugins/color/night-light-enabled"
4 | value: "true"
5 | state: present
6 |
7 | - name: Configure GNOME Auto Move Windows extension workspace rules
8 | community.general.dconf:
9 | key: "/org/gnome/shell/extensions/auto-move-windows/application-list"
10 | value: "['org.gnome.Calendar.desktop:2', 'org.signal.Signal.desktop:2', 'firefox-esr.desktop:3']"
11 | state: present
12 |
--------------------------------------------------------------------------------
/tasks/setup_pipewire.yml:
--------------------------------------------------------------------------------
1 | - name: Ensure ~/.config/pipewire/ directory exists
2 | ansible.builtin.file:
3 | path: "{{ pipewire_config_dir }}"
4 | state: directory
5 |
6 | - name: Copy pipewire.conf to user's config directory
7 | ansible.builtin.copy:
8 | src: /usr/share/pipewire/pipewire.conf
9 | dest: "{{ pipewire_config_dir }}pipewire.conf"
10 | force: false
11 |
12 | - name: Update Pipewire allowed sample rates
13 | ansible.builtin.lineinfile:
14 | path: "{{ pipewire_config_dir }}pipewire.conf"
15 | regexp: '^\s*#\s*default.clock.allowed-rates\s*='
16 | line: "default.clock.allowed-rates = [ 44100 48000 88200 96000 176400 192000 ]"
17 | backrefs: true
18 | register: samplerates_updated
19 |
20 | - name: Create pipewire group
21 | ansible.builtin.group:
22 | name: pipewire
23 |
--------------------------------------------------------------------------------
/tasks/stow_dotfiles.yml:
--------------------------------------------------------------------------------
1 | - name: Create ~/.dotfiles directory
2 | ansible.builtin.file:
3 | path: "{{ ansible_env.HOME }}/.dotfiles"
4 | state: directory
5 |
6 | - name: Copy dotfiles to home directory
7 | ansible.builtin.copy:
8 | src: "{{ playbook_dir }}/dotfiles/"
9 | dest: "{{ ansible_env.HOME }}/.dotfiles/"
10 |
11 | - name: Run stow
12 | ansible.builtin.command:
13 | chdir: "{{ ansible_facts['user_dir'] }}/.dotfiles"
14 | cmd: >
15 | stow --target={{ ansible_facts['user_dir'] }} autostart helix mpv shell pandoc kitty lazygit keepassxc aichat sidplayfp marksman config
16 | --verbose=2
17 | register: result
18 | changed_when: 'result.stderr is search("LINK: ")'
19 | failed_when: 'result.rc != 0 and "Conflicting" in result.stderr'
20 |
--------------------------------------------------------------------------------
/tasks/update_bashrc.yml:
--------------------------------------------------------------------------------
1 | - name: Update .bashrc by appending extra config
2 | ansible.builtin.blockinfile:
3 | block: "{{ lookup('ansible.builtin.file', 'bashrc.bash') }}"
4 | path: "{{ ansible_env.HOME }}/.bashrc"
5 | backup: true
6 |
7 | - name: Update .profile with shared environment variables for bash and zsh
8 | ansible.builtin.blockinfile:
9 | block: "{{ lookup('ansible.builtin.file', 'profile.sh') }}"
10 | path: "{{ ansible_env.HOME }}/.profile"
11 | backup: true
12 |
--------------------------------------------------------------------------------