commit 84b5cd816c1a8f893e0da8d3683975f17cd40fe7 Author: Swarsel Date: Mon Dec 11 02:57:34 2023 +0100 move flake to own repository diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 0000000..da6e190 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,104 @@ +###### Disclaimer + +You probably do not want to use this setup verbatim. This is made to fit my specific use cases, with some strings hardcoded and some niche settings that are not needed on most hosts. Also, nothing is ever stable here and changes are made on a daily basis. + +That being said, there is a lot of general configuration that you *probably* can use without changes; if you only want to use this repository as a starting point for your own configuration, you should be fine. See below for more information. Also, if you see something that can be done more efficiently or better in general, please let me know! :) + +# \~SwarselSystems\~ + + + +| | | +|---------------|----------------------| +| **Shell:** | zsh | +| **DM:** | greetd | +| **WM:** | SwayFX | +| **Bar:** | Waybar | +| **Editor:** | Emacs | +| **Terminal:** | kitty | +| **Launcher:** | fuzzel | +| **Alerts:** | mako | +| **Browser:** | firefox | +| **Theme:** | city-lights | + +The files that are possibly of biggest interest are found here: + +- [flake.nix](../.dotfiles/flake.nix) +- [Nix.org](../.dotfiles/Nix.org) +- [early-init.el](../.dotfiles/programs/emacs/early-init.el) +- [Emacs.org](../.dotfiles/Emacs.org) + +This is a nix flakes based setup that manages multiple hosts, including mixed (NixOS with home-manager as a submodule) as well as standalone home-manager machines, also using some overlays etc. It is all wrapped in literal configuration .org files, because that allows me to have easy access without actually having to remember where the specific configuration files are all located. flake.nix and early-init.el are not tangled at the moment, flake.nix mostly for the reason that I rarely need to update it; early-init.el for the reason that adding it would break the emacs-overlay parsing. + +Have fun! + +### General Nix tips +Sadly all things nix feel a bit underdocumented. Below is a small list of tips that I thought could be helpful if you are new to the nix ecosystem: + +- Once you have the experimental feature `nix-command` enabled, you can temporarily install any package using `nix shell nixpkgs#` - this can be e.g. useful if you accidentally removed home-manager from your packages on a non-NixOS machine. + - The `nix [...]` commands are generally very useful, more info can be found here: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix +- These links are your best friends: + - https://search.nixos.org/packages + - https://search.nixos.org/options + - https://nix-community.github.io/home-manager/options.html / https://mipmip.github.io/home-manager-option-search/ +- Also useful is the [NixOS wiki](https://nixos.wiki/wiki/Main_Page), but some pages are outdated, so use with some care +- When you are trying to setup a new configuration part, GitHub code search can really help you to find a working configuration. +- getting packages not maintained in a standard repository can be done in most cases easily with fetchFromGithub (https://ryantm.github.io/nixpkgs/builders/fetchers/) + +### Deployment +Below is a rough general guide to setup this system on a new NixOS host. **Again**, this is not recommended as this is a personal configuration. This also might not be the most efficient way to deploy a new Nix system, but it should work in the general case. + +For a pure Home-Manager configuration, you need a few different steps. The biggest change is that you then want to call `home-manager --flake .#@ switch` as the last step instead of `nixos-rebuild [...]`. A complete general guide for that case cannot really be given since you are most likely setting up the flake on a existing machine that already has a lot of configuration. If you are setting up a new system, I would recommend to use NixOS unless circumstances force you to use something else. + + +###### To do that: +1) adapt [flake.nix](../.dotfiles/flake.nix): + - Copy either one of the nixosSystem or homeManagerConfiguration blocks depending on what configuration you are going to be using. + - Adapt all lines referencing the host- and username to the names chosen for your system. + - Also adapt the file paths to reference the files where you want your specific configuration to be stored. + - If using home-manager on the host, consider the settings for `home-manager.useGlobalPkgs` and `home-manager.useUserPackages` - in this repo they are moved to the general NixOS section to reduce code duplication. +2) adapt [Nix.org](../.dotfiles/Nix.org) + - Make a copy of "System Specific Configurations/TEMPLATE". + - Adapt all references to TEMPLATE to your host- and usernames etc (make sure to also create that directory where it is to be tangled to). + - Add the settings needed for your specific machine. + - Make sure Nix.org was actually tangled. + - **Beware:** This assumes you have access to a way of tangling an .org file (for most people this will mean having a working Emacs). If you do not have that, see below. +3) Add your changes to your fork of the repository. +###### If you have no way of tangling .org files +In that case make a copy of the /.dotfiles/profiles/TEMPLATE folder and adapt each file manually according to the above. +##### Actual system setup +0) Make sure you have an internet connection (ethernet or for Wi-Fi e.g. call `nmtui`) +1) `sudo nano /etc/nixos/configuration.nix` +- add the following packages to `environment.systemPackages`: + - `git ` + - `gnupg` + - `ssh-to-age` +- add +```nix +nix = { + package = pkgs.nixFlakes; + extraOptions = '' + experimental-features = nix-command flakes + ''; +}; +``` +2) `sudo nixos-rebuild switch` +###### Setup of the bare repository (these steps are not mandatory but make managing the repository easier) +3) `echo ".cfg" >> .gitignore` +4) `git clone --bare https://github.com/Swarsel/dotfiles.git $HOME/.cfg` +5) `alias config='git --git-dir=$HOME/.cfg --work-tree=$HOME'` +6) `config config --local status.showUntrackedFiles no` +7) `config checkout` +###### Host SSH key setup for use with sops-nix +8) `ssh-keygen -t ed25519 -C " sops"`, use e.g. "sops" as name for `` +9) `cd ~/.dotfiles` +10) `cat ~/.pub | ssh-to-age >> ~/.dotfiles/.sops.yaml` +11) `nano .sops.yaml` - add last line to keys and make a new &system_ entry, make sure to remove that last line +12) `cp ~/.pub ~/.dotfiles/secrets/keys/.pub` +13) move `` to where you want to store your host private key +14) update entry for `sops.age.sshKeyPaths` in Nix.org to the location that you have just moved the private key to (or manually edit `.dotfiles/profiles//home.nix`) +###### Switching to the configuration +15) `cp /etc/nixos/hardware-configuration.nix ~/.dotfiles/profiles/` +16) `sudo nixos-rebuild --flake .# switch` + - This build will take a while (mostly because it fully builds Emacs), so do not worry too much :) + - In case you get a dependency error for some of the `firefox-addons`, just comment out those specific extensions and try to uncomment them again a few days later. Sometimes when these packages are updated, the old .xpi file is deleted by the addon developer and the download link breaks. It is usually updated swiftly. If you do not want to wait, you can also package the addon yourself - there is one example in the files how this is generally done. diff --git a/.github/swarselsystems_preview.png b/.github/swarselsystems_preview.png new file mode 100644 index 0000000..a8b229a Binary files /dev/null and b/.github/swarselsystems_preview.png differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..48a6888 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +secrets/keys/pubring.kbx +secrets/keys/private-keys-v1.d/ diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..f2f2d57 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,24 @@ +# This example uses YAML anchors which allows reuse of multiple keys +# without having to repeat yourself. +# Also see https://github.com/Mic92/dotfiles/blob/master/nixos/.sops.yaml +# for a more complex example. +keys: + - &admin_swarsel 4BE7925262289B476DBBC17B76FD3810215AE097 + - &server_nixos age1zdjm8qa5t25mca0xxhhkpuh85mgg4l267mqjj2pdttksq7zg4unqdmqyp4 + - &server_surface age1zlnxraee6tddr07xn59mx5rdexw8qxryd53eqlsajasfhfy78fkq705dfg + - &server_stand age1hkajkcje5xvg8jd4zj2e0s9tndpv36hwhn7p38x9lyq2z8g7v45q2nhlej +creation_rules: + - path_regex: secrets/general/[^/]+\.(yaml|json|env|ini)$ + key_groups: + - pgp: + - *admin_swarsel + age: + - *server_nixos + - *server_surface + - *server_stand + - path_regex: secrets/surface/[^/]+\.(yaml|json|env|ini)$ + key_groups: + - pgp: + - *admin_swarsel + age: + - *server_surface diff --git a/Emacs.org b/Emacs.org new file mode 100644 index 0000000..ee21dd7 --- /dev/null +++ b/Emacs.org @@ -0,0 +1,2490 @@ +#+title: Emacs Configuration +#+PROPERTY: header-args:emacs-lisp :tangle programs/emacs/init.el :mkdirp yes + +** TODO Agenda for this file [1/4] +- [ ] Content [0/2] + - [ ] Structure this file in a readable manner + - [ ] Add commentary to major sections +- [-] Language [1/2] + - [X] English across the entire file + - [ ] Stay in first person +- [X] Formatting [3/3] + - [X] One free line at start and end of each source block + - [X] Uniform indentation across file + - [X] One free line at the start and end of each header +- [ ] Finish all TODO blocks in this file + + +* Initialization +** Startup performance + +#+begin_src emacs-lisp + + ;; The default is 800 kilobytes. Measured in bytes. + (setq gc-cons-threshold (* 50 1000 1000)) + +#+end_src + +** System specific configuration + +- You might need to readjust some of these settings based on your OS and system setup +- Don't forget to install the sync software (here: nextcloud-client). On fedora: 'sudo dnf install nextcloud-client' + +#+begin_src emacs-lisp + + ;; use UTF-8 everywhere + (set-language-environment "UTF-8") + + ;; set default font size + (defvar swarsel/default-font-size 130) + (setq swarsel-standard-font "FiraCode Nerd Font Mono" + swarsel-alt-font "FiraCode Nerd Font Mono") + + ;; set Nextcloud directory for journals etc. + (setq swarsel-sync-directory "~/Nextcloud" + swarsel-emacs-directory "~/.emacs.d" + swarsel-dotfiles-directory "~/.dotfiles" + swarsel-projects-directory "~/Documents/GitHub") + + (setq swarsel-emacs-org-filepath (expand-file-name "Emacs.org" swarsel-dotfiles-directory) + swarsel-nix-org-filepath (expand-file-name "Nix.org" swarsel-dotfiles-directory)) + + + ;; set Emacs main configuration .org names + (setq swarsel-emacs-org-file "Emacs.org" + swarsel-anki-org-file "Anki.org" + swarsel-tasks-org-file "Tasks.org" + swarsel-archive-org-file "Archive.org" + swarsel-org-folder-name "org" + swarsel-obsidian-daily-folder-name "⭐ Personal/Journal" + swarsel-obsidian-folder-name "Obsidian" + swarsel-obsidian-vault-name "Main") + + + ;; set directory paths + (setq swarsel-org-directory (expand-file-name swarsel-org-folder-name swarsel-sync-directory)) ; path to org folder + (setq swarsel-obsidian-directory (expand-file-name swarsel-obsidian-folder-name swarsel-sync-directory)) ; path to obsidian + (setq swarsel-obsidian-vault-directory (expand-file-name swarsel-obsidian-vault-name swarsel-obsidian-directory)) ; path to obsidian vault + (setq swarsel-obsidian-daily-directory (expand-file-name swarsel-obsidian-daily-folder-name swarsel-obsidian-vault-directory)) ; path to obsidian daily folder + + ;; filepaths to certain documents + (setq swarsel-org-anki-filepath (expand-file-name swarsel-anki-org-file swarsel-org-directory) ; path to anki export file + swarsel-org-tasks-filepath (expand-file-name swarsel-tasks-org-file swarsel-org-directory) + swarsel-org-archive-filepath (expand-file-name swarsel-archive-org-file swarsel-org-directory)) + + ;; set paths to authentication files (forge) + ;; (setq auth-source-pass-filename "~/.local/share/password-store" + (setq auth-sources '( "~/.emacs.d/.caldav" "~/.emacs.d/.authinfo.gpg") + auth-source-cache-expiry nil) ; default is 2h + + ;; set pandoc for markdown compilation + (setq markdown-command "pandoc") + + ;; set org-caldav-sync-initalization + (setq swarsel-caldav-synced 0) + +#+end_src + +** Package System Setup + +This is handles by nix, no configuration is needed here. Do note that package.el must stay enabled in early-init.el. + +** Keeping .emacs.d clean + +#+begin_src emacs-lisp + + ;; Change the user-emacs-directory to keep unwanted things out of ~/.emacs.d + (setq user-emacs-directory (expand-file-name "~/.cache/emacs/") + url-history-file (expand-file-name "url/history" user-emacs-directory)) + + ;; Use no-littering to automatically set common paths to the new user-emacs-directory + (use-package no-littering) + (setq custom-file (expand-file-name "programs/emacs/custom.el" swarsel-dotfiles-directory)) + (load custom-file t) + +#+end_src + +* Behavior +** General + +Here I set up some things that are too minor to put under other categories. +- Firstly we disable to having to type `yes` and `no` and switch it to `y` and `n`. +- We also enable the marking of trailing whitespaces. +- Also, make emacs highlight the current line globally +- Emacs defaults to pausing all display redrawing on any input. This may have been useful previously, but is not necessary nowadays. +- I also disable the suspend-frame function, as I never use it and it is quite confusing when accidentally hitting the keys for it. + +#+begin_src emacs-lisp + + (defalias 'yes-or-no-p 'y-or-n-p) + ;;(setq-default show-trailing-whitespace t) + (add-hook 'before-save-hook 'delete-trailing-whitespace) + (global-hl-line-mode 1) + ;; (setq redisplay-dont-pause t) ;; obsolete + (delete-selection-mode 1) + (pixel-scroll-precision-mode 1) + (setq vc-follow-symlinks t) + (setq require-final-newline t) + (winner-mode 1) + ;; less noise when compiling elisp + (setq byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local)) + (setq native-comp-async-report-warnings-errors nil) + (setq load-prefer-newer t) + + ;; disable a keybind that does more harm than good + (global-set-key [remap suspend-frame] + (lambda () + (interactive) + (message "This keybinding is disabled (was 'suspend-frame')"))) + +#+end_src + +** Disable GUI distractions + +These settings are mostly useless in my eyes and provide little more than a distraction. + +#+begin_src emacs-lisp + + ;; (scroll-bar-mode -1) + ;; (tool-bar-mode -1) + ;; (tooltip-mode -1) + ;; (menu-bar-mode -1) + (setq visible-bell nil) + (setq initial-major-mode 'fundamental-mode + initial-scratch-message nil) + +#+end_src + +** Indentation + +#+begin_src emacs-lisp + + (setq-default indent-tabs-mode nil + tab-width 2) + + (setq tab-always-indent 'complete) + +(use-package highlight-indent-guides + :hook (prog-mode . highlight-indent-guides-mode) + :init + (setq highlight-indent-guides-method 'character) + (setq highlight-indent-guides-character "‖") + (setq highlight-indent-guides-responsive 'top) + ) + +#+end_src + +** Scrolling + +By default, emacs scrolls half a page when reaching the bottom of the buffer. This is extremely annoying. + +#+begin_src emacs-lisp + + (setq scroll-step 1 + scroll-margin 4 + scroll-conservatively 5) + +#+end_src + +** Create non-existant directories when finding file + +This function will check if a directory for which a file we want to open exists; if not, it will offer to create the directories for me. + +#+begin_src emacs-lisp + + (defun swarsel/with-buffer-name-prompt-and-make-subdirs () + (let ((parent-directory (file-name-directory buffer-file-name))) + (when (and (not (file-exists-p parent-directory)) + (y-or-n-p (format "Directory `%s' does not exist! Create it? " parent-directory))) + (make-directory parent-directory t)))) + + (add-to-list 'find-file-not-found-functions #'swarsel/with-buffer-name-prompt-and-make-subdirs) + +#+end_src + +** Evil +#+begin_src emacs-lisp + + ;; Emulate vim in emacs + (use-package evil + :init + (setq evil-want-integration t) ; loads evil + (setq evil-want-keybinding nil) ; loads "helpful bindings" for other modes + (setq evil-want-C-u-scroll t) ; scrolling using C-u + (setq evil-want-C-i-jump nil) ; jumping with C-i + (setq evil-want-Y-yank-to-eol t) ; give Y some utility + (setq evil-shift-width 2) ; uniform indent + (setq evil-respect-visual-line-mode t) ; i am torn on this one + ; sane splitting + (setq evil-split-window-below t) + (setq evil-vsplit-window-right t) + :config + (evil-mode 1) + (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state) ; alternative for exiting insert mode + (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join) ; dont show help but instead do normal vim delete backwards + + ;; evil undo system + (evil-set-undo-system 'undo-tree) + ;; Use visual line motions even outside of visual-line-mode buffers + ;; (evil-global-set-key 'motion "j" 'evil-next-visual-line) + ;; (evil-global-set-key 'motion "k" 'evil-previous-visual-line) + + ;; Don't use evil-mode in these contexts, or use it in a specific mode + (evil-set-initial-state 'messages-buffer-mode 'emacs) + (evil-set-initial-state 'dashboard-mode 'emacs) + (evil-set-initial-state 'dired-mode 'emacs) + (evil-set-initial-state 'cfw:details-mode 'emacs) + (evil-set-initial-state 'Custom-mode 'emacs) ; god knows why this mode is in uppercase + + ; require a specific evil state + (evil-set-initial-state 'mu4e-headers-mode 'normal) + (evil-set-initial-state 'python-inferior-mode 'normal) + (add-hook 'org-capture-mode-hook 'evil-insert-state) + (add-to-list 'evil-buffer-regexps '("COMMIT_EDITMSG" . insert))) + + ;; Evil configuration for different modes + (use-package evil-collection + :after evil + :config + (evil-collection-init) + (setq forge-add-default-bindings nil)) + + + + (use-package evil-snipe + :after evil + :demand + :config + (evil-snipe-mode +1) + (evil-snipe-override-mode +1)) + + (use-package evil-cleverparens) + + + (use-package evil-surround) + + (use-package evil-goggles + :after evil + :demand + :init + (setq evil-goggles-duration 0.05) + :config + (push '(evil-operator-eval + :face evil-goggles-yank-face + :switch evil-goggles-enable-yank + :advice evil-goggles--generic-async-advice) + evil-goggles--commands) + (evil-goggles-mode) + (evil-goggles-use-diff-faces) + ) + +#+end_src + +** undo-tree + +Base emacs undo logic is very useful, but not easy to understand. I prefer undo-tree, which makes switching between branches easier and also allows quickly switching back to a much older state using the visualizer + +#+begin_src emacs-lisp + + (use-package undo-tree + ;; :init (global-undo-tree-mode) + :bind (:map undo-tree-visualizer-mode-map + ("h" . undo-tree-visualize-switch-branch-left) + ("l" . undo-tree-visualize-switch-branch-left) + ("j" . undo-tree-visualize-redo) + ("k" . undo-tree-visualize-undo)) + :config + (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo"))) + ) + (add-hook 'prog-mode-hook 'undo-tree-mode) + (add-hook 'text-mode-hook 'undo-tree-mode) + (add-hook 'org-mode-hook 'undo-tree-mode) + (add-hook 'latex-mode-hook 'undo-tree-mode) +#+end_src + +** Move backup files to another location + +#+begin_src emacs-lisp + + (let ((backup-dir "~/tmp/emacs/backups") + (auto-saves-dir "~/tmp/emacs/auto-saves/")) + (dolist (dir (list backup-dir auto-saves-dir)) + (when (not (file-directory-p dir)) + (make-directory dir t))) + (setq backup-directory-alist `(("." . ,backup-dir)) + auto-save-file-name-transforms `((".*" ,auto-saves-dir t)) + auto-save-list-file-prefix (concat auto-saves-dir ".saves-") + tramp-backup-directory-alist `((".*" . ,backup-dir)) + tramp-auto-save-directory auto-saves-dir)) + + (setq backup-by-copying t ; Don't delink hardlinks + delete-old-versions t ; Clean up the backups + version-control t ; Use version numbers on backups, + kept-new-versions 5 ; keep some new versions + kept-old-versions 2) ; and some old ones, too + +#+end_src + +* Custom Keybindings +#+begin_src emacs-lisp + + ;; Make ESC quit prompts + (global-set-key (kbd "") 'keyboard-escape-quit) + + ;; Set up general keybindings + (use-package general + :config + (general-create-definer swarsel/leader-keys + :keymaps '(normal insert visual emacs) + :prefix "SPC" + :global-prefix "C-SPC") + + (swarsel/leader-keys + "t" '(:ignore t :which-key "toggles") + "ts" '(hydra-text-scale/body :which-key "scale text") + "tl" '(display-line-numbers-mode :which-key "line numbers") + "to" '(olivetti-mode :wk "olivetti") + "td" '(darkroom-tentative-mode :wk "darkroom") + "tw" '((lambda () (interactive) (toggle-truncate-lines)) :which-key "line wrapping") + "m" '(:ignore m :which-key "modes/programs") + "mm" '((lambda () (interactive) (mu4e)) :which-key "mu4e") + "mg" '((lambda () (interactive) (magit-list-repositories)) :which-key "magit-list-repos") + "mc" '((lambda () (interactive) (swarsel/open-calendar)) :which-key "calendar") + "mp" '(popper-toggle :which-key "popper") + "md" '(dirvish :which-key "dirvish") + "c" '(:ignore c :which-key "capture") + "cj" '((lambda () (interactive) (org-capture nil "jj")) :which-key "journal") + "cs" '(markdown-download-screenshot :which-key "screenshot") + "l" '(:ignore l :which-key "links") + "le" '((lambda () (interactive) (find-file swarsel-emacs-org-filepath)) :which-key "Emacs.org") + "ls" '((lambda () (interactive) (find-file "/smb:Swarsel@192.168.1.3:")) :which-key "Server") + "lo" '(dired swarsel-obsidian-vault-directory :which-key "obsidian") + "la" '((lambda () (interactive) (find-file swarsel-org-anki-filepath)) :which-key "anki") + "ln" '((lambda () (interactive) (find-file swarsel-nix-org-filepath)) :which-key "Nix.org") + "lp" '((lambda () (interactive) (projectile-switch-project)) :which-key "switch project") + "lg" '((lambda () (interactive) (magit-list-repositories)) :which-key "list git repos") + "a" '(:ignore a :which-key "anki") + "ap" '(anki-editor-push-tree :which-key "push new cards") + "an" '((lambda () (interactive) (org-capture nil "a")) :which-key "new card") + "as" '(swarsel-anki-set-deck-and-notetype :which-key "change deck and notetype") + "h" '(:ignore h :which-key "help") + "hy" '(yas-describe-tables :which-key "yas tables") + "hb" '(embark-bindings :which-key "current key bindings") + "h" '(:ignore t :which-key "describe") + "he" 'view-echo-area-messages + "hf" 'describe-function + "hF" 'describe-face + "hl" '(view-lossage :which-key "show command keypresses") + "hL" 'find-library + "hm" 'describe-mode + "hk" 'describe-key + "hK" 'describe-keymap + "hp" 'describe-package + "hv" 'describe-variable + "hd" 'devdocs-lookup + "w" '(:ignore t :which-key "window") + "wl" 'windmove-right + "wh" 'windmove-left + "wk" 'windmove-up + "wj" 'windmove-down + "wr" 'winner-redo + "wd" 'delete-window + "w=" 'balance-windows-area + "wD" 'kill-buffer-and-window + "wu" 'winner-undo + "wr" 'winner-redo + "w/" 'evil-window-vsplit + "w-" 'evil-window-split + "wm" '(delete-other-windows :wk "maximize") + )) + + ;; General often used hotkeys + (general-define-key + "C-M-a" (lambda () (interactive) (org-capture nil "a")) ; make new anki card + "C-M-d" 'swarsel-obsidian-daily ; open daily obsidian file and create if not exist + "C-M-S" 'swarsel-anki-set-deck-and-notetype ; switch deck and notetye for new anki cards + "C-M-s" 'markdown-download-screenshot ; wrapper for org-download-screenshot + "C-c d" 'duplicate-line ; duplicate line on CURSOR + "C-M-j" 'consult-buffer + "C-s" 'consult-line + ) + +#+end_src + +* UI +** General + +- This sets up some basic UI elements + +#+begin_src emacs-lisp + + (setq inhibit-startup-message t) + + ;; (set-fringe-mode nil) ; Give some breathing room + + ;; Increase undo limit and allow for more fine grained undo, base emacs deletes way too much on undo + (setq undo-limit 80000000 + evil-want-fine-undo t + auto-save-default t + password-cache-expiry nil + ) + + ;; (display-time-mode 1) + (global-subword-mode 1) ; Iterate through CamelCase words + + (use-package rainbow-mode + :config (rainbow-mode)) + + (setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; one line at a time + (setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling + (setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse + + + (add-hook 'prog-mode-hook 'display-line-numbers-mode) + (add-hook 'text-mode-hook 'display-line-numbers-mode) + +#+end_src + +** Looks +*** Font Configuration + +- You have to install these fonts manually on Windows: https://github.com/tonsky/FiraCode/releases/download/6.2/Fira_Code_v6.2.zip +- On linux (fedora): 'sudo dnf install fira-code-fonts' + +#+begin_src emacs-lisp + + ;; (defun swarsel/font-setup (frame) + ;; (set-face-attribute 'default nil :font swarsel-standard-font :height swarsel/default-font-size) + ;; ;; Set the fixed pitch face - basically normal text + ;; (set-face-attribute 'fixed-pitch nil :font swarsel-standard-font :height 140) + ;; ;; Set the variable pitch face - basically headers etc + ;; (set-face-attribute 'variable-pitch nil :font swarsel-alt-font :height 100 :weight 'regular) + ;; (set-face-attribute 'region nil :foreground "cyan" :background "gray40" :weight 'bold) + ;; ;; (remove-hook 'after-make-frame-functions #'swarsel/font-setup) + ;; ) + + ;; (add-hook 'after-make-frame-functions #'swarsel/font-setup) + + ;; (defun swarsel/font-setup (frame) + (dolist (face '(default fixed-pitch)) + (set-face-attribute face nil + :font "FiraCode Nerd Font Mono")) + (add-to-list 'default-frame-alist '(font . "FiraCode Nerd Font Mono")) + + (set-face-attribute 'default nil :height 100) + (set-face-attribute 'fixed-pitch nil :height 1.0) + + (set-face-attribute 'variable-pitch nil + :family "IBM Plex Sans" + :weight 'regular + :height 1.06) + ;; (enable-theme 'doom-city-lights) + ;; ) + + ;; (add-hook 'after-make-frame-functions #'swarsel/font-setup) +#+end_src + +*** Color Theme + +#+begin_src emacs-lisp + + (use-package doom-themes + :init (load-theme 'doom-city-lights t)) + + (use-package solaire-mode + :init (solaire-global-mode +1)) +#+end_src + +*** Transparent background + +#+begin_src emacs-lisp + + ;; (set-frame-parameter (selected-frame) 'alpha '(95 . 95)) + ;; (add-to-list 'default-frame-alist '(alpha . (95 . 95))) + ;; (set-frame-parameter (selected-frame) 'fullscreen 'maximized) + ;; (add-to-list 'default-frame-alist '(fullscreen . maximized)) + +#+end_src + +*** Variable Pitch Mode + +#+begin_src emacs-lisp + +(use-package mixed-pitch + :custom + (mixed-pitch-set-height nil) + (mixed-pitch-variable-pitch-cursor nil) + :hook + (text-mode . mixed-pitch-mode)) + + +#+end_src + +** Modeline + +Here I set up the modeline with some information that I find useful. Specficially I am using the doom modeline. + +#+begin_src emacs-lisp + + (use-package nerd-icons) + + ;; Adds a more beautiful modeline with less clutter + (use-package doom-modeline + :init (doom-modeline-mode) + :custom + ((doom-modeline-height 22) + (doom-modeline-indent-info t))) + + ;; Generally show line numbers + (column-number-mode) + + ;; (unless (string-match-p "^Power N/A" (battery)) ; On laptops... + ;; (display-battery-mode 1)) + +#+end_src + +** Helper Modes (Ivy..., Vertico..., which-key, helpful) +*** Vertico and friends + +Soon I want to try out this new hot stuff - just at the moment there is too much other stuff to do. + +#+begin_src emacs-lisp + + (use-package vertico + :custom + (vertico-scroll-margin 0) + (vertico-count 10) + (vertico-resize t) + (vertico-cycle t) + :init + (vertico-mode) + (vertico-mouse-mode)) + + (use-package vertico-directory + :ensure nil + :after vertico + :bind (:map vertico-map + ("RET" . vertico-directory-enter) + ("DEL" . vertico-directory-delete-char) + ("M-DEL" . vertico-directory-delete-word)) + ;; Tidy shadowed file names + :hook (rfn-eshadow-update-overlay . vertico-directory-tidy)) + + (use-package orderless + :custom + (completion-styles '(orderless flex basic)) + (completion-category-overrides '((file (styles . (partial-completion))) + (eglot (styles orderless))))) + + (use-package consult + :config + (setq consult-fontify-max-size 1024) + :bind + ("C-x b" . consult-buffer) + ("C-c " . consult-global-mark) + ("C-c C-a" . consult-org-agenda) + ("C-x O" . consult-outline) + ("M-g M-g" . consult-goto-line) + ("M-g i" . consult-imenu) + ("M-s s" . consult-line) + ("M-s M-s" . consult-line-multi)) + + (use-package embark + :bind + (("C-." . embark-act) + ("M-." . embark-dwim) + ("C-h B" . embark-bindings)) + :custom + (prefix-help-command #'embark-prefix-help-command) + (embark-quit-after-action '((t . nil))) + :config + (add-to-list 'display-buffer-alist + '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" + nil + (window-parameters (mode-line-format . none))))) + + (use-package embark-consult + :after (embark consult) + :demand t ; only necessary if you have the hook below + ;; if you want to have consult previews as you move around an + ;; auto-updating embark collect buffer + :hook + (embark-collect-mode . consult-preview-at-point-mode)) + + (use-package marginalia + :after vertico + :init + (marginalia-mode) + (setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))) + + (use-package nerd-icons-completion + :after (marginalia nerd-icons) + :hook (marginalia-mode . nerd-icons-completion-marginalia-setup) + :init + (nerd-icons-completion-mode)) + + +#+end_src + +*** Ivy + Counsel + +#+begin_src emacs-lisp + + ;; (use-package ivy + ;; :init (ivy-mode 1) + ;; :diminish + ;; :bind (("C-s" . swiper) ; call swiper (find tool) + ;; :map ivy-minibuffer-map + ;; ;("TAB" . ivy-alt-done) ; autocomplete + ;; ("C-l" . ivy-alt-done) + ;; ("C-" . ivy-alt-done) ; for kyria + ;; ("C-h" . counsel-up-directory) ; for kyria + ;; ("C-" . counsel-up-directory) ; for kyria + ;; ("C-j" . ivy-next-line) ; go up and down in ivy using vim keys + ;; ("C-" . ivy-next-line) ; for kyria + ;; ("C-k" . ivy-previous-line) + ;; ("C-" . ivy-previous-line) ; for kyria + ;; :map ivy-switch-buffer-map + ;; ("C-k" . ivy-previous-line) + ;; ("C-" . ivy-previous-line) ; for kyria + ;; ("C-l" . ivy-done) + ;; ("C-" . ivy-done) ; for kyria + ;; ("C-d" . ivy-switch-buffer-kill) + ;; :map ivy-reverse-i-search-map + ;; ("C-k" . ivy-previous-line) + ;; ("C-" . ivy-previous-line) ; for kyria + ;; ("C-d" . ivy-reverse-i-search-kill)) + ;; :config + ;; (setq ivy-use-virtual-buffers t) + ;; (setq ivy-count-format "(%d/%d) ") + ;; (setq ivy-wrap t)) + + ;; ;; More information about functions in ivy-mode + ;; (use-package ivy-rich + ;; :init + ;; (ivy-rich-mode 1)) + + ;; (use-package counsel + ;; :init (counsel-mode 1) + ;; :bind (("C-M-j" . counsel-switch-buffer) + ;; ("M-x" . counsel-M-x) + ;; ("C-x b" . counsel-ibuffer) + ;; ("C-x C-f" . counsel-find-file) + ;; :map minibuffer-local-map + ;; ("C-r" . 'counsel-minibuffer-history)) + ;; :config + ;; (setq ivy-initial-inputs-alist nil)) + +#+end_src + +*** Helpful + which-key: Better help defaults + +#+begin_src emacs-lisp + + (use-package which-key + :init (which-key-mode) + :diminish which-key-mode + :config + (setq which-key-idle-delay 0.3)) + + ;; (use-package helpful + ;; :custom + ;; (counsel-describe-function-function #'helpful-callable) + ;; (counsel-describe-variable-function #'helpful-variable) + ;; :bind + ;; ([remap describe-function] . counsel-describe-function) + ;; ([remap describe-command] . helpful-command) + ;; ([remap describe-variable] . counsel-describe-variable) + ;; ([remap describe-key] . helpful-key)) + + (use-package helpful + :custom + (help-select-window t) + :bind + (("C-h f" . helpful-callable) + ("C-h v" . helpful-variable) + ("C-h k" . helpful-key) + ("C-h C-." . helpful-at-point))) + +#+end_src + +** Text Scaling +#+begin_src emacs-lisp + + (use-package hydra) + + ;; change the text size of the current buffer + (defhydra hydra-text-scale (:timeout 4) + "scale text" + ("j" text-scale-increase "in") + ("k" text-scale-decrease "out") + ("f" nil "finished" :exit t)) + +#+end_src + +** Ligatures + +#+begin_src emacs-lisp + +(use-package ligature + :config + (ligature-set-ligatures 'prog-mode + '("|||>" "<|||" "<==>" "" "---" "-<<" + "<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->" + "<--" "<-<" "<<=" "<<-" "<<<" "<+>" "" "###" "#_(" "..<" + "..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~=" + "~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|" + "[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:" + ">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:" + "<$" "<=" "<>" "<-" "<<" "<+" "" "++" "?:" "?=" + "?." "??" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)" "\\\\" + "://" ";;")) + (global-ligature-mode t)) + +#+end_src + +** Popup + Shackle Buffers + +#+begin_src emacs-lisp + + (use-package popper + :bind (("M-[" . popper-toggle)) + :init + (setq popper-reference-buffers + '("\\*Messages\\*" + ("\\*Warnings\\*" . hide) + "Output\\*$" + "\\*Async Shell Command\\*" + "\\*Async-native-compile-log\\*" + help-mode + helpful-mode + "*Occur*" + "*scratch*" + "*julia*" + "*Python*" + ;; ("*tex-shell*" . hide) + (compilation-mode . hide))) + (popper-mode +1) + (popper-echo-mode +1)) + + (use-package shackle + :config + (setq shackle-rules '(("*Messages*" :select t :popup t :align right :size 0.3) + ("*Warnings*" :ignore t :popup t :align right :size 0.3) + ("*Occur*" :select t :popup t :align below :size 0.2) + ("*scratch*" :select t :popup t :align below :size 0.2) + ("*Python*" :select t :popup t :align below :size 0.2) + ("*tex-shell*" :ignore t :popup t :align below :size 0.2) + (helpful-mode :select t :popup t :align right :size 0.35) + (help-mode :select t :popup t :align right :size 0.4))) + (shackle-mode 1)) + +#+end_src + +** Indicate first and last line of buffer + +#+begin_src emacs-lisp + +(setq-default indicate-buffer-boundaries t) + +#+end_src + +* Org Mode +** General + +#+begin_src emacs-lisp + + (defun swarsel/org-mode-setup () + (org-indent-mode) + (variable-pitch-mode 1) + ;;(auto-fill-mode 0) + (setq display-line-numbers-type 'relative + display-line-numbers-current-absolute 1 + display-line-numbers-width-start nil + display-line-numbers-width 6 + display-line-numbers-grow-only 1) + (add-hook 'org-tab-first-hook 'org-end-of-line) + (visual-line-mode 1)) + ;; (setq evil-auto-indent nil) + ;;(diminish org-indent-mode) + + (defun swarsel/org-font-setup () + ;; Replace list hyphen with dot + (font-lock-add-keywords 'org-mode + '(("^ *\\([-]\\) " + (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))) + + (use-package org + ;;:diminish (org-indent-mode) + :hook (org-mode . swarsel/org-mode-setup) + :bind ("C-" . org-fold-outer) + :config + (setq org-ellipsis " ⤵" + org-hide-emphasis-markers t) + (setq org-startup-folded t) + (setq org-support-shift-select t) + (setq org-agenda-start-with-log-mode t) + (setq org-log-done 'time) + (setq org-log-into-drawer t) + (setq org-startup-with-inline-images t) + (setq org-image-actual-width nil) + (setq org-format-latex-options '(:foreground "White" :background default :scale 2.0 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0 :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))) + + ;; (setq org-agenda-files + ;; '(swarsel-org-tasks-filepath + ;; swarsel-org-archive-filepath + ;; swarsel-org-anki-filepath)) + + (setq org-agenda-files + '("~/Calendars/leon_cal.org")) + + (require 'org-habit) + (add-to-list 'org-modules 'org-habit) + (setq org-habit-graph-column 60) + + (setq org-todo-keywords + '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)") + (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANC(k@)"))) + + (setq org-refile-targets + '((swarsel-archive-org-file :maxlevel . 1) + (swarsel-anki-org-file :maxlevel . 1) + (swarsel-tasks-org-file :maxlevel . 1))) + + ;; Configure custom agenda views + (setq org-agenda-custom-commands + '(("d" "Dashboard" + ((agenda "" ((org-deadline-warning-days 7))) + (todo "NEXT" + ((org-agenda-overriding-header "Next Tasks"))) + (tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects"))))) + + ("n" "Next Tasks" + ((todo "NEXT" + ((org-agenda-overriding-header "Next Tasks"))))) + + ("W" "Work Tasks" tags-todo "+work-email") + + ;; Low-effort next actions + ("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0" + ((org-agenda-overriding-header "Low Effort Tasks") + (org-agenda-max-todos 20) + (org-agenda-files org-agenda-files))) + + ("w" "Workflow Status" + ((todo "WAIT" + ((org-agenda-overriding-header "Waiting on External") + (org-agenda-files org-agenda-files))) + (todo "REVIEW" + ((org-agenda-overriding-header "In Review") + (org-agenda-files org-agenda-files))) + (todo "PLAN" + ((org-agenda-overriding-header "In Planning") + (org-agenda-todo-list-sublevels nil) + (org-agenda-files org-agenda-files))) + (todo "BACKLOG" + ((org-agenda-overriding-header "Project Backlog") + (org-agenda-todo-list-sublevels nil) + (org-agenda-files org-agenda-files))) + (todo "READY" + ((org-agenda-overriding-header "Ready for Work") + (org-agenda-files org-agenda-files))) + (todo "ACTIVE" + ((org-agenda-overriding-header "Active Projects") + (org-agenda-files org-agenda-files))) + (todo "COMPLETED" + ((org-agenda-overriding-header "Completed Projects") + (org-agenda-files org-agenda-files))) + (todo "CANC" + ((org-agenda-overriding-header "Cancelled Projects") + (org-agenda-files org-agenda-files))))))) + + (setq org-capture-templates + `( + ("a" "Anki basic" + entry + (file+headline swarsel-org-anki-filepath "Dispatch") + (function swarsel-anki-make-template-string)) + + ("A" "Anki cloze" + entry + (file+headline org-swarsel-anki-file "Dispatch") + "* %<%H:%M>\n:PROPERTIES:\n:ANKI_NOTE_TYPE: Cloze\n:ANKI_DECK: 🦁 All::01 ❤️ Various::00 ✨ Allgemein\n:END:\n** Text\n%?\n** Extra\n") + ("t" "Tasks / Projects") + ("tt" "Task" entry (file+olp swarsel-org-tasks-filepath "Inbox") + "* TODO %?\n %U\n %a\n %i" :empty-lines 1) + + ("j" "Journal Entries") + ("jj" "Journal" entry + (file+olp+datetree swarsel-org-journal-filepath) + "\n* %<%I:%M %p> - Journal :journal:\n\n%?\n\n" + ;; ,(dw/read-file-as-string "~/Notes/Templates/Daily.org") + :clock-in :clock-resume + :empty-lines 1))) + + (swarsel/org-font-setup)) +#+end_src + +** Font Faces + +#+begin_src emacs-lisp + + + + ;; ;; Set faces for heading levels + ;; (with-eval-after-load 'org-faces (dolist (face '((org-level-1 . 1.3) + ;; (org-level-2 . 1.2) + ;; (org-level-3 . 1.15) + ;; (org-level-4 . 1.1) + ;; (org-level-5 . 1.1) + ;; (org-level-6 . 1.1) + ;; (org-level-7 . 1.1) + ;; (org-level-8 . 1.1))) + ;; (set-face-attribute (car face) nil :font swarsel-alt-font :weight 'regular :height (cdr face))) + + ;; ;; Ensure that anything that should be fixed-pitch in Org files appears that way + ;; (set-face-attribute 'org-block nil :inherit '(fixed-pitch)) + ;; (set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch)) + ;; (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch)) + ;; (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch)) + ;; (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch)) + ;; (set-face-attribute 'org-checkbox nil :inherit '(fixed-pitch))) + +#+end_src + +** org-appear + +#+begin_src emacs-lisp + + ;; Show hidden emphasis markers + (use-package org-appear + :hook (org-mode . org-appear-mode) + :init + (setq org-appear-autolinks t) + (setq org-appear-autosubmarkers t) + ) + +#+end_src + +** Heading Bullets + +#+begin_src emacs-lisp + + (use-package org-bullets + :after org + :hook (org-mode . org-bullets-mode) + :custom + (org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●"))) + +#+end_src + +** Centered org-mode Buffers + +#+begin_src emacs-lisp + + (defun swarsel/org-mode-visual-fill () + (setq visual-fill-column-width 150 + visual-fill-column-center-text t) + (visual-fill-column-mode 1)) + + (use-package visual-fill-column + :hook (org-mode . swarsel/org-mode-visual-fill)) + +#+end_src + +** Fix headings not folding sometimes + +#+begin_src emacs-lisp + + (setq org-fold-core-style 'overlays) + +#+end_src + +** Babel +*** Language Configuration + +- This configures the languages that babel recognizes + +#+begin_src emacs-lisp + + (org-babel-do-load-languages + 'org-babel-load-languages + '((emacs-lisp . t) + (python . t))) + + (push '("conf-unix" . conf-unix) org-src-lang-modes) + +#+end_src + +*** old easy structure templates + +- org 9.2 changed the way structure templates work. This brings back the old way it worked. + + #+begin_src emacs-lisp + + (require 'org-tempo) + (add-to-list 'org-structure-template-alist '("sh" . "src shell")) + (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) + (add-to-list 'org-structure-template-alist '("py" . "src python")) + (add-to-list 'org-structure-template-alist '("nix" . "src nix :tangle")) + + #+end_src + +** Auto-tangle Configuration Files + +- Automatically tangles all configuration blocks in this file to the defined Emacs orgfile + +#+begin_src emacs-lisp + + (defun swarsel/org-babel-tangle-config () + (when (string-equal (buffer-file-name) + swarsel-emacs-org-filepath) + ;; Dynamic scoping to the rescue + (let ((org-confirm-babel-evaluate nil)) + (org-babel-tangle))) + (when (string-equal (buffer-file-name) + swarsel-nix-org-filepath) + ;; Dynamic scoping to the rescue + (let ((org-confirm-babel-evaluate nil)) + (org-babel-tangle)))) + + (add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'swarsel/org-babel-tangle-config))) + +#+end_src + +** aucTex + +#+begin_src emacs-lisp :tangle yes + + (use-package auctex) + (setq TeX-auto-save t) + (setq TeX-save-query nil) + (setq TeX-parse-self t) + (setq-default TeX-master nil) + + ;; (add-hook 'LaTeX-mode-hook 'visual-line-mode) + ;; (add-hook 'LaTeX-mode-hook 'flyspell-mode) + ;; (add-hook 'LaTeX-mode-hook 'LaTeX-math-mode) + + ;; (add-hook 'LaTeX-mode-hook 'turn-on-reftex) + ;; (setq reftex-plug-into-AUCTeX t) + +#+end_src + +** TeX + +#+begin_src emacs-lisp + + (add-hook 'markdown-mode-hook + (lambda () + (local-set-key (kbd "C-c C-x C-l") 'org-latex-preview) + (local-set-key (kbd "C-c C-x C-u") 'markdown-toggle-url-hiding) + )) + +#+end_src + +** org-download + +#+begin_src emacs-lisp + + (use-package org-download + :after org + :defer nil + :custom + (org-download-method 'directory) + (org-download-image-dir "./images") + (org-download-heading-lvl 0) + (org-download-timestamp "org_%Y%m%d-%H%M%S_") + ;;(org-image-actual-width 500) + (org-download-screenshot-method "grim -g \"$(slurp)\" %s") + :bind + ("C-M-y" . org-download-screenshot) + :config + (require 'org-download)) + +#+end_src + +** org-fragtog + +#+begin_src emacs-lisp + + (use-package org-fragtog) + (add-hook 'org-mode-hook 'org-fragtog-mode) + (add-hook 'markdown-mode-hook 'org-fragtog-mode) + +#+end_src + +** Fold current heading + +#+begin_src emacs-lisp + +(defun org-fold-outer () + (interactive) + (org-beginning-of-line) + (if (string-match "^*+" (thing-at-point 'line t)) + (outline-up-heading 1)) + (outline-hide-subtree) + ) + +#+end_src + +** org-modern + +#+begin_src emacs-lisp + + (use-package org-modern + :config (setq org-modern-block-name + '((t . t) + ("src" "»" "∥"))) + :hook (org-mode . org-modern-mode)) + +#+end_src + +* Nix Mode + +#+begin_src emacs-lisp + + (use-package nix-mode + :mode "\\.nix\\'") + +#+end_src + +* Markdown Mode +** Mode + +#+begin_src emacs-lisp :tangle yes + +(use-package markdown-mode + :ensure t + :mode ("README\\.md\\'" . gfm-mode) + :init (setq markdown-command "multimarkdown") + :bind (:map markdown-mode-map + ("C-c C-e" . markdown-do))) + +#+end_src + +** org-download port + +This is a section adapted from org-download to make some org-download functions available in markdown mode. I need this because I am still using Obsidian to manage my notes, and that used markdown files. + +#+begin_src emacs-lisp + + ;; https://github.com/mooreryan/markdown-dnd-images + ;; (add-to-list 'load-path "~/.emacs.d/packages") + ;; (require 'markdown-dnd-images) + ;; (setq dnd-save-directory "images") + + ;; (setq dnd-save-buffer-name nil) + + ;; (setq dnd-view-inline t) + + ;; (setq dnd-capture-source nil) + + ;; ;; these ne + xt lines provide an interface for org-download in markdown mode for use with obsidian + + (defvar org-download-markdown-link-format + "![[./%s]]\n" + "Format of the file link to insert.") + + (defcustom org-download-markdown-link-format-function #'org-download-markdown-link-format-function-default + "Function that takes FILENAME and returns a org link." + :type 'function) + + (defun org-download-markdown-link-format-function-default (filename) + "The default function of `org-download-link-format-function'." + (if (and (>= (string-to-number org-version) 9.3) + (eq org-download-method 'attach)) + (format "[[attachment:%s]]\n" + (org-link-escape + (file-relative-name filename (org-attach-dir)))) + (format org-download-markdown-link-format + (org-link-escape + (funcall org-download-abbreviate-filename-function filename))))) + + (defun org-download-markdown-image (link) + "Save image at address LINK to `org-download--dir'." + (interactive "sUrl: ") + (let* ((link-and-ext (org-download--parse-link link)) + (filename + (cond ((and (derived-mode-p 'org-mode) + (eq org-download-method 'attach)) + (let ((org-download-image-dir (org-attach-dir t)) + org-download-heading-lvl) + (apply #'org-download--fullname link-and-ext))) + ((fboundp org-download-method) + (funcall org-download-method link)) + (t + (apply #'org-download--fullname link-and-ext))))) + (setq org-download-path-last-file filename) + (org-download--image link filename) + (when (org-download-org-mode-p) + (when (eq org-download-method 'attach) + (org-attach-attach filename nil 'none)) + (org-download-markdown-insert-link link filename)) + (when (and (eq org-download-delete-image-after-download t) + (not (url-handler-file-remote-p (current-kill 0)))) + (delete-file link delete-by-moving-to-trash)))) + + (defun org-download-markdown-screenshot (&optional basename) + "Capture screenshot and insert the resulting file. + The screenshot tool is determined by `org-download-screenshot-method'." + (interactive) + (let* ((screenshot-dir (file-name-directory org-download-screenshot-file)) + (org-download-screenshot-file + (if basename + (concat screenshot-dir basename) org-download-screenshot-file))) + (make-directory screenshot-dir t) + (if (functionp org-download-screenshot-method) + (funcall org-download-screenshot-method + org-download-screenshot-file) + (shell-command-to-string + (format org-download-screenshot-method + org-download-screenshot-file))) + (when (file-exists-p org-download-screenshot-file) + (org-download-markdown-image org-download-screenshot-file) + (delete-file org-download-screenshot-file)))) + + + (defun org-download-markdown-insert-link (link filename) + (let* ((beg (point)) + (line-beg (line-beginning-position)) + (indent (- beg line-beg)) + (in-item-p (org-in-item-p)) + str) + (if (looking-back "^[ \t]+" line-beg) + (delete-region (match-beginning 0) (match-end 0)) + (newline)) + (insert (funcall org-download-annotate-function link)) + (dolist (attr org-download-image-attr-list) + (insert attr "\n")) + (insert (if (= org-download-image-html-width 0) + "" + (format "#+attr_html: :width %dpx\n" org-download-image-html-width))) + (insert (if (= org-download-image-latex-width 0) + "" + (format "#+attr_latex: :width %dcm\n" org-download-image-latex-width))) + (insert (if (= org-download-image-org-width 0) + "" + (format "#+attr_org: :width %dpx\n" org-download-image-org-width))) + (insert (funcall org-download-markdown-link-format-function filename)) + (org-download--display-inline-images) + (setq str (buffer-substring-no-properties line-beg (point))) + (when in-item-p + (indent-region line-beg (point) indent)) + str)) + + (defun markdown-download-screenshot () + (interactive) + (org-mode) + (org-download-markdown-screenshot) + (markdown-mode)) + + (add-hook 'markdown-mode-hook (lambda () (org-display-inline-images))) + +#+end_src + +* Writing +** Olivetti + +#+begin_src emacs-lisp + + (use-package olivetti + :init + (setq olivetti-body-width 100) + (setq olivetti-recall-visual-line-mode-entry-state t)) + +#+end_src + +** darkroom + +#+begin_src emacs-lisp + +(use-package darkroom + :init + (setq darkroom-text-scale-increase 3)) + +#+end_src + +* Development +** Ripgrep + +#+begin_src emacs-lisp + + (use-package rg) + +#+end_src +** Tree-sitter + +In order to update the language grammars, run the next command below. + +#+begin_src emacs-lisp :tangle no + + (mapc #'treesit-install-language-grammar (mapcar #'car treesit-language-source-alist)) + +#+end_src + +#+begin_src emacs-lisp + + ;; (setq treesit-language-source-alist + ;; '((bash "https://github.com/tree-sitter/tree-sitter-bash") + ;; (cmake "https://github.com/uyha/tree-sitter-cmake") + ;; (c "https://github.com/tree-sitter/tree-sitter-c") + ;; (cpp "https://github.com/tree-sitter/tree-sitter-cpp") + ;; (css "https://github.com/tree-sitter/tree-sitter-css") + ;; (elisp "https://github.com/Wilfred/tree-sitter-elisp") + ;; (go "https://github.com/tree-sitter/tree-sitter-go") + ;; (html "https://github.com/tree-sitter/tree-sitter-html") + ;; (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src") + ;; (json "https://github.com/tree-sitter/tree-sitter-json") + ;; (make "https://github.com/alemuller/tree-sitter-make") + ;; (markdown "https://github.com/ikatyang/tree-sitter-markdown") + ;; (python "https://github.com/tree-sitter/tree-sitter-python") + ;; (toml "https://github.com/tree-sitter/tree-sitter-toml") + ;; (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src") + ;; (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src") + ;; (rust "https://github.com/tree-sitter/tree-sitter-rust") + ;; (sql "https://github.com/m-novikov/tree-sitter-sql") + ;; (yaml "https://github.com/ikatyang/tree-sitter-yaml"))) + + ;; (add-hook 'rustic-mode-hook 'tree-sitter-mode) + ;; (add-hook 'rustic-mode-hook 'tree-sitter-hl-mode) + + (use-package emacs + :ensure nil + :init + (setq treesit-language-source-alist + '((bash . ("https://github.com/tree-sitter/tree-sitter-bash")) + (c . ("https://github.com/tree-sitter/tree-sitter-c")) + (cmake . ("https://github.com/uyha/tree-sitter-cmake")) + (cpp . ("https://github.com/tree-sitter/tree-sitter-cpp")) + (css . ("https://github.com/tree-sitter/tree-sitter-css")) + (elisp . ("https://github.com/Wilfred/tree-sitter-elisp")) + (go . ("https://github.com/tree-sitter/tree-sitter-go")) + (html . ("https://github.com/tree-sitter/tree-sitter-html")) + (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript")) + (json . ("https://github.com/tree-sitter/tree-sitter-json")) + (julia . ("https://github.com/tree-sitter/tree-sitter-julia")) + (latex . ("https://github.com/latex-lsp/tree-sitter-latex")) + (make . ("https://github.com/alemuller/tree-sitter-make")) + (markdown . ("https://github.com/ikatyang/tree-sitter-markdown")) + (R . ("https://github.com/r-lib/tree-sitter-r")) + (python . ("https://github.com/tree-sitter/tree-sitter-python")) + (typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "typescript/src" "typescript")) + (rust . ("https://github.com/tree-sitter/tree-sitter-rust")) + (sql . ("https://github.com/m-novikov/tree-sitter-sql")) + (toml . ("https://github.com/tree-sitter/tree-sitter-toml")) + (yaml . ("https://github.com/ikatyang/tree-sitter-yaml")))) + ;; :hook (((rustic-mode) . tree-sitter-mode) + ;; ((rustic-mode) . tree-sitter-hl-mode)) + ) + + (use-package treesit-auto + :config + (global-treesit-auto-mode) + (setq treesit-auto-install 'prompt)) + + +#+end_src + +** direnv + +#+begin_src emacs-lisp + + (use-package direnv + ;; :init (add-hook 'prog-mode-hook #'direnv-update-environment) + :custom (direnv-always-show-summary nil) + :config (direnv-mode)) + +#+end_src + +** devdocs + +#+begin_src emacs-lisp + +(use-package devdocs) + +#+end_src + +** Projectile +#+begin_src emacs-lisp + + (use-package projectile + :diminish projectile-mode + :config (projectile-mode) + :custom ((projectile-completion-system 'ivy)) ;; integrate ivy into completion system + :bind-keymap + ("C-c p" . projectile-command-map) ; all projectile commands under this + :init + ;; NOTE: Set this to the folder where you keep your Git repos! + (when (file-directory-p swarsel-projects-directory) + (setq projectile-project-search-path (list swarsel-projects-directory))) + ;(setq projectile-switch-project-action #'projectile-dired) ;list files + (setq projectile-switch-project-action #'magit-status)) + + ;; (use-package counsel-projectile + ;; :config (counsel-projectile-mode)) + +#+end_src + +** Project.el + +#+begin_src emacs-lisp + + ;; (use-package project + ;; :ensure nil + ;; :bind + ;; (:map project-prefix-map + ;; ("v" . magit-project-status)) + ;; :config + ;; (add-to-list 'project-switch-commands '(magit-project-status "Magit" "m"))) + +#+end_src + +** Magit + +- setup permanent github auth using Github CLI https://docs.github.com/en/get-started/getting-started-with-git/caching-your-github-credentials-in-git#platform-linux +- on fedora: 'sudo dnf install gh' and then 'gh auth login' + +#+begin_src emacs-lisp + + (use-package magit + :config + (setq magit-repository-directories `((,swarsel-projects-directory . 1) + (,swarsel-emacs-directory . 0) + (,swarsel-obsidian-directory . 0))) + :custom + (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)) ; stay in the same window + +#+end_src + +** Forge + +NOTE: Make sure to configure a GitHub token before using this package! +- https://magit.vc/manual/forge/Token-Creation.html#Token-Creation +- https://magit.vc/manual/ghub/Getting-Started.html#Getting-Started +- https://magit.vc/manual/ghub/Storing-a-Token.html +- https://www.emacswiki.org/emacs/GnuPG + + (1) in practice: github -<> settings -<> developer option -<> + create classic token with repo; user; read:org permissions + (2) install GnuGP (and add to PATH) + (3) create ~/.authinfo.gpg with the following info scheme: + machine api.github.com login USERNAME^forge password 012345abcdef... + +#+begin_src emacs-lisp + + (use-package forge + :after magit) + +(with-eval-after-load 'forge + (add-to-list 'forge-alist + '("sgit.iue.tuwien.ac.at" + "sgit.iue.tuwien.ac.at/api/v1" + "sgit.iue.tuwien.ac.at" + forge-gitea-repository))) +#+end_src + +** git-timemachine + +#+begin_src emacs-lisp + + (use-package git-timemachine + :hook (git-time-machine-mode . evil-normalize-keymaps) + :init (setq git-timemachine-show-minibuffer-details t) + :general + (general-nmap "SPC g t" 'git-timemachine-toggle) + (git-timemachine-mode-map + "C-k" 'git-timemachine-show-previous-revision + "C-j" 'git-timemachine-show-next-revision + "q" 'git-timemachine-quit)) + +#+end_src + +** Delimiters (brackets) + +- rainbow-delimiters colors all delimiters, also ones not in current selection +- paren highlights the current delimiter selection especially bold +- highlight-parentheses boldly highlights all delimiters in current selection + +I am not completely sure on electric-pair-mode yet, sometimes it is very helpful, sometimes it annoys me to no end. + +#+begin_src emacs-lisp + + (use-package rainbow-delimiters + :hook (prog-mode . rainbow-delimiters-mode)) + + (use-package highlight-parentheses + :config + (setq highlight-parentheses-colors nil) + (setq highlight-parentheses-background-colors '("magenta" "blue" "cyan" "green" "yellow" "orange" "red")) + (global-highlight-parentheses-mode t)) + + (electric-pair-mode 1) + (setq electric-pair-preserve-balance nil) + ;; don't skip newline when auto-pairing parenthesis + (setq electric-pair-skip-whitespace-chars '(9 32)) + +#+end_src + +** IDE + +This section currently holds three different lsp-client implementations; at the moment I am using eglot; it is very sad that there is no end-all solution. All configs are left in for - I like lsp-mode for the debugging and lsp-bridge because asynchronous lsp is quite nice. However eglot is fast enough and I am mostly working on small projects anyways. Still, it is annoying to not have a debugger readily available. + +*** DISABLED Company mode + +The plan is to in the future use Vertico etc. instead and then switch to Corfu. Again, I do not have the time for this yet. + +#+begin_src emacs-lisp + + ;; (use-package company + ;; :after lsp-mode + ;; :hook (lsp-mode . company-mode) + ;; :bind (:map company-active-map + ;; ("" . company-complete-selection)) + ;; (:map lsp-mode-map + ;; ("" . company-indent-or-complete-common)) + ;; :custom + ;; (company-minimum-prefix-length 1) + ;; (company-idle-delay 0.7)) + + ;; (use-package company-box + ;; :hook (company-mode . company-box-mode)) + +#+end_src + +*** IN USE Corfu + +Currently unused. + +#+begin_src emacs-lisp + + ;; (use-package corfu + ;; :custom + ;; (corfu-cycle t) + ;; :init + ;; (global-corfu-mode)) + + (use-package corfu + :init + (global-corfu-mode) + (corfu-history-mode) + (corfu-popupinfo-mode) ; Popup completion info + :custom + (corfu-auto t) + (corfu-auto-prefix 3) + (corfu-auto-delay 0.3) + (corfu-cycle t) + (corfu-quit-no-match 'separator) + (corfu-separator ?\s) + (corfu-quit-no-match t) + (corfu-popupinfo-max-height 70) + (corfu-popupinfo-delay '(0.5 . 0.2)) + ;; (corfu-preview-current 'insert) ; insert previewed candidate + (corfu-preselect 'prompt) + (corfu-on-exact-match nil) ; Don't auto expand tempel snippets + ;; Optionally use TAB for cycling, default is `corfu-complete'. + :bind (:map corfu-map + ("M-SPC" . corfu-insert-separator) + ("" . swarsel/corfu-normal-return) + ("S-" . corfu-popupinfo-scroll-down) + ("S-" . corfu-popupinfo-scroll-up) + ("C-" . corfu-previous) + ("C-" . corfu-next) + ("" . swarsel/corfu-quit-and-up) + ("" . swarsel/corfu-quit-and-down)) + ) + + ;; dont disrupt file navigation with completions + (defun swarsel/corfu-normal-return (&optional arg) + (interactive) + (corfu-complete) + (corfu-quit)) + + (defun swarsel/corfu-quit-and-up (&optional arg) + (interactive) + (corfu-quit) + (evil-previous-visual-line)) + + (defun swarsel/corfu-quit-and-down (&optional arg) + (interactive) + (corfu-quit) + (evil-next-visual-line)) + + (use-package nerd-icons-corfu) + + (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter) + + (setq nerd-icons-corfu-mapping + '((array :style "cod" :icon "symbol_array" :face font-lock-type-face) + (boolean :style "cod" :icon "symbol_boolean" :face font-lock-builtin-face) + ;; ... + (t :style "cod" :icon "code" :face font-lock-warning-face))) + + (use-package cape + ;; Bind dedicated completion commands + ;; Alternative prefix keys: C-c p, M-p, M-+, ... + ;; :bind (("C-c p p" . completion-at-point) ;; capf + ;; ("C-c p t" . complete-tag) ;; etags + ;; ("C-c p d" . cape-dabbrev) ;; or dabbrev-completion + ;; ("C-c p h" . cape-history) + ;; ("C-c p f" . cape-file) + ;; ("C-c p k" . cape-keyword) + ;; ("C-c p s" . cape-elisp-symbol) + ;; ("C-c p e" . cape-elisp-block) + ;; ("C-c p a" . cape-abbrev) + ;; ("C-c p l" . cape-line) + ;; ("C-c p w" . cape-dict) + ;; ("C-c p :" . cape-emoji) + ;; ("C-c p \\" . cape-tex) + ;; ("C-c p _" . cape-tex) + ;; ("C-c p ^" . cape-tex) + ;; ("C-c p &" . cape-sgml) + ;; ("C-c p r" . cape-rfc1345)) + :init + ;; Add to the global default value of `completion-at-point-functions' which is + ;; used by `completion-at-point'. The order of the functions matters, the + ;; first function returning a result wins. Note that the list of buffer-local + ;; completion functions takes precedence over the global list. + (add-to-list 'completion-at-point-functions #'cape-dabbrev) + (add-to-list 'completion-at-point-functions #'cape-file) + (add-to-list 'completion-at-point-functions #'cape-elisp-block) + ;;(add-to-list 'completion-at-point-functions #'cape-history) + ;;(add-to-list 'completion-at-point-functions #'cape-keyword) + ;;(add-to-list 'completion-at-point-functions #'cape-tex) + ;;(add-to-list 'completion-at-point-functions #'cape-sgml) + ;;(add-to-list 'completion-at-point-functions #'cape-rfc1345) + ;;(add-to-list 'completion-at-point-functions #'cape-abbrev) + ;;(add-to-list 'completion-at-point-functions #'cape-dict) + ;;(add-to-list 'completion-at-point-functions #'cape-elisp-symbol) + ;;(add-to-list 'completion-at-point-functions #'cape-line) + ) + +#+end_src + +*** rust + +#+begin_src emacs-lisp + + ;; (use-package rustic + ;; :ensure + ;; :bind (:map rustic-mode-map + ;; ("M-j" . lsp-ui-imenu) + ;; ("M-?" . lsp-find-references) + ;; ("C-c C-c l" . flycheck-list-errors) + ;; ("C-c C-c a" . lsp-execute-code-action) + ;; ("C-c C-c r" . lsp-rename) + ;; ("C-c C-c q" . lsp-workspace-restart) + ;; ("C-c C-c Q" . lsp-workspace-shutdown) + ;; ("C-c C-c s" . lsp-rust-analyzer-status)) + ;; :config + + ;; (setq rustic-format-on-save t) + ;; (add-hook 'rustic-mode-hook 'rk/rustic-mode-hook)) + + ;; (defun rk/rustic-mode-hook () + ;; ;; so that run C-c C-c C-r works without having to confirm, but don't try to + ;; ;; save rust buffers that are not file visiting. Once + ;; ;; https://github.com/brotzeit/rustic/issues/253 has been resolved this should + ;; ;; no longer be necessary. + ;; (when buffer-file-name + ;; (setq-local buffer-save-without-query t)) + ;; (add-hook 'before-save-hook 'lsp-format-buffer nil t)) + + ;; (use-package rustic + ;; :config + ;; (setq rustic-format-on-save t) + ;; (setq rustic-lsp-client 'eglot) + ;; :custom + ;; (lsp-rust-analyzer-cargo-watch-command "clippy") + ;; (lsp-rust-analyzer-server-display-inlay-hints t) + ;; :mode ("\\.rs" . rustic-mode)) + + (use-package rustic + :config + (setq rustic-format-on-save t) + (setq rustic-lsp-client 'eglot) + :mode ("\\.rs" . rustic-mode)) +#+end_src + +*** Python + +#+begin_src emacs-lisp + + ;; run the python inferior shell immediately upon entering a python buffer + (add-hook 'python-mode-hook 'swarsel/run-python) + +(defun swarsel/run-python () + (save-selected-window + (switch-to-buffer-other-window (process-buffer (python-shell-get-or-create-process (python-shell-parse-command)))))) +#+end_src + +*** CUDA + +1. M-x dap-cpptools-setup + +#+begin_src emacs-lisp + + ;; (use-package cuda-mode) + + ;; ;; add path manually; + ;; (add-hook 'cuda-mode-hook + ;; (lambda () + ;; ( setq c-basic-offset 4 + ;; flycheck-cuda-include-path (list ".")) + ;; )) + +#+end_src + +*** Tramp + +#+begin_src emacs-lisp + + + +(use-package tramp + :init + (setq vc-ignore-dir-regexp + (format "\\(%s\\)\\|\\(%s\\)" + vc-ignore-dir-regexp + tramp-file-name-regexp)) + (setq tramp-default-method "ssh") + (setq tramp-auto-save-directory + (expand-file-name "tramp-auto-save" user-emacs-directory)) + (setq tramp-persistency-file-name + (expand-file-name "tramp-connection-history" user-emacs-directory)) + (setq password-cache-expiry nil) + (setq tramp-use-ssh-controlmaster-options nil) + (setq remote-file-name-inhibit-cache nil) + :config + (customize-set-variable 'tramp-ssh-controlmaster-options + (concat + "-o ControlPath=/tmp/ssh-tramp-%%r@%%h:%%p " + "-o ControlMaster=auto -o ControlPersist=yes")) +) + + + +#+end_src + +*** Commenting + +#+begin_src emacs-lisp + + (use-package evil-nerd-commenter + :bind ("M-/" . evilnc-comment-or-uncomment-lines)) + +#+end_src + +*** yasnippet + +#+begin_src emacs-lisp + + (use-package yasnippet + :init (yas-global-mode 1) + :config + (yas-reload-all) + ) + + ;; (use-package yasnippet-snippets) + +#+end_src + +The following block is 100% stolen from Dominik :P + +#+begin_src emacs-lisp + + + (setq wtf/latex-greek-prefix "'") + (setq wtf/latex-math-prefix "`") + (setq wtf/latex-mathbb-prefix "''") + (setq swarsel/latex-mathcal-prefix "``") + + (use-package yasnippet + :config + (setq swtf/greek-alphabet + '(("a" . "\\alpha") + ("b" . "\\beta" ) + ("g" . "\\gamma") + ("d" . "\\delta") + ("e" . "\\epsilon") + ("z" . "\\zeta") + ("h" . "\\eta") + ("t" . "\\theta") + ("i" . "\\iota") + ("k" . "\\kappa") + ("l" . "\\lambda") + ("m" . "\\mu") + ("n" . "\\nu") + ("x" . "\\xi") + ("p" . "\\pi") + ("r" . "\\rho") + ("s" . "\\sigma") + ("t" . "\\tau") + ("u" . "\\upsilon") + ("f" . "\\phi") + ("c" . "\\chi") + ("v" . "\\psi") + ("o" . "\\omega"))) + + + ;; The same for capitalized letters + (dolist (elem swtf/greek-alphabet) + (let ((key (car elem)) + (value (cdr elem))) + (when (string-equal key (downcase key)) + (add-to-list 'swtf/greek-alphabet + (cons + (capitalize (car elem)) + (concat + (substring value 0 1) + (capitalize (substring value 1 2)) + (substring value 2))))))) + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (list (concat wtf/latex-greek-prefix (car elem)) (cdr elem) (concat "Greek letter " (car elem)))) + swtf/greek-alphabet)) + + (setq wtf/english-alphabet + '("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z")) + + (dolist (elem wtf/english-alphabet) + (when (string-equal elem (downcase elem)) + (add-to-list 'wtf/english-alphabet (upcase elem)))) + + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (list (concat wtf/latex-mathbb-prefix elem) (concat "\\mathbb{" elem "}") (concat "Mathbb letter " elem))) + wtf/english-alphabet)) + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (list (concat swarsel/latex-mathcal-prefix elem) (concat "\\mathcal{" elem "}") (concat "Mathcal letter " elem))) + wtf/english-alphabet)) + + (setq swtf/latex-math-symbols + '(("x" . "\\times") + ("*" . "\\cdot") + ("." . "\\ldots") + ("op" . "\\operatorname{$1}$0") + ("o" . "\\circ") + ("V" . "\\forall") + ("v" . "\\vee") + ("w" . "\\wedge") + ("q" . "\\quad") + ("f" . "\\frac{$1}{$2}$0") + ("s" . "\\sum_{$1}^{$2}$0") + ("p" . "\\prod_{$1}^{$2}$0") + ("e" . "\\exists") + ("i" . "\\int_{$1}^{$2}$0") + ("c" . "\\cap") + ("u" . "\\cup") + ("0" . "\\emptyset"))) + + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (let ((key (car elem)) + (value (cdr elem))) + (list (concat wtf/latex-math-prefix key) value (concat "Math symbol " value)))) + swtf/latex-math-symbols)) + ) + + + +#+end_src + + + +*** Duplicate Lines + +#+begin_src emacs-lisp + + (defun duplicate-line (arg) + "Duplicate current line, leaving point in lower line." + (interactive "*p") + + ;; save the point for undo + (setq buffer-undo-list (cons (point) buffer-undo-list)) + + ;; local variables for start and end of line + (let ((bol (save-excursion (beginning-of-line) (point))) + eol) + (save-excursion + + ;; don't use forward-line for this, because you would have + ;; to check whether you are at the end of the buffer + (end-of-line) + (setq eol (point)) + + ;; store the line and disable the recording of undo information + (let ((line (buffer-substring bol eol)) + (buffer-undo-list t) + (count arg)) + ;; insert the line arg times + (while (> count 0) + (newline) ;; because there is no newline in 'line' + (insert line) + (setq count (1- count))) + ) + + ;; create the undo information + (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list))) + ) ; end-of-let + + ;; put the point in the lowest line and return + (next-line arg)) + +#+end_src + +*** DISABLED lsp-mode + +#+begin_src emacs-lisp + + ;; (use-package lsp-mode + ;; :ensure t + ;; :init + ;; ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l") + ;; (setq lsp-keymap-prefix "C-c l") + ;; :hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode) + ;; (python-mode . lsp) + ;; (c++-mode . lsp) + ;; (c-mode . lsp) + ;; (cuda-mode . lsp) + ;; (rustic-mode . lsp) + ;; ;; if you want which-key integration + ;; (lsp-mode . lsp-enable-which-key-integration)) + ;; :commands lsp) + + ;; (use-package lsp-ui + ;; :config + ;; (setq lsp-ui-doc-enable t + ;; lsp-ui-doc-show-with-cursor t + ;; lsp-ui-doc-delay 0.5 + ;; lsp-ui-doc-max-height 70) + ;; ) + + ;; optionally if you want to use debugger + ;; (use-package dap-mode) + + ;; (use-package lsp-treemacs + ;; :after lsp) + + ;; ;; currently there is a bug with the double click behavior that was recently added. Fixed by this + ;; (autoload 'treemacs-define-doubleclick-action "treemacs-mouse-interface" nil nil) + + ;; ;; (use-package flycheck + ;; :hook + ;; ((lsp-mode text-mode) . flycheck-mode) + ;; :config + ;; (define-key flycheck-mode-map flycheck-keymap-prefix nil) + ;; ;;(setq flycheck-keymap-prefix (kbd my-flycheck-prefix)) + ;; (define-key flycheck-mode-map flycheck-keymap-prefix + ;; flycheck-command-map)) + + ;; ;; (use-package flycheck-posframe + ;; :ensure t + ;; :after flycheck + ;; :config (add-hook 'flycheck-mode-hook #'flycheck-posframe-mode) + ;; :init + ;; (setq + ;; flycheck-posframe-position 'point-top-left-corner + ;; flycheck-posframe-error-prefix "❌ " + ;; flycheck-posframe-info-prefix "ℹ️️️ " + ;; flycheck-posframe-warning-prefix "⚠️ " + ;; flycheck-posframe-prefix "💬 ")) +#+end_src + +*** IN USE eglot + +#+begin_src emacs-lisp + + (use-package eglot + :ensure nil + :hook + ((python-mode + c-mode + c++-mode + ) . (lambda () (progn + (eglot-ensure) + (add-hook 'before-save-hook 'eglot-format nil 'local)))) + :custom + (eldoc-echo-area-use-multiline-p nil) + (completion-category-defaults nil) + :config + ;; (push '(rustic-ts-mode . eglot-rust-analyzer) eglot-server-programs) + (push '(rustic-mode . eglot-rust-analyzer) eglot-server-programs) + (add-to-list 'eglot-server-programs '((rust-mode) . (eglot-rust-analyzer "rust-analyzer"))) + ;; (add-to-list 'eglot-server-programs '((python-mode) . ("pylsp"))) + ;; (add-to-list 'eglot-server-programs '((c-mode) . ("clangd"))) + :bind (:map eglot-mode-map + ("M-(" . flymake-goto-next-error) + ("C-c ," . eglot-code-actions))) + + (use-package breadcrumb + :config (breadcrumb-mode)) + + +#+end_src + +*** DISABLED lsp-bridge + +#+begin_src emacs-lisp + + ;; (use-package lsp-bridge + ;; :ensure nil + ;; :init + ;; (global-lsp-bridge-mode) + ;; :config + ;; (setq lsp-bridge-enable-debug nil + ;; lsp-bridge-enable-auto-format-code 0 + ;; lsp-bridge-python-lsp-server 'pylsp + ;; lsp-bridge-disable-backup nil + ;; lsp-bridge-enable-org-babel 1 + ;; acm-enable-search-file-words 0 + ;; lsp-bridge-enable-hover-diagnostic 1) + ;; ) + + + +#+end_src + +** Prevent breaking of hardlinks + +#+begin_src emacs-lisp + + (setq backup-by-copying-when-linked t) + +#+end_src + +* File Management +** Dired + +#+begin_src emacs-lisp + + ;; (use-package dired + ;; :ensure nil + ;; :commands (dired dired-jump) + ;; :bind (("C-x C-j" . dired-jump)) + ;; :custom ((dired-listing-switches "-agho --group-directories-first")) + ;; :config + ;; (evil-collection-define-key 'normal 'dired-mode-map + ;; "h" 'dired-single-up-directory + ;; "l" 'dired-single-buffer)) + + ;; (use-package dired-single) + + ;; (use-package nerd-icons-dired + ;; :hook + ;; (dired-mode . nerd-icons-dired-mode)) + ;; (use-package nerd-icons-completion + ;; :after nerd-icons) + ;; (use-package nerd-icons-ivy-rich) + ;; (use-package nerd-icons-ibuffer) + ;; ;; more colorful dired + ;; (use-package diredfl + ;; :hook + ;; (dired-mode . diredfl-mode)) + +#+end_src +** Dirvish + +#+begin_src emacs-lisp + + (use-package dirvish + :init + (dirvish-override-dired-mode) + :config + (dirvish-peek-mode) + (dirvish-side-follow-mode) + :custom + (delete-by-moving-to-trash t) + (dired-listing-switches + "-l --almost-all --human-readable --group-directories-first --no-group") + (dirvish-attributes + '(vc-state subtree-state nerd-icons collapse file-time file-size)) + (dirvish-quick-access-entries + '(("h" "~/" "Home") + ("c" "~/.dotfiles/" "Config") + ("d" "~/Downloads/" "Downloads") + ("D" "~/Documents/" "Documents") + ("p" "~/Documents/GitHub/" "Projects") + ("/" "/" "Root"))) + :bind + ((" d" . 'dirvish) + ("C-=" . 'dirvish-side) + :map dirvish-mode-map + ("h" . dired-up-directory) + ("" . dired-up-directory) + ("l" . dired-find-file) + ("" . dired-find-file) + ("j" . evil-next-visual-line) + ("k" . evil-previous-visual-line) + ("a" . dirvish-quick-access) + ("f" . dirvish-file-info-menu) + ("z" . dirvish-history-last) + ("J" . dirvish-history-jump) + ("y" . dirvish-yank-menu) + ("TAB" . dirvish-subtree-toggle) + ("M-f" . dirvish-history-go-forward) + ("M-b" . dirvish-history-go-backward) + ("M-l" . dirvish-ls-switches-menu) + ("M-m" . dirvish-mark-menu) + ("M-t" . dirvish-layout-toggle) + ("M-s" . dirvish-setup-menu) + ("M-e" . dirvish-emerge-menu) + ("M-j" . dirvish-fd-jump))) + +#+end_src +** pdf support + +#+begin_src emacs-lisp + +(use-package pdf-tools + :init + (if (not (boundp 'pdf-tools-directory)) + (pdf-tools-install)) + :mode ("\\.pdf" . pdf-view-mode)) + +#+end_src + +** open some file types in external programs + +#+begin_src emacs-lisp + + (use-package openwith) + (openwith-mode t) + ;; (setq openwith-associations '(("\\.pdf\\'" "evince" (file)) ("\\.xopp\\'" "xournalpp" (file)))) + (setq openwith-associations '(("\\.xopp\\'" "xournalpp" (file)))) + ;(setq openwith-associations '(("\\.xopp\\'" "xournalpp" (file)))) +#+end_src + +** Jupyter + +#+begin_src emacs-lisp + + (use-package ein) + +#+end_src + +* Applications +** Obsidian + +#+begin_src emacs-lisp + + (use-package obsidian + :ensure t + :demand t + :config + (obsidian-specify-path swarsel-obsidian-vault-directory) + (global-obsidian-mode t) + :custom + ;; This directory will be used for `obsidian-capture' if set. + (obsidian-inbox-directory "Inbox") + (bind-key (kbd "C-c M-o") 'obsidian-hydra/body 'obsidian-mode-map) + :bind (:map obsidian-mode-map + ;; Replace C-c C-o with Obsidian.el's implementation. It's ok to use another key binding. + ("C-c C-o" . obsidian-follow-link-at-point) + ;; Jump to backlinks + ("C-c C-b" . obsidian-backlink-jump) + ;; If you prefer you can use `obsidian-insert-link' + ("C-c C-l" . obsidian-insert-wikilink))) + +#+end_src + +** Anki + +*** Basic Anki setup + +#+begin_src emacs-lisp + + (use-package anki-editor + :after org + :bind (:map org-mode-map + ("" . anki-editor-cloze-region-auto-incr) + ("" . anki-editor-cloze-region-dont-incr) + ("" . anki-editor-reset-cloze-number) + ("" . anki-editor-push-tree)) + :hook (org-capture-after-finalize . anki-editor-reset-cloze-number) ; Reset cloze-number after each capture. + :config + (setq anki-editor-create-decks t ;; Allow anki-editor to create a new deck if it doesn't exist + anki-editor-org-tags-as-anki-tags t) + + (defun anki-editor-cloze-region-auto-incr (&optional arg) + "Cloze region without hint and increase card number." + (interactive) + (anki-editor-cloze-region swarsel-anki-editor-cloze-number "") + (setq swarsel-anki-editor-cloze-number (1+ swarsel-anki-editor-cloze-number)) + (forward-sexp)) + (defun anki-editor-cloze-region-dont-incr (&optional arg) + "Cloze region without hint using the previous card number." + (interactive) + (anki-editor-cloze-region (1- swarsel-anki-editor-cloze-number) "") + (forward-sexp)) + (defun anki-editor-reset-cloze-number (&optional arg) + "Reset cloze number to ARG or 1" + (interactive) + (setq swarsel-anki-editor-cloze-number (or arg 1))) + (defun anki-editor-push-tree () + "Push all notes under a tree." + (interactive) + (anki-editor-push-notes '(4)) + (anki-editor-reset-cloze-number)) + ;; Initialize + (anki-editor-reset-cloze-number) + ) + + (require 'anki-editor) + +#+end_src + +*** Own Anki functions + +- These functions enable you to quickly set the destination note type and deck + +#+begin_src emacs-lisp + + (defvar swarsel-anki-deck nil) + (defvar swarsel-anki-notetype nil) + (defvar swarsel-anki-fields nil) + + (defun swarsel-anki-set-deck-and-notetype () + (interactive) + (setq swarsel-anki-deck (completing-read "Choose a deck: " + (sort (anki-editor-deck-names) #'string-lessp))) + (setq swarsel-anki-notetype (completing-read "Choose a note type: " + (sort (anki-editor-note-types) #'string-lessp))) + (setq swarsel-anki-fields (progn + (anki-editor--anki-connect-invoke-result "modelFieldNames" `((modelName . ,swarsel-anki-notetype))))) + ) + + (defun swarsel-anki-make-template-string () + (if (not swarsel-anki-deck) + (call-interactively 'swarsel-anki-set-deck-and-notetype)) + (setq swarsel-temp swarsel-anki-fields) + (concat (concat "* %<%H:%M>\n:PROPERTIES:\n:ANKI_NOTE_TYPE: " swarsel-anki-notetype "\n:ANKI_DECK: " swarsel-anki-deck "\n:END:\n** ")(pop swarsel-temp) "\n%?\n** " (mapconcat 'identity swarsel-temp "\n\n** ") "\n\n")) + + (defun swarsel-today() + (format-time-string "%Y-%m-%d")) + + (defun swarsel-obsidian-daily () + (interactive) + (if (not (file-exists-p (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory))) + (write-region "" nil (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory)) + ) + (find-file (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory))) + +#+end_src + +* Email + Calendar +** mu4e + +#+begin_src emacs-lisp + + (use-package mu4e + :ensure nil + ;; :load-path "/usr/share/emacs/site-lisp/mu4e/" + ;;:defer 20 ; Wait until 20 seconds after startup + :config + + ;; This is set to 't' to avoid mail syncing issues when using mbsync + (setq mu4e-change-filenames-when-moving t) + (setq mu4e-mu-binary (executable-find "mu")) + + ;; Refresh mail using isync every 10 minutes + (setq mu4e-update-interval (* 10 60)) + (setq mu4e-get-mail-command "mbsync -a") + (setq mu4e-maildir "~/Mail") + ;;(setq mu4e t) + + (setq mu4e-drafts-folder "/Drafts") + (setq mu4e-sent-folder "/Sent Mail") + (setq mu4e-refile-folder "/All Mail") + (setq mu4e-trash-folder "/Trash") + + (setq mu4e-maildir-shortcuts + '((:maildir "/leon/Inbox" :key ?1) + (:maildir "/nautilus/Inbox" :key ?2) + (:maildir "/mrswarsel/Inbox" :key ?3) + (:maildir "/Sent Mail" :key ?s) + (:maildir "/Trash" :key ?t) + (:maildir "/Drafts" :key ?d) + (:maildir "/All Mail" :key ?a)))) + + (setq user-mail-address "leon.schwarzaeugl@gmail.com" + user-full-name "Leon Schwarzäugl") + +#+end_src + +** make sure mu4e is found + +#+begin_src emacs-lisp + + (let ((mu4epath + (concat + (f-dirname + (file-truename + (executable-find "mu"))) + "/../share/emacs/site-lisp/mu4e"))) + (when (and + (string-prefix-p "/nix/store/" mu4epath) + (file-directory-p mu4epath)) + (add-to-list 'load-path mu4epath))) + +#+end_src + +** Calendar + +#+begin_src emacs-lisp + + (use-package org-caldav + :init + + (setq org-caldav-url "https://stash.swarsel.win/remote.php/dav/calendars/Swarsele") + (setq org-caldav-calendars + '((:calendar-id "personal" + :inbox "~/Calendars/leon_cal.org"))) + ;; (setq org-caldav-backup-file "~/org-caldav/org-caldav-backup.org") + ;; (setq org-caldav-save-directory "~/org-caldav/") + + :config + (setq org-icalendar-alarm-time 1) + ;; This makes sure to-do items as a category can show up on the calendar + (setq org-icalendar-include-todo t) + ;; This ensures all org "deadlines" show up, and show up as due dates + (setq org-icalendar-use-deadline '(event-if-todo event-if-not-todo todo-due)) + ;; This ensures "scheduled" org items show up, and show up as start times + (setq org-icalendar-use-scheduled '(todo-start event-if-todo event-if-not-todo)) + ) + + (use-package calfw + :ensure nil + :bind ("C-c A" . swarsel/open-calendar) + :init + (use-package calfw-cal + :ensure nil) + (use-package calfw-org + :ensure nil) + (use-package calfw-ical + :ensure nil) + :config + (bind-key "g" 'cfw:refresh-calendar-buffer cfw:calendar-mode-map) + (bind-key "q" 'evil-quit cfw:details-mode-map) + ;; (custom-set-faces + ;; '(cfw:face-title ((t (:foreground "#f0dfaf" :weight bold :height 65)))) + ;; ) + ) + + (defun swarsel/open-calendar () + (interactive) + (unless (eq swarsel-caldav-synced 1) (org-caldav-sync) (setq swarsel-caldav-synced 1)) + ;; (select-frame (make-frame '((name . "calendar")))) ; makes a new frame and selects it + ;; (set-face-attribute 'default (selected-frame) :height 65) ; reduces the font size of the new frame + (cfw:open-calendar-buffer + :contents-sources + (list + (cfw:org-create-source "Purple") ; orgmode source + (cfw:ical-create-source "TISS" "https://tiss.tuwien.ac.at/events/rest/calendar/personal?locale=de&token=4463bf7a-87a3-490a-b54c-99b4a65192f3" "Cyan")))) + +#+end_src + +** mu4e-alert + +Choose the style you prefer for desktop notifications +If you are on Linux you can use +1. notifications - Emacs lisp implementation of the Desktop Notifications API +2. libnotify - Notifications using the `notify-send' program, requires `notify-send' to be in PATH + +On Mac OSX you can set style to +1. notifier - Notifications using the `terminal-notifier' program, requires `terminal-notifier' to be in PATH +1. growl - Notifications using the `growl' program, requires `growlnotify' to be in PATH + +#+begin_src emacs-lisp + + (use-package mu4e-alert) + (mu4e-alert-set-default-style 'libnotify) + (add-hook 'after-init-hook #'mu4e-alert-enable-notifications) + +#+end_src + +* Startup Application Scripts + +Yep, none currently. + +* Emacs startup screen +#+begin_src emacs-lisp + ;;show mail + ;;(mu4e) + + (use-package dashboard + :ensure t + :config + (dashboard-setup-startup-hook) + ;; (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))) + (setq dashboard-display-icons-p t ;; display icons on both GUI and terminal + dashboard-icon-type 'nerd-icons ;; use `nerd-icons' package + dashboard-set-file-icons t + dashboard-items '((recents . 5) + (projects . 5) + (agenda . 5)) + dashboard-set-footer nil + dashboard-banner-logo-title "Welcome to SwarsEmacs!" + dashboard-image-banner-max-height 300 + dashboard-startup-banner "~/.dotfiles/wallpaper/swarsel.png" + dashboard-projects-backend 'projectile + dashboard-set-navigator t + dashboard-navigator-buttons + `(;; line1 + ((,"" + "SwarselSocial" + "Browse Swarsele" + (lambda (&rest _) (browse-url "instagram.com/Swarsele"))) + + (,"" + "SwarselSound" + "Browse SwarselSound" + (lambda (&rest _) (browse-url "sound.swarsel.win")) ) + (,"" + "SwarselSwarsel" + "Browse Swarsel" + (lambda (&rest _) (browse-url "github.com/Swarsel")) ) + (,"" + "SwarselStash" + "Browse SwarselStash" + (lambda (&rest _) (browse-url "stash.swarsel.win")) ) + (,"󰫑" + "SwarselSport" + "Browse SwarselSports" + (lambda (&rest _) (browse-url "social.parkour.wien/@Lenno"))) + ) + ( + (,"󱄅" + "swarsel.win" + "Browse swarsel.win" + (lambda (&rest _) (browse-url "swarsel.win"))) + ) + ))) + (setq dashboard-projects-switch-function 'counsel-projectile-switch-project-by-name) + + +#+end_src +* Fix gpg hangup bug + +We need to add this last line, because otherwise gpg will crash on the most recent version when saving a .gpg file within emacs. + +#+begin_src emacs-lisp + (fset 'epg-wait-for-status 'ignore) +#+end_src diff --git a/Nix.org b/Nix.org new file mode 100644 index 0000000..e8d6481 --- /dev/null +++ b/Nix.org @@ -0,0 +1,2988 @@ +#+title: Nix Configuration + +This file holds the entirety of all configuration files for both NixOS as well as home manager across all machines that I currently use. + +The only exception is my Emacs configuration which is held in its own .org file - this is done because that allows for upon-switch parsing of that file and installation of all emacs-packages through home-manager. The init.el file cannot be used there as it contains UTF-8 characters that would break the nix function responsible for handling the emacs-package building process. + +* Noweb-Ref blocks + +These blocks are used in several places throughout the configurations, but not on all machines necessarily. For example, the themeing section needs to be in a NixOS block on NixOS machines but in a home-manager block on non-NixOS. This serves to reduce code duplication. + +** All systems +*** Themeing + +This is where the theme for the whole OS is defined. This noweb-ref section cannot be copied to the general NixOS config for now since they are on different levels in the config, which would make the flake impure. + +#+begin_src nix :noweb-ref theme + + + stylix = { + base16Scheme = ../../wallpaper/swarsel.yaml; + # base16Scheme = "${pkgs.base16-schemes}/share/themes/shapeshifter.yaml"; + polarity = "dark"; + opacity.popups = 0.5; + cursor = { + package = pkgs.capitaine-cursors; + name = "capitaine-cursors"; + size = 16; + }; + fonts = { + sizes = { + terminal = 10; + applications = 11; + }; + serif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + sansSerif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + monospace = { + package = (pkgs.nerdfonts.override { fonts = [ "FiraCode"]; }); + name = "FiraCode Nerd Font Mono"; + }; + + emoji = { + package = pkgs.noto-fonts-emoji; + name = "Noto Color Emoji"; + }; + }; + }; + + + +#+end_src +*** Waybar items - LAPTOPS + +#+begin_src nix :noweb-ref waybarlaptop + + programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" + "mpris" + "custom/left-arrow-light" + "network" + "custom/left-arrow-dark" + "pulseaudio" + "custom/left-arrow-light" + "custom/pseudobat" + "battery" + "custom/left-arrow-dark" + "group/hardware" + "custom/left-arrow-light" + "clock#2" + "custom/left-arrow-dark" + "clock#1" + ]; + +#+end_src +*** Waybar items - PC + +#+begin_src nix :noweb-ref waybarpc + + programs.waybar.settings.mainBar."custom/pseudobat"= { + format= ""; + on-click-right= "wlogout -p layer-shell"; + }; + programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" + "mpris" + "custom/left-arrow-light" + "network" + "custom/left-arrow-dark" + "pulseaudio" + "custom/left-arrow-light" + "custom/pseudobat" + "battery" + "custom/left-arrow-dark" + "group/hardware" + "custom/left-arrow-light" + "clock#2" + "custom/left-arrow-dark" + "clock#1" + ]; + +#+end_src +** NixOS +*** Sway Startup commands + +#+begin_src nix :noweb-ref startupnixos + + { command = "nextcloud --background";} + { command = "spotify";} + { command = "discord --start-minimized";} + { command = "schildichat-desktop --disable-gpu-driver-bug-workarounds --hidden";} + { command = "ANKI_WAYLAND=1 anki";} + { command = "OBSIDIAN_USE_WAYLAND=1 obsidian";} + { command = "nm-applet";} + +#+end_src + +*** gpg-agent + +#+begin_src nix :noweb-ref gpgagent + + services.gpg-agent = { + enable = true; + enableSshSupport = true; + }; + +#+end_src + +*** Wrap with hardware-configuration + +#+begin_src nix :noweb-ref wrap + + imports = + [ + ./hardware-configuration.nix + ]; + +#+end_src + +* TODO System specific configuration + +This section mainly exists house different `configuration.nix` files for system level configurations of NixOS systems as well as `home.nix` for user level configurations on all systems. + +Important: Think about if a settings really needs to go into this area - chances are that the settings can also go to the general settings. + +** Template (for new machines) + +This section holds the minimum configuration that is needed on a new host. These assume a NixOS machine (so not standalone home-manager on a non-NixOS host), as this is the setting that I will most likely use in the future now. All of these blocks need to be updated, with entries called TEMPLATE mostly needed to be filled with host-/user-specific values or other inputs. If TEMPLATE is given in a comment section, see the provided values as likely defaults. The TEMPLATE comments should afterwards be deleted for clarity. + +If a non-NixOS host must be used, check the Surface configuration for pointers. Most likely the waybar settings need to be adjusted, since non-NixOS (as of writing this) fails to display drawers in the waybar properly. + +No matter what you do, check the initial /etc/nixos/configuration.nix for notable changes that might emerge in future versions of nix. + +*** NixOS + +#+begin_src nix :noweb yes :tangle profiles/TEMPLATE/nixos.nix + + { config, lib, pkgs, inputs, ... }: + + { + + <> + + services = { + getty.autologinUser = "TEMPLATE"; + greetd.settings.initial_session.user="TEMPLATE"; + }; + + # Bootloader + boot.loader.grub.enable = true; + boot.loader.grub.device = "/dev/sda"; # TEMPLATE - if only one disk, this will work + boot.loader.grub.useOSProber = true; + + # -------------------------------------- + # you might need a configuration like this instead: + # Bootloader + # boot.loader.grub.enable = true; + # boot.loader.grub.devices = ["nodev" ]; + # boot.loader.grub.useOSProber = true; + # boot.kernelPackages = pkgs.linuxPackages_latest; + # -------------------------------------- + + networking.hostName = "TEMPLATE"; # Define your hostname. + + stylix.image = ../../wallpaper/TEMPLATEwp.png; + <> + + # Configure keymap in X11 (only used for login) + services.xserver = { + layout = "us"; + xkbVariant = "altgr-intl"; + }; + + users.users.TEMPLATE = { + isNormalUser = true; + description = "TEMPLATE"; + extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ]; + packages = with pkgs; []; + }; + + environment.systemPackages = with pkgs; [ + ]; + + system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change + + + } + +#+end_src + +*** Home Manager +#+begin_src nix :noweb yes :tangle profiles/TEMPLATE/home.nix + + { config, pkgs, lib, fetchFromGitHub, ... }: + + { + + <> + home = { + username = "TEMPLATE"; + homeDirectory = "/home/TEMPLATE"; + stateVersion = "23.05"; # TEMPLATE -- Please read the comment before changing. + keyboard.layout = "us"; # TEMPLATE + home.packages = with pkgs; [ + # xdg-utils + # nodejs_20 + # --------------------------------------------------------------- + # if schildichat works on this machine, use it, otherwise go for element + # element-desktop + # --------------------------------------------------------------- + ]; + }; + # update path if the sops private key is stored somewhere else + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + # waybar config - TEMPLATE - update for cores and temp + programs.waybar.settings.mainBar = { + #cpu.format = "{icon0} {icon1} {icon2} {icon3}"; + cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}"; + temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input"; + }; + + # ----------------------------------------------------------------- + # is this machine always connected to power? If yes, use this block: + # <> + # ----------------------------------------------------------------- + + # ----------------------------------------------------------------- + # if not always connected to power (laptop), use this (default): + <> + # ----------------------------------------------------------------- + + wayland.windowManager.sway= { + config = rec { + # update for actual inputs here, + input = { + "36125:53060:splitkb.com_Kyria_rev3" = { + xkb_layout = "us"; + xkb_variant = "altgr-intl"; + }; + "1:1:AT_Translated_Set_2_keyboard" = { # TEMPLATE + xkb_layout = "us"; + xkb_options = "grp:win_space_toggle"; + # xkb_options = "ctrl:nocaps,grp:win_space_toggle"; + xkb_variant = "altgr-intl"; + }; + "type:touchpad" = { + dwt = "enabled"; + tap = "enabled"; + natural_scroll = "enabled"; + middle_emulation = "enabled"; + }; + + }; + + output = { + DP-1 = { + mode = "2560x1440"; # TEMPLATE + scale = "1"; + bg = "~/.dotfiles/wallpaper/TEMPLATE.png fill"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + # TEMPLATE + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\""; + # "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkelement.sh\""; + }; + + startup = [ + <> + ]; + }; + }; + } + +#+end_src + +** TODO Surface + +My Surface Pro 3, only used for on-the-go university work. Be careful when pushing largechanges to this machine, as it easily runs out of memory on large switches. At the moment the only machine running non-NixOS, so special care must be taken not to break this one during updates. + +*** TODO Channel setup + +This installs nixGL, which is needed to run GL apps installed through home-manager, since this machine is not using NixOS. + +- TODO: move this to flake.nix by using an overlay + +1) Install nixGL: + +#+begin_src nix + nix-channel --add https://github.com/guibou/nixGL/archive/main.tar.gz nixgl && nix-channel --update + nix-env -iA nixgl.auto.nixGLDefault # or replace `nixGLDefault` with your desired wrapper +#+end_src + +This is needed in order to use EGL. Prefix programs that use it with `nixGL` + +*** Home manager + +#+begin_src nix :noweb yes :tangle profiles/surface/home.nix + + { config, pkgs, lib, fetchFromGitHub, ... }: + + { + programs.home-manager.enable = true; + home.username = "leons"; + home.homeDirectory = "/home/leons"; + + home.stateVersion = "23.05"; # Please read the comment before changing. + + stylix.image = ../../wallpaper/surfacewp.png; + <> + + nixpkgs = { + config = { + allowUnfree = true; + allowUnfreePredicate = (_: true); + }; + }; + services.xcape = { + enable = true; + mapExpression = { + Control_L = "Escape"; + }; + }; + #keyboard config + home.keyboard.layout = "us"; + + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + # waybar config + programs.waybar.settings.mainBar.cpu.format = "{icon0} {icon1} {icon2} {icon3}"; + + programs.waybar.settings.mainBar.temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon3/temp3_input"; + programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" "mpris" "custom/left-arrow-light" + "network" + "custom/left-arrow-dark" + "pulseaudio" + "custom/left-arrow-light" + "battery" + "custom/left-arrow-dark" + "temperature" + "custom/left-arrow-light" + "disk" + "custom/left-arrow-dark" + "memory" + "custom/left-arrow-light" + "cpu" + "custom/left-arrow-dark" + "tray" + "custom/left-arrow-light" + "clock#2" + "custom/left-arrow-dark" + "clock#1" ]; + services.blueman-applet.enable = true; + home.packages = with pkgs; [ + # nixgl.auto.nixGLDefault + evince + # nodejs_20 + + # messaging + # we use gomuks for RAM preservation, but keep schildi around for files and images + ]; + + programs.zsh.initExtra = " + export GPG_TTY=\"$(tty)\" + export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) + gpgconf --launch gpg-agent + "; + + # sway config + wayland.windowManager.sway= { + config = rec { + input = { + "*" = { + xkb_layout = "us"; + xkb_options = "ctrl:nocaps,grp:win_space_toggle"; + xkb_variant = "altgr-intl"; + }; + "type:touchpad" = { + dwt = "enabled"; + tap = "enabled"; + natural_scroll = "enabled"; + middle_emulation = "enabled"; + }; + }; + + output = { + eDP-1 = { + mode = "2160x1440@59.955Hz"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/surfacewp.png fill"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+F2" = "exec brightnessctl set +5%"; + "${modifier}+F1"= "exec brightnessctl set 5%-"; + "${modifier}+n" = "exec sway output eDP-1 transform normal, splith"; + "${modifier}+Ctrl+p" = "exec nixGL wl-mirror eDP-1"; + "${modifier}+t" = "exec sway output eDP-1 transform 90, splitv"; + "${modifier}+XF86AudioLowerVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+XF86AudioRaiseVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkgomuks.sh\""; + }; + + startup = [ + { command = "sleep 60 && nixGL nextcloud --background";} + # { command = "sleep 60 && nixGL spotify";} + { command = "sleep 60 && nixGL discord --start-minimized -enable-features=UseOzonePlatform -ozone-platform=wayland";} + # { command = "sleep 60 && nixGL schildichat-desktop --hidden";} + { command = "sleep 60 && nixGL syncthingtray --wait"; } + { command = "sleep 60 && ANKI_WAYLAND=1 nixGL anki";} + { command = "nm-applet --indicator";} + { command = "sleep 60 && OBSIDIAN_USE_WAYLAND=1 nixGL obsidian -enable-features=UseOzonePlatform -ozone-platform=wayland";} + ]; + + keycodebindings = { + "124" = "exec systemctl suspend"; + }; + }; + + extraConfig = " + exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05 map_to_output eDP-1 + exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05_Stylus map_to_output eDP-1 + "; + }; + } + +#+end_src + +** Onett (Lenovo Y510P) + +My laptop, sadly soon to be replaced by a new one, since most basic functions are stopping to work lately. + +*** NixOS + +#+begin_src nix :noweb yes :tangle profiles/onett/nixos.nix + + { config, lib, pkgs, inputs, ... }: + + { + + <> + + services = { + greetd.settings.initial_session.user ="swarsel"; + xserver.videoDrivers = ["nvidia"]; + }; + + hardware = { + nvidia = { + modesetting.enable = true; + powerManagement.enable = true; + prime = { + intelBusId = "PCI:0:2:0"; + nvidiaBusId = "PCI:1:0:0"; + sync.enable = true; + }; + }; + pulseaudio.configFile = pkgs.runCommand "default.pa" {} '' + sed 's/module-udev-detect$/module-udev-detect tsched=0/' \ + ${pkgs.pulseaudio}/etc/pulse/default.pa > $out + ''; + bluetooth.enable = true; + }; + + stylix.image = ../../wallpaper/lenovowp.png; + <> + + boot.loader.grub = { + enable = true; + device = "/dev/sda"; + useOSProber = true; + }; + + networking.hostName = "onett"; # Define your hostname. + + users.users.swarsel = { + isNormalUser = true; + description = "Leon S"; + extraGroups = [ "networkmanager" "wheel" "lp"]; + packages = with pkgs; []; + }; + + system.stateVersion = "23.05"; # Did you read the comment? + + } + +#+end_src + +*** Home Manager + +#+begin_src nix :noweb yes :tangle profiles/onett/home.nix + + { config, pkgs, lib, fetchFromGitHub, ... }: + + { + + <> + + home = { + username = "swarsel"; + homeDirectory = "/home/swarsel"; + stateVersion = "23.05"; # Please read the comment before changing. + keyboard.layout = "de"; + packages = with pkgs; [ + # xdg-utils + # nodejs_20 + ]; + }; + + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + # # waybar config + programs.waybar.settings.mainBar = { + cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}"; + temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon3/temp3_input"; + }; + <> + + services.blueman-applet.enable = true; + + wayland.windowManager.sway= { + config = rec { + input = { + "1:1:AT_Translated_Set_2_keyboard" = { + xkb_layout = "us"; + xkb_options = "grp:win_space_toggle"; + # xkb_options = "ctrl:nocaps,grp:win_space_toggle"; + xkb_variant = "altgr-intl"; + }; + "2362:33538:ipad_keyboard_Keyboard" = { + xkb_layout = "us"; + xkb_options = "altwin:swap_lalt_lwin,ctrl:nocaps,grp:win_space_toggle"; + xkb_variant = "colemak_dh"; + }; + "36125:53060:splitkb.com_Kyria_rev3" = { + xkb_layout = "us"; + xkb_variant = "altgr-intl"; + }; + + "type:touchpad" = { + dwt = "enabled"; + tap = "enabled"; + natural_scroll = "enabled"; + middle_emulation = "enabled"; + }; + }; + + output = { + eDP-1 = { + mode = "1920x1080"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/lenovowp.png fill"; + position = "1920,0"; + }; + VGA-1 = { + mode = "1920x1080"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/lenovowp.png fill"; + position = "0,0"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+F2" = "exec brightnessctl set +5%"; + "${modifier}+F1"= "exec brightnessctl set 5%-"; + "XF86MonBrightnessUp" = "exec brightnessctl set +5%"; + "XF86MonBrightnessDown"= "exec brightnessctl set 5%-"; + "${modifier}+Ctrl+p" = "exec wl-mirror eDP-1"; + "XF86HomePage" = "exec wtype -P Escape -p Escape"; + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\""; + }; + keycodebindings = { + "94" = "exec wtype c"; + "Shift+94" = "exec wtype C"; + "Ctrl+94" = "exec wtype -M ctrl c -m ctrl"; + "Ctrl+Shift+94" = "exec wtype -M ctrl -M shift c -m ctrl -m shift"; + }; + + startup = [ + <> + ]; + }; + + extraConfig = " + "; + }; + } + +#+end_src + +** Stand + +My home PC, the most powerful machine. Sadly Sway cannot make good use out of it's NVIDIA card, so it runs a dual boot setup with a kind of broken GRUB that does not autodetect the windows partition. + +*** NixOS + +#+begin_src nix :noweb yes :tangle profiles/stand/nixos.nix + + { config, lib, pkgs, inputs, ... }: + + { + + <> + + services = { + getty.autologinUser = "homelen"; + greetd.settings.initial_session.user="homelen"; + }; + + stylix.image = ../../wallpaper/standwp.png; + <> + + # Bootloader. + boot.loader.grub = { + enable = true; + devices = ["nodev" ]; + useOSProber = true; + }; + + # boot.kernelPackages = pkgs.linuxPackages_latest; + networking = { + hostName = "stand"; # Define your hostname. + enableIPv6 = false; + firewall.enable = false; + # networkmanager.enable = true; + }; + + hardware = { + bluetooth.enable = true; + }; + + users.users.homelen = { + isNormalUser = true; + description = "Leon S"; + extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ]; + packages = with pkgs; []; + }; + + environment.systemPackages = with pkgs; [ + ]; + + system.stateVersion = "23.05"; # Did you read the comment? Dont change this basically + + } + +#+end_src + +*** Home Manager +#+begin_src nix :noweb yes :tangle profiles/stand/home.nix + + { config, pkgs, lib, fetchFromGitHub, ... }: + + { + + <> + + home = { + username = "homelen"; + homeDirectory = "/home/homelen"; + stateVersion = "23.05"; # Please read the comment before changing. + keyboard.layout = "us"; + packages = with pkgs; [ + # xdg-utils + # nodejs_20 + # element-desktop + ]; + }; + + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + services.blueman-applet.enable = true; + + # waybar config + programs.waybar.settings.mainBar = { + cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}"; + temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input"; + }; + <> + + wayland.windowManager.sway= { + config = rec { + input = { + "36125:53060:splitkb.com_Kyria_rev3" = { + xkb_layout = "us"; + xkb_variant = "altgr-intl"; + }; + }; + + output = { + DP-1 = { + mode = "2560x1440"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/standwp.png fill"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\""; + }; + + startup = [ + <> + ]; + }; + }; + } + +#+end_src + +** Threed (Surface Pro 3) + +New setup for the SP3, this time using NixOS - another machine will take over the HM-only config for compatibility in the future. + +*** NixOS + +#+begin_src nix :noweb yes :tangle profiles/threed/nixos.nix + + { config, lib, pkgs, inputs, ... }: + + { + <> + + services = { + getty.autologinUser = "swarsel"; + greetd.settings.initial_session.user="swarsel"; + }; + + # Bootloader + boot = { + loader.systemd-boot.enable = lib.mkForce false; + lanzaboote = { + enable = true; + pkiBundle = "/etc/secureboot"; + }; + loader.efi.canTouchEfiVariables = true; + # use bootspec instead of lzbt for secure boot. This is not a generally needed setting + bootspec.enable = true; + # kernelPackages = pkgs.linuxPackages_latest; + }; + + networking = { + hostName = "threed"; + enableIPv6 = false; + firewall.enable = false; + }; + + stylix.image = ../../wallpaper/surfacewp.png; + <> + + users.users.swarsel = { + isNormalUser = true; + description = "Leon S"; + extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ]; + packages = with pkgs; []; + }; + + environment.systemPackages = with pkgs; [ + ]; + + system.stateVersion = "23.05"; + + } + +#+end_src + +*** Home Manager +#+begin_src nix :noweb yes :tangle profiles/threed/home.nix + + { config, pkgs, lib, fetchFromGitHub, ... }: + + { + + <> + + home = { + username = "swarsel"; + homeDirectory = "/home/swarsel"; + stateVersion = "23.05"; # Please read the comment before changing. + keyboard.layout = "us"; + packages = with pkgs; [ + # xdg-utils + # nodejs_20 + ]; + }; + + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + programs.waybar.settings.mainBar = { + cpu.format = "{icon0} {icon1} {icon2} {icon3}"; + temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input"; + }; + <> + + wayland.windowManager.sway= { + config = rec { + input = { + "*" = { + xkb_layout = "us"; + xkb_options = "grp:win_space_toggle"; + xkb_variant = "altgr-intl"; + }; + "type:touchpad" = { + dwt = "enabled"; + tap = "enabled"; + natural_scroll = "enabled"; + middle_emulation = "enabled"; + }; + }; + + output = { + eDP-1 = { + mode = "2160x1440@59.955Hz"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/surfacewp.png fill"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+F2" = "exec brightnessctl set +5%"; + "${modifier}+F1"= "exec brightnessctl set 5%-"; + "${modifier}+n" = "exec sway output eDP-1 transform normal, splith"; + "${modifier}+Ctrl+p" = "exec wl-mirror eDP-1"; + "${modifier}+t" = "exec sway output eDP-1 transform 90, splitv"; + "${modifier}+XF86AudioLowerVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+XF86AudioRaiseVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\""; + }; + + startup = [ + <> + ]; + + keycodebindings = { + "124" = "exec systemctl suspend"; + }; + }; + + extraConfig = " + exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05 map_to_output eDP-1 + exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05_Stylus map_to_output eDP-1 + "; + }; + } +#+end_src + +* Common NixOS + +These are system-level settings specific to NixOS machines. All settings that are required on all machines go here. + +** General + +Section for all settings that are not really deserving of their own section. + +#+begin_src nix :tangle profiles/common/nixos.nix + + { config, lib, pkgs, inputs, ... }: + + { + + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + + # login keymap + services.xserver = { + layout = "us"; + xkbVariant = "altgr-intl"; + }; + + # mount NAS drive + # works only at home, but w/e + fileSystems."/mnt/smb" = { + device = "//192.168.1.3/Eternor"; + fsType = "cifs"; + options = let + # this line prevents hanging on network split + automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s"; + in ["${automount_opts},credentials=/etc/nixos/smb-secrets,uid=1000,gid=100"]; + }; + + # enable flakes - urgent line!! + nix.settings.experimental-features = ["nix-command" "flakes"]; + environment.sessionVariables.NIXOS_OZONE_WL = "1"; + # correct time between linux and windows + time.hardwareClockInLocalTime = true; + + # dont style GRUB with stylix + stylix.targets.grub.enable = false; # the styling makes grub more ugly + + # cura fix + # xdg.portal = { + # enable = true; + # extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + # wlr.enable = true; + # config = { + # common = { + # default = [ + # "*" + # ]; + # }; + # }; + # }; + # wayland-related + security.polkit.enable = true; + hardware.opengl = { + enable = true; + driSupport = true; + driSupport32Bit = true; + }; + + # audio + sound.enable = true; + # nixpkgs.config.pulseaudio = true; + hardware.pulseaudio= { + enable = true; + package = pkgs.pulseaudioFull; + }; + hardware.enableAllFirmware = true; + hardware.bluetooth.powerOnBoot = true; + hardware.bluetooth.settings = { + General = { + Enable = "Source,Sink,Media,Socket"; + }; + }; + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + networking.networkmanager.enable = true; + + time.timeZone = "Europe/Vienna"; + + i18n.defaultLocale = "en_US.UTF-8"; + i18n.extraLocaleSettings = { + LC_ADDRESS = "de_AT.UTF-8"; + LC_IDENTIFICATION = "de_AT.UTF-8"; + LC_MEASUREMENT = "de_AT.UTF-8"; + LC_MONETARY = "de_AT.UTF-8"; + LC_NAME = "de_AT.UTF-8"; + LC_NUMERIC = "de_AT.UTF-8"; + LC_PAPER = "de_AT.UTF-8"; + LC_TELEPHONE = "de_AT.UTF-8"; + LC_TIME = "de_AT.UTF-8"; + }; + +#+end_src + +** System Packages + +Mostly used to install some compilers and lps's that I want to have available when not using a devShell flake. + +#+begin_src nix :tangle profiles/common/nixos.nix + + environment.systemPackages = with pkgs; [ + # yubikey packages + gnupg + yubikey-personalization + yubikey-personalization-gui + yubico-pam + yubioath-flutter + yubikey-manager + yubikey-manager-qt + yubico-piv-tool + pinentry + + # theme related + gnome.adwaita-icon-theme + + # kde-connect + xdg-desktop-portal + + # bluetooth + bluez + + # lsp-related ------------------------------- + # nix + rnix-lsp + # latex + texlab + ghostscript_headless + # rust + rust-analyzer + clippy + rustfmt + # cpp + clang-tools + # + cuda + cudatoolkit + #lsp-bridge / python + gcc + gdb + (python3.withPackages(ps: with ps; [ jupyter ipython pyqt5 epc orjson sexpdata six setuptools paramiko numpy pandas scipy matplotlib requests debugpy flake8 gnureadline python-lsp-server])) + # (python3.withPackages(ps: with ps; [ jupyter ipython pyqt5 numpy pandas scipy matplotlib requests debugpy flake8 gnureadline python-lsp-server])) + # -------------------------------------------- + ]; + +#+end_src + +** Programs (including zsh setup) + +Some programs profit from being installed through dedicated NixOS settings on system-level; these go here. Notably the zsh setup goes here and cannot be deleted under any circumstances. + +#+begin_src nix :tangle profiles/common/nixos.nix + + programs.dconf.enable = true; + programs.evince.enable = true; + programs.kdeconnect.enable = true; + + + # zsh section, do not delete ------ + programs.zsh.enable = true; + users.defaultUserShell = pkgs.zsh; + environment.shells = with pkgs; [ zsh ]; + environment.pathsToLink = [ "/share/zsh" ]; + # --------------------------------- + +#+end_src + +** Services + +Setting up some hardware services as well as keyboard related settings. Here we make sure that we can use the CAPS key as a ESC/CTRL double key, which is a lifesaver. + +#+begin_src nix :tangle profiles/common/nixos.nix + + services.blueman.enable = true; + + # enable discovery and usage of network devices (esp. printers) + services.printing.enable = true; + services.avahi = { + enable = true; + nssmdns = true; + openFirewall = true; + }; + + # nautilus file manager + services.gvfs.enable = true; + + # Make CAPS work as a dual function ESC/CTRL key + services.interception-tools = { + enable = true; + udevmonConfig = let + dualFunctionKeysConfig = builtins.toFile "dual-function-keys.yaml" '' + TIMING: + TAP_MILLISEC: 200 + DOUBLE_TAP_MILLISEC: 0 + + MAPPINGS: + - KEY: KEY_CAPSLOCK + TAP: KEY_ESC + HOLD: KEY_LEFTCTRL + ''; + in '' + - JOB: | + ${pkgs.interception-tools}/bin/intercept -g $DEVNODE \ + | ${pkgs.interception-tools-plugins.dual-function-keys}/bin/dual-function-keys -c ${dualFunctionKeysConfig} \ + | ${pkgs.interception-tools}/bin/uinput -d $DEVNODE + DEVICE: + EVENTS: + EV_KEY: [KEY_CAPSLOCK] + ''; + }; + +#+end_src + +** Yubikey settings + +It makes sense to house these settings in their own section, since they are all needed really. Note that the starting of the gpg-agent is done in the sway settings, to also perform this step of the setup for non NixOS-machines at the same time. + +The exception is the system packages, since that cannot be defined twice in the same file (common.nix). The comment is left in as a remider for that. + +#+begin_src nix :tangle profiles/common/nixos.nix + + programs.ssh.startAgent = false; + + services.pcscd.enable = true; + + # environment.systemPackages = with pkgs; [ + # --- IN SYSTEM PACKAGES SECTION --- + # ]; + + services.udev.packages = with pkgs; [ + yubikey-personalization + ]; + + +#+end_src + +** System Login + +This section houses the greetd related settings. I do not really want to use a display manager, but it is useful to have setup in some ways - in my case for starting sway on system startup. Notably the default user login setting that is commented out here goes into the *system specific* settings, make sure to update it there + +#+begin_src nix :tangle profiles/common/nixos.nix + + services.greetd = { + enable = true; + settings = { + initial_session.command = "sway"; + # initial_session.user ="swarsel"; + default_session.command = '' + ${pkgs.greetd.tuigreet}/bin/tuigreet \ + --time \ + --asterisks \ + --user-menu \ + --cmd sway + ''; + }; + }; + + environment.etc."greetd/environments".text = '' + sway + ''; + +#+end_src + +* Common Home-Manager +** Installed packages + +Here are defined some packages that I would like to use across all my machines. Most of these should not require further setup. Notably the cura package is severely outdated on nixpkgs, so I just fetch a more recent AppImage and run that instead. + +Also, I define some useful shell scripts here. + +#+begin_src nix :tangle profiles/common/home.nix + + { config, pkgs, lib, fetchFromGitHub , ... }: + + { + home.packages = with pkgs; [ + + # "big" programs + filebot + gimp + zoom-us + nomacs + libreoffice-qt + xournalpp + obsidian + spotify + discord + nextcloud-client + spotify-tui + schildichat-desktop + + # kyria + qmk + qmk-udev-rules + + # games + lutris + wine + + # firefox related + tridactyl-native + + # mako related + mako + libnotify + + # general utilities + unrar + samba + cifs-utils + zbar # qr codes + readline + autotiling + brightnessctl + libappindicator-gtk3 + sqlite + speechd + networkmanagerapplet + psmisc # kill etc + jq # used for searching the i3 tree in check.sh files + + # specifically needed for anki + mpv + anki-bin + + # dirvish file previews + fd + imagemagick + poppler + ffmpegthumbnailer + mediainfo + gnutar + unzip + + #nautilus + gnome.nautilus + xfce.tumbler + libgsf + + # wayland stuff + wtype + wl-clipboard + wl-mirror + + # screenshotting tools + grim + slurp + + # the following packages are used (in some way) by waybar + playerctl + pavucontrol + pamixer + gnome.gnome-clocks + wlogout + jdiskreport + syncthingtray + monitor + + #keychain + qalculate-gtk + gcr # needed for gnome-secrets to work + gnome.seahorse + + # sops-related + sops + ssh-to-age + + # mail related packages + mu + + # latex and related packages + (pkgs.texlive.combine { + inherit (pkgs.texlive) scheme-full + dvisvgm dvipng # for preview and export as html + wrapfig amsmath ulem hyperref capt-of; + }) + + # font stuff + (nerdfonts.override { fonts = [ "FiraMono" "FiraCode" "NerdFontsSymbolsOnly"]; }) + noto-fonts-emoji + font-awesome_5 + noto-fonts + noto-fonts-cjk-sans + + # cura + (let cura5 = appimageTools.wrapType2 rec { + name = "cura5"; + version = "5.4.0"; + src = fetchurl { + url = "https://github.com/Ultimaker/Cura/releases/download/${version}/UltiMaker-Cura-${version}-linux-modern.AppImage"; + hash = "sha256-QVv7Wkfo082PH6n6rpsB79st2xK2+Np9ivBg/PYZd74="; + }; + extraPkgs = pkgs: with pkgs; [ ]; + }; in writeScriptBin "cura" '' + #! ${pkgs.bash}/bin/bash + # AppImage version of Cura loses current working directory and treats all paths relateive to $HOME. + # So we convert each of the files passed as argument to an absolute path. + # This fixes use cases like `cd /path/to/my/files; cura mymodel.stl anothermodel.stl`. + args=() + for a in "$@"; do + if [ -e "$a" ]; then + a="$(realpath "$a")" + fi + args+=("$a") + done + exec "${cura5}/bin/cura5" "''${args[@]}" + '') + + #E: hides scratchpad depending on state, calls emacsclient for edit and then restores the scratchpad state + (pkgs.writeShellScriptBin "e" '' + bash ~/.dotfiles/scripts/editor_nowait.sh "$@" + '') + (pkgs.writeShellScriptBin "timer" '' + sleep "$1"; while true; do spd-say "$2"; sleep 0.5; done; + '') + + (pkgs.writeScriptBin "project" '' + #! ${pkgs.bash}/bin/bash + if [ "$1" == "rust" ]; then + cp ~/.dotfiles/templates/rust_flake.nix ./flake.nix + cp ~/.dotfiles/templates/toolchain.toml . + elif [ "$1" == "cpp" ]; then + cp ~/.dotfiles/templates/cpp_flake.nix ./flake.nix + elif [ "$1" == "python" ]; then + cp ~/.dotfiles/templates/py_flake.nix ./flake.nix + elif [ "$1" == "cuda" ]; then + cp ~/.dotfiles/templates/cu_flake.nix ./flake.nix + elif [ "$1" == "latex" ]; then + if [ "$2" == "" ]; then + echo "No filename specified, usage: 'project latex '" + exit 0 + fi + cp ~/.dotfiles/templates/tex_standard.tex ./"$2".tex + exit 0 + else + echo "No valid argument given. Valid arguments are rust cpp python, cuda" + exit 0 + fi + echo "use flake" >> .envrc + direnv allow + '') + + (pkgs.writeShellApplication { + name = "pass-fuzzel"; + runtimeInputs = [ pkgs.pass pkgs.fuzzel ]; + text = '' + shopt -s nullglob globstar + + typeit=0 + if [[ $# -ge 1 && $1 == "--type" ]]; then + typeit=1 + shift + fi + + export PASSWORD_STORE_DIR=~/.local/share/password-store + prefix=''${PASSWORD_STORE_DIR-~/.local/share/password-store} + password_files=( "$prefix"/**/*.gpg ) + password_files=( "''${password_files[@]#"$prefix"/}" ) + password_files=( "''${password_files[@]%.gpg}" ) + + password=$(printf '%s\n' "''${password_files[@]}" | fuzzel --dmenu "$@") + + [[ -n $password ]] || exit + + if [[ $typeit -eq 0 ]]; then + pass show -c "$password" &>/tmp/pass-fuzzel + else + pass show "$password" | { IFS= read -r pass; printf %s "$pass"; } | wtype - + fi + notify-send -u critical -a pass -t 1000 "Copied/Typed Password" + ''; + }) + + + ]; + + + # MIGHT NEED TO ENABLE THIS ON SURFACE!! + + +#+end_src + +** SSH Machines + +It is very convenient to have SSH aliases in place for machines that I use. This is mainly used for some server machines and some university clusters. + +#+begin_src nix :tangle profiles/common/home.nix + + programs.ssh= { + enable = true; + extraConfig = "SetEnv TERM=xterm-256color"; + matchBlocks = { + "nginx" = { + hostname = "192.168.2.14"; + port = 22; + user = "root"; + }; + "pfsense" = { + hostname = "192.168.1.1"; + port = 22; + user = "root"; + }; + "proxmox" = { + hostname = "192.168.1.2"; + port = 22; + user = "root"; + }; + "transmission" = { + hostname = "192.168.1.6"; + port = 22; + user = "root"; + }; + "omv" = { + hostname = "192.168.1.3"; + port = 22; + user = "root"; + }; + "webbot" = { + hostname = "192.168.1.11"; + port = 22; + user = "root"; + }; + "plex" = { + hostname = "192.168.1.16"; + port = 22; + user = "root"; + }; + "nextcloud" = { + hostname = "192.168.2.5"; + port = 22; + user = "root"; + }; + "subsonic" = { + hostname = "192.168.2.13"; + port = 22; + user = "root"; + }; + "wordpress" = { + hostname = "192.168.2.7"; + port = 22; + user = "root"; + }; + "turn" = { + hostname = "192.168.2.17"; + port = 22; + user = "root"; + }; + "hugo" = { + hostname = "192.168.2.19"; + port = 22; + user = "root"; + }; + "matrix" = { + hostname = "192.168.2.20"; + port = 22; + user = "root"; + }; + "database" = { + hostname = "192.168.2.21"; + port = 22; + user = "root"; + }; + "pkv" = { + hostname = "46.232.248.161"; + port = 22; + user = "root"; + }; + "calibre" = { + hostname = "192.168.2.22"; + port = 22; + user = "root"; + }; + "nebula" = { + hostname = "128.131.171.15"; + port = 22; + user = "amp23s56"; + compression = true; + identityFile = "~/.ssh/id_ed25519"; + proxyCommand = "ssh -p 1022 -i ~/.ssh/id_ed25519 -q -W %h:%p %r@venus.par.tuwien.ac.at"; + extraOptions = { + "TCPKeepAlive" = "yes"; + }; + }; + "efficient" = { + hostname = "g0.complang.tuwien.ac.at"; + port = 22; + forwardAgent = true; + user = "ep01427399"; + + # leaving the below lines in for future reference + + # remoteForwards = [ + # { + # bind.address = "/run/user/21217/gnupg/S.gpg-agent"; + # host.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + # } + # { + # bind.address = "/run/user/21217/gnupg/S.gpg-agent.ssh"; + # host.address = "/run/user/1000/gnupg/S.gpg-agent.ssh"; + # } + # ]; + # extraOptions = { + # "RemoteForward" = "/run/user/21217/gnupg/S.gpg-agent /run/user/1000/gnupg/S.gpg-agent.extra"; + # "StreamLocalBindUnlink" = "yes"; + # "RemoteForward" = "/run/user/21217/gnupg/S.gpg-agent.ssh /run/user/1000/gnupg/S.gpg-agent.ssh"; + # }; + # setEnv = { + # "TERM" = "xterm"; + # }; + }; + "hydra" = { + hostname = "128.131.171.215"; + port = 22; + user = "hpc23w33"; + compression = true; + forwardAgent = true; + # identityFile = "~/.ssh/id_tuwien_hpc"; + # proxyCommand = "ssh -p 1022 -i ~/.ssh/id_tuwien_hpc -q -W %h:%p %r@venus.par.tuwien.ac.at"; + proxyCommand = "ssh -p 1022 -q -W %h:%p %r@venus.par.tuwien.ac.at"; + extraOptions = { + "TCPKeepAlive" = "yes"; + }; + }; + }; + }; + +#+end_src + +** sops + +I use sops-nix to handle secrets that I want to have available on my machines at all times. Procedure to add a new machine: +- `ssh-keygen -t ed25519 -C "NAME sops"` in .ssh directory (or wherever) - name e.g. "sops" +- cat ~/.ssh/sops.pub | ssh-to-age | wl-copy +- add the output to .sops.yaml +- cp ~/.ssh/sops.pub ~/.dotfiles/secrets/keys/NAME.pub +- update entry for sops.age.sshKeyPaths + +#+begin_src nix :tangle profiles/common/home.nix + + sops.defaultSopsFile = "${config.home.homeDirectory}/.dotfiles/secrets/general/secrets.yaml"; + sops.validateSopsFiles = false; + # sops.gnupg.home = "/home/swarsel/.dotfiles/secrets/keys"; + # since we are using the home-manager implementation, we need to specify the runtime path for each secret + sops.secrets.mrswarsel = {path = "/run/user/1000/secrets/mrswarsel";}; + # sops.secrets.mrswarsel = { }; + sops.secrets.nautilus = {path = "/run/user/1000/secrets/nautilus";}; + # sops.secrets.nautilus = { }; + sops.secrets.leon = {path = "/run/user/1000/secrets/leon";}; + sops.secrets.caldav = {path = "${config.home.homeDirectory}/.emacs.d/.caldav";}; + # sops.secrets.leon = { }; +#+end_src + +** Fonts + Theme + +These section allows home-manager to allow theme settings, and handles some other appearance-related settings like cursor styles. Interestingly, system icons (adwaita) still need to be setup on system-level, and will break if defined here. + +#+begin_src nix :tangle profiles/common/home.nix + + stylix.targets.emacs.enable = false; + + # fonts.fontconfig.enable = true; + # gtk = { + # enable = true; + + # theme = { + # name = "Arc-Dark"; + # package = pkgs.arc-theme; + # }; + + # cursorTheme = { + # name = "capitaine-cursors"; + # package = pkgs.capitaine-cursors; + # }; + + # gtk3.extraConfig = { + # Settings = '' + # gtk-application-prefer-dark-theme=1 + # ''; + # }; + + # gtk4.extraConfig = { + # Settings = '' + # gtk-application-prefer-dark-theme=1 + # ''; + # }; + # }; + +#+end_src + +** TODO Desktop Entries + +Some programs lack a dmenu launcher - I define them myself here. + +TODO: Non-NixOS machines (=sp3) should not use these by default, but instead the programs prefixed with "nixGL". I need to figure out how to automate this process, as it is not feasible to write desktop entries for all programs installed on that machine. + +#+begin_src nix :tangle profiles/common/home.nix + + xdg.desktopEntries = { + + cura = { + name = "Ultimaker Cura"; + genericName = "Cura"; + exec = "cura"; + terminal = false; + categories = [ "Application"]; + }; + + anki = { + name = "Anki Flashcards"; + genericName = "Anki"; + exec = "anki"; + terminal = false; + categories = [ "Application"]; + }; + + schlidichat = { + name = "SchildiChat Matrix Client"; + genericName = "SchildiChat"; + exec = "schildichat-desktop -enable-features=UseOzonePlatform -ozone-platform=wayland --disable-gpu-driver-bug-workarounds"; + terminal = false; + categories = [ "Application"]; + }; + + # currently unused but kept for possible future use-case + # not needed as long as schildichat is working properly + # element = { + # name = "Element Matrix Client"; + # genericName = "Element"; + # exec = "element-desktop"; + # terminal = false; + # categories = [ "Application"]; + # }; + + }; + +#+end_src + +** TODO Sourcing dotfiles and environment variables + +This section should be used in order to symlink already existing configuration files using `home.file` and setting session variables using `home.sessionVariables`. + +TODO At the moment this is only used for emacs' init.el and early-init.el - I plan to migrate them to a NUR emacs-init setup at some point in the future, but that is a lot of work and will take possibly more time than I am able to spend on this right now + +As for the `home.sessionVariables`, it should be noted that environment variables that are needed at system start should NOT be loaded here, but instead in `programs.zsh.config.extraSessionCommands` (in the home-manager programs section). This is also where all the wayland related variables are stored. + +#+begin_src nix :tangle profiles/common/home.nix + + home.file = { + "init.el" = { + source = ../../programs/emacs/init.el; + target = ".emacs.d/init.el"; + }; + "early-init.el" = { + source = ../../programs/emacs/early-init.el; + target = ".emacs.d/early-init.el"; + }; + }; + + home.sessionVariables = { + EDITOR = "bash ~/.dotfiles/scripts/editor.sh"; + GTK_THEME = "Arc-Dark"; + }; + +#+end_src + +** Programs + +Let Home Manager install and manage itself - this is needed. + + +Other programs: + +*** General + +#+begin_src nix :tangle profiles/common/home.nix + + programs.password-store = { + enable = true; + package = pkgs.pass.withExtensions (exts: [exts.pass-otp]); + }; + # zsh Integration is enabled by default for these + programs.fzf.enable = true; + programs.direnv.enable = true; + programs.zoxide.enable = true; + programs.navi.enable = true; + programs.eza = { + enable = true; + enableAliases = true; + icons = true; + git = true; + extraOptions = [ + "-l" + "--group-directories-first" + ]; + }; + programs.git = { + enable = true; + aliases = { + c = "commit"; + co = "checkout"; + s = "status"; + p = "pull"; + pp = "push"; + }; + signing = { + key = "0x76FD3810215AE097"; + signByDefault = true; + }; + userEmail = "leon.schwarzaeugl@gmail.com"; + userName = "Swarsel"; + }; + +#+end_src + +*** Fuzzel + +#+begin_src nix :tangle profiles/common/home.nix + + programs.fuzzel = { + enable = true; + settings = { + main = { + layer = "overlay"; + # font = "Monospace:size=8"; + lines = "10"; + width = "40"; + }; + colors = { + # background="293744dd"; + # text="f8f8f2ff"; + # match="8be9fdff"; + # selection-match="8be9fdff"; + # selection="44475add"; + # selection-text="f8f8f2ff"; + # border="ffd700ff"; + }; + border.radius = "0"; + }; + }; + +#+end_src + +*** Starship + +#+begin_src nix :tangle profiles/common/home.nix + + programs.starship = { + enable = true; + enableZshIntegration = true; + settings = { + add_newline = false; + format = "$character"; + right_format = "$all"; + command_timeout = 3000; + + directory.substitutions = { + "Documents" = "󰈙 "; + "Downloads" = " "; + "Music" = " "; + "Pictures" = " "; + }; + + git_status = { + style = "bg:#394260"; + format = "[[($all_status$ahead_behind )](fg:#769ff0 bg:#394260)]($style)"; + }; + + character = { + success_symbol = "[λ](bold green)"; + error_symbol = "[λ](bold red)"; + }; + + aws.symbol = " "; + buf.symbol = " "; + c.symbol = " "; + conda.symbol = " "; + dart.symbol = " "; + directory.read_only = " 󰌾"; + docker_context.symbol = " "; + elixir.symbol = " "; + elm.symbol = " "; + fossil_branch.symbol = " "; + git_branch.symbol = " "; + golang.symbol = " "; + guix_shell.symbol = " "; + haskell.symbol = " "; + haxe.symbol = " "; + hg_branch.symbol = " "; + hostname.ssh_symbol = " "; + java.symbol = " "; + julia.symbol = " "; + lua.symbol = " "; + memory_usage.symbol = "󰍛 "; + meson.symbol = "󰔷 "; + nim.symbol = "󰆥 "; + nix_shell.symbol = " "; + nodejs.symbol = " "; + + os.symbols = { + Alpaquita = " "; + Alpine = " "; + Amazon = " "; + Android = " "; + Arch = " "; + Artix = " "; + CentOS = " "; + Debian = " "; + DragonFly = " "; + Emscripten = " "; + EndeavourOS = " "; + Fedora = " "; + FreeBSD = " "; + Garuda = "󰛓 "; + Gentoo = " "; + HardenedBSD = "󰞌 "; + Illumos = "󰈸 "; + Linux = " "; + Mabox = " "; + Macos = " "; + Manjaro = " "; + Mariner = " "; + MidnightBSD = " "; + Mint = " "; + NetBSD = " "; + NixOS = " "; + OpenBSD = "󰈺 "; + openSUSE = " "; + OracleLinux = "󰌷 "; + Pop = " "; + Raspbian = " "; + Redhat = " "; + RedHatEnterprise = " "; + Redox = "󰀘 "; + Solus = "󰠳 "; + SUSE = " "; + Ubuntu = " "; + Unknown = " "; + Windows = "󰍲 "; + }; + + package.symbol = "󰏗 "; + pijul_channel.symbol = " "; + python.symbol = " "; + rlang.symbol = "󰟔 "; + ruby.symbol = " "; + rust.symbol = " "; + scala.symbol = " "; + }; + }; + +#+end_src + +*** Kitty + +Kitty is the terminal emulator of choice for me, it is nice to configure using nix, fast, and has a nice style. + +#+begin_src nix :tangle profiles/common/home.nix + + programs.kitty = { + enable = true; + keybindings = { + "ctrl+shift+left" = "no_op"; + "ctrl+shift+right" = "no_op"; + "ctrl+shift+home" = "no_op"; + "ctrl+shift+end" = "no_op"; + }; + # theme = "citylights"; + }; + +#+end_src + +*** zsh + +zsh is clearly the most convenient shell for me and it happens to be super neat to configure within home manager. + + +#+begin_src nix :tangle profiles/common/home.nix + + programs.zsh = { + enable = true; + shellAliases = { + hg = "history | grep"; + hmswitch = "cd ~/.dotfiles; home-manager --flake .#$(whoami)@$(hostname) switch; cd -;"; + nswitch = "cd ~/.dotfiles; sudo nixos-rebuild --flake .#$(hostname) switch; cd -;"; + edithome = "bash ~/.dotfiles/scripts/editor.sh ~/.dotfiles/Nix.org"; + magit = "emacsclient -nc -e \"(magit-status)\""; + config="git --git-dir=$HOME/.cfg/ --work-tree=$HOME"; + c="git --git-dir=$HOME/.cfg/ --work-tree=$HOME"; + passpush = "cd ~/.local/share/password-store; git add .; git commit -m 'pass file changes'; git push; cd -;"; + passpull = "cd ~/.local/share/password-store; git pull; cd -;"; + }; + enableAutosuggestions = true; + enableCompletion = true; + syntaxHighlighting.enable = true; + autocd = false; + cdpath = [ + "~/.dotfiles" + # "~/Documents/GitHub" + ]; + defaultKeymap = "emacs"; + dirHashes = { + dl = "$HOME/Downloads"; + }; + history = { + expireDuplicatesFirst = true; + path = "$HOME/.histfile"; + save = 10000; + size = 10000; + }; + historySubstringSearch.enable = true; + }; + +#+end_src + +*** Mail + +#+begin_src nix :tangle profiles/common/home.nix + + programs.mbsync = { + enable = true; + }; + # this is needed so that mbsync can use the passwords from sops + systemd.user.services.mbsync.Unit.After = [ "sops-nix.service" ]; + + programs.msmtp = { + enable = true; + }; + + programs.mu = { + enable = true; + }; + + accounts.email = { + maildirBasePath = "Mail"; + accounts.leon = { + primary = true; + address = "leon.schwarzaeugl@gmail.com"; + userName = "leon.schwarzaeugl@gmail.com"; + realName = "Leon Schwarzäugl"; + passwordCommand = "cat ${config.sops.secrets.leon.path}"; + # passwordCommand = "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.local/share/password-store/mail/mbsync/leon.schwarzaeugl@gmail.com.gpg"; + gpg = { + key = "0x76FD3810215AE097"; + signByDefault = true; + }; + imap.host = "imap.gmail.com"; + smtp.host = "smtp.gmail.com"; + mu.enable = true; + msmtp = { + enable = true; + }; + mbsync = { + enable = true; + create= "maildir"; + expunge = "both"; + patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"]; + extraConfig = { + channel = { + Sync = "All"; + }; + account = { + Timeout = 120; + PipelineDepth = 1; + }; + }; + }; + }; + + accounts.nautilus = { + primary = false; + address = "nautilus.dw@gmail.com"; + userName = "nautilus.dw@gmail.com"; + realName = "Nautilus"; + passwordCommand = "cat ${config.sops.secrets.nautilus.path}"; + # passwordCommand = "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.local/share/password-store/mail/mbsync/nautilus.dw@gmail.com.gpg"; + imap.host = "imap.gmail.com"; + smtp.host = "smtp.gmail.com"; + msmtp.enable = true; + mu.enable = true; + mbsync = { + enable = true; + create= "maildir"; + expunge = "both"; + patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"]; + extraConfig = { + channel = { + Sync = "All"; + }; + account = { + Timeout = 120; + PipelineDepth = 1; + }; + }; + }; + }; + accounts.mrswarsel = { + primary = false; + address = "mrswarsel@gmail.com"; + userName = "mrswarsel@gmail.com"; + realName = "Swarsel"; + # passwordCommand = "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.local/share/password-store/mail/mbsync/mrswarsel@gmail.com.gpg"; + passwordCommand = "cat ${config.sops.secrets.mrswarsel.path}"; + imap.host = "imap.gmail.com"; + smtp.host = "smtp.gmail.com"; + msmtp.enable = true; + mu.enable = true; + mbsync = { + enable = true; + create= "maildir"; + expunge = "both"; + patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"]; + extraConfig = { + channel = { + Sync = "All"; + }; + account = { + Timeout = 120; + PipelineDepth = 1; + }; + }; + }; + }; + }; + +#+end_src + +*** Emacs + +#+begin_src nix :tangle profiles/common/home.nix + + # enable emacs overlay for bleeding edge features + # also read init.el file and install use-package packages + programs.emacs = { + enable = true; + package = (pkgs.emacsWithPackagesFromUsePackage { + config = ../../Emacs.org; # tangling my Emacs.org file here instead of directly putting init.el allows avoidance of automatically installing packages in blocks using UTF-8 characters, which would break the nix evaluation happening in this line. This line is also the reason why (for now) the Emacs configuration lives in a different .org file + package = pkgs.emacs-pgtk; + alwaysEnsure = true; + alwaysTangle = true; + extraEmacsPackages = epkgs: [ + epkgs.mu4e + epkgs.use-package + epkgs.lsp-bridge + epkgs.doom-themes + + # build the rest of the packages myself + # org-calfw is severely outdated on MELPA and throws many warnings on emacs startup + # build the package from the haji-ali fork, which is well-maintained + (epkgs.trivialBuild rec { + pname = "calfw"; + version = "1.0.0-20231002"; + src = pkgs.fetchFromGitHub { + owner = "haji-ali"; + repo = "emacs-calfw"; + rev = "bc99afee611690f85f0cd0bd33300f3385ddd3d3"; + hash = "sha256-0xMII1KJhTBgQ57tXJks0ZFYMXIanrOl9XyqVmu7a7Y="; + }; + packageRequires = [ epkgs.howm ]; + }) + + ]; + }); + }; + +#+end_src + +*** Waybar + +Again I am just using the first bar option here that I was able to find good understandable documentation for. Of note is that the `cpu` section's `format` is not defined here, but in section 1 (since not every machine has the same number of cores) + +#+begin_src nix :tangle profiles/common/home.nix + + programs.waybar = { + + enable = true; + # systemd.enable = true; + settings = { + mainBar = { + layer = "top"; + position = "top"; + modules-left = [ "sway/workspaces" "custom/outer-right-arrow-dark" "sway/window"]; + modules-center = [ "sway/mode" "custom/configwarn" ]; + "sway/mode" = { + format = "{}"; + }; + + "custom/configwarn" = { + exec= "bash ~/.dotfiles/scripts/checkconfigstatus.sh"; + interval= 60; + }; + + "group/hardware" = { + orientation = "inherit"; + drawer = { + "transition-left-to-right" = true; + }; + modules = [ + "tray" + "temperature" + "custom/left-arrow-light" + "disk" + "custom/left-arrow-dark" + "memory" + "custom/left-arrow-light" + "cpu" + "custom/left-arrow-dark" + ]; + }; + + temperature = { + critical-threshold = 80; + format-critical = " {temperatureC}°C"; + format = " {temperatureC}°C"; + + }; + + mpris = { + format= "{player_icon} {title} [{position}/{length}]"; + format-paused= "{player_icon} {title} [{position}/{length}]"; + player-icons= { + "default" = "▶ "; + "mpv" = "🎵 "; + "spotify" = " "; + }; + status-icons= { + "paused"= " "; + }; + interval = 1; + title-len = 20; + artist-len = 20; + album-len = 10; + }; + "custom/left-arrow-dark" = { + format = ""; + tooltip = false; + }; + "custom/outer-left-arrow-dark"= { + format = ""; + tooltip = false; + }; + "custom/left-arrow-light"= { + format= ""; + tooltip= false; + }; + "custom/right-arrow-dark"= { + format= ""; + tooltip= false; + }; + "custom/outer-right-arrow-dark"= { + format= ""; + tooltip= false; + }; + "custom/right-arrow-light"= { + format= ""; + tooltip= false; + }; + "sway/workspaces"= { + disable-scroll= true; + format= "{name}"; + }; + + "clock#1"= { + min-length= 8; + interval= 1; + format= "{:%H:%M:%S}"; + on-click-right= "gnome-clocks"; + tooltip-format= "{:%Y %B}\n{calendar}\n\nR:Clocks"; + }; + + "clock#2"= { + format= "{:%d. %B %Y}"; + on-click-right= "gnome-clocks"; + tooltip-format= "{:%Y %B}\n{calendar}\n\nR:Clocks"; + }; + + + pulseaudio= { + format= "{icon} {volume:2}%"; + format-bluetooth= "{icon} {volume}%"; + format-muted= "MUTE"; + format-icons= { + headphones= ""; + default= [ + "" + "" + ]; + }; + scroll-step= 1; + on-click= "pamixer -t"; + on-click-right= "pavucontrol"; + }; + memory= { + interval= 5; + format= " {}%"; + tooltip-format= "Memory: {used:0.1f}G/{total:0.1f}G\nSwap: {swapUsed}G/{swapTotal}G"; + }; + cpu= { + min-length= 6; + interval= 5; + format-icons = ["▁" "▂" "▃" "▄" "▅" "▆" "▇" "█"]; + on-click-right= "com.github.stsdc.monitor"; + + }; + battery= { + states= { + "warning"= 60; + "error"= 30; + "critical"= 15; + }; + interval=5; + format= "{icon} {capacity}%"; + format-charging= "{capacity}% "; + format-plugged= "{capacity}% "; + format-icons= [ + "" + "" + "" + "" + "" + ]; + on-click-right= "wlogout -p layer-shell"; + }; + disk= { + interval= 30; + format= "Disk {percentage_used:2}%"; + path= "/"; + states= { + "warning"= 80; + "critical"= 90; + }; + tooltip-format = "{used} used out of {total} on {path} ({percentage_used}%)\n{free} free on {path} ({percentage_free}%)"; + }; + tray= { + icon-size= 20; + }; + network= { + interval = 5; + format-wifi= "{signalStrength}% "; + format-ethernet= ""; + format-linked= "{ifname} (No IP) "; + format-disconnected= "Disconnected ⚠"; + format-alt= "{ifname}: {ipaddr}/{cidr}"; + tooltip-format-ethernet= "{ifname} via {gwaddr}: {essid} {ipaddr}/{cidr}\n\n⇡{bandwidthUpBytes} ⇣{bandwidthDownBytes}"; + tooltip-format-wifi= "{ifname} via {gwaddr}: {essid} {ipaddr}/{cidr} \n{signaldBm}dBm @ {frequency}MHz\n\n⇡{bandwidthUpBytes} ⇣{bandwidthDownBytes}"; + }; + }; + }; + + style = '' + @define-color foreground #fdf6e3; + @define-color background #1a1a1a; + @define-color background-alt #292b2e; + @define-color foreground-warning #268bd2; + @define-color background-warning @background; + @define-color foreground-error red; + @define-color background-error @background; + @define-color foreground-critical gold; + @define-color background-critical blue; + + + ,* { + border: none; + border-radius: 0; + font-family: "FiraCode Nerd Font Propo", "Font Awesome 5 Free"; + font-size: 14px; + min-height: 0; + margin: -1px 0px; + } + + window#waybar { + background: transparent; + color: @foreground; + transition-duration: .5s; + } + + window#waybar.hidden { + opacity: 0.2; + } + + + #mpris { + padding: 0 10px; + background-color: transparent; + color: #1DB954; + font-family: Monospace; + font-size: 12px; + } + + #custom-right-arrow-dark, + #custom-left-arrow-dark { + color: @background; + background: @background-alt; + font-size: 24px; + } + + #window { + font-size: 12px; + padding: 0 20px; + } + + #mode { + background: @background-critical; + color: @foreground-critical; + padding: 0 3px; + } + + #custom-configwarn { + color: black; + padding: 0 3px; + animation-name: configblink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + } + + #custom-outer-right-arrow-dark, + #custom-outer-left-arrow-dark { + color: @background; + font-size: 24px; + } + + #custom-outer-left-arrow-dark, + #custom-left-arrow-dark, + #custom-left-arrow-light { + margin: 0 -1px; + } + + #custom-right-arrow-light, + #custom-left-arrow-light { + color: @background-alt; + background: @background; + font-size: 24px; + } + + #workspaces, + #clock.1, + #clock.2, + #clock.3, + #pulseaudio, + #memory, + #cpu, + #temperature, + #mpris, + #tray { + background: @background; + } + + #network, + #clock.2, + #battery, + #cpu, + #custom-pseudobat, + #disk { + background: @background-alt; + } + + + #workspaces button { + padding: 0 2px; + color: #fdf6e3; + } + #workspaces button.focused { + color: @foreground-warning; + } + + #workspaces button:hover { + background: @foreground; + color: @background; + border: @foreground; + padding: 0 2px; + box-shadow: inherit; + text-shadow: inherit; + } + + #workspaces button.urgent { + color: @background-critical; + background: @foreground-critical; + } + + #network { + color: #cc99c9; + } + + #temperature { + color: #9ec1cf; + } + + #disk { + /*color: #b58900;*/ + color: #9ee09e; + } + + #disk.warning { + color: @foreground-error; + background-color: @background-error; + } + #disk.critical, + #temperature.critical { + color: @foreground-critical; + background-color: @background-critical; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + } + #pulseaudio.muted { + color: @foreground-error; + } + #memory { + /*color: #2aa198;*/ + color: #fdfd97; + } + #cpu { + /*color: #6c71c4;*/ + color: #feb144; + } + + #pulseaudio { + /*color: #268bd2;*/ + color: #ff6663; + } + + #battery, + #custom-pseudobat { + color: cyan; + } + #battery.discharging { + color: #859900; + } + + @keyframes blink { + to { + color: @foreground-error; + background-color: @background-error; + } + } + @keyframes configblink { + to { + color: @foreground-error; + background-color: transparent; + } + } + + #battery.critical:not(.charging) { + color: @foreground-critical; + background-color: @background-critical; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + } + + #clock.1, + #clock.2, + #clock.3 { + font-family: Monospace; + } + + #clock, + #pulseaudio, + #memory, + #cpu, + #tray, + #temperature, + #network, + #mpris, + #battery, + #custom-pseudobat, + #disk { + padding: 0 3px; + } + ''; + }; + +#+end_src + +*** Firefox + +#+begin_src nix :tangle profiles/common/home.nix + + programs.firefox = { + enable = true; + package = pkgs.firefox.override { + nativeMessagingHosts = [ + pkgs.tridactyl-native + pkgs.browserpass + pkgs.plasma5Packages.plasma-browser-integration + ]; + }; + policies = { + CaptivePortal = false; + DisableFirefoxStudies = true; + DisablePocket = true; + DisableTelemetry = true; + DisableFirefoxAccounts = false; + NoDefaultBookmarks = true; + OfferToSaveLogins = false; + OfferToSaveLoginsDefault = false; + EnableTrackingProtection = true; + }; + profiles.default = { + isDefault = true; + extensions = with pkgs.nur.repos.rycee.firefox-addons; [ + tridactyl + browserpass + clearurls + darkreader + enhancer-for-youtube + istilldontcareaboutcookies + translate-web-pages + ublock-origin + reddit-enhancement-suite + pushbullet + sponsorblock + web-archives + single-file + widegithub + enhanced-github + unpaywall + # fastforwardteam + don-t-fuck-with-paste + plasma-integration + + # build the rest of my firefox addons myself + # app id can be found in the manifest.json file of the .xpi + # (.xpi is just a normal archive) + # url can be found by copy url of the "add extension" button on the addon page + # the rest of the information is also found in the manifest.json, but might not be + # needed + + (let version = "3.4.5.0"; + in buildFirefoxXpiAddon { + pname = "bypass-paywalls-clean"; + inherit version; + addonId = "magnolia@12.34"; + url = + "https://gitlab.com/magnolia1234/bpc-uploads/-/raw/master/bypass_paywalls_clean-3.4.5.0.xpi"; + sha256 = "703d30c15b88291bd0305cc59013693aea5f75a40ea98fb8e252d1c7bfb43514"; + meta = with lib; { + homepage = + "https://gitlab.com/magnolia1234/bypass-paywalls-firefox-clean"; + description = "Bypass Paywalls of (custom) news sites"; + license = licenses.mit; + platforms = platforms.all; + }; + }) + + + (buildFirefoxXpiAddon { + pname = ":emoji:"; + version = "0.1.3"; + addonId = "gonelf@gmail.com"; + url = "https://addons.mozilla.org/firefox/downloads/file/3365324/emojidots-0.1.3.xpi"; + sha256 = "4f7cc25c478fe52eb82f37c9ff4978dcaa3f95020398c5b184e517f6efa2c201"; + meta = with lib; + { + description = "emoji autocomplete anywhere on the internet"; + mozPermissions = [ "https://gist.githubusercontent.com/gonelf/d8ae3ccb7902b501c4a5dd625d4089da/raw/5eeda197ba92f8c8139e846a1225d5640077e06f/emoji_pretty.json" "tabs" "storage"]; + platforms = platforms.all; + }; + }) + + ]; + search.engines = { + "Nix Packages" = { + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ + { name = "type"; value = "packages"; } + { name = "query"; value = "{searchTerms}"; } + ]; + }]; + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@np" ]; + }; + + "NixOS Wiki" = { + urls = [{ + template = "https://nixos.wiki/index.php?search={searchTerms}"; + }]; + iconUpdateURL = "https://nixos.wiki/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; # every day + definedAliases = [ "@nw" ]; + }; + + "NixOS Options" = { + urls = [{ + template = "https://search.nixos.org/options"; + params = [ + { name = "query"; value = "{searchTerms}"; } + ]; + }]; + + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@no" ]; + }; + + "Home Manager Options" = { + urls = [{ template = "https://mipmip.github.io/home-manager-option-search/"; + params = [ + { name = "query"; value = "{searchTerms}"; } + ]; + }]; + + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@hm" ]; + }; + + "Google".metaData.alias = "@g"; + }; + search.force = true; # this is required because otherwise the search.json.mozlz4 symlink gets replaced on every firefox restart + }; + }; + +#+end_src + +*** Browserpass + +#+begin_src nix :tangle profiles/common/home.nix + + # programs.browserpass = { + # enable = true; + # browsers = [ + # "firefox" + # ]; + # }; + +#+end_src + +** Services + +Services that can be defined through home-manager should be defined here. + +*** General + +#+begin_src nix :tangle profiles/common/home.nix + + services.gnome-keyring = { + enable = true; + }; + + services.mbsync = { + enable = false; + }; + + + services.kdeconnect = { + enable = true; + indicator = true; + }; + + services.syncthing = { + enable = true; + }; + + # this enables the emacs server + services.emacs.enable = true; + +#+end_src + +*** Mako + +The `extraConfig` section here CANNOT be reindented. This has something to do with how nix handles multiline strings, when indented Mako will fail to start. This might be a mako bug as well. + +#+begin_src nix :tangle profiles/common/home.nix + + services.mako = { + enable = true; + # backgroundColor = "#2e3440"; + # borderColor = "#88c0d0"; + borderRadius = 15; + borderSize = 1; + defaultTimeout = 5000; + height = 150; + icons = true; + ignoreTimeout = true; + layer = "overlay"; + maxIconSize = 64; + sort = "-time"; + width = 300; + # font = "monospace 10"; + extraConfig = "[urgency=low] + border-color=#cccccc + [urgency=normal] + border-color=#d08770 + [urgency=high] + border-color=#bf616a + default-timeout=3000 + [category=mpd] + default-timeout=2000 + group-by=category + "; + }; + +#+end_src + +** Sway + +I am currently using SwayFX, which adds some nice effects to sway, like rounded corners and hiding the separator between title and content of a window. + +#+begin_src nix :tangle profiles/common/home.nix + + wayland.windowManager.sway = { + enable = true; + package = pkgs.swayfx; + systemd.enable = true; + systemd.xdgAutostart = true; + wrapperFeatures.gtk = true; + config = rec { + modifier = "Mod4"; + terminal = "kitty"; + menu = "fuzzel"; + bars = [{ command = "waybar";}]; + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+q" = "kill"; + "${modifier}+f" = "exec firefox"; + "${modifier}+Space" = "exec fuzzel"; + "${modifier}+Shift+Space" = "floating toggle"; + "${modifier}+e" = "exec emacsclient -nquc -a emacs -e \"(dashboard-open)\""; + "${modifier}+Shift+m" = "exec \"bash ~/.dotfiles/scripts/checkspotify.sh\""; + "${modifier}+m" = "exec \"bash ~/.dotfiles/scripts/checkspotifytui.sh\""; + "${modifier}+x" = "exec \"bash ~/.dotfiles/scripts/checkkitty.sh\""; + "${modifier}+d" = "exec \"bash ~/.dotfiles/scripts/checkdiscord.sh\""; + "${modifier}+Shift+r" = "exec \"bash ~/.dotfiles/scripts/restart.sh\""; + "${modifier}+Shift+F12" = "move scratchpad"; + "${modifier}+F12" = "scratchpad show"; + "${modifier}+c" = "exec qalculate-gtk"; + "${modifier}+p" = "exec pass-fuzzel"; + "${modifier}+Shift+p" = "exec pass-fuzzel --type"; + "${modifier}+Escape" = "mode $exit"; + "${modifier}+Shift+Escape" = "exec com.github.stsdc.monitor"; + "${modifier}+s" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+i" = "exec \"bash ~/.dotfiles/scripts/startup.sh\""; + "${modifier}+1" = "workspace 1:一"; + "${modifier}+Shift+1" = "move container to workspace 1:一"; + "${modifier}+2" = "workspace 2:二"; + "${modifier}+Shift+2" = "move container to workspace 2:二"; + "${modifier}+3" = "workspace 3:三"; + "${modifier}+Shift+3" = "move container to workspace 3:三"; + "${modifier}+4" = "workspace 4:四"; + "${modifier}+Shift+4" = "move container to workspace 4:四"; + "${modifier}+5" = "workspace 5:五"; + "${modifier}+Shift+5" = "move container to workspace 5:五"; + "${modifier}+6" = "workspace 6:六"; + "${modifier}+Shift+6" = "move container to workspace 6:六"; + "${modifier}+7" = "workspace 7:七"; + "${modifier}+Shift+7" = "move container to workspace 7:七"; + "${modifier}+8" = "workspace 8:八"; + "${modifier}+Shift+8" = "move container to workspace 8:八"; + "${modifier}+9" = "workspace 9:九"; + "${modifier}+Shift+9" = "move container to workspace 9:九"; + "${modifier}+0" = "workspace 10:十"; + "${modifier}+Shift+0" = "move container to workspace 10:十"; + "XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +5%"; + "XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -5%"; + "${modifier}+Left" = "focus left"; + "${modifier}+Right" = "focus right"; + "${modifier}+Down" = "focus down"; + "${modifier}+Up" = "focus up"; + "${modifier}+Shift+Left" = "move left 40px"; + "${modifier}+Shift+Right" = "move right 40px"; + "${modifier}+Shift+Down" = "move down 40px"; + "${modifier}+Shift+Up" = "move up 40px"; + "${modifier}+h" = "focus left"; + "${modifier}+l" = "focus right"; + "${modifier}+j" = "focus down"; + "${modifier}+k" = "focus up"; + "${modifier}+Shift+h" = "move left 40px"; + "${modifier}+Shift+l" = "move right 40px"; + "${modifier}+Shift+j" = "move down 40px"; + "${modifier}+Shift+k" = "move up 40px"; + "${modifier}+Shift+c" = "reload"; + "${modifier}+Shift+e" = "exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'"; + "${modifier}+r" = "mode resize"; + "${modifier}+Return" = "exec kitty"; + }; + modes = { + resize = { + Down = "resize grow height 10 px or 10 ppt"; + Escape = "mode default"; + Left = "resize shrink width 10 px or 10 ppt"; + Return = "mode default"; + Right = "resize grow width 10 px or 10 ppt"; + Up = "resize shrink height 10 px or 10 ppt"; + }; + }; + defaultWorkspace = "workspace 1:一"; + startup = [ + { command = "kitty -T kittyterm";} + { command = "sleep 60; kitty -T spotifytui spt";} + ]; + window = { + border = 1; + titlebar = false; + }; + assigns = { + # disabled, this is too annoying to be of use + # "1:一" = [{ app_id = "^firefox$"; }]; + }; + colors = { + focused = { + # background = "#080808"; + # border = "#80a0ff"; + # childBorder = "#80a0ff"; + # indicator = "#080808"; + # text = "#ffd700"; + }; + unfocused = { + # background = "#080808"; + # border = "#80a0ff"; + # childBorder = "#303030"; + # indicator = "#80a0ff"; + # text = "#c6c6c6"; + }; + }; + floating = { + border = 1; + criteria = [ + {title = "^Picture-in-Picture$";} + {app_id = "qalculate-gtk";} + {app_id = "org.gnome.clocks";} + {app_id = "com.github.stsdc.monitor";} + {app_id = "blueman";} + {app_id = "pavucontrol";} + {app_id = "syncthingtray";} + {app_id = "SchildiChat";} + {class = "Element";} + {title = "Element";} + {app_id = "com.nextcloud.desktopclient.nextcloud";} + {app_id = "gnome-system-monitor";} + {title = "(?:Open|Save) (?:File|Folder|As)";} + {title = "^Add$";} + {title = "com-jgoodies-jdiskreport-JDiskReport";} + {app_id = "discord";} + {window_role = "pop-up";} + {window_role = "bubble";} + {window_role = "dialog";} + {window_role = "task_dialog";} + {window_role = "menu";} + {window_role = "Preferences";} + ]; + titlebar = false; + }; + window = { + commands = [ + { + command = "opacity 0.95"; + criteria = { + class = ".*"; + }; + } + { + command = "opacity 0.95"; + criteria = { + app_id = ".*"; + }; + } + { + command = "opacity 0.99"; + criteria = { + app_id = "firefox"; + }; + } + { + command = "sticky enable, shadows enable"; + criteria = { + title="^Picture-in-Picture$"; + }; + } + { + command = "opacity 0.8, sticky enable, border normal, move container to scratchpad"; + criteria = { + title="kittyterm"; + }; + } + { + command = "opacity 0.95, sticky enable, border normal, move container to scratchpad"; + criteria = { + title="spotifytui"; + }; + } + { + command = "resize set width 60 ppt height 60 ppt, sticky enable, move container to scratchpad"; + criteria = { + app_id="^$"; + class="^$"; + }; + } + { + + command = "resize set width 60 ppt height 60 ppt, sticky enable, move container to scratchpad"; + criteria = { + class="Spotify"; + }; + } + { + command = "sticky enable"; + criteria = { + app_id = "discord"; + }; + } + { + command = "resize set width 60 ppt height 60 ppt, sticky enable"; + criteria = { + class = "Element"; + }; + } + { + command = "resize set width 60 ppt height 60 ppt, sticky enable"; + criteria = { + app_id = "SchildiChat"; + }; + } + ]; + }; + gaps = { + inner = 5; + }; + }; + extraSessionCommands ='' + export SDL_VIDEODRIVER=wayland + export QT_QPA_PLATFORM=wayland + export QT_WAYLAND_DISABLE_WINDOWDECORATION="1" + export _JAVA_AWT_WM_NONREPARENTING=1 + export XDG_CURRENT_DESKTOP=sway + export XDG_SESSION_DESKTOP=sway + export QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox"; + export ANKI_WAYLAND=1; + export OBSIDIAN_USE_WAYLAND=1; + ''; + # extraConfigEarly = " + # exec systemctl --user import-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK + # exec hash dbus-update-activation-environment 2>/dev/null && dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK + # "; + extraConfig =let + modifier = config.wayland.windowManager.sway.config.modifier; + in " + exec_always autotiling + set $exit \"exit: [s]leep, [p]oweroff, [r]eboot, [l]ogout\" + mode $exit { + + bindsym --to-code { + s exec \"systemctl suspend\", mode \"default\" + p exec \"systemctl poweroff\" + r exec \"systemctl reboot\" + l exec \"swaymsg exit\" + + Return mode \"default\" + Escape mode \"default\" + ${modifier}+x mode \"default\" + } + } + + exec systemctl --user import-environment + + blur enable + blur_xray disable + blur_passes 1 + blur_radius 1 + shadows enable + corner_radius 2 + titlebar_separator disable + default_dim_inactive 0.02 + + "; + }; + +#+end_src + +* TODO Manual tasks and Closing Parenthesis (this needs to be the last heading) + +Here are listed some tasks that I was not able to automate yet, these need to be done automatically for now. Also, this section exists to add an extra closing parenthesis to common.nix so that I do not need to think about this anymore if I ever decide to add more headings towards the end of this file ;) + +- TODO: Check if the below tasks can be automated + +1) In blueman, toggle the `ConnectionNotifier` plugin to off (since it is highly annoing) + +The last blocks exist to close the opening parenthesis of modules/common.nix (home-manager) and profiles/common.nix (NixOS): + + +#+begin_src nix :tangle profiles/common/home.nix + + } + +#+end_src + +#+begin_src nix :tangle profiles/common/nixos.nix + + } + +#+end_src diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..9c5e499 --- /dev/null +++ b/flake.lock @@ -0,0 +1,692 @@ +{ + "nodes": { + "base16": { + "inputs": { + "fromYaml": "fromYaml" + }, + "locked": { + "lastModified": 1689633990, + "narHash": "sha256-iwvQg2Vx0IIDWZaKo8Xmzxlv1YPHg+Kp/QSv8dRv0RY=", + "owner": "SenchoPens", + "repo": "base16.nix", + "rev": "dddf2e1c04845d43c89a8e9e37d574519649a404", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "base16.nix", + "type": "github" + } + }, + "base16-alacritty": { + "flake": false, + "locked": { + "lastModified": 1674275109, + "narHash": "sha256-Adwx9yP70I6mJrjjODOgZJjt4OPPe8gJu7UuBboXO4M=", + "owner": "aarowill", + "repo": "base16-alacritty", + "rev": "63d8ae5dfefe5db825dd4c699d0cdc2fc2c3eaf7", + "type": "github" + }, + "original": { + "owner": "aarowill", + "repo": "base16-alacritty", + "type": "github" + } + }, + "base16-fish": { + "flake": false, + "locked": { + "lastModified": 1622559957, + "narHash": "sha256-PebymhVYbL8trDVVXxCvZgc0S5VxI7I1Hv4RMSquTpA=", + "owner": "tomyun", + "repo": "base16-fish", + "rev": "2f6dd973a9075dabccd26f1cded09508180bf5fe", + "type": "github" + }, + "original": { + "owner": "tomyun", + "repo": "base16-fish", + "type": "github" + } + }, + "base16-foot": { + "flake": false, + "locked": { + "lastModified": 1696725948, + "narHash": "sha256-65bz2bUL/yzZ1c8/GQASnoiGwaF8DczlxJtzik1c0AU=", + "owner": "tinted-theming", + "repo": "base16-foot", + "rev": "eedbcfa30de0a4baa03e99f5e3ceb5535c2755ce", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-foot", + "type": "github" + } + }, + "base16-helix": { + "flake": false, + "locked": { + "lastModified": 1696727917, + "narHash": "sha256-FVrbPk+NtMra0jtlC5oxyNchbm8FosmvXIatkRbYy1g=", + "owner": "tinted-theming", + "repo": "base16-helix", + "rev": "dbe1480d99fe80f08df7970e471fac24c05f2ddb", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-helix", + "type": "github" + } + }, + "base16-kitty": { + "flake": false, + "locked": { + "lastModified": 1665001328, + "narHash": "sha256-aRaizTYPpuWEcvoYE9U+YRX+Wsc8+iG0guQJbvxEdJY=", + "owner": "kdrag0n", + "repo": "base16-kitty", + "rev": "06bb401fa9a0ffb84365905ffbb959ae5bf40805", + "type": "github" + }, + "original": { + "owner": "kdrag0n", + "repo": "base16-kitty", + "type": "github" + } + }, + "base16-tmux": { + "flake": false, + "locked": { + "lastModified": 1696725902, + "narHash": "sha256-wDPg5elZPcQpu7Df0lI5O8Jv4A3T6jUQIVg63KDU+3Q=", + "owner": "tinted-theming", + "repo": "base16-tmux", + "rev": "c02050bebb60dbb20cb433cd4d8ce668ecc11ba7", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-tmux", + "type": "github" + } + }, + "base16-vim": { + "flake": false, + "locked": { + "lastModified": 1663659192, + "narHash": "sha256-uJvaYYDMXvoo0fhBZUhN8WBXeJ87SRgof6GEK2efFT0=", + "owner": "chriskempson", + "repo": "base16-vim", + "rev": "3be3cd82cd31acfcab9a41bad853d9c68d30478d", + "type": "github" + }, + "original": { + "owner": "chriskempson", + "repo": "base16-vim", + "type": "github" + } + }, + "crane": { + "inputs": { + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1699218802, + "narHash": "sha256-5l0W4Q7z7A4BCstaF5JuBqXOVrZ3Vqst5+hUnP7EdUc=", + "owner": "ipetkov", + "repo": "crane", + "rev": "2d6c2aaff5a05e443eb15efddc21f9c73720340c", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "emacs-overlay": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1702175135, + "narHash": "sha256-oiXRVftJwABfQ85KucnUp35RN8F4jxGDg3kXMURspXo=", + "owner": "nix-community", + "repo": "emacs-overlay", + "rev": "956b70d64d5ff36c53242cd335fe8274c0cfa2e7", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "emacs-overlay", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1698882062, + "narHash": "sha256-HkhafUayIqxXyHH1X8d9RDl1M2CkFgZLjKD3MzabiEo=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "8c9fa2545007b49a5db5f650ae91f227672c3877", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "fromYaml": { + "flake": false, + "locked": { + "lastModified": 1689549921, + "narHash": "sha256-iX0pk/uB019TdBGlaJEWvBCfydT6sRq+eDcGPifVsCM=", + "owner": "SenchoPens", + "repo": "fromYaml", + "rev": "11fbbbfb32e3289d3c631e0134a23854e7865c84", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "fromYaml", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "lanzaboote", + "pre-commit-hooks-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1702159252, + "narHash": "sha256-4mYOL1EhOmt92OtYsHXRViWrSHvR5obLfCllMmQsUzY=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "e6b7303bd149723c57ca23f5a9428482d6b07306", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "stylix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1700847865, + "narHash": "sha256-uWaOIemGl9LF813MW0AEgCBpKwFo2t1Wv3BZc6e5Frw=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "8cedd63eede4c22deb192f1721dd67e7460e1ebe", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "lanzaboote": { + "inputs": { + "crane": "crane", + "flake-compat": "flake-compat", + "flake-parts": "flake-parts", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs", + "pre-commit-hooks-nix": "pre-commit-hooks-nix", + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1701686621, + "narHash": "sha256-OAR4jhfldEGuXH8DB9w8YrFLcEsZsApWdYPsmJHwM/E=", + "owner": "nix-community", + "repo": "lanzaboote", + "rev": "5655251a38f2a31f26aebae3e0d7fe0f5bd74683", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "lanzaboote", + "type": "github" + } + }, + "nixgl": { + "inputs": { + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1685908677, + "narHash": "sha256-E4zUPEUFyVWjVm45zICaHRpfGepfkE9Z2OECV9HXfA4=", + "owner": "guibou", + "repo": "nixGL", + "rev": "489d6b095ab9d289fe11af0219a9ff00fe87c7c5", + "type": "github" + }, + "original": { + "owner": "guibou", + "repo": "nixGL", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1699354722, + "narHash": "sha256-abmqUReg4PsyQSwv4d0zjcWpMHrd3IFJiTb2tZpfF04=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cfbb29d76949ae53c457f152c52c173ea4bdd862", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable-small", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1701805708, + "narHash": "sha256-hh0S14E816Img0tPaNQSEKFvSscSIrvu1ypubtfh6M4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0561103cedb11e7554cf34cea81e5f5d578a4753", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1685801374, + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_3": { + "locked": { + "lastModified": 1702148972, + "narHash": "sha256-h2jODFP6n+ABrUWcGRSVPRFfLOkM9TJ2pO+h+9JcaL0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b8f33c044e51de6dde3ad80a9676945e0e4e3227", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1660551188, + "narHash": "sha256-a1LARMMYQ8DPx1BgoI/UN4bXe12hhZkCNqdxNi6uS0g=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "441dc5d512153039f19ef198e662e4f3dbb9fd65", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1701718080, + "narHash": "sha256-6ovz0pG76dE0P170pmmZex1wWcQoeiomUZGggfH9XPs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "2c7f3c0fb7c08a0814627611d9d7d45ab6d75335", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1702029940, + "narHash": "sha256-qM3Du0perpLesh5hr87mVPZ79McMUKIWUH7EQMh2kWo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e9ef8a102c555da4f8f417fe5cf5bd539d8a38b7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1700856099, + "narHash": "sha256-RnEA7iJ36Ay9jI0WwP+/y4zjEhmeN6Cjs9VOFBH7eVQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0bd59c54ef06bc34eca01e37d689f5e46b3fe2f1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nur": { + "locked": { + "lastModified": 1702190088, + "narHash": "sha256-TpNx/FtOHakBT29LOaG9Cd73lF+4PLzEadPGnkExHrM=", + "owner": "nix-community", + "repo": "NUR", + "rev": "d4924c10dd9ea639e32cee3761adfa0461c5130a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, + "pre-commit-hooks-nix": { + "inputs": { + "flake-compat": [ + "lanzaboote", + "flake-compat" + ], + "flake-utils": [ + "lanzaboote", + "flake-utils" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_2" + }, + "locked": { + "lastModified": 1699271226, + "narHash": "sha256-8Jt1KW3xTjolD6c6OjJm9USx/jmL+VVmbooADCkdDfU=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "ea758da1a6dcde6dc36db348ed690d09b9864128", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "emacs-overlay": "emacs-overlay", + "home-manager": "home-manager", + "lanzaboote": "lanzaboote", + "nixgl": "nixgl", + "nixpkgs": "nixpkgs_3", + "nur": "nur", + "sops-nix": "sops-nix", + "stylix": "stylix" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": [ + "lanzaboote", + "flake-utils" + ], + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1699409596, + "narHash": "sha256-L3g1smIol3dGTxkUQOlNShJtZLvjLzvtbaeTRizwZBU=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "58240e1ac627cef3ea30c7732fedfb4f51afd8e7", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": "nixpkgs_4", + "nixpkgs-stable": "nixpkgs-stable_3" + }, + "locked": { + "lastModified": 1702177193, + "narHash": "sha256-J2409SyXROoUHYXVy9h4Pj0VU8ReLuy/mzBc9iK4DBg=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "d806e546f96c88cd9f7d91c1c19ebc99ba6277d9", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" + } + }, + "stylix": { + "inputs": { + "base16": "base16", + "base16-alacritty": "base16-alacritty", + "base16-fish": "base16-fish", + "base16-foot": "base16-foot", + "base16-helix": "base16-helix", + "base16-kitty": "base16-kitty", + "base16-tmux": "base16-tmux", + "base16-vim": "base16-vim", + "flake-compat": "flake-compat_2", + "home-manager": "home-manager_2", + "nixpkgs": "nixpkgs_5" + }, + "locked": { + "lastModified": 1701532764, + "narHash": "sha256-Jrizp/nITbul2HBIraQRDw5lyJnzTsj0K9wZUFYX2gg=", + "owner": "danth", + "repo": "stylix", + "rev": "17a452c5d58bb90057d49c7e3e613b5e6dc1c0f4", + "type": "github" + }, + "original": { + "owner": "danth", + "repo": "stylix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..9c1af37 --- /dev/null +++ b/flake.nix @@ -0,0 +1,127 @@ +{ + description = "SwarseFlake - Nix Flake for all SwarselSystems"; + + inputs = { + nixpkgs.url = github:nixos/nixpkgs/nixos-unstable; + + # user-level configuration + home-manager = { + url = github:nix-community/home-manager; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + # overlay to access bleeding edge emacs + emacs-overlay = { + url = github:nix-community/emacs-overlay; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + # nix user repository + # i use this mainly to not have to build all firefox extensions + # myself as well as for the emacs-init package (tbd) + nur.url = github:nix-community/NUR; + + # provides GL to non-NixOS hosts + nixgl.url = github:guibou/nixGL; + + # manages all themeing using Home-Manager + stylix.url = github:danth/stylix; + + # nix secrets management + sops-nix.url = github:Mic92/sops-nix; + + # enable secure boot on NixOS + lanzaboote.url = github:nix-community/lanzaboote; + + }; + + outputs = inputs@{ self, nixpkgs, home-manager, emacs-overlay, nur, nixgl, stylix, sops-nix, lanzaboote, ... }: let + system = "x86_64-linux"; # not very portable, but I do not use other architectures at the moment + pkgs = import nixpkgs { inherit system; + overlays = [ emacs-overlay.overlay + nur.overlay + nixgl.overlay + ]; + config.allowUnfree = true; + }; + # NixOS modules that can only be used on NixOS systems + nixModules = [ stylix.nixosModules.stylix + ./profiles/common/nixos.nix + ]; + + # Home-Manager modules wanted on non-NixOS systems + homeModules = [ stylix.homeManagerModules.stylix + ]; + # Home-Manager modules wanted on both NixOS and non-NixOS systems + mixedModules = [ sops-nix.homeManagerModules.sops + ./profiles/common/home.nix + ]; + in { + + # NixOS setups - run home-manager as a NixOS module for better compatibility + # another benefit - full rebuild on nixos-rebuild switch + # run rebuild using `nswitch` + + # NEW HOSTS: For a new host, decide whether a NixOS (nixosConfigurations) or non-NixOS (homeConfigurations) is used. + # Make sure to move hardware-configuration to the appropriate location, by default it is found in /etc/nixos/. + + nixosConfigurations = { + + onett = nixpkgs.lib.nixosSystem { + specialArgs = {inherit inputs pkgs; }; + modules = nixModules ++ [ + ./profiles/onett/nixos.nix + home-manager.nixosModules.home-manager + { + home-manager.users.swarsel.imports = mixedModules ++ [ + ./profiles/onett/home.nix + ]; + } + ]; + }; + + stand = nixpkgs.lib.nixosSystem { + specialArgs = {inherit inputs pkgs; }; + modules = nixModules ++ [ + ./profiles/stand/nixos.nix + home-manager.nixosModules.home-manager + { + home-manager.users.homelen.imports = mixedModules ++ [ + ./profiles/stand/home.nix + ]; + } + ]; + }; + + threed = nixpkgs.lib.nixosSystem { + specialArgs = {inherit inputs pkgs; }; + modules = nixModules ++ [ + lanzaboote.nixosModules.lanzaboote + ./profiles/threed/nixos.nix + home-manager.nixosModules.home-manager + { + home-manager.users.swarsel.imports = mixedModules ++ [ + ./profiles/threed/home.nix + ]; + } + ]; + }; + + }; + + # pure Home Manager setups - for non-NixOS machines + # run rebuild using `hmswitch` + + homeConfigurations = { + + "leons@PCisLee" = home-manager.lib.homeManagerConfiguration { + inherit pkgs; + modules = homeModules ++ mixedModules ++ [ + ./profiles/surface/home.nix + ]; + }; + + }; + + }; +} diff --git a/profiles/TEMPLATE/home.nix b/profiles/TEMPLATE/home.nix new file mode 100644 index 0000000..8606e95 --- /dev/null +++ b/profiles/TEMPLATE/home.nix @@ -0,0 +1,130 @@ +{ config, pkgs, lib, fetchFromGitHub, ... }: + +{ + + + home = { + username = "TEMPLATE"; + homeDirectory = "/home/TEMPLATE"; + stateVersion = "23.05"; # TEMPLATE -- Please read the comment before changing. + keyboard.layout = "us"; # TEMPLATE + home.packages = with pkgs; [ + # xdg-utils + # nodejs_20 + # --------------------------------------------------------------- + # if schildichat works on this machine, use it, otherwise go for element + # element-desktop + # --------------------------------------------------------------- + ]; + }; + # update path if the sops private key is stored somewhere else + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + # waybar config - TEMPLATE - update for cores and temp + programs.waybar.settings.mainBar = { + #cpu.format = "{icon0} {icon1} {icon2} {icon3}"; + cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}"; + temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input"; + }; + + # ----------------------------------------------------------------- + # is this machine always connected to power? If yes, use this block: + # + # programs.waybar.settings.mainBar."custom/pseudobat"= { + # format= ""; + # on-click-right= "wlogout -p layer-shell"; + # }; + # programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" + # "mpris" + # "custom/left-arrow-light" + # "network" + # "custom/left-arrow-dark" + # "pulseaudio" + # "custom/left-arrow-light" + # "custom/pseudobat" + # "battery" + # "custom/left-arrow-dark" + # "group/hardware" + # "custom/left-arrow-light" + # "clock#2" + # "custom/left-arrow-dark" + # "clock#1" + # ]; + # + # ----------------------------------------------------------------- + + # ----------------------------------------------------------------- + # if not always connected to power (laptop), use this (default): + + programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" + "mpris" + "custom/left-arrow-light" + "network" + "custom/left-arrow-dark" + "pulseaudio" + "custom/left-arrow-light" + "custom/pseudobat" + "battery" + "custom/left-arrow-dark" + "group/hardware" + "custom/left-arrow-light" + "clock#2" + "custom/left-arrow-dark" + "clock#1" + ]; + + # ----------------------------------------------------------------- + + wayland.windowManager.sway= { + config = rec { + # update for actual inputs here, + input = { + "36125:53060:splitkb.com_Kyria_rev3" = { + xkb_layout = "us"; + xkb_variant = "altgr-intl"; + }; + "1:1:AT_Translated_Set_2_keyboard" = { # TEMPLATE + xkb_layout = "us"; + xkb_options = "grp:win_space_toggle"; + # xkb_options = "ctrl:nocaps,grp:win_space_toggle"; + xkb_variant = "altgr-intl"; + }; + "type:touchpad" = { + dwt = "enabled"; + tap = "enabled"; + natural_scroll = "enabled"; + middle_emulation = "enabled"; + }; + + }; + + output = { + DP-1 = { + mode = "2560x1440"; # TEMPLATE + scale = "1"; + bg = "~/.dotfiles/wallpaper/TEMPLATE.png fill"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + # TEMPLATE + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\""; + # "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkelement.sh\""; + }; + + startup = [ + + { command = "nextcloud --background";} + { command = "spotify";} + { command = "discord --start-minimized";} + { command = "schildichat-desktop --disable-gpu-driver-bug-workarounds --hidden";} + { command = "ANKI_WAYLAND=1 anki";} + { command = "OBSIDIAN_USE_WAYLAND=1 obsidian";} + { command = "nm-applet";} + + ]; + }; + }; +} diff --git a/profiles/TEMPLATE/nixos.nix b/profiles/TEMPLATE/nixos.nix new file mode 100644 index 0000000..fb6f2f7 --- /dev/null +++ b/profiles/TEMPLATE/nixos.nix @@ -0,0 +1,103 @@ +{ config, lib, pkgs, inputs, ... }: + +{ + + + imports = + [ + ./hardware-configuration.nix + ]; + + + services = { + getty.autologinUser = "TEMPLATE"; + greetd.settings.initial_session.user="TEMPLATE"; + }; + + # Bootloader + boot.loader.grub.enable = true; + boot.loader.grub.device = "/dev/sda"; # TEMPLATE - if only one disk, this will work + boot.loader.grub.useOSProber = true; + + # -------------------------------------- + # you might need a configuration like this instead: + # Bootloader + # boot.loader.grub.enable = true; + # boot.loader.grub.devices = ["nodev" ]; + # boot.loader.grub.useOSProber = true; + # boot.kernelPackages = pkgs.linuxPackages_latest; + # -------------------------------------- + + networking.hostName = "TEMPLATE"; # Define your hostname. + + stylix.image = ../../wallpaper/TEMPLATEwp.png; + + + stylix = { + base16Scheme = ../../wallpaper/swarsel.yaml; + # base16Scheme = "${pkgs.base16-schemes}/share/themes/shapeshifter.yaml"; + polarity = "dark"; + opacity.popups = 0.5; + cursor = { + package = pkgs.capitaine-cursors; + name = "capitaine-cursors"; + size = 16; + }; + fonts = { + sizes = { + terminal = 10; + applications = 11; + }; + serif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + sansSerif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + monospace = { + package = (pkgs.nerdfonts.override { fonts = [ "FiraCode"]; }); + name = "FiraCode Nerd Font Mono"; + }; + + emoji = { + package = pkgs.noto-fonts-emoji; + name = "Noto Color Emoji"; + }; + }; + }; + + + + + # Configure keymap in X11 (only used for login) + services.xserver = { + layout = "us"; + xkbVariant = "altgr-intl"; + }; + + users.users.TEMPLATE = { + isNormalUser = true; + description = "TEMPLATE"; + extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ]; + packages = with pkgs; []; + }; + + environment.systemPackages = with pkgs; [ + ]; + + system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change + + +} diff --git a/profiles/common/home.nix b/profiles/common/home.nix new file mode 100644 index 0000000..358d231 --- /dev/null +++ b/profiles/common/home.nix @@ -0,0 +1,1650 @@ +{ config, pkgs, lib, fetchFromGitHub , ... }: + +{ + home.packages = with pkgs; [ + + # "big" programs + filebot + gimp + zoom-us + nomacs + libreoffice-qt + xournalpp + obsidian + spotify + discord + nextcloud-client + spotify-tui + schildichat-desktop + + # kyria + qmk + qmk-udev-rules + + # games + lutris + wine + + # firefox related + tridactyl-native + + # mako related + mako + libnotify + + # general utilities + unrar + samba + cifs-utils + zbar # qr codes + readline + autotiling + brightnessctl + libappindicator-gtk3 + sqlite + speechd + networkmanagerapplet + psmisc # kill etc + jq # used for searching the i3 tree in check.sh files + + # specifically needed for anki + mpv + anki-bin + + # dirvish file previews + fd + imagemagick + poppler + ffmpegthumbnailer + mediainfo + gnutar + unzip + + #nautilus + gnome.nautilus + xfce.tumbler + libgsf + + # wayland stuff + wtype + wl-clipboard + wl-mirror + + # screenshotting tools + grim + slurp + + # the following packages are used (in some way) by waybar + playerctl + pavucontrol + pamixer + gnome.gnome-clocks + wlogout + jdiskreport + syncthingtray + monitor + + #keychain + qalculate-gtk + gcr # needed for gnome-secrets to work + gnome.seahorse + + # sops-related + sops + ssh-to-age + + # mail related packages + mu + + # latex and related packages + (pkgs.texlive.combine { + inherit (pkgs.texlive) scheme-full + dvisvgm dvipng # for preview and export as html + wrapfig amsmath ulem hyperref capt-of; + }) + + # font stuff + (nerdfonts.override { fonts = [ "FiraMono" "FiraCode" "NerdFontsSymbolsOnly"]; }) + noto-fonts-emoji + font-awesome_5 + noto-fonts + noto-fonts-cjk-sans + + # cura + (let cura5 = appimageTools.wrapType2 rec { + name = "cura5"; + version = "5.4.0"; + src = fetchurl { + url = "https://github.com/Ultimaker/Cura/releases/download/${version}/UltiMaker-Cura-${version}-linux-modern.AppImage"; + hash = "sha256-QVv7Wkfo082PH6n6rpsB79st2xK2+Np9ivBg/PYZd74="; + }; + extraPkgs = pkgs: with pkgs; [ ]; + }; in writeScriptBin "cura" '' + #! ${pkgs.bash}/bin/bash + # AppImage version of Cura loses current working directory and treats all paths relateive to $HOME. + # So we convert each of the files passed as argument to an absolute path. + # This fixes use cases like `cd /path/to/my/files; cura mymodel.stl anothermodel.stl`. + args=() + for a in "$@"; do + if [ -e "$a" ]; then + a="$(realpath "$a")" + fi + args+=("$a") + done + exec "${cura5}/bin/cura5" "''${args[@]}" + '') + + #E: hides scratchpad depending on state, calls emacsclient for edit and then restores the scratchpad state + (pkgs.writeShellScriptBin "e" '' + bash ~/.dotfiles/scripts/editor_nowait.sh "$@" + '') + (pkgs.writeShellScriptBin "timer" '' + sleep "$1"; while true; do spd-say "$2"; sleep 0.5; done; + '') + + (pkgs.writeScriptBin "project" '' + #! ${pkgs.bash}/bin/bash + if [ "$1" == "rust" ]; then + cp ~/.dotfiles/templates/rust_flake.nix ./flake.nix + cp ~/.dotfiles/templates/toolchain.toml . + elif [ "$1" == "cpp" ]; then + cp ~/.dotfiles/templates/cpp_flake.nix ./flake.nix + elif [ "$1" == "python" ]; then + cp ~/.dotfiles/templates/py_flake.nix ./flake.nix + elif [ "$1" == "cuda" ]; then + cp ~/.dotfiles/templates/cu_flake.nix ./flake.nix + elif [ "$1" == "latex" ]; then + if [ "$2" == "" ]; then + echo "No filename specified, usage: 'project latex '" + exit 0 + fi + cp ~/.dotfiles/templates/tex_standard.tex ./"$2".tex + exit 0 + else + echo "No valid argument given. Valid arguments are rust cpp python, cuda" + exit 0 + fi + echo "use flake" >> .envrc + direnv allow + '') + + (pkgs.writeShellApplication { + name = "pass-fuzzel"; + runtimeInputs = [ pkgs.pass pkgs.fuzzel ]; + text = '' + shopt -s nullglob globstar + + typeit=0 + if [[ $# -ge 1 && $1 == "--type" ]]; then + typeit=1 + shift + fi + + export PASSWORD_STORE_DIR=~/.local/share/password-store + prefix=''${PASSWORD_STORE_DIR-~/.local/share/password-store} + password_files=( "$prefix"/**/*.gpg ) + password_files=( "''${password_files[@]#"$prefix"/}" ) + password_files=( "''${password_files[@]%.gpg}" ) + + password=$(printf '%s\n' "''${password_files[@]}" | fuzzel --dmenu "$@") + + [[ -n $password ]] || exit + + if [[ $typeit -eq 0 ]]; then + pass show -c "$password" &>/tmp/pass-fuzzel + else + pass show "$password" | { IFS= read -r pass; printf %s "$pass"; } | wtype - + fi + notify-send -u critical -a pass -t 1000 "Copied/Typed Password" + ''; + }) + + + ]; + + + # MIGHT NEED TO ENABLE THIS ON SURFACE!! + +programs.ssh= { + enable = true; + extraConfig = "SetEnv TERM=xterm-256color"; + matchBlocks = { + "nginx" = { + hostname = "192.168.2.14"; + port = 22; + user = "root"; + }; + "pfsense" = { + hostname = "192.168.1.1"; + port = 22; + user = "root"; + }; + "proxmox" = { + hostname = "192.168.1.2"; + port = 22; + user = "root"; + }; + "transmission" = { + hostname = "192.168.1.6"; + port = 22; + user = "root"; + }; + "omv" = { + hostname = "192.168.1.3"; + port = 22; + user = "root"; + }; + "webbot" = { + hostname = "192.168.1.11"; + port = 22; + user = "root"; + }; + "plex" = { + hostname = "192.168.1.16"; + port = 22; + user = "root"; + }; + "nextcloud" = { + hostname = "192.168.2.5"; + port = 22; + user = "root"; + }; + "subsonic" = { + hostname = "192.168.2.13"; + port = 22; + user = "root"; + }; + "wordpress" = { + hostname = "192.168.2.7"; + port = 22; + user = "root"; + }; + "turn" = { + hostname = "192.168.2.17"; + port = 22; + user = "root"; + }; + "hugo" = { + hostname = "192.168.2.19"; + port = 22; + user = "root"; + }; + "matrix" = { + hostname = "192.168.2.20"; + port = 22; + user = "root"; + }; + "database" = { + hostname = "192.168.2.21"; + port = 22; + user = "root"; + }; + "pkv" = { + hostname = "46.232.248.161"; + port = 22; + user = "root"; + }; + "calibre" = { + hostname = "192.168.2.22"; + port = 22; + user = "root"; + }; + "nebula" = { + hostname = "128.131.171.15"; + port = 22; + user = "amp23s56"; + compression = true; + identityFile = "~/.ssh/id_ed25519"; + proxyCommand = "ssh -p 1022 -i ~/.ssh/id_ed25519 -q -W %h:%p %r@venus.par.tuwien.ac.at"; + extraOptions = { + "TCPKeepAlive" = "yes"; + }; + }; + "efficient" = { + hostname = "g0.complang.tuwien.ac.at"; + port = 22; + forwardAgent = true; + user = "ep01427399"; + + # leaving the below lines in for future reference + + # remoteForwards = [ + # { + # bind.address = "/run/user/21217/gnupg/S.gpg-agent"; + # host.address = "/run/user/1000/gnupg/S.gpg-agent.extra"; + # } + # { + # bind.address = "/run/user/21217/gnupg/S.gpg-agent.ssh"; + # host.address = "/run/user/1000/gnupg/S.gpg-agent.ssh"; + # } + # ]; + # extraOptions = { + # "RemoteForward" = "/run/user/21217/gnupg/S.gpg-agent /run/user/1000/gnupg/S.gpg-agent.extra"; + # "StreamLocalBindUnlink" = "yes"; + # "RemoteForward" = "/run/user/21217/gnupg/S.gpg-agent.ssh /run/user/1000/gnupg/S.gpg-agent.ssh"; + # }; + # setEnv = { + # "TERM" = "xterm"; + # }; + }; + "hydra" = { + hostname = "128.131.171.215"; + port = 22; + user = "hpc23w33"; + compression = true; + forwardAgent = true; + # identityFile = "~/.ssh/id_tuwien_hpc"; + # proxyCommand = "ssh -p 1022 -i ~/.ssh/id_tuwien_hpc -q -W %h:%p %r@venus.par.tuwien.ac.at"; + proxyCommand = "ssh -p 1022 -q -W %h:%p %r@venus.par.tuwien.ac.at"; + extraOptions = { + "TCPKeepAlive" = "yes"; + }; + }; + }; +}; + +sops.defaultSopsFile = "${config.home.homeDirectory}/.dotfiles/secrets/general/secrets.yaml"; +sops.validateSopsFiles = false; +# sops.gnupg.home = "/home/swarsel/.dotfiles/secrets/keys"; +# since we are using the home-manager implementation, we need to specify the runtime path for each secret +sops.secrets.mrswarsel = {path = "/run/user/1000/secrets/mrswarsel";}; +# sops.secrets.mrswarsel = { }; +sops.secrets.nautilus = {path = "/run/user/1000/secrets/nautilus";}; +# sops.secrets.nautilus = { }; +sops.secrets.leon = {path = "/run/user/1000/secrets/leon";}; +sops.secrets.caldav = {path = "${config.home.homeDirectory}/.emacs.d/.caldav";}; +# sops.secrets.leon = { }; + +stylix.targets.emacs.enable = false; + + # fonts.fontconfig.enable = true; + # gtk = { + # enable = true; + + # theme = { + # name = "Arc-Dark"; + # package = pkgs.arc-theme; + # }; + + # cursorTheme = { + # name = "capitaine-cursors"; + # package = pkgs.capitaine-cursors; + # }; + + # gtk3.extraConfig = { + # Settings = '' + # gtk-application-prefer-dark-theme=1 + # ''; + # }; + + # gtk4.extraConfig = { + # Settings = '' + # gtk-application-prefer-dark-theme=1 + # ''; + # }; + # }; + +xdg.desktopEntries = { + + cura = { + name = "Ultimaker Cura"; + genericName = "Cura"; + exec = "cura"; + terminal = false; + categories = [ "Application"]; + }; + + anki = { + name = "Anki Flashcards"; + genericName = "Anki"; + exec = "anki"; + terminal = false; + categories = [ "Application"]; + }; + + schlidichat = { + name = "SchildiChat Matrix Client"; + genericName = "SchildiChat"; + exec = "schildichat-desktop -enable-features=UseOzonePlatform -ozone-platform=wayland --disable-gpu-driver-bug-workarounds"; + terminal = false; + categories = [ "Application"]; + }; + + # currently unused but kept for possible future use-case + # not needed as long as schildichat is working properly +# element = { +# name = "Element Matrix Client"; +# genericName = "Element"; +# exec = "element-desktop"; +# terminal = false; +# categories = [ "Application"]; +# }; + +}; + +home.file = { + "init.el" = { + source = ../../programs/emacs/init.el; + target = ".emacs.d/init.el"; + }; + "early-init.el" = { + source = ../../programs/emacs/early-init.el; + target = ".emacs.d/early-init.el"; + }; +}; + +home.sessionVariables = { + EDITOR = "bash ~/.dotfiles/scripts/editor.sh"; + GTK_THEME = "Arc-Dark"; +}; + +programs.password-store = { + enable = true; + package = pkgs.pass.withExtensions (exts: [exts.pass-otp]); +}; +# zsh Integration is enabled by default for these +programs.fzf.enable = true; +programs.direnv.enable = true; +programs.zoxide.enable = true; +programs.navi.enable = true; +programs.eza = { + enable = true; + enableAliases = true; + icons = true; + git = true; + extraOptions = [ + "-l" + "--group-directories-first" + ]; +}; +programs.git = { + enable = true; + aliases = { + c = "commit"; + co = "checkout"; + s = "status"; + p = "pull"; + pp = "push"; + }; + signing = { + key = "0x76FD3810215AE097"; + signByDefault = true; + }; + userEmail = "leon.schwarzaeugl@gmail.com"; + userName = "Swarsel"; +}; + +programs.fuzzel = { + enable = true; + settings = { + main = { + layer = "overlay"; + # font = "Monospace:size=8"; + lines = "10"; + width = "40"; + }; + colors = { + # background="293744dd"; + # text="f8f8f2ff"; + # match="8be9fdff"; + # selection-match="8be9fdff"; + # selection="44475add"; + # selection-text="f8f8f2ff"; + # border="ffd700ff"; + }; + border.radius = "0"; + }; +}; + +programs.starship = { + enable = true; + enableZshIntegration = true; + settings = { + add_newline = false; + format = "$character"; + right_format = "$all"; + command_timeout = 3000; + + directory.substitutions = { + "Documents" = "󰈙 "; + "Downloads" = " "; + "Music" = " "; + "Pictures" = " "; + }; + + git_status = { + style = "bg:#394260"; + format = "[[($all_status$ahead_behind )](fg:#769ff0 bg:#394260)]($style)"; + }; + + character = { + success_symbol = "[λ](bold green)"; + error_symbol = "[λ](bold red)"; + }; + + aws.symbol = " "; + buf.symbol = " "; + c.symbol = " "; + conda.symbol = " "; + dart.symbol = " "; + directory.read_only = " 󰌾"; + docker_context.symbol = " "; + elixir.symbol = " "; + elm.symbol = " "; + fossil_branch.symbol = " "; + git_branch.symbol = " "; + golang.symbol = " "; + guix_shell.symbol = " "; + haskell.symbol = " "; + haxe.symbol = " "; + hg_branch.symbol = " "; + hostname.ssh_symbol = " "; + java.symbol = " "; + julia.symbol = " "; + lua.symbol = " "; + memory_usage.symbol = "󰍛 "; + meson.symbol = "󰔷 "; + nim.symbol = "󰆥 "; + nix_shell.symbol = " "; + nodejs.symbol = " "; + + os.symbols = { + Alpaquita = " "; + Alpine = " "; + Amazon = " "; + Android = " "; + Arch = " "; + Artix = " "; + CentOS = " "; + Debian = " "; + DragonFly = " "; + Emscripten = " "; + EndeavourOS = " "; + Fedora = " "; + FreeBSD = " "; + Garuda = "󰛓 "; + Gentoo = " "; + HardenedBSD = "󰞌 "; + Illumos = "󰈸 "; + Linux = " "; + Mabox = " "; + Macos = " "; + Manjaro = " "; + Mariner = " "; + MidnightBSD = " "; + Mint = " "; + NetBSD = " "; + NixOS = " "; + OpenBSD = "󰈺 "; + openSUSE = " "; + OracleLinux = "󰌷 "; + Pop = " "; + Raspbian = " "; + Redhat = " "; + RedHatEnterprise = " "; + Redox = "󰀘 "; + Solus = "󰠳 "; + SUSE = " "; + Ubuntu = " "; + Unknown = " "; + Windows = "󰍲 "; + }; + + package.symbol = "󰏗 "; + pijul_channel.symbol = " "; + python.symbol = " "; + rlang.symbol = "󰟔 "; + ruby.symbol = " "; + rust.symbol = " "; + scala.symbol = " "; + }; +}; + +programs.kitty = { + enable = true; + keybindings = { + "ctrl+shift+left" = "no_op"; + "ctrl+shift+right" = "no_op"; + "ctrl+shift+home" = "no_op"; + "ctrl+shift+end" = "no_op"; + }; + # theme = "citylights"; +}; + +programs.zsh = { + enable = true; + shellAliases = { + hg = "history | grep"; + hmswitch = "cd ~/.dotfiles; home-manager --flake .#$(whoami)@$(hostname) switch; cd -;"; + nswitch = "cd ~/.dotfiles; sudo nixos-rebuild --flake .#$(hostname) switch; cd -;"; + edithome = "bash ~/.dotfiles/scripts/editor.sh ~/.dotfiles/Nix.org"; + magit = "emacsclient -nc -e \"(magit-status)\""; + config="git --git-dir=$HOME/.cfg/ --work-tree=$HOME"; + c="git --git-dir=$HOME/.cfg/ --work-tree=$HOME"; + passpush = "cd ~/.local/share/password-store; git add .; git commit -m 'pass file changes'; git push; cd -;"; + passpull = "cd ~/.local/share/password-store; git pull; cd -;"; + }; + enableAutosuggestions = true; + enableCompletion = true; + syntaxHighlighting.enable = true; + autocd = false; + cdpath = [ + "~/.dotfiles" + # "~/Documents/GitHub" + ]; + defaultKeymap = "emacs"; + dirHashes = { + dl = "$HOME/Downloads"; + }; + history = { + expireDuplicatesFirst = true; + path = "$HOME/.histfile"; + save = 10000; + size = 10000; + }; + historySubstringSearch.enable = true; +}; + +programs.mbsync = { + enable = true; +}; +# this is needed so that mbsync can use the passwords from sops +systemd.user.services.mbsync.Unit.After = [ "sops-nix.service" ]; + +programs.msmtp = { + enable = true; +}; + +programs.mu = { + enable = true; +}; + +accounts.email = { + maildirBasePath = "Mail"; + accounts.leon = { + primary = true; + address = "leon.schwarzaeugl@gmail.com"; + userName = "leon.schwarzaeugl@gmail.com"; + realName = "Leon Schwarzäugl"; + passwordCommand = "cat ${config.sops.secrets.leon.path}"; + # passwordCommand = "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.local/share/password-store/mail/mbsync/leon.schwarzaeugl@gmail.com.gpg"; + gpg = { + key = "0x76FD3810215AE097"; + signByDefault = true; + }; + imap.host = "imap.gmail.com"; + smtp.host = "smtp.gmail.com"; + mu.enable = true; + msmtp = { + enable = true; + }; + mbsync = { + enable = true; + create= "maildir"; + expunge = "both"; + patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"]; + extraConfig = { + channel = { + Sync = "All"; + }; + account = { + Timeout = 120; + PipelineDepth = 1; + }; + }; + }; + }; + + accounts.nautilus = { + primary = false; + address = "nautilus.dw@gmail.com"; + userName = "nautilus.dw@gmail.com"; + realName = "Nautilus"; + passwordCommand = "cat ${config.sops.secrets.nautilus.path}"; + # passwordCommand = "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.local/share/password-store/mail/mbsync/nautilus.dw@gmail.com.gpg"; + imap.host = "imap.gmail.com"; + smtp.host = "smtp.gmail.com"; + msmtp.enable = true; + mu.enable = true; + mbsync = { + enable = true; + create= "maildir"; + expunge = "both"; + patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"]; + extraConfig = { + channel = { + Sync = "All"; + }; + account = { + Timeout = 120; + PipelineDepth = 1; + }; + }; + }; + }; + accounts.mrswarsel = { + primary = false; + address = "mrswarsel@gmail.com"; + userName = "mrswarsel@gmail.com"; + realName = "Swarsel"; + # passwordCommand = "gpg --quiet --for-your-eyes-only --no-tty --decrypt ~/.local/share/password-store/mail/mbsync/mrswarsel@gmail.com.gpg"; + passwordCommand = "cat ${config.sops.secrets.mrswarsel.path}"; + imap.host = "imap.gmail.com"; + smtp.host = "smtp.gmail.com"; + msmtp.enable = true; + mu.enable = true; + mbsync = { + enable = true; + create= "maildir"; + expunge = "both"; + patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"]; + extraConfig = { + channel = { + Sync = "All"; + }; + account = { + Timeout = 120; + PipelineDepth = 1; + }; + }; + }; + }; +}; + +# enable emacs overlay for bleeding edge features +# also read init.el file and install use-package packages +programs.emacs = { + enable = true; + package = (pkgs.emacsWithPackagesFromUsePackage { + config = ../../Emacs.org; # tangling my Emacs.org file here instead of directly putting init.el allows avoidance of automatically installing packages in blocks using UTF-8 characters, which would break the nix evaluation happening in this line. This line is also the reason why (for now) the Emacs configuration lives in a different .org file + package = pkgs.emacs-pgtk; + alwaysEnsure = true; + alwaysTangle = true; + extraEmacsPackages = epkgs: [ + epkgs.mu4e + epkgs.use-package + epkgs.lsp-bridge + epkgs.doom-themes + + # build the rest of the packages myself + # org-calfw is severely outdated on MELPA and throws many warnings on emacs startup + # build the package from the haji-ali fork, which is well-maintained + (epkgs.trivialBuild rec { + pname = "calfw"; + version = "1.0.0-20231002"; + src = pkgs.fetchFromGitHub { + owner = "haji-ali"; + repo = "emacs-calfw"; + rev = "bc99afee611690f85f0cd0bd33300f3385ddd3d3"; + hash = "sha256-0xMII1KJhTBgQ57tXJks0ZFYMXIanrOl9XyqVmu7a7Y="; + }; + packageRequires = [ epkgs.howm ]; + }) + + ]; + }); +}; + +programs.waybar = { + + enable = true; + # systemd.enable = true; + settings = { + mainBar = { + layer = "top"; + position = "top"; + modules-left = [ "sway/workspaces" "custom/outer-right-arrow-dark" "sway/window"]; + modules-center = [ "sway/mode" "custom/configwarn" ]; + "sway/mode" = { + format = "{}"; + }; + + "custom/configwarn" = { + exec= "bash ~/.dotfiles/scripts/checkconfigstatus.sh"; + interval= 60; + }; + + "group/hardware" = { + orientation = "inherit"; + drawer = { + "transition-left-to-right" = true; + }; + modules = [ + "tray" + "temperature" + "custom/left-arrow-light" + "disk" + "custom/left-arrow-dark" + "memory" + "custom/left-arrow-light" + "cpu" + "custom/left-arrow-dark" + ]; + }; + + temperature = { + critical-threshold = 80; + format-critical = " {temperatureC}°C"; + format = " {temperatureC}°C"; + + }; + + mpris = { + format= "{player_icon} {title} [{position}/{length}]"; + format-paused= "{player_icon} {title} [{position}/{length}]"; + player-icons= { + "default" = "▶ "; + "mpv" = "🎵 "; + "spotify" = " "; + }; + status-icons= { + "paused"= " "; + }; + interval = 1; + title-len = 20; + artist-len = 20; + album-len = 10; + }; + "custom/left-arrow-dark" = { + format = ""; + tooltip = false; + }; + "custom/outer-left-arrow-dark"= { + format = ""; + tooltip = false; + }; + "custom/left-arrow-light"= { + format= ""; + tooltip= false; + }; + "custom/right-arrow-dark"= { + format= ""; + tooltip= false; + }; + "custom/outer-right-arrow-dark"= { + format= ""; + tooltip= false; + }; + "custom/right-arrow-light"= { + format= ""; + tooltip= false; + }; + "sway/workspaces"= { + disable-scroll= true; + format= "{name}"; + }; + + "clock#1"= { + min-length= 8; + interval= 1; + format= "{:%H:%M:%S}"; + on-click-right= "gnome-clocks"; + tooltip-format= "{:%Y %B}\n{calendar}\n\nR:Clocks"; + }; + + "clock#2"= { + format= "{:%d. %B %Y}"; + on-click-right= "gnome-clocks"; + tooltip-format= "{:%Y %B}\n{calendar}\n\nR:Clocks"; + }; + + + pulseaudio= { + format= "{icon} {volume:2}%"; + format-bluetooth= "{icon} {volume}%"; + format-muted= "MUTE"; + format-icons= { + headphones= ""; + default= [ + "" + "" + ]; + }; + scroll-step= 1; + on-click= "pamixer -t"; + on-click-right= "pavucontrol"; + }; + memory= { + interval= 5; + format= " {}%"; + tooltip-format= "Memory: {used:0.1f}G/{total:0.1f}G\nSwap: {swapUsed}G/{swapTotal}G"; + }; + cpu= { + min-length= 6; + interval= 5; + format-icons = ["▁" "▂" "▃" "▄" "▅" "▆" "▇" "█"]; + on-click-right= "com.github.stsdc.monitor"; + + }; + battery= { + states= { + "warning"= 60; + "error"= 30; + "critical"= 15; + }; + interval=5; + format= "{icon} {capacity}%"; + format-charging= "{capacity}% "; + format-plugged= "{capacity}% "; + format-icons= [ + "" + "" + "" + "" + "" + ]; + on-click-right= "wlogout -p layer-shell"; + }; + disk= { + interval= 30; + format= "Disk {percentage_used:2}%"; + path= "/"; + states= { + "warning"= 80; + "critical"= 90; + }; + tooltip-format = "{used} used out of {total} on {path} ({percentage_used}%)\n{free} free on {path} ({percentage_free}%)"; + }; + tray= { + icon-size= 20; + }; + network= { + interval = 5; + format-wifi= "{signalStrength}% "; + format-ethernet= ""; + format-linked= "{ifname} (No IP) "; + format-disconnected= "Disconnected ⚠"; + format-alt= "{ifname}: {ipaddr}/{cidr}"; + tooltip-format-ethernet= "{ifname} via {gwaddr}: {essid} {ipaddr}/{cidr}\n\n⇡{bandwidthUpBytes} ⇣{bandwidthDownBytes}"; + tooltip-format-wifi= "{ifname} via {gwaddr}: {essid} {ipaddr}/{cidr} \n{signaldBm}dBm @ {frequency}MHz\n\n⇡{bandwidthUpBytes} ⇣{bandwidthDownBytes}"; + }; + }; + }; + + style = '' + @define-color foreground #fdf6e3; + @define-color background #1a1a1a; + @define-color background-alt #292b2e; + @define-color foreground-warning #268bd2; + @define-color background-warning @background; + @define-color foreground-error red; + @define-color background-error @background; + @define-color foreground-critical gold; + @define-color background-critical blue; + + + * { + border: none; + border-radius: 0; + font-family: "FiraCode Nerd Font Propo", "Font Awesome 5 Free"; + font-size: 14px; + min-height: 0; + margin: -1px 0px; + } + + window#waybar { + background: transparent; + color: @foreground; + transition-duration: .5s; + } + + window#waybar.hidden { + opacity: 0.2; + } + + + #mpris { + padding: 0 10px; + background-color: transparent; + color: #1DB954; + font-family: Monospace; + font-size: 12px; + } + + #custom-right-arrow-dark, + #custom-left-arrow-dark { + color: @background; + background: @background-alt; + font-size: 24px; + } + + #window { + font-size: 12px; + padding: 0 20px; + } + + #mode { + background: @background-critical; + color: @foreground-critical; + padding: 0 3px; + } + + #custom-configwarn { + color: black; + padding: 0 3px; + animation-name: configblink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + } + + #custom-outer-right-arrow-dark, + #custom-outer-left-arrow-dark { + color: @background; + font-size: 24px; + } + + #custom-outer-left-arrow-dark, + #custom-left-arrow-dark, + #custom-left-arrow-light { + margin: 0 -1px; + } + + #custom-right-arrow-light, + #custom-left-arrow-light { + color: @background-alt; + background: @background; + font-size: 24px; + } + + #workspaces, + #clock.1, + #clock.2, + #clock.3, + #pulseaudio, + #memory, + #cpu, + #temperature, + #mpris, + #tray { + background: @background; + } + + #network, + #clock.2, + #battery, + #cpu, + #custom-pseudobat, + #disk { + background: @background-alt; + } + + + #workspaces button { + padding: 0 2px; + color: #fdf6e3; + } + #workspaces button.focused { + color: @foreground-warning; + } + + #workspaces button:hover { + background: @foreground; + color: @background; + border: @foreground; + padding: 0 2px; + box-shadow: inherit; + text-shadow: inherit; + } + + #workspaces button.urgent { + color: @background-critical; + background: @foreground-critical; + } + + #network { + color: #cc99c9; + } + + #temperature { + color: #9ec1cf; + } + + #disk { + /*color: #b58900;*/ + color: #9ee09e; + } + + #disk.warning { + color: @foreground-error; + background-color: @background-error; + } + #disk.critical, + #temperature.critical { + color: @foreground-critical; + background-color: @background-critical; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + } + #pulseaudio.muted { + color: @foreground-error; + } + #memory { + /*color: #2aa198;*/ + color: #fdfd97; + } + #cpu { + /*color: #6c71c4;*/ + color: #feb144; + } + + #pulseaudio { + /*color: #268bd2;*/ + color: #ff6663; + } + + #battery, + #custom-pseudobat { + color: cyan; + } + #battery.discharging { + color: #859900; + } + + @keyframes blink { + to { + color: @foreground-error; + background-color: @background-error; + } + } + @keyframes configblink { + to { + color: @foreground-error; + background-color: transparent; + } + } + + #battery.critical:not(.charging) { + color: @foreground-critical; + background-color: @background-critical; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + } + + #clock.1, + #clock.2, + #clock.3 { + font-family: Monospace; + } + + #clock, + #pulseaudio, + #memory, + #cpu, + #tray, + #temperature, + #network, + #mpris, + #battery, + #custom-pseudobat, + #disk { + padding: 0 3px; + } + ''; +}; + +programs.firefox = { + enable = true; + package = pkgs.firefox.override { + nativeMessagingHosts = [ + pkgs.tridactyl-native + pkgs.browserpass + pkgs.plasma5Packages.plasma-browser-integration + ]; + }; + policies = { + CaptivePortal = false; + DisableFirefoxStudies = true; + DisablePocket = true; + DisableTelemetry = true; + DisableFirefoxAccounts = false; + NoDefaultBookmarks = true; + OfferToSaveLogins = false; + OfferToSaveLoginsDefault = false; + EnableTrackingProtection = true; + }; + profiles.default = { + isDefault = true; + extensions = with pkgs.nur.repos.rycee.firefox-addons; [ + tridactyl + browserpass + clearurls + darkreader + enhancer-for-youtube + istilldontcareaboutcookies + translate-web-pages + ublock-origin + reddit-enhancement-suite + pushbullet + sponsorblock + web-archives + single-file + widegithub + enhanced-github + unpaywall + # fastforwardteam + don-t-fuck-with-paste + plasma-integration + + # build the rest of my firefox addons myself + # app id can be found in the manifest.json file of the .xpi + # (.xpi is just a normal archive) + # url can be found by copy url of the "add extension" button on the addon page + # the rest of the information is also found in the manifest.json, but might not be + # needed + + (let version = "3.4.5.0"; + in buildFirefoxXpiAddon { + pname = "bypass-paywalls-clean"; + inherit version; + addonId = "magnolia@12.34"; + url = + "https://gitlab.com/magnolia1234/bpc-uploads/-/raw/master/bypass_paywalls_clean-3.4.5.0.xpi"; + sha256 = "703d30c15b88291bd0305cc59013693aea5f75a40ea98fb8e252d1c7bfb43514"; + meta = with lib; { + homepage = + "https://gitlab.com/magnolia1234/bypass-paywalls-firefox-clean"; + description = "Bypass Paywalls of (custom) news sites"; + license = licenses.mit; + platforms = platforms.all; + }; +}) + + + (buildFirefoxXpiAddon { + pname = ":emoji:"; + version = "0.1.3"; + addonId = "gonelf@gmail.com"; + url = "https://addons.mozilla.org/firefox/downloads/file/3365324/emojidots-0.1.3.xpi"; + sha256 = "4f7cc25c478fe52eb82f37c9ff4978dcaa3f95020398c5b184e517f6efa2c201"; + meta = with lib; + { + description = "emoji autocomplete anywhere on the internet"; + mozPermissions = [ "https://gist.githubusercontent.com/gonelf/d8ae3ccb7902b501c4a5dd625d4089da/raw/5eeda197ba92f8c8139e846a1225d5640077e06f/emoji_pretty.json" "tabs" "storage"]; + platforms = platforms.all; + }; + }) + + ]; + search.engines = { + "Nix Packages" = { + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ + { name = "type"; value = "packages"; } + { name = "query"; value = "{searchTerms}"; } + ]; + }]; + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@np" ]; + }; + + "NixOS Wiki" = { + urls = [{ + template = "https://nixos.wiki/index.php?search={searchTerms}"; + }]; + iconUpdateURL = "https://nixos.wiki/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; # every day + definedAliases = [ "@nw" ]; + }; + + "NixOS Options" = { + urls = [{ + template = "https://search.nixos.org/options"; + params = [ + { name = "query"; value = "{searchTerms}"; } + ]; + }]; + + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@no" ]; + }; + + "Home Manager Options" = { + urls = [{ template = "https://mipmip.github.io/home-manager-option-search/"; + params = [ + { name = "query"; value = "{searchTerms}"; } + ]; + }]; + + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@hm" ]; + }; + + "Google".metaData.alias = "@g"; + }; + search.force = true; # this is required because otherwise the search.json.mozlz4 symlink gets replaced on every firefox restart + }; +}; + +# programs.browserpass = { +# enable = true; +# browsers = [ +# "firefox" +# ]; +# }; + +services.gnome-keyring = { + enable = true; +}; + +services.mbsync = { + enable = false; +}; + + +services.kdeconnect = { + enable = true; + indicator = true; +}; + +services.syncthing = { + enable = true; +}; + +# this enables the emacs server +services.emacs.enable = true; + +services.mako = { + enable = true; + # backgroundColor = "#2e3440"; + # borderColor = "#88c0d0"; + borderRadius = 15; + borderSize = 1; + defaultTimeout = 5000; + height = 150; + icons = true; + ignoreTimeout = true; + layer = "overlay"; + maxIconSize = 64; + sort = "-time"; + width = 300; + # font = "monospace 10"; + extraConfig = "[urgency=low] +border-color=#cccccc +[urgency=normal] +border-color=#d08770 +[urgency=high] +border-color=#bf616a +default-timeout=3000 +[category=mpd] +default-timeout=2000 +group-by=category +"; +}; + +wayland.windowManager.sway = { + enable = true; + package = pkgs.swayfx; + systemd.enable = true; + systemd.xdgAutostart = true; + wrapperFeatures.gtk = true; + config = rec { + modifier = "Mod4"; + terminal = "kitty"; + menu = "fuzzel"; + bars = [{ command = "waybar";}]; + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+q" = "kill"; + "${modifier}+f" = "exec firefox"; + "${modifier}+Space" = "exec fuzzel"; + "${modifier}+Shift+Space" = "floating toggle"; + "${modifier}+e" = "exec emacsclient -nquc -a emacs -e \"(dashboard-open)\""; + "${modifier}+Shift+m" = "exec \"bash ~/.dotfiles/scripts/checkspotify.sh\""; + "${modifier}+m" = "exec \"bash ~/.dotfiles/scripts/checkspotifytui.sh\""; + "${modifier}+x" = "exec \"bash ~/.dotfiles/scripts/checkkitty.sh\""; + "${modifier}+d" = "exec \"bash ~/.dotfiles/scripts/checkdiscord.sh\""; + "${modifier}+Shift+r" = "exec \"bash ~/.dotfiles/scripts/restart.sh\""; + "${modifier}+Shift+F12" = "move scratchpad"; + "${modifier}+F12" = "scratchpad show"; + "${modifier}+c" = "exec qalculate-gtk"; + "${modifier}+p" = "exec pass-fuzzel"; + "${modifier}+Shift+p" = "exec pass-fuzzel --type"; + "${modifier}+Escape" = "mode $exit"; + "${modifier}+Shift+Escape" = "exec com.github.stsdc.monitor"; + "${modifier}+s" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+i" = "exec \"bash ~/.dotfiles/scripts/startup.sh\""; + "${modifier}+1" = "workspace 1:一"; + "${modifier}+Shift+1" = "move container to workspace 1:一"; + "${modifier}+2" = "workspace 2:二"; + "${modifier}+Shift+2" = "move container to workspace 2:二"; + "${modifier}+3" = "workspace 3:三"; + "${modifier}+Shift+3" = "move container to workspace 3:三"; + "${modifier}+4" = "workspace 4:四"; + "${modifier}+Shift+4" = "move container to workspace 4:四"; + "${modifier}+5" = "workspace 5:五"; + "${modifier}+Shift+5" = "move container to workspace 5:五"; + "${modifier}+6" = "workspace 6:六"; + "${modifier}+Shift+6" = "move container to workspace 6:六"; + "${modifier}+7" = "workspace 7:七"; + "${modifier}+Shift+7" = "move container to workspace 7:七"; + "${modifier}+8" = "workspace 8:八"; + "${modifier}+Shift+8" = "move container to workspace 8:八"; + "${modifier}+9" = "workspace 9:九"; + "${modifier}+Shift+9" = "move container to workspace 9:九"; + "${modifier}+0" = "workspace 10:十"; + "${modifier}+Shift+0" = "move container to workspace 10:十"; + "XF86AudioRaiseVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ +5%"; + "XF86AudioLowerVolume" = "exec pactl set-sink-volume @DEFAULT_SINK@ -5%"; + "${modifier}+Left" = "focus left"; + "${modifier}+Right" = "focus right"; + "${modifier}+Down" = "focus down"; + "${modifier}+Up" = "focus up"; + "${modifier}+Shift+Left" = "move left 40px"; + "${modifier}+Shift+Right" = "move right 40px"; + "${modifier}+Shift+Down" = "move down 40px"; + "${modifier}+Shift+Up" = "move up 40px"; + "${modifier}+h" = "focus left"; + "${modifier}+l" = "focus right"; + "${modifier}+j" = "focus down"; + "${modifier}+k" = "focus up"; + "${modifier}+Shift+h" = "move left 40px"; + "${modifier}+Shift+l" = "move right 40px"; + "${modifier}+Shift+j" = "move down 40px"; + "${modifier}+Shift+k" = "move up 40px"; + "${modifier}+Shift+c" = "reload"; + "${modifier}+Shift+e" = "exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'"; + "${modifier}+r" = "mode resize"; + "${modifier}+Return" = "exec kitty"; + }; + modes = { + resize = { + Down = "resize grow height 10 px or 10 ppt"; + Escape = "mode default"; + Left = "resize shrink width 10 px or 10 ppt"; + Return = "mode default"; + Right = "resize grow width 10 px or 10 ppt"; + Up = "resize shrink height 10 px or 10 ppt"; + }; + }; + defaultWorkspace = "workspace 1:一"; + startup = [ + { command = "kitty -T kittyterm";} + { command = "sleep 60; kitty -T spotifytui spt";} + ]; + window = { + border = 1; + titlebar = false; + }; + assigns = { + # disabled, this is too annoying to be of use + # "1:一" = [{ app_id = "^firefox$"; }]; + }; + colors = { + focused = { + # background = "#080808"; + # border = "#80a0ff"; + # childBorder = "#80a0ff"; + # indicator = "#080808"; + # text = "#ffd700"; + }; + unfocused = { + # background = "#080808"; + # border = "#80a0ff"; + # childBorder = "#303030"; + # indicator = "#80a0ff"; + # text = "#c6c6c6"; + }; + }; + floating = { + border = 1; + criteria = [ + {title = "^Picture-in-Picture$";} + {app_id = "qalculate-gtk";} + {app_id = "org.gnome.clocks";} + {app_id = "com.github.stsdc.monitor";} + {app_id = "blueman";} + {app_id = "pavucontrol";} + {app_id = "syncthingtray";} + {app_id = "SchildiChat";} + {class = "Element";} + {title = "Element";} + {app_id = "com.nextcloud.desktopclient.nextcloud";} + {app_id = "gnome-system-monitor";} + {title = "(?:Open|Save) (?:File|Folder|As)";} + {title = "^Add$";} + {title = "com-jgoodies-jdiskreport-JDiskReport";} + {app_id = "discord";} + {window_role = "pop-up";} + {window_role = "bubble";} + {window_role = "dialog";} + {window_role = "task_dialog";} + {window_role = "menu";} + {window_role = "Preferences";} + ]; + titlebar = false; + }; + window = { + commands = [ + { + command = "opacity 0.95"; + criteria = { + class = ".*"; + }; + } + { + command = "opacity 0.95"; + criteria = { + app_id = ".*"; + }; + } + { + command = "opacity 0.99"; + criteria = { + app_id = "firefox"; + }; + } + { + command = "sticky enable, shadows enable"; + criteria = { + title="^Picture-in-Picture$"; + }; + } + { + command = "opacity 0.8, sticky enable, border normal, move container to scratchpad"; + criteria = { + title="kittyterm"; + }; + } + { + command = "opacity 0.95, sticky enable, border normal, move container to scratchpad"; + criteria = { + title="spotifytui"; + }; + } + { + command = "resize set width 60 ppt height 60 ppt, sticky enable, move container to scratchpad"; + criteria = { + app_id="^$"; + class="^$"; + }; + } + { + + command = "resize set width 60 ppt height 60 ppt, sticky enable, move container to scratchpad"; + criteria = { + class="Spotify"; + }; + } + { + command = "sticky enable"; + criteria = { + app_id = "discord"; + }; + } + { + command = "resize set width 60 ppt height 60 ppt, sticky enable"; + criteria = { + class = "Element"; + }; + } + { + command = "resize set width 60 ppt height 60 ppt, sticky enable"; + criteria = { + app_id = "SchildiChat"; + }; + } + ]; + }; + gaps = { + inner = 5; + }; + }; + extraSessionCommands ='' + export SDL_VIDEODRIVER=wayland + export QT_QPA_PLATFORM=wayland + export QT_WAYLAND_DISABLE_WINDOWDECORATION="1" + export _JAVA_AWT_WM_NONREPARENTING=1 + export XDG_CURRENT_DESKTOP=sway + export XDG_SESSION_DESKTOP=sway + export QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox"; + export ANKI_WAYLAND=1; + export OBSIDIAN_USE_WAYLAND=1; + ''; + # extraConfigEarly = " + # exec systemctl --user import-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK + # exec hash dbus-update-activation-environment 2>/dev/null && dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK + # "; + extraConfig =let + modifier = config.wayland.windowManager.sway.config.modifier; + in " + exec_always autotiling + set $exit \"exit: [s]leep, [p]oweroff, [r]eboot, [l]ogout\" + mode $exit { + + bindsym --to-code { + s exec \"systemctl suspend\", mode \"default\" + p exec \"systemctl poweroff\" + r exec \"systemctl reboot\" + l exec \"swaymsg exit\" + + Return mode \"default\" + Escape mode \"default\" + ${modifier}+x mode \"default\" + } + } + + exec systemctl --user import-environment + + blur enable + blur_xray disable + blur_passes 1 + blur_radius 1 + shadows enable + corner_radius 2 + titlebar_separator disable + default_dim_inactive 0.02 + + "; +}; + +} diff --git a/profiles/common/nixos.nix b/profiles/common/nixos.nix new file mode 100644 index 0000000..fe61649 --- /dev/null +++ b/profiles/common/nixos.nix @@ -0,0 +1,211 @@ +{ config, lib, pkgs, inputs, ... }: + +{ + + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + + # login keymap + services.xserver = { + layout = "us"; + xkbVariant = "altgr-intl"; + }; + + # mount NAS drive + # works only at home, but w/e + fileSystems."/mnt/smb" = { + device = "//192.168.1.3/Eternor"; + fsType = "cifs"; + options = let + # this line prevents hanging on network split + automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s"; + in ["${automount_opts},credentials=/etc/nixos/smb-secrets,uid=1000,gid=100"]; + }; + + # enable flakes - urgent line!! + nix.settings.experimental-features = ["nix-command" "flakes"]; + environment.sessionVariables.NIXOS_OZONE_WL = "1"; + # correct time between linux and windows + time.hardwareClockInLocalTime = true; + + # dont style GRUB with stylix + stylix.targets.grub.enable = false; # the styling makes grub more ugly + + # cura fix + # xdg.portal = { + # enable = true; + # extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + # wlr.enable = true; + # config = { + # common = { + # default = [ + # "*" + # ]; + # }; + # }; + # }; + # wayland-related + security.polkit.enable = true; + hardware.opengl = { + enable = true; + driSupport = true; + driSupport32Bit = true; + }; + + # audio + sound.enable = true; + # nixpkgs.config.pulseaudio = true; + hardware.pulseaudio= { + enable = true; + package = pkgs.pulseaudioFull; + }; + hardware.enableAllFirmware = true; + hardware.bluetooth.powerOnBoot = true; + hardware.bluetooth.settings = { + General = { + Enable = "Source,Sink,Media,Socket"; + }; + }; + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + networking.networkmanager.enable = true; + + time.timeZone = "Europe/Vienna"; + + i18n.defaultLocale = "en_US.UTF-8"; + i18n.extraLocaleSettings = { + LC_ADDRESS = "de_AT.UTF-8"; + LC_IDENTIFICATION = "de_AT.UTF-8"; + LC_MEASUREMENT = "de_AT.UTF-8"; + LC_MONETARY = "de_AT.UTF-8"; + LC_NAME = "de_AT.UTF-8"; + LC_NUMERIC = "de_AT.UTF-8"; + LC_PAPER = "de_AT.UTF-8"; + LC_TELEPHONE = "de_AT.UTF-8"; + LC_TIME = "de_AT.UTF-8"; + }; + +environment.systemPackages = with pkgs; [ + # yubikey packages + gnupg + yubikey-personalization + yubikey-personalization-gui + yubico-pam + yubioath-flutter + yubikey-manager + yubikey-manager-qt + yubico-piv-tool + pinentry + + # theme related + gnome.adwaita-icon-theme + + # kde-connect + xdg-desktop-portal + + # bluetooth + bluez + + # lsp-related ------------------------------- + # nix + rnix-lsp + # latex + texlab + ghostscript_headless + # rust + rust-analyzer + clippy + rustfmt + # cpp + clang-tools + # + cuda + cudatoolkit + #lsp-bridge / python + gcc + gdb + (python3.withPackages(ps: with ps; [ jupyter ipython pyqt5 epc orjson sexpdata six setuptools paramiko numpy pandas scipy matplotlib requests debugpy flake8 gnureadline python-lsp-server])) + # (python3.withPackages(ps: with ps; [ jupyter ipython pyqt5 numpy pandas scipy matplotlib requests debugpy flake8 gnureadline python-lsp-server])) + # -------------------------------------------- +]; + +programs.dconf.enable = true; +programs.evince.enable = true; +programs.kdeconnect.enable = true; + + +# zsh section, do not delete ------ +programs.zsh.enable = true; +users.defaultUserShell = pkgs.zsh; +environment.shells = with pkgs; [ zsh ]; +environment.pathsToLink = [ "/share/zsh" ]; +# --------------------------------- + +services.blueman.enable = true; + +# enable discovery and usage of network devices (esp. printers) +services.printing.enable = true; +services.avahi = { + enable = true; + nssmdns = true; + openFirewall = true; +}; + +# nautilus file manager +services.gvfs.enable = true; + +# Make CAPS work as a dual function ESC/CTRL key +services.interception-tools = { + enable = true; + udevmonConfig = let + dualFunctionKeysConfig = builtins.toFile "dual-function-keys.yaml" '' + TIMING: + TAP_MILLISEC: 200 + DOUBLE_TAP_MILLISEC: 0 + + MAPPINGS: + - KEY: KEY_CAPSLOCK + TAP: KEY_ESC + HOLD: KEY_LEFTCTRL + ''; + in '' + - JOB: | + ${pkgs.interception-tools}/bin/intercept -g $DEVNODE \ + | ${pkgs.interception-tools-plugins.dual-function-keys}/bin/dual-function-keys -c ${dualFunctionKeysConfig} \ + | ${pkgs.interception-tools}/bin/uinput -d $DEVNODE + DEVICE: + EVENTS: + EV_KEY: [KEY_CAPSLOCK] + ''; +}; + +programs.ssh.startAgent = false; + +services.pcscd.enable = true; + +# environment.systemPackages = with pkgs; [ +# --- IN SYSTEM PACKAGES SECTION --- +# ]; + +services.udev.packages = with pkgs; [ + yubikey-personalization +]; + +services.greetd = { + enable = true; + settings = { + initial_session.command = "sway"; + # initial_session.user ="swarsel"; + default_session.command = '' + ${pkgs.greetd.tuigreet}/bin/tuigreet \ + --time \ + --asterisks \ + --user-menu \ + --cmd sway + ''; + }; +}; + +environment.etc."greetd/environments".text = '' + sway + ''; + +} diff --git a/profiles/onett/hardware-configuration.nix b/profiles/onett/hardware-configuration.nix new file mode 100644 index 0000000..037bd7f --- /dev/null +++ b/profiles/onett/hardware-configuration.nix @@ -0,0 +1,33 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ata_piix" "usb_storage" "sd_mod" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/147e3682-eb15-4e96-9cac-4f2fb5888a69"; + fsType = "ext4"; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp7s0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp8s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/profiles/onett/home.nix b/profiles/onett/home.nix new file mode 100644 index 0000000..5521f3f --- /dev/null +++ b/profiles/onett/home.nix @@ -0,0 +1,127 @@ +{ config, pkgs, lib, fetchFromGitHub, ... }: + +{ + + + services.gpg-agent = { + enable = true; + enableSshSupport = true; + }; + + + home = { + username = "swarsel"; + homeDirectory = "/home/swarsel"; + stateVersion = "23.05"; # Please read the comment before changing. + keyboard.layout = "de"; + packages = with pkgs; [ + # xdg-utils + # nodejs_20 + ]; + }; + + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + # # waybar config + programs.waybar.settings.mainBar = { + cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}"; + temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon3/temp3_input"; + }; + + programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" + "mpris" + "custom/left-arrow-light" + "network" + "custom/left-arrow-dark" + "pulseaudio" + "custom/left-arrow-light" + "custom/pseudobat" + "battery" + "custom/left-arrow-dark" + "group/hardware" + "custom/left-arrow-light" + "clock#2" + "custom/left-arrow-dark" + "clock#1" + ]; + + + services.blueman-applet.enable = true; + + wayland.windowManager.sway= { + config = rec { + input = { + "1:1:AT_Translated_Set_2_keyboard" = { + xkb_layout = "us"; + xkb_options = "grp:win_space_toggle"; + # xkb_options = "ctrl:nocaps,grp:win_space_toggle"; + xkb_variant = "altgr-intl"; + }; + "2362:33538:ipad_keyboard_Keyboard" = { + xkb_layout = "us"; + xkb_options = "altwin:swap_lalt_lwin,ctrl:nocaps,grp:win_space_toggle"; + xkb_variant = "colemak_dh"; + }; + "36125:53060:splitkb.com_Kyria_rev3" = { + xkb_layout = "us"; + xkb_variant = "altgr-intl"; + }; + + "type:touchpad" = { + dwt = "enabled"; + tap = "enabled"; + natural_scroll = "enabled"; + middle_emulation = "enabled"; + }; + }; + + output = { + eDP-1 = { + mode = "1920x1080"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/lenovowp.png fill"; + position = "1920,0"; + }; + VGA-1 = { + mode = "1920x1080"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/lenovowp.png fill"; + position = "0,0"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+F2" = "exec brightnessctl set +5%"; + "${modifier}+F1"= "exec brightnessctl set 5%-"; + "XF86MonBrightnessUp" = "exec brightnessctl set +5%"; + "XF86MonBrightnessDown"= "exec brightnessctl set 5%-"; + "${modifier}+Ctrl+p" = "exec wl-mirror eDP-1"; + "XF86HomePage" = "exec wtype -P Escape -p Escape"; + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\""; + }; + keycodebindings = { + "94" = "exec wtype c"; + "Shift+94" = "exec wtype C"; + "Ctrl+94" = "exec wtype -M ctrl c -m ctrl"; + "Ctrl+Shift+94" = "exec wtype -M ctrl -M shift c -m ctrl -m shift"; + }; + + startup = [ + + { command = "nextcloud --background";} + { command = "spotify";} + { command = "discord --start-minimized";} + { command = "schildichat-desktop --disable-gpu-driver-bug-workarounds --hidden";} + { command = "ANKI_WAYLAND=1 anki";} + { command = "OBSIDIAN_USE_WAYLAND=1 obsidian";} + { command = "nm-applet";} + + ]; + }; + + extraConfig = " + "; + }; +} diff --git a/profiles/onett/nixos.nix b/profiles/onett/nixos.nix new file mode 100644 index 0000000..53db7a9 --- /dev/null +++ b/profiles/onett/nixos.nix @@ -0,0 +1,102 @@ +{ config, lib, pkgs, inputs, ... }: + +{ + + + imports = + [ + ./hardware-configuration.nix + ]; + + + services = { + greetd.settings.initial_session.user ="swarsel"; + xserver.videoDrivers = ["nvidia"]; + }; + + hardware = { + nvidia = { + modesetting.enable = true; + powerManagement.enable = true; + prime = { + intelBusId = "PCI:0:2:0"; + nvidiaBusId = "PCI:1:0:0"; + sync.enable = true; + }; + }; + pulseaudio.configFile = pkgs.runCommand "default.pa" {} '' + sed 's/module-udev-detect$/module-udev-detect tsched=0/' \ + ${pkgs.pulseaudio}/etc/pulse/default.pa > $out + ''; + bluetooth.enable = true; + }; + + stylix.image = ../../wallpaper/lenovowp.png; + + + stylix = { + base16Scheme = ../../wallpaper/swarsel.yaml; + # base16Scheme = "${pkgs.base16-schemes}/share/themes/shapeshifter.yaml"; + polarity = "dark"; + opacity.popups = 0.5; + cursor = { + package = pkgs.capitaine-cursors; + name = "capitaine-cursors"; + size = 16; + }; + fonts = { + sizes = { + terminal = 10; + applications = 11; + }; + serif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + sansSerif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + monospace = { + package = (pkgs.nerdfonts.override { fonts = [ "FiraCode"]; }); + name = "FiraCode Nerd Font Mono"; + }; + + emoji = { + package = pkgs.noto-fonts-emoji; + name = "Noto Color Emoji"; + }; + }; + }; + + + + + boot.loader.grub = { + enable = true; + device = "/dev/sda"; + useOSProber = true; + }; + + networking.hostName = "onett"; # Define your hostname. + + users.users.swarsel = { + isNormalUser = true; + description = "Leon S"; + extraGroups = [ "networkmanager" "wheel" "lp"]; + packages = with pkgs; []; + }; + + system.stateVersion = "23.05"; # Did you read the comment? + +} diff --git a/profiles/stand/home.nix b/profiles/stand/home.nix new file mode 100644 index 0000000..a610aa8 --- /dev/null +++ b/profiles/stand/home.nix @@ -0,0 +1,92 @@ +{ config, pkgs, lib, fetchFromGitHub, ... }: + +{ + + + services.gpg-agent = { + enable = true; + enableSshSupport = true; + }; + + + home = { + username = "homelen"; + homeDirectory = "/home/homelen"; + stateVersion = "23.05"; # Please read the comment before changing. + keyboard.layout = "us"; + packages = with pkgs; [ + # xdg-utils + # nodejs_20 + # element-desktop + ]; + }; + + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + services.blueman-applet.enable = true; + + # waybar config + programs.waybar.settings.mainBar = { + cpu.format = "{icon0} {icon1} {icon2} {icon3} {icon4} {icon5} {icon6} {icon7}"; + temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input"; + }; + + programs.waybar.settings.mainBar."custom/pseudobat"= { + format= ""; + on-click-right= "wlogout -p layer-shell"; + }; + programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" + "mpris" + "custom/left-arrow-light" + "network" + "custom/left-arrow-dark" + "pulseaudio" + "custom/left-arrow-light" + "custom/pseudobat" + "battery" + "custom/left-arrow-dark" + "group/hardware" + "custom/left-arrow-light" + "clock#2" + "custom/left-arrow-dark" + "clock#1" + ]; + + + wayland.windowManager.sway= { + config = rec { + input = { + "36125:53060:splitkb.com_Kyria_rev3" = { + xkb_layout = "us"; + xkb_variant = "altgr-intl"; + }; + }; + + output = { + DP-1 = { + mode = "2560x1440"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/standwp.png fill"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\""; + }; + + startup = [ + + { command = "nextcloud --background";} + { command = "spotify";} + { command = "discord --start-minimized";} + { command = "schildichat-desktop --disable-gpu-driver-bug-workarounds --hidden";} + { command = "ANKI_WAYLAND=1 anki";} + { command = "OBSIDIAN_USE_WAYLAND=1 obsidian";} + { command = "nm-applet";} + + ]; + }; + }; +} diff --git a/profiles/stand/nixos.nix b/profiles/stand/nixos.nix new file mode 100644 index 0000000..765f876 --- /dev/null +++ b/profiles/stand/nixos.nix @@ -0,0 +1,99 @@ +{ config, lib, pkgs, inputs, ... }: + +{ + + + imports = + [ + ./hardware-configuration.nix + ]; + + + services = { + getty.autologinUser = "homelen"; + greetd.settings.initial_session.user="homelen"; + }; + + stylix.image = ../../wallpaper/standwp.png; + + + stylix = { + base16Scheme = ../../wallpaper/swarsel.yaml; + # base16Scheme = "${pkgs.base16-schemes}/share/themes/shapeshifter.yaml"; + polarity = "dark"; + opacity.popups = 0.5; + cursor = { + package = pkgs.capitaine-cursors; + name = "capitaine-cursors"; + size = 16; + }; + fonts = { + sizes = { + terminal = 10; + applications = 11; + }; + serif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + sansSerif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + monospace = { + package = (pkgs.nerdfonts.override { fonts = [ "FiraCode"]; }); + name = "FiraCode Nerd Font Mono"; + }; + + emoji = { + package = pkgs.noto-fonts-emoji; + name = "Noto Color Emoji"; + }; + }; + }; + + + + + # Bootloader. + boot.loader.grub = { + enable = true; + devices = ["nodev" ]; + useOSProber = true; + }; + + # boot.kernelPackages = pkgs.linuxPackages_latest; + networking = { + hostName = "stand"; # Define your hostname. + enableIPv6 = false; + firewall.enable = false; + # networkmanager.enable = true; + }; + + hardware = { + bluetooth.enable = true; + }; + + users.users.homelen = { + isNormalUser = true; + description = "Leon S"; + extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ]; + packages = with pkgs; []; + }; + + environment.systemPackages = with pkgs; [ + ]; + + system.stateVersion = "23.05"; # Did you read the comment? Dont change this basically + +} diff --git a/profiles/surface/home.nix b/profiles/surface/home.nix new file mode 100644 index 0000000..139cfff --- /dev/null +++ b/profiles/surface/home.nix @@ -0,0 +1,177 @@ +{ config, pkgs, lib, fetchFromGitHub, ... }: + +{ + programs.home-manager.enable = true; + home.username = "leons"; + home.homeDirectory = "/home/leons"; + + home.stateVersion = "23.05"; # Please read the comment before changing. + + stylix.image = ../../wallpaper/surfacewp.png; + + + stylix = { + base16Scheme = ../../wallpaper/swarsel.yaml; + # base16Scheme = "${pkgs.base16-schemes}/share/themes/shapeshifter.yaml"; + polarity = "dark"; + opacity.popups = 0.5; + cursor = { + package = pkgs.capitaine-cursors; + name = "capitaine-cursors"; + size = 16; + }; + fonts = { + sizes = { + terminal = 10; + applications = 11; + }; + serif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + sansSerif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + monospace = { + package = (pkgs.nerdfonts.override { fonts = [ "FiraCode"]; }); + name = "FiraCode Nerd Font Mono"; + }; + + emoji = { + package = pkgs.noto-fonts-emoji; + name = "Noto Color Emoji"; + }; + }; + }; + + + + + nixpkgs = { + config = { + allowUnfree = true; + allowUnfreePredicate = (_: true); + }; + }; + services.xcape = { + enable = true; + mapExpression = { + Control_L = "Escape"; + }; + }; + #keyboard config + home.keyboard.layout = "us"; + + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + # waybar config + programs.waybar.settings.mainBar.cpu.format = "{icon0} {icon1} {icon2} {icon3}"; + + programs.waybar.settings.mainBar.temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon3/temp3_input"; + programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" "mpris" "custom/left-arrow-light" + "network" + "custom/left-arrow-dark" + "pulseaudio" + "custom/left-arrow-light" + "battery" + "custom/left-arrow-dark" + "temperature" + "custom/left-arrow-light" + "disk" + "custom/left-arrow-dark" + "memory" + "custom/left-arrow-light" + "cpu" + "custom/left-arrow-dark" + "tray" + "custom/left-arrow-light" + "clock#2" + "custom/left-arrow-dark" + "clock#1" ]; + services.blueman-applet.enable = true; + home.packages = with pkgs; [ + # nixgl.auto.nixGLDefault + evince + # nodejs_20 + + # messaging + # we use gomuks for RAM preservation, but keep schildi around for files and images + ]; + + programs.zsh.initExtra = " +export GPG_TTY=\"$(tty)\" +export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) +gpgconf --launch gpg-agent + "; + + # sway config + wayland.windowManager.sway= { + config = rec { + input = { + "*" = { + xkb_layout = "us"; + xkb_options = "ctrl:nocaps,grp:win_space_toggle"; + xkb_variant = "altgr-intl"; + }; + "type:touchpad" = { + dwt = "enabled"; + tap = "enabled"; + natural_scroll = "enabled"; + middle_emulation = "enabled"; + }; + }; + + output = { + eDP-1 = { + mode = "2160x1440@59.955Hz"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/surfacewp.png fill"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+F2" = "exec brightnessctl set +5%"; + "${modifier}+F1"= "exec brightnessctl set 5%-"; + "${modifier}+n" = "exec sway output eDP-1 transform normal, splith"; + "${modifier}+Ctrl+p" = "exec nixGL wl-mirror eDP-1"; + "${modifier}+t" = "exec sway output eDP-1 transform 90, splitv"; + "${modifier}+XF86AudioLowerVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+XF86AudioRaiseVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkgomuks.sh\""; + }; + + startup = [ + { command = "sleep 60 && nixGL nextcloud --background";} + # { command = "sleep 60 && nixGL spotify";} + { command = "sleep 60 && nixGL discord --start-minimized -enable-features=UseOzonePlatform -ozone-platform=wayland";} + # { command = "sleep 60 && nixGL schildichat-desktop --hidden";} + { command = "sleep 60 && nixGL syncthingtray --wait"; } + { command = "sleep 60 && ANKI_WAYLAND=1 nixGL anki";} + { command = "nm-applet --indicator";} + { command = "sleep 60 && OBSIDIAN_USE_WAYLAND=1 nixGL obsidian -enable-features=UseOzonePlatform -ozone-platform=wayland";} + ]; + + keycodebindings = { + "124" = "exec systemctl suspend"; + }; + }; + + extraConfig = " + exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05 map_to_output eDP-1 + exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05_Stylus map_to_output eDP-1 + "; + }; +} diff --git a/profiles/threed/home.nix b/profiles/threed/home.nix new file mode 100644 index 0000000..a69d67a --- /dev/null +++ b/profiles/threed/home.nix @@ -0,0 +1,102 @@ +{ config, pkgs, lib, fetchFromGitHub, ... }: + +{ + + + + home = { + username = "swarsel"; + homeDirectory = "/home/swarsel"; + stateVersion = "23.05"; # Please read the comment before changing. + keyboard.layout = "us"; + packages = with pkgs; [ + # xdg-utils + # nodejs_20 + ]; + }; + + sops.age.sshKeyPaths = [ "${config.home.homeDirectory}/.ssh/sops" ]; + + programs.waybar.settings.mainBar = { + cpu.format = "{icon0} {icon1} {icon2} {icon3}"; + temperature.hwmon-path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp3_input"; + }; + + programs.waybar.settings.mainBar.modules-right = ["custom/outer-left-arrow-dark" + "mpris" + "custom/left-arrow-light" + "network" + "custom/left-arrow-dark" + "pulseaudio" + "custom/left-arrow-light" + "custom/pseudobat" + "battery" + "custom/left-arrow-dark" + "group/hardware" + "custom/left-arrow-light" + "clock#2" + "custom/left-arrow-dark" + "clock#1" + ]; + + + wayland.windowManager.sway= { + config = rec { + input = { + "*" = { + xkb_layout = "us"; + xkb_options = "grp:win_space_toggle"; + xkb_variant = "altgr-intl"; + }; + "type:touchpad" = { + dwt = "enabled"; + tap = "enabled"; + natural_scroll = "enabled"; + middle_emulation = "enabled"; + }; + }; + + output = { + eDP-1 = { + mode = "2160x1440@59.955Hz"; + scale = "1"; + bg = "~/.dotfiles/wallpaper/surfacewp.png fill"; + }; + }; + + keybindings = let + modifier = config.wayland.windowManager.sway.config.modifier; + in { + "${modifier}+F2" = "exec brightnessctl set +5%"; + "${modifier}+F1"= "exec brightnessctl set 5%-"; + "${modifier}+n" = "exec sway output eDP-1 transform normal, splith"; + "${modifier}+Ctrl+p" = "exec wl-mirror eDP-1"; + "${modifier}+t" = "exec sway output eDP-1 transform 90, splitv"; + "${modifier}+XF86AudioLowerVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+XF86AudioRaiseVolume" = "exec grim -g \"$(slurp)\" -t png - | wl-copy -t image/png"; + "${modifier}+w" = "exec \"bash ~/.dotfiles/scripts/checkschildi.sh\""; + }; + + startup = [ + + { command = "nextcloud --background";} + { command = "spotify";} + { command = "discord --start-minimized";} + { command = "schildichat-desktop --disable-gpu-driver-bug-workarounds --hidden";} + { command = "ANKI_WAYLAND=1 anki";} + { command = "OBSIDIAN_USE_WAYLAND=1 obsidian";} + { command = "nm-applet";} + + ]; + + keycodebindings = { + "124" = "exec systemctl suspend"; + }; + }; + + extraConfig = " + exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05 map_to_output eDP-1 + exec swaymsg input 7062:6917:NTRG0001:01_1B96:1B05_Stylus map_to_output eDP-1 + "; + }; +} diff --git a/profiles/threed/nixos.nix b/profiles/threed/nixos.nix new file mode 100644 index 0000000..7e91cf4 --- /dev/null +++ b/profiles/threed/nixos.nix @@ -0,0 +1,98 @@ +{ config, lib, pkgs, inputs, ... }: + +{ + + imports = + [ + ./hardware-configuration.nix + ]; + + + services = { + getty.autologinUser = "swarsel"; + greetd.settings.initial_session.user="swarsel"; + }; + + # Bootloader + boot = { + loader.systemd-boot.enable = lib.mkForce false; + lanzaboote = { + enable = true; + pkiBundle = "/etc/secureboot"; + }; + loader.efi.canTouchEfiVariables = true; + # use bootspec instead of lzbt for secure boot. This is not a generally needed setting + bootspec.enable = true; + # kernelPackages = pkgs.linuxPackages_latest; + }; + + networking = { + hostName = "threed"; + enableIPv6 = false; + firewall.enable = false; + }; + + stylix.image = ../../wallpaper/surfacewp.png; + + + stylix = { + base16Scheme = ../../wallpaper/swarsel.yaml; + # base16Scheme = "${pkgs.base16-schemes}/share/themes/shapeshifter.yaml"; + polarity = "dark"; + opacity.popups = 0.5; + cursor = { + package = pkgs.capitaine-cursors; + name = "capitaine-cursors"; + size = 16; + }; + fonts = { + sizes = { + terminal = 10; + applications = 11; + }; + serif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + sansSerif = { + # package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; }); + package = pkgs.cantarell-fonts; + # package = pkgs.montserrat; + name = "Cantarell"; + # name = "FiraCode Nerd Font Propo"; + # name = "Montserrat"; + }; + + monospace = { + package = (pkgs.nerdfonts.override { fonts = [ "FiraCode"]; }); + name = "FiraCode Nerd Font Mono"; + }; + + emoji = { + package = pkgs.noto-fonts-emoji; + name = "Noto Color Emoji"; + }; + }; + }; + + + + + users.users.swarsel = { + isNormalUser = true; + description = "Leon S"; + extraGroups = [ "networkmanager" "wheel" "lp" "audio" "video" ]; + packages = with pkgs; []; + }; + + environment.systemPackages = with pkgs; [ + ]; + + system.stateVersion = "23.05"; + +} diff --git a/programs/emacs/custom.el b/programs/emacs/custom.el new file mode 100644 index 0000000..7e55da5 --- /dev/null +++ b/programs/emacs/custom.el @@ -0,0 +1,45 @@ +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(browse-url-browser-function 'browse-url-firefox) + '(custom-safe-themes + '("7ec8fd456c0c117c99e3a3b16aaf09ed3fb91879f6601b1ea0eeaee9c6def5d9" + "badd1a5e20bd0c29f4fe863f3b480992c65ef1fa63951f59aa5d6b129a3f9c4c" + "2e05569868dc11a52b08926b4c1a27da77580daa9321773d92822f7a639956ce" + default)) + '(org-agenda-files '("/home/swarsel/Calendars/leon_cal.org")) + '(send-mail-function 'sendmail-send-it) + '(warning-suppress-log-types + '(((python python-shell-completion-native-turn-on-maybe)) (comp) + ((defvaralias losing-value org-tab-first-hook)))) + '(warning-suppress-types '(((defvaralias losing-value org-tab-first-hook))))) +;; (custom-set-faces +;; ;; custom-set-faces was added by Custom. +;; ;; If you edit it by hand, you could mess it up, so be careful. +;; ;; Your init file should contain only one such instance. +;; ;; If there is more than one, they won't work right. +;; '(evil-goggles-change-face ((t (:inherit diff-removed)))) +;; '(evil-goggles-delete-face ((t (:inherit diff-removed)))) +;; '(evil-goggles-paste-face ((t (:inherit diff-added)))) +;; '(evil-goggles-undo-redo-add-face ((t (:inherit diff-added)))) +;; '(evil-goggles-undo-redo-change-face ((t (:inherit diff-changed)))) +;; '(evil-goggles-undo-redo-remove-face ((t (:inherit diff-removed)))) +;; '(evil-goggles-yank-face ((t (:inherit diff-changed)))) +;; '(flycheck-posframe-border-face ((t (:foreground "darkgrey")))) +;; '(ivy-current-match ((t (:extend t :background "dark cyan" :foreground "black")))) +;; '(org-block ((t (:inherit fixed-pitch :extend t :background "#20282F")))) +;; '(org-block-begin-line ((t (:inherit org-block :extend t :background "#20282F" :foreground "DeepSkyBlue4" :weight bold))))) +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(evil-goggles-change-face ((t (:inherit diff-removed)))) + '(evil-goggles-delete-face ((t (:inherit diff-removed)))) + '(evil-goggles-paste-face ((t (:inherit diff-added)))) + '(evil-goggles-undo-redo-add-face ((t (:inherit diff-added)))) + '(evil-goggles-undo-redo-change-face ((t (:inherit diff-changed)))) + '(evil-goggles-undo-redo-remove-face ((t (:inherit diff-removed)))) + '(evil-goggles-yank-face ((t (:inherit diff-changed))))) diff --git a/programs/emacs/early-init.el b/programs/emacs/early-init.el new file mode 100644 index 0000000..87fb359 --- /dev/null +++ b/programs/emacs/early-init.el @@ -0,0 +1,39 @@ +(setq gc-cons-threshold most-positive-fixnum + gc-cons-percentage 0.6) + +(tool-bar-mode 0) +(menu-bar-mode 0) +(scroll-bar-mode 0) + +(setq frame-inhibit-implied-resize t) + + (setq default-frame-alist + (append + (list + '(undecorated . t) + '(min-height . 1) + '(height . 42) + '(min-width . 1) + '(width . 100) + '(vertical-scroll-bars . nil) + '(internal-border-width . 10) + '(tool-bar-lines . 0) + '(menu-bar-lines . 0)))) + + (setq-default left-margin-width 1 + right-margin-width 1) + + (add-hook + 'after-make-frame-functions + (defun setup-blah-keys (frame) + (with-selected-frame frame + (when (display-graphic-p) + (define-key input-decode-map (kbd "C-i") [C-i]) + (define-key input-decode-map (kbd "C-[") [C-lsb]) + (define-key input-decode-map (kbd "C-m") [C-m]) + )))) + +(defun swarsel/last-buffer () (interactive) (switch-to-buffer nil)) +(global-set-key (kbd "") #'swarsel/last-buffer) + +(setq comp-deferred-compilation nil) diff --git a/programs/emacs/init.el b/programs/emacs/init.el new file mode 100644 index 0000000..4594f35 --- /dev/null +++ b/programs/emacs/init.el @@ -0,0 +1,1848 @@ +;; The default is 800 kilobytes. Measured in bytes. +(setq gc-cons-threshold (* 50 1000 1000)) + +;; use UTF-8 everywhere +(set-language-environment "UTF-8") + +;; set default font size +(defvar swarsel/default-font-size 130) +(setq swarsel-standard-font "FiraCode Nerd Font Mono" + swarsel-alt-font "FiraCode Nerd Font Mono") + +;; set Nextcloud directory for journals etc. +(setq swarsel-sync-directory "~/Nextcloud" + swarsel-emacs-directory "~/.emacs.d" + swarsel-dotfiles-directory "~/.dotfiles" + swarsel-projects-directory "~/Documents/GitHub") + +(setq swarsel-emacs-org-filepath (expand-file-name "Emacs.org" swarsel-dotfiles-directory) + swarsel-nix-org-filepath (expand-file-name "Nix.org" swarsel-dotfiles-directory)) + + +;; set Emacs main configuration .org names +(setq swarsel-emacs-org-file "Emacs.org" + swarsel-anki-org-file "Anki.org" + swarsel-tasks-org-file "Tasks.org" + swarsel-archive-org-file "Archive.org" + swarsel-org-folder-name "org" + swarsel-obsidian-daily-folder-name "⭐ Personal/Journal" + swarsel-obsidian-folder-name "Obsidian" + swarsel-obsidian-vault-name "Main") + + +;; set directory paths +(setq swarsel-org-directory (expand-file-name swarsel-org-folder-name swarsel-sync-directory)) ; path to org folder +(setq swarsel-obsidian-directory (expand-file-name swarsel-obsidian-folder-name swarsel-sync-directory)) ; path to obsidian +(setq swarsel-obsidian-vault-directory (expand-file-name swarsel-obsidian-vault-name swarsel-obsidian-directory)) ; path to obsidian vault +(setq swarsel-obsidian-daily-directory (expand-file-name swarsel-obsidian-daily-folder-name swarsel-obsidian-vault-directory)) ; path to obsidian daily folder + +;; filepaths to certain documents +(setq swarsel-org-anki-filepath (expand-file-name swarsel-anki-org-file swarsel-org-directory) ; path to anki export file + swarsel-org-tasks-filepath (expand-file-name swarsel-tasks-org-file swarsel-org-directory) + swarsel-org-archive-filepath (expand-file-name swarsel-archive-org-file swarsel-org-directory)) + +;; set paths to authentication files (forge) +;; (setq auth-source-pass-filename "~/.local/share/password-store" +(setq auth-sources '( "~/.emacs.d/.caldav" "~/.emacs.d/.authinfo.gpg") + auth-source-cache-expiry nil) ; default is 2h + +;; set pandoc for markdown compilation +(setq markdown-command "pandoc") + +;; set org-caldav-sync-initalization +(setq swarsel-caldav-synced 0) + +;; Change the user-emacs-directory to keep unwanted things out of ~/.emacs.d +(setq user-emacs-directory (expand-file-name "~/.cache/emacs/") + url-history-file (expand-file-name "url/history" user-emacs-directory)) + +;; Use no-littering to automatically set common paths to the new user-emacs-directory +(use-package no-littering) +(setq custom-file (expand-file-name "programs/emacs/custom.el" swarsel-dotfiles-directory)) +(load custom-file t) + +(defalias 'yes-or-no-p 'y-or-n-p) +;;(setq-default show-trailing-whitespace t) +(add-hook 'before-save-hook 'delete-trailing-whitespace) +(global-hl-line-mode 1) +;; (setq redisplay-dont-pause t) ;; obsolete +(delete-selection-mode 1) +(pixel-scroll-precision-mode 1) +(setq vc-follow-symlinks t) +(setq require-final-newline t) +(winner-mode 1) +;; less noise when compiling elisp +(setq byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local)) +(setq native-comp-async-report-warnings-errors nil) +(setq load-prefer-newer t) + +;; disable a keybind that does more harm than good +(global-set-key [remap suspend-frame] + (lambda () + (interactive) + (message "This keybinding is disabled (was 'suspend-frame')"))) + +;; (scroll-bar-mode -1) +;; (tool-bar-mode -1) +;; (tooltip-mode -1) +;; (menu-bar-mode -1) +(setq visible-bell nil) +(setq initial-major-mode 'fundamental-mode + initial-scratch-message nil) + +(setq-default indent-tabs-mode nil + tab-width 2) + + (setq tab-always-indent 'complete) + +(use-package highlight-indent-guides + :hook (prog-mode . highlight-indent-guides-mode) + :init + (setq highlight-indent-guides-method 'character) + (setq highlight-indent-guides-character "‖") + (setq highlight-indent-guides-responsive 'top) + ) + +(setq scroll-step 1 + scroll-margin 4 + scroll-conservatively 5) + +(defun swarsel/with-buffer-name-prompt-and-make-subdirs () + (let ((parent-directory (file-name-directory buffer-file-name))) + (when (and (not (file-exists-p parent-directory)) + (y-or-n-p (format "Directory `%s' does not exist! Create it? " parent-directory))) + (make-directory parent-directory t)))) + +(add-to-list 'find-file-not-found-functions #'swarsel/with-buffer-name-prompt-and-make-subdirs) + +;; Emulate vim in emacs + (use-package evil + :init + (setq evil-want-integration t) ; loads evil + (setq evil-want-keybinding nil) ; loads "helpful bindings" for other modes + (setq evil-want-C-u-scroll t) ; scrolling using C-u + (setq evil-want-C-i-jump nil) ; jumping with C-i + (setq evil-want-Y-yank-to-eol t) ; give Y some utility + (setq evil-shift-width 2) ; uniform indent + (setq evil-respect-visual-line-mode t) ; i am torn on this one + ; sane splitting + (setq evil-split-window-below t) + (setq evil-vsplit-window-right t) + :config + (evil-mode 1) + (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state) ; alternative for exiting insert mode + (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join) ; dont show help but instead do normal vim delete backwards + + ;; evil undo system + (evil-set-undo-system 'undo-tree) + ;; Use visual line motions even outside of visual-line-mode buffers + ;; (evil-global-set-key 'motion "j" 'evil-next-visual-line) + ;; (evil-global-set-key 'motion "k" 'evil-previous-visual-line) + + ;; Don't use evil-mode in these contexts, or use it in a specific mode + (evil-set-initial-state 'messages-buffer-mode 'emacs) + (evil-set-initial-state 'dashboard-mode 'emacs) + (evil-set-initial-state 'dired-mode 'emacs) + (evil-set-initial-state 'cfw:details-mode 'emacs) + (evil-set-initial-state 'Custom-mode 'emacs) ; god knows why this mode is in uppercase + + ; require a specific evil state + (evil-set-initial-state 'mu4e-headers-mode 'normal) + (evil-set-initial-state 'python-inferior-mode 'normal) + (add-hook 'org-capture-mode-hook 'evil-insert-state) + (add-to-list 'evil-buffer-regexps '("COMMIT_EDITMSG" . insert))) + + ;; Evil configuration for different modes + (use-package evil-collection + :after evil + :config + (evil-collection-init) + (setq forge-add-default-bindings nil)) + + + + (use-package evil-snipe + :after evil + :demand + :config + (evil-snipe-mode +1) + (evil-snipe-override-mode +1)) + +(use-package evil-cleverparens) + + +(use-package evil-surround) + + (use-package evil-goggles + :after evil + :demand + :init + (setq evil-goggles-duration 0.05) + :config + (push '(evil-operator-eval + :face evil-goggles-yank-face + :switch evil-goggles-enable-yank + :advice evil-goggles--generic-async-advice) + evil-goggles--commands) + (evil-goggles-mode) + (evil-goggles-use-diff-faces) + ) + +(use-package undo-tree + ;; :init (global-undo-tree-mode) + :bind (:map undo-tree-visualizer-mode-map + ("h" . undo-tree-visualize-switch-branch-left) + ("l" . undo-tree-visualize-switch-branch-left) + ("j" . undo-tree-visualize-redo) + ("k" . undo-tree-visualize-undo)) + :config + (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo"))) + ) +(add-hook 'prog-mode-hook 'undo-tree-mode) +(add-hook 'text-mode-hook 'undo-tree-mode) +(add-hook 'org-mode-hook 'undo-tree-mode) +(add-hook 'latex-mode-hook 'undo-tree-mode) + +(let ((backup-dir "~/tmp/emacs/backups") + (auto-saves-dir "~/tmp/emacs/auto-saves/")) + (dolist (dir (list backup-dir auto-saves-dir)) + (when (not (file-directory-p dir)) + (make-directory dir t))) + (setq backup-directory-alist `(("." . ,backup-dir)) + auto-save-file-name-transforms `((".*" ,auto-saves-dir t)) + auto-save-list-file-prefix (concat auto-saves-dir ".saves-") + tramp-backup-directory-alist `((".*" . ,backup-dir)) + tramp-auto-save-directory auto-saves-dir)) + +(setq backup-by-copying t ; Don't delink hardlinks + delete-old-versions t ; Clean up the backups + version-control t ; Use version numbers on backups, + kept-new-versions 5 ; keep some new versions + kept-old-versions 2) ; and some old ones, too + +;; Make ESC quit prompts +(global-set-key (kbd "") 'keyboard-escape-quit) + +;; Set up general keybindings +(use-package general + :config + (general-create-definer swarsel/leader-keys + :keymaps '(normal insert visual emacs) + :prefix "SPC" + :global-prefix "C-SPC") + + (swarsel/leader-keys + "t" '(:ignore t :which-key "toggles") + "ts" '(hydra-text-scale/body :which-key "scale text") + "tl" '(display-line-numbers-mode :which-key "line numbers") + "to" '(olivetti-mode :wk "olivetti") + "td" '(darkroom-tentative-mode :wk "darkroom") + "tw" '((lambda () (interactive) (toggle-truncate-lines)) :which-key "line wrapping") + "m" '(:ignore m :which-key "modes/programs") + "mm" '((lambda () (interactive) (mu4e)) :which-key "mu4e") + "mg" '((lambda () (interactive) (magit-list-repositories)) :which-key "magit-list-repos") + "mc" '((lambda () (interactive) (swarsel/open-calendar)) :which-key "calendar") + "mp" '(popper-toggle :which-key "popper") + "md" '(dirvish :which-key "dirvish") + "c" '(:ignore c :which-key "capture") + "cj" '((lambda () (interactive) (org-capture nil "jj")) :which-key "journal") + "cs" '(markdown-download-screenshot :which-key "screenshot") + "l" '(:ignore l :which-key "links") + "le" '((lambda () (interactive) (find-file swarsel-emacs-org-filepath)) :which-key "Emacs.org") + "ls" '((lambda () (interactive) (find-file "/smb:Swarsel@192.168.1.3:")) :which-key "Server") + "lo" '(dired swarsel-obsidian-vault-directory :which-key "obsidian") + "la" '((lambda () (interactive) (find-file swarsel-org-anki-filepath)) :which-key "anki") + "ln" '((lambda () (interactive) (find-file swarsel-nix-org-filepath)) :which-key "Nix.org") + "lp" '((lambda () (interactive) (projectile-switch-project)) :which-key "switch project") + "lg" '((lambda () (interactive) (magit-list-repositories)) :which-key "list git repos") + "a" '(:ignore a :which-key "anki") + "ap" '(anki-editor-push-tree :which-key "push new cards") + "an" '((lambda () (interactive) (org-capture nil "a")) :which-key "new card") + "as" '(swarsel-anki-set-deck-and-notetype :which-key "change deck and notetype") + "h" '(:ignore h :which-key "help") + "hy" '(yas-describe-tables :which-key "yas tables") + "hb" '(embark-bindings :which-key "current key bindings") + "h" '(:ignore t :which-key "describe") + "he" 'view-echo-area-messages + "hf" 'describe-function + "hF" 'describe-face + "hl" '(view-lossage :which-key "show command keypresses") + "hL" 'find-library + "hm" 'describe-mode + "hk" 'describe-key + "hK" 'describe-keymap + "hp" 'describe-package + "hv" 'describe-variable + "hd" 'devdocs-lookup + "w" '(:ignore t :which-key "window") + "wl" 'windmove-right + "wh" 'windmove-left + "wk" 'windmove-up + "wj" 'windmove-down + "wr" 'winner-redo + "wd" 'delete-window + "w=" 'balance-windows-area + "wD" 'kill-buffer-and-window + "wu" 'winner-undo + "wr" 'winner-redo + "w/" 'evil-window-vsplit + "w-" 'evil-window-split + "wm" '(delete-other-windows :wk "maximize") + )) + +;; General often used hotkeys +(general-define-key + "C-M-a" (lambda () (interactive) (org-capture nil "a")) ; make new anki card + "C-M-d" 'swarsel-obsidian-daily ; open daily obsidian file and create if not exist + "C-M-S" 'swarsel-anki-set-deck-and-notetype ; switch deck and notetye for new anki cards + "C-M-s" 'markdown-download-screenshot ; wrapper for org-download-screenshot + "C-c d" 'duplicate-line ; duplicate line on CURSOR + "C-M-j" 'consult-buffer + "C-s" 'consult-line + ) + +(setq inhibit-startup-message t) + +;; (set-fringe-mode nil) ; Give some breathing room + +;; Increase undo limit and allow for more fine grained undo, base emacs deletes way too much on undo +(setq undo-limit 80000000 + evil-want-fine-undo t + auto-save-default t + password-cache-expiry nil + ) + +;; (display-time-mode 1) +(global-subword-mode 1) ; Iterate through CamelCase words + +(use-package rainbow-mode + :config (rainbow-mode)) + +(setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; one line at a time +(setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling +(setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse + + +(add-hook 'prog-mode-hook 'display-line-numbers-mode) +(add-hook 'text-mode-hook 'display-line-numbers-mode) + +;; (defun swarsel/font-setup (frame) + ;; (set-face-attribute 'default nil :font swarsel-standard-font :height swarsel/default-font-size) + ;; ;; Set the fixed pitch face - basically normal text + ;; (set-face-attribute 'fixed-pitch nil :font swarsel-standard-font :height 140) + ;; ;; Set the variable pitch face - basically headers etc + ;; (set-face-attribute 'variable-pitch nil :font swarsel-alt-font :height 100 :weight 'regular) + ;; (set-face-attribute 'region nil :foreground "cyan" :background "gray40" :weight 'bold) + ;; ;; (remove-hook 'after-make-frame-functions #'swarsel/font-setup) + ;; ) + + ;; (add-hook 'after-make-frame-functions #'swarsel/font-setup) + +;; (defun swarsel/font-setup (frame) +(dolist (face '(default fixed-pitch)) + (set-face-attribute face nil + :font "FiraCode Nerd Font Mono")) + (add-to-list 'default-frame-alist '(font . "FiraCode Nerd Font Mono")) + + (set-face-attribute 'default nil :height 100) + (set-face-attribute 'fixed-pitch nil :height 1.0) + + (set-face-attribute 'variable-pitch nil + :family "IBM Plex Sans" + :weight 'regular + :height 1.06) + ;; (enable-theme 'doom-city-lights) + ;; ) + + ;; (add-hook 'after-make-frame-functions #'swarsel/font-setup) + +(use-package doom-themes + :init (load-theme 'doom-city-lights t)) + +(use-package solaire-mode + :init (solaire-global-mode +1)) + +;; (set-frame-parameter (selected-frame) 'alpha '(95 . 95)) +;; (add-to-list 'default-frame-alist '(alpha . (95 . 95))) +;; (set-frame-parameter (selected-frame) 'fullscreen 'maximized) +;; (add-to-list 'default-frame-alist '(fullscreen . maximized)) + +(use-package mixed-pitch + :custom + (mixed-pitch-set-height nil) + (mixed-pitch-variable-pitch-cursor nil) + :hook + (text-mode . mixed-pitch-mode)) + +(use-package nerd-icons) + +;; Adds a more beautiful modeline with less clutter +(use-package doom-modeline + :init (doom-modeline-mode) + :custom + ((doom-modeline-height 22) + (doom-modeline-indent-info t))) + +;; Generally show line numbers +(column-number-mode) + +;; (unless (string-match-p "^Power N/A" (battery)) ; On laptops... +;; (display-battery-mode 1)) + +(use-package vertico + :custom + (vertico-scroll-margin 0) + (vertico-count 10) + (vertico-resize t) + (vertico-cycle t) + :init + (vertico-mode) + (vertico-mouse-mode)) + + (use-package vertico-directory + :ensure nil + :after vertico + :bind (:map vertico-map + ("RET" . vertico-directory-enter) + ("DEL" . vertico-directory-delete-char) + ("M-DEL" . vertico-directory-delete-word)) + ;; Tidy shadowed file names + :hook (rfn-eshadow-update-overlay . vertico-directory-tidy)) + + (use-package orderless + :custom + (completion-styles '(orderless flex basic)) + (completion-category-overrides '((file (styles . (partial-completion))) + (eglot (styles orderless))))) + + (use-package consult + :config + (setq consult-fontify-max-size 1024) + :bind + ("C-x b" . consult-buffer) + ("C-c " . consult-global-mark) + ("C-c C-a" . consult-org-agenda) + ("C-x O" . consult-outline) + ("M-g M-g" . consult-goto-line) + ("M-g i" . consult-imenu) + ("M-s s" . consult-line) + ("M-s M-s" . consult-line-multi)) + + (use-package embark + :bind + (("C-." . embark-act) + ("M-." . embark-dwim) + ("C-h B" . embark-bindings)) + :custom + (prefix-help-command #'embark-prefix-help-command) + (embark-quit-after-action '((t . nil))) + :config + (add-to-list 'display-buffer-alist + '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" + nil + (window-parameters (mode-line-format . none))))) + + (use-package embark-consult + :after (embark consult) + :demand t ; only necessary if you have the hook below + ;; if you want to have consult previews as you move around an + ;; auto-updating embark collect buffer + :hook + (embark-collect-mode . consult-preview-at-point-mode)) + + (use-package marginalia + :after vertico + :init + (marginalia-mode) + (setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))) + +(use-package nerd-icons-completion + :after (marginalia nerd-icons) + :hook (marginalia-mode . nerd-icons-completion-marginalia-setup) + :init + (nerd-icons-completion-mode)) + +;; (use-package ivy +;; :init (ivy-mode 1) +;; :diminish +;; :bind (("C-s" . swiper) ; call swiper (find tool) +;; :map ivy-minibuffer-map +;; ;("TAB" . ivy-alt-done) ; autocomplete +;; ("C-l" . ivy-alt-done) +;; ("C-" . ivy-alt-done) ; for kyria +;; ("C-h" . counsel-up-directory) ; for kyria +;; ("C-" . counsel-up-directory) ; for kyria +;; ("C-j" . ivy-next-line) ; go up and down in ivy using vim keys +;; ("C-" . ivy-next-line) ; for kyria +;; ("C-k" . ivy-previous-line) +;; ("C-" . ivy-previous-line) ; for kyria +;; :map ivy-switch-buffer-map +;; ("C-k" . ivy-previous-line) +;; ("C-" . ivy-previous-line) ; for kyria +;; ("C-l" . ivy-done) +;; ("C-" . ivy-done) ; for kyria +;; ("C-d" . ivy-switch-buffer-kill) +;; :map ivy-reverse-i-search-map +;; ("C-k" . ivy-previous-line) +;; ("C-" . ivy-previous-line) ; for kyria +;; ("C-d" . ivy-reverse-i-search-kill)) +;; :config +;; (setq ivy-use-virtual-buffers t) +;; (setq ivy-count-format "(%d/%d) ") +;; (setq ivy-wrap t)) + +;; ;; More information about functions in ivy-mode +;; (use-package ivy-rich +;; :init +;; (ivy-rich-mode 1)) + +;; (use-package counsel +;; :init (counsel-mode 1) +;; :bind (("C-M-j" . counsel-switch-buffer) +;; ("M-x" . counsel-M-x) +;; ("C-x b" . counsel-ibuffer) +;; ("C-x C-f" . counsel-find-file) +;; :map minibuffer-local-map +;; ("C-r" . 'counsel-minibuffer-history)) +;; :config +;; (setq ivy-initial-inputs-alist nil)) + +(use-package which-key + :init (which-key-mode) + :diminish which-key-mode + :config + (setq which-key-idle-delay 0.3)) + +;; (use-package helpful +;; :custom +;; (counsel-describe-function-function #'helpful-callable) +;; (counsel-describe-variable-function #'helpful-variable) +;; :bind +;; ([remap describe-function] . counsel-describe-function) +;; ([remap describe-command] . helpful-command) +;; ([remap describe-variable] . counsel-describe-variable) +;; ([remap describe-key] . helpful-key)) + +(use-package helpful + :custom + (help-select-window t) + :bind + (("C-h f" . helpful-callable) + ("C-h v" . helpful-variable) + ("C-h k" . helpful-key) + ("C-h C-." . helpful-at-point))) + +(use-package hydra) + +;; change the text size of the current buffer +(defhydra hydra-text-scale (:timeout 4) + "scale text" + ("j" text-scale-increase "in") + ("k" text-scale-decrease "out") + ("f" nil "finished" :exit t)) + +(use-package ligature + :config + (ligature-set-ligatures 'prog-mode + '("|||>" "<|||" "<==>" "" "---" "-<<" + "<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->" + "<--" "<-<" "<<=" "<<-" "<<<" "<+>" "" "###" "#_(" "..<" + "..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~=" + "~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|" + "[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:" + ">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:" + "<$" "<=" "<>" "<-" "<<" "<+" "" "++" "?:" "?=" + "?." "??" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)" "\\\\" + "://" ";;")) + (global-ligature-mode t)) + +(use-package popper +:bind (("M-[" . popper-toggle)) +:init +(setq popper-reference-buffers + '("\\*Messages\\*" + ("\\*Warnings\\*" . hide) + "Output\\*$" + "\\*Async Shell Command\\*" + "\\*Async-native-compile-log\\*" + help-mode + helpful-mode + "*Occur*" + "*scratch*" + "*julia*" + "*Python*" + ;; ("*tex-shell*" . hide) + (compilation-mode . hide))) +(popper-mode +1) +(popper-echo-mode +1)) + +(use-package shackle +:config +(setq shackle-rules '(("*Messages*" :select t :popup t :align right :size 0.3) + ("*Warnings*" :ignore t :popup t :align right :size 0.3) + ("*Occur*" :select t :popup t :align below :size 0.2) + ("*scratch*" :select t :popup t :align below :size 0.2) + ("*Python*" :select t :popup t :align below :size 0.2) + ("*tex-shell*" :ignore t :popup t :align below :size 0.2) + (helpful-mode :select t :popup t :align right :size 0.35) + (help-mode :select t :popup t :align right :size 0.4))) +(shackle-mode 1)) + +(setq-default indicate-buffer-boundaries t) + +(defun swarsel/org-mode-setup () + (org-indent-mode) + (variable-pitch-mode 1) + ;;(auto-fill-mode 0) + (setq display-line-numbers-type 'relative + display-line-numbers-current-absolute 1 + display-line-numbers-width-start nil + display-line-numbers-width 6 + display-line-numbers-grow-only 1) + (add-hook 'org-tab-first-hook 'org-end-of-line) + (visual-line-mode 1)) +;; (setq evil-auto-indent nil) +;;(diminish org-indent-mode) + +(defun swarsel/org-font-setup () + ;; Replace list hyphen with dot + (font-lock-add-keywords 'org-mode + '(("^ *\\([-]\\) " + (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))) + +(use-package org + ;;:diminish (org-indent-mode) + :hook (org-mode . swarsel/org-mode-setup) + :bind ("C-" . org-fold-outer) + :config + (setq org-ellipsis " ⤵" + org-hide-emphasis-markers t) + (setq org-startup-folded t) + (setq org-support-shift-select t) + (setq org-agenda-start-with-log-mode t) + (setq org-log-done 'time) + (setq org-log-into-drawer t) + (setq org-startup-with-inline-images t) + (setq org-image-actual-width nil) + (setq org-format-latex-options '(:foreground "White" :background default :scale 2.0 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0 :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))) + + ;; (setq org-agenda-files + ;; '(swarsel-org-tasks-filepath + ;; swarsel-org-archive-filepath + ;; swarsel-org-anki-filepath)) + + (setq org-agenda-files + '("~/Calendars/leon_cal.org")) + + (require 'org-habit) + (add-to-list 'org-modules 'org-habit) + (setq org-habit-graph-column 60) + + (setq org-todo-keywords + '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)") + (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANC(k@)"))) + + (setq org-refile-targets + '((swarsel-archive-org-file :maxlevel . 1) + (swarsel-anki-org-file :maxlevel . 1) + (swarsel-tasks-org-file :maxlevel . 1))) + + ;; Configure custom agenda views + (setq org-agenda-custom-commands + '(("d" "Dashboard" + ((agenda "" ((org-deadline-warning-days 7))) + (todo "NEXT" + ((org-agenda-overriding-header "Next Tasks"))) + (tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects"))))) + + ("n" "Next Tasks" + ((todo "NEXT" + ((org-agenda-overriding-header "Next Tasks"))))) + + ("W" "Work Tasks" tags-todo "+work-email") + + ;; Low-effort next actions + ("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0" + ((org-agenda-overriding-header "Low Effort Tasks") + (org-agenda-max-todos 20) + (org-agenda-files org-agenda-files))) + + ("w" "Workflow Status" + ((todo "WAIT" + ((org-agenda-overriding-header "Waiting on External") + (org-agenda-files org-agenda-files))) + (todo "REVIEW" + ((org-agenda-overriding-header "In Review") + (org-agenda-files org-agenda-files))) + (todo "PLAN" + ((org-agenda-overriding-header "In Planning") + (org-agenda-todo-list-sublevels nil) + (org-agenda-files org-agenda-files))) + (todo "BACKLOG" + ((org-agenda-overriding-header "Project Backlog") + (org-agenda-todo-list-sublevels nil) + (org-agenda-files org-agenda-files))) + (todo "READY" + ((org-agenda-overriding-header "Ready for Work") + (org-agenda-files org-agenda-files))) + (todo "ACTIVE" + ((org-agenda-overriding-header "Active Projects") + (org-agenda-files org-agenda-files))) + (todo "COMPLETED" + ((org-agenda-overriding-header "Completed Projects") + (org-agenda-files org-agenda-files))) + (todo "CANC" + ((org-agenda-overriding-header "Cancelled Projects") + (org-agenda-files org-agenda-files))))))) + + (setq org-capture-templates + `( + ("a" "Anki basic" + entry + (file+headline swarsel-org-anki-filepath "Dispatch") + (function swarsel-anki-make-template-string)) + + ("A" "Anki cloze" + entry + (file+headline org-swarsel-anki-file "Dispatch") + "* %<%H:%M>\n:PROPERTIES:\n:ANKI_NOTE_TYPE: Cloze\n:ANKI_DECK: 🦁 All::01 ❤️ Various::00 ✨ Allgemein\n:END:\n** Text\n%?\n** Extra\n") + ("t" "Tasks / Projects") + ("tt" "Task" entry (file+olp swarsel-org-tasks-filepath "Inbox") + "* TODO %?\n %U\n %a\n %i" :empty-lines 1) + + ("j" "Journal Entries") + ("jj" "Journal" entry + (file+olp+datetree swarsel-org-journal-filepath) + "\n* %<%I:%M %p> - Journal :journal:\n\n%?\n\n" + ;; ,(dw/read-file-as-string "~/Notes/Templates/Daily.org") + :clock-in :clock-resume + :empty-lines 1))) + + (swarsel/org-font-setup)) + +;; ;; Set faces for heading levels +;; (with-eval-after-load 'org-faces (dolist (face '((org-level-1 . 1.3) +;; (org-level-2 . 1.2) +;; (org-level-3 . 1.15) +;; (org-level-4 . 1.1) +;; (org-level-5 . 1.1) +;; (org-level-6 . 1.1) +;; (org-level-7 . 1.1) +;; (org-level-8 . 1.1))) +;; (set-face-attribute (car face) nil :font swarsel-alt-font :weight 'regular :height (cdr face))) + +;; ;; Ensure that anything that should be fixed-pitch in Org files appears that way +;; (set-face-attribute 'org-block nil :inherit '(fixed-pitch)) +;; (set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch)) +;; (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch)) +;; (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch)) +;; (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch)) +;; (set-face-attribute 'org-checkbox nil :inherit '(fixed-pitch))) + +;; Show hidden emphasis markers +(use-package org-appear + :hook (org-mode . org-appear-mode) + :init + (setq org-appear-autolinks t) + (setq org-appear-autosubmarkers t) + ) + +(use-package org-bullets + :after org + :hook (org-mode . org-bullets-mode) + :custom + (org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●"))) + +(defun swarsel/org-mode-visual-fill () + (setq visual-fill-column-width 150 + visual-fill-column-center-text t) + (visual-fill-column-mode 1)) + +(use-package visual-fill-column + :hook (org-mode . swarsel/org-mode-visual-fill)) + +(setq org-fold-core-style 'overlays) + +(org-babel-do-load-languages + 'org-babel-load-languages + '((emacs-lisp . t) + (python . t))) + +(push '("conf-unix" . conf-unix) org-src-lang-modes) + +(require 'org-tempo) +(add-to-list 'org-structure-template-alist '("sh" . "src shell")) +(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) +(add-to-list 'org-structure-template-alist '("py" . "src python")) +(add-to-list 'org-structure-template-alist '("nix" . "src nix :tangle")) + +(defun swarsel/org-babel-tangle-config () + (when (string-equal (buffer-file-name) + swarsel-emacs-org-filepath) + ;; Dynamic scoping to the rescue + (let ((org-confirm-babel-evaluate nil)) + (org-babel-tangle))) + (when (string-equal (buffer-file-name) + swarsel-nix-org-filepath) + ;; Dynamic scoping to the rescue + (let ((org-confirm-babel-evaluate nil)) + (org-babel-tangle)))) + +(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'swarsel/org-babel-tangle-config))) + +(add-hook 'markdown-mode-hook + (lambda () + (local-set-key (kbd "C-c C-x C-l") 'org-latex-preview) + (local-set-key (kbd "C-c C-x C-u") 'markdown-toggle-url-hiding) + )) + +(use-package org-download + :after org + :defer nil + :custom + (org-download-method 'directory) + (org-download-image-dir "./images") + (org-download-heading-lvl 0) + (org-download-timestamp "org_%Y%m%d-%H%M%S_") + ;;(org-image-actual-width 500) + (org-download-screenshot-method "grim -g \"$(slurp)\" %s") + :bind + ("C-M-y" . org-download-screenshot) + :config + (require 'org-download)) + +(use-package org-fragtog) +(add-hook 'org-mode-hook 'org-fragtog-mode) +(add-hook 'markdown-mode-hook 'org-fragtog-mode) + +(defun org-fold-outer () + (interactive) + (org-beginning-of-line) + (if (string-match "^*+" (thing-at-point 'line t)) + (outline-up-heading 1)) + (outline-hide-subtree) + ) + +(use-package org-modern + :config (setq org-modern-block-name + '((t . t) + ("src" "»" "∥"))) + :hook (org-mode . org-modern-mode)) + +(use-package nix-mode + :mode "\\.nix\\'") + +;; https://github.com/mooreryan/markdown-dnd-images +;; (add-to-list 'load-path "~/.emacs.d/packages") +;; (require 'markdown-dnd-images) +;; (setq dnd-save-directory "images") + +;; (setq dnd-save-buffer-name nil) + +;; (setq dnd-view-inline t) + +;; (setq dnd-capture-source nil) + +;; ;; these ne +xt lines provide an interface for org-download in markdown mode for use with obsidian + +(defvar org-download-markdown-link-format + "![[./%s]]\n" + "Format of the file link to insert.") + +(defcustom org-download-markdown-link-format-function #'org-download-markdown-link-format-function-default + "Function that takes FILENAME and returns a org link." + :type 'function) + +(defun org-download-markdown-link-format-function-default (filename) + "The default function of `org-download-link-format-function'." + (if (and (>= (string-to-number org-version) 9.3) + (eq org-download-method 'attach)) + (format "[[attachment:%s]]\n" + (org-link-escape + (file-relative-name filename (org-attach-dir)))) + (format org-download-markdown-link-format + (org-link-escape + (funcall org-download-abbreviate-filename-function filename))))) + +(defun org-download-markdown-image (link) + "Save image at address LINK to `org-download--dir'." + (interactive "sUrl: ") + (let* ((link-and-ext (org-download--parse-link link)) + (filename + (cond ((and (derived-mode-p 'org-mode) + (eq org-download-method 'attach)) + (let ((org-download-image-dir (org-attach-dir t)) + org-download-heading-lvl) + (apply #'org-download--fullname link-and-ext))) + ((fboundp org-download-method) + (funcall org-download-method link)) + (t + (apply #'org-download--fullname link-and-ext))))) + (setq org-download-path-last-file filename) + (org-download--image link filename) + (when (org-download-org-mode-p) + (when (eq org-download-method 'attach) + (org-attach-attach filename nil 'none)) + (org-download-markdown-insert-link link filename)) + (when (and (eq org-download-delete-image-after-download t) + (not (url-handler-file-remote-p (current-kill 0)))) + (delete-file link delete-by-moving-to-trash)))) + +(defun org-download-markdown-screenshot (&optional basename) + "Capture screenshot and insert the resulting file. + The screenshot tool is determined by `org-download-screenshot-method'." + (interactive) + (let* ((screenshot-dir (file-name-directory org-download-screenshot-file)) + (org-download-screenshot-file + (if basename + (concat screenshot-dir basename) org-download-screenshot-file))) + (make-directory screenshot-dir t) + (if (functionp org-download-screenshot-method) + (funcall org-download-screenshot-method + org-download-screenshot-file) + (shell-command-to-string + (format org-download-screenshot-method + org-download-screenshot-file))) + (when (file-exists-p org-download-screenshot-file) + (org-download-markdown-image org-download-screenshot-file) + (delete-file org-download-screenshot-file)))) + + +(defun org-download-markdown-insert-link (link filename) + (let* ((beg (point)) + (line-beg (line-beginning-position)) + (indent (- beg line-beg)) + (in-item-p (org-in-item-p)) + str) + (if (looking-back "^[ \t]+" line-beg) + (delete-region (match-beginning 0) (match-end 0)) + (newline)) + (insert (funcall org-download-annotate-function link)) + (dolist (attr org-download-image-attr-list) + (insert attr "\n")) + (insert (if (= org-download-image-html-width 0) + "" + (format "#+attr_html: :width %dpx\n" org-download-image-html-width))) + (insert (if (= org-download-image-latex-width 0) + "" + (format "#+attr_latex: :width %dcm\n" org-download-image-latex-width))) + (insert (if (= org-download-image-org-width 0) + "" + (format "#+attr_org: :width %dpx\n" org-download-image-org-width))) + (insert (funcall org-download-markdown-link-format-function filename)) + (org-download--display-inline-images) + (setq str (buffer-substring-no-properties line-beg (point))) + (when in-item-p + (indent-region line-beg (point) indent)) + str)) + +(defun markdown-download-screenshot () + (interactive) + (org-mode) + (org-download-markdown-screenshot) + (markdown-mode)) + +(add-hook 'markdown-mode-hook (lambda () (org-display-inline-images))) + +(use-package olivetti + :init + (setq olivetti-body-width 100) + (setq olivetti-recall-visual-line-mode-entry-state t)) + +(use-package darkroom + :init + (setq darkroom-text-scale-increase 3)) + +(use-package rg) + +;; (setq treesit-language-source-alist +;; '((bash "https://github.com/tree-sitter/tree-sitter-bash") +;; (cmake "https://github.com/uyha/tree-sitter-cmake") +;; (c "https://github.com/tree-sitter/tree-sitter-c") +;; (cpp "https://github.com/tree-sitter/tree-sitter-cpp") +;; (css "https://github.com/tree-sitter/tree-sitter-css") +;; (elisp "https://github.com/Wilfred/tree-sitter-elisp") +;; (go "https://github.com/tree-sitter/tree-sitter-go") +;; (html "https://github.com/tree-sitter/tree-sitter-html") +;; (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src") +;; (json "https://github.com/tree-sitter/tree-sitter-json") +;; (make "https://github.com/alemuller/tree-sitter-make") +;; (markdown "https://github.com/ikatyang/tree-sitter-markdown") +;; (python "https://github.com/tree-sitter/tree-sitter-python") +;; (toml "https://github.com/tree-sitter/tree-sitter-toml") +;; (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src") +;; (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src") +;; (rust "https://github.com/tree-sitter/tree-sitter-rust") +;; (sql "https://github.com/m-novikov/tree-sitter-sql") +;; (yaml "https://github.com/ikatyang/tree-sitter-yaml"))) + +;; (add-hook 'rustic-mode-hook 'tree-sitter-mode) +;; (add-hook 'rustic-mode-hook 'tree-sitter-hl-mode) + +(use-package emacs + :ensure nil + :init + (setq treesit-language-source-alist + '((bash . ("https://github.com/tree-sitter/tree-sitter-bash")) + (c . ("https://github.com/tree-sitter/tree-sitter-c")) + (cmake . ("https://github.com/uyha/tree-sitter-cmake")) + (cpp . ("https://github.com/tree-sitter/tree-sitter-cpp")) + (css . ("https://github.com/tree-sitter/tree-sitter-css")) + (elisp . ("https://github.com/Wilfred/tree-sitter-elisp")) + (go . ("https://github.com/tree-sitter/tree-sitter-go")) + (html . ("https://github.com/tree-sitter/tree-sitter-html")) + (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript")) + (json . ("https://github.com/tree-sitter/tree-sitter-json")) + (julia . ("https://github.com/tree-sitter/tree-sitter-julia")) + (latex . ("https://github.com/latex-lsp/tree-sitter-latex")) + (make . ("https://github.com/alemuller/tree-sitter-make")) + (markdown . ("https://github.com/ikatyang/tree-sitter-markdown")) + (R . ("https://github.com/r-lib/tree-sitter-r")) + (python . ("https://github.com/tree-sitter/tree-sitter-python")) + (typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "typescript/src" "typescript")) + (rust . ("https://github.com/tree-sitter/tree-sitter-rust")) + (sql . ("https://github.com/m-novikov/tree-sitter-sql")) + (toml . ("https://github.com/tree-sitter/tree-sitter-toml")) + (yaml . ("https://github.com/ikatyang/tree-sitter-yaml")))) + ;; :hook (((rustic-mode) . tree-sitter-mode) + ;; ((rustic-mode) . tree-sitter-hl-mode)) + ) + +(use-package treesit-auto + :config + (global-treesit-auto-mode) + (setq treesit-auto-install 'prompt)) + +(use-package direnv + ;; :init (add-hook 'prog-mode-hook #'direnv-update-environment) + :custom (direnv-always-show-summary nil) + :config (direnv-mode)) + +(use-package devdocs) + +(use-package projectile + :diminish projectile-mode + :config (projectile-mode) + :custom ((projectile-completion-system 'ivy)) ;; integrate ivy into completion system + :bind-keymap + ("C-c p" . projectile-command-map) ; all projectile commands under this + :init + ;; NOTE: Set this to the folder where you keep your Git repos! + (when (file-directory-p swarsel-projects-directory) + (setq projectile-project-search-path (list swarsel-projects-directory))) + ;(setq projectile-switch-project-action #'projectile-dired) ;list files + (setq projectile-switch-project-action #'magit-status)) + +;; (use-package counsel-projectile +;; :config (counsel-projectile-mode)) + +;; (use-package project +;; :ensure nil +;; :bind +;; (:map project-prefix-map +;; ("v" . magit-project-status)) +;; :config +;; (add-to-list 'project-switch-commands '(magit-project-status "Magit" "m"))) + +(use-package magit + :config + (setq magit-repository-directories `((,swarsel-projects-directory . 1) + (,swarsel-emacs-directory . 0) + (,swarsel-obsidian-directory . 0))) + :custom + (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)) ; stay in the same window + +(use-package forge + :after magit) + +(with-eval-after-load 'forge + (add-to-list 'forge-alist + '("sgit.iue.tuwien.ac.at" + "sgit.iue.tuwien.ac.at/api/v1" + "sgit.iue.tuwien.ac.at" + forge-gitea-repository))) + +(use-package git-timemachine + :hook (git-time-machine-mode . evil-normalize-keymaps) + :init (setq git-timemachine-show-minibuffer-details t) + :general + (general-nmap "SPC g t" 'git-timemachine-toggle) + (git-timemachine-mode-map + "C-k" 'git-timemachine-show-previous-revision + "C-j" 'git-timemachine-show-next-revision + "q" 'git-timemachine-quit)) + +(use-package rainbow-delimiters + :hook (prog-mode . rainbow-delimiters-mode)) + +(use-package highlight-parentheses + :config + (setq highlight-parentheses-colors nil) + (setq highlight-parentheses-background-colors '("magenta" "blue" "cyan" "green" "yellow" "orange" "red")) + (global-highlight-parentheses-mode t)) + +(electric-pair-mode 1) +(setq electric-pair-preserve-balance nil) +;; don't skip newline when auto-pairing parenthesis +(setq electric-pair-skip-whitespace-chars '(9 32)) + +;; (use-package company +;; :after lsp-mode +;; :hook (lsp-mode . company-mode) +;; :bind (:map company-active-map +;; ("" . company-complete-selection)) +;; (:map lsp-mode-map +;; ("" . company-indent-or-complete-common)) +;; :custom +;; (company-minimum-prefix-length 1) +;; (company-idle-delay 0.7)) + +;; (use-package company-box +;; :hook (company-mode . company-box-mode)) + +;; (use-package corfu + ;; :custom + ;; (corfu-cycle t) + ;; :init + ;; (global-corfu-mode)) + + (use-package corfu + :init + (global-corfu-mode) + (corfu-history-mode) + (corfu-popupinfo-mode) ; Popup completion info + :custom + (corfu-auto t) + (corfu-auto-prefix 3) + (corfu-auto-delay 0.3) + (corfu-cycle t) + (corfu-quit-no-match 'separator) + (corfu-separator ?\s) + (corfu-quit-no-match t) + (corfu-popupinfo-max-height 70) + (corfu-popupinfo-delay '(0.5 . 0.2)) + ;; (corfu-preview-current 'insert) ; insert previewed candidate + (corfu-preselect 'prompt) + (corfu-on-exact-match nil) ; Don't auto expand tempel snippets + ;; Optionally use TAB for cycling, default is `corfu-complete'. + :bind (:map corfu-map + ("M-SPC" . corfu-insert-separator) + ("" . swarsel/corfu-normal-return) + ("S-" . corfu-popupinfo-scroll-down) + ("S-" . corfu-popupinfo-scroll-up) + ("C-" . corfu-previous) + ("C-" . corfu-next) + ("" . swarsel/corfu-quit-and-up) + ("" . swarsel/corfu-quit-and-down)) + ) + + ;; dont disrupt file navigation with completions + (defun swarsel/corfu-normal-return (&optional arg) + (interactive) + (corfu-complete) + (corfu-quit)) + + (defun swarsel/corfu-quit-and-up (&optional arg) + (interactive) + (corfu-quit) + (evil-previous-visual-line)) + + (defun swarsel/corfu-quit-and-down (&optional arg) + (interactive) + (corfu-quit) + (evil-next-visual-line)) + + (use-package nerd-icons-corfu) + + (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter) + + (setq nerd-icons-corfu-mapping + '((array :style "cod" :icon "symbol_array" :face font-lock-type-face) + (boolean :style "cod" :icon "symbol_boolean" :face font-lock-builtin-face) + ;; ... + (t :style "cod" :icon "code" :face font-lock-warning-face))) + +(use-package cape + ;; Bind dedicated completion commands + ;; Alternative prefix keys: C-c p, M-p, M-+, ... + ;; :bind (("C-c p p" . completion-at-point) ;; capf + ;; ("C-c p t" . complete-tag) ;; etags + ;; ("C-c p d" . cape-dabbrev) ;; or dabbrev-completion + ;; ("C-c p h" . cape-history) + ;; ("C-c p f" . cape-file) + ;; ("C-c p k" . cape-keyword) + ;; ("C-c p s" . cape-elisp-symbol) + ;; ("C-c p e" . cape-elisp-block) + ;; ("C-c p a" . cape-abbrev) + ;; ("C-c p l" . cape-line) + ;; ("C-c p w" . cape-dict) + ;; ("C-c p :" . cape-emoji) + ;; ("C-c p \\" . cape-tex) + ;; ("C-c p _" . cape-tex) + ;; ("C-c p ^" . cape-tex) + ;; ("C-c p &" . cape-sgml) + ;; ("C-c p r" . cape-rfc1345)) + :init + ;; Add to the global default value of `completion-at-point-functions' which is + ;; used by `completion-at-point'. The order of the functions matters, the + ;; first function returning a result wins. Note that the list of buffer-local + ;; completion functions takes precedence over the global list. + (add-to-list 'completion-at-point-functions #'cape-dabbrev) + (add-to-list 'completion-at-point-functions #'cape-file) + (add-to-list 'completion-at-point-functions #'cape-elisp-block) + ;;(add-to-list 'completion-at-point-functions #'cape-history) + ;;(add-to-list 'completion-at-point-functions #'cape-keyword) + ;;(add-to-list 'completion-at-point-functions #'cape-tex) + ;;(add-to-list 'completion-at-point-functions #'cape-sgml) + ;;(add-to-list 'completion-at-point-functions #'cape-rfc1345) + ;;(add-to-list 'completion-at-point-functions #'cape-abbrev) + ;;(add-to-list 'completion-at-point-functions #'cape-dict) + ;;(add-to-list 'completion-at-point-functions #'cape-elisp-symbol) + ;;(add-to-list 'completion-at-point-functions #'cape-line) +) + +;; (use-package rustic + ;; :ensure + ;; :bind (:map rustic-mode-map + ;; ("M-j" . lsp-ui-imenu) + ;; ("M-?" . lsp-find-references) + ;; ("C-c C-c l" . flycheck-list-errors) + ;; ("C-c C-c a" . lsp-execute-code-action) + ;; ("C-c C-c r" . lsp-rename) + ;; ("C-c C-c q" . lsp-workspace-restart) + ;; ("C-c C-c Q" . lsp-workspace-shutdown) + ;; ("C-c C-c s" . lsp-rust-analyzer-status)) + ;; :config + + ;; (setq rustic-format-on-save t) + ;; (add-hook 'rustic-mode-hook 'rk/rustic-mode-hook)) + +;; (defun rk/rustic-mode-hook () +;; ;; so that run C-c C-c C-r works without having to confirm, but don't try to +;; ;; save rust buffers that are not file visiting. Once +;; ;; https://github.com/brotzeit/rustic/issues/253 has been resolved this should +;; ;; no longer be necessary. +;; (when buffer-file-name +;; (setq-local buffer-save-without-query t)) +;; (add-hook 'before-save-hook 'lsp-format-buffer nil t)) + +;; (use-package rustic +;; :config +;; (setq rustic-format-on-save t) +;; (setq rustic-lsp-client 'eglot) +;; :custom +;; (lsp-rust-analyzer-cargo-watch-command "clippy") +;; (lsp-rust-analyzer-server-display-inlay-hints t) +;; :mode ("\\.rs" . rustic-mode)) + +(use-package rustic + :config + (setq rustic-format-on-save t) + (setq rustic-lsp-client 'eglot) + :mode ("\\.rs" . rustic-mode)) + +;; run the python inferior shell immediately upon entering a python buffer + (add-hook 'python-mode-hook 'swarsel/run-python) + +(defun swarsel/run-python () + (save-selected-window + (switch-to-buffer-other-window (process-buffer (python-shell-get-or-create-process (python-shell-parse-command)))))) + +;; (use-package cuda-mode) + +;; ;; add path manually; +;; (add-hook 'cuda-mode-hook +;; (lambda () +;; ( setq c-basic-offset 4 +;; flycheck-cuda-include-path (list ".")) +;; )) + +(use-package tramp + :init + (setq vc-ignore-dir-regexp + (format "\\(%s\\)\\|\\(%s\\)" + vc-ignore-dir-regexp + tramp-file-name-regexp)) + (setq tramp-default-method "ssh") + (setq tramp-auto-save-directory + (expand-file-name "tramp-auto-save" user-emacs-directory)) + (setq tramp-persistency-file-name + (expand-file-name "tramp-connection-history" user-emacs-directory)) + (setq password-cache-expiry nil) + (setq tramp-use-ssh-controlmaster-options nil) + (setq remote-file-name-inhibit-cache nil) + :config + (customize-set-variable 'tramp-ssh-controlmaster-options + (concat + "-o ControlPath=/tmp/ssh-tramp-%%r@%%h:%%p " + "-o ControlMaster=auto -o ControlPersist=yes")) +) + +(use-package evil-nerd-commenter + :bind ("M-/" . evilnc-comment-or-uncomment-lines)) + +(use-package yasnippet + :init (yas-global-mode 1) + :config + (yas-reload-all) + ) + + ;; (use-package yasnippet-snippets) + +(setq wtf/latex-greek-prefix "'") +(setq wtf/latex-math-prefix "`") +(setq wtf/latex-mathbb-prefix "''") +(setq swarsel/latex-mathcal-prefix "``") + +(use-package yasnippet + :config + (setq swtf/greek-alphabet + '(("a" . "\\alpha") + ("b" . "\\beta" ) + ("g" . "\\gamma") + ("d" . "\\delta") + ("e" . "\\epsilon") + ("z" . "\\zeta") + ("h" . "\\eta") + ("t" . "\\theta") + ("i" . "\\iota") + ("k" . "\\kappa") + ("l" . "\\lambda") + ("m" . "\\mu") + ("n" . "\\nu") + ("x" . "\\xi") + ("p" . "\\pi") + ("r" . "\\rho") + ("s" . "\\sigma") + ("t" . "\\tau") + ("u" . "\\upsilon") + ("f" . "\\phi") + ("c" . "\\chi") + ("v" . "\\psi") + ("o" . "\\omega"))) + + + ;; The same for capitalized letters + (dolist (elem swtf/greek-alphabet) + (let ((key (car elem)) + (value (cdr elem))) + (when (string-equal key (downcase key)) + (add-to-list 'swtf/greek-alphabet + (cons + (capitalize (car elem)) + (concat + (substring value 0 1) + (capitalize (substring value 1 2)) + (substring value 2))))))) + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (list (concat wtf/latex-greek-prefix (car elem)) (cdr elem) (concat "Greek letter " (car elem)))) + swtf/greek-alphabet)) + + (setq wtf/english-alphabet + '("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z")) + + (dolist (elem wtf/english-alphabet) + (when (string-equal elem (downcase elem)) + (add-to-list 'wtf/english-alphabet (upcase elem)))) + + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (list (concat wtf/latex-mathbb-prefix elem) (concat "\\mathbb{" elem "}") (concat "Mathbb letter " elem))) + wtf/english-alphabet)) + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (list (concat swarsel/latex-mathcal-prefix elem) (concat "\\mathcal{" elem "}") (concat "Mathcal letter " elem))) + wtf/english-alphabet)) + + (setq swtf/latex-math-symbols + '(("x" . "\\times") + ("*" . "\\cdot") + ("." . "\\ldots") + ("op" . "\\operatorname{$1}$0") + ("o" . "\\circ") + ("V" . "\\forall") + ("v" . "\\vee") + ("w" . "\\wedge") + ("q" . "\\quad") + ("f" . "\\frac{$1}{$2}$0") + ("s" . "\\sum_{$1}^{$2}$0") + ("p" . "\\prod_{$1}^{$2}$0") + ("e" . "\\exists") + ("i" . "\\int_{$1}^{$2}$0") + ("c" . "\\cap") + ("u" . "\\cup") + ("0" . "\\emptyset"))) + + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (let ((key (car elem)) + (value (cdr elem))) + (list (concat wtf/latex-math-prefix key) value (concat "Math symbol " value)))) + swtf/latex-math-symbols)) + ) + +(defun duplicate-line (arg) + "Duplicate current line, leaving point in lower line." + (interactive "*p") + + ;; save the point for undo + (setq buffer-undo-list (cons (point) buffer-undo-list)) + + ;; local variables for start and end of line + (let ((bol (save-excursion (beginning-of-line) (point))) + eol) + (save-excursion + + ;; don't use forward-line for this, because you would have + ;; to check whether you are at the end of the buffer + (end-of-line) + (setq eol (point)) + + ;; store the line and disable the recording of undo information + (let ((line (buffer-substring bol eol)) + (buffer-undo-list t) + (count arg)) + ;; insert the line arg times + (while (> count 0) + (newline) ;; because there is no newline in 'line' + (insert line) + (setq count (1- count))) + ) + + ;; create the undo information + (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list))) + ) ; end-of-let + + ;; put the point in the lowest line and return + (next-line arg)) + +;; (use-package lsp-mode + ;; :ensure t + ;; :init + ;; ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l") + ;; (setq lsp-keymap-prefix "C-c l") + ;; :hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode) + ;; (python-mode . lsp) + ;; (c++-mode . lsp) + ;; (c-mode . lsp) + ;; (cuda-mode . lsp) + ;; (rustic-mode . lsp) + ;; ;; if you want which-key integration + ;; (lsp-mode . lsp-enable-which-key-integration)) + ;; :commands lsp) + + ;; (use-package lsp-ui + ;; :config + ;; (setq lsp-ui-doc-enable t + ;; lsp-ui-doc-show-with-cursor t + ;; lsp-ui-doc-delay 0.5 + ;; lsp-ui-doc-max-height 70) + ;; ) + + ;; optionally if you want to use debugger + ;; (use-package dap-mode) + +;; (use-package lsp-treemacs +;; :after lsp) + +;; ;; currently there is a bug with the double click behavior that was recently added. Fixed by this +;; (autoload 'treemacs-define-doubleclick-action "treemacs-mouse-interface" nil nil) + +;; ;; (use-package flycheck +;; :hook +;; ((lsp-mode text-mode) . flycheck-mode) +;; :config +;; (define-key flycheck-mode-map flycheck-keymap-prefix nil) +;; ;;(setq flycheck-keymap-prefix (kbd my-flycheck-prefix)) +;; (define-key flycheck-mode-map flycheck-keymap-prefix +;; flycheck-command-map)) + +;; ;; (use-package flycheck-posframe +;; :ensure t +;; :after flycheck +;; :config (add-hook 'flycheck-mode-hook #'flycheck-posframe-mode) +;; :init +;; (setq +;; flycheck-posframe-position 'point-top-left-corner +;; flycheck-posframe-error-prefix "❌ " +;; flycheck-posframe-info-prefix "ℹ️️️ " +;; flycheck-posframe-warning-prefix "⚠️ " +;; flycheck-posframe-prefix "💬 ")) + +(use-package eglot + :ensure nil + :hook + ((python-mode + c-mode + c++-mode + ) . (lambda () (progn + (eglot-ensure) + (add-hook 'before-save-hook 'eglot-format nil 'local)))) + :custom + (eldoc-echo-area-use-multiline-p nil) + (completion-category-defaults nil) + :config + ;; (push '(rustic-ts-mode . eglot-rust-analyzer) eglot-server-programs) + (push '(rustic-mode . eglot-rust-analyzer) eglot-server-programs) + (add-to-list 'eglot-server-programs '((rust-mode) . (eglot-rust-analyzer "rust-analyzer"))) + ;; (add-to-list 'eglot-server-programs '((python-mode) . ("pylsp"))) + ;; (add-to-list 'eglot-server-programs '((c-mode) . ("clangd"))) + :bind (:map eglot-mode-map + ("M-(" . flymake-goto-next-error) + ("C-c ," . eglot-code-actions))) + +(use-package breadcrumb + :config (breadcrumb-mode)) + +;; (use-package lsp-bridge +;; :ensure nil +;; :init +;; (global-lsp-bridge-mode) +;; :config +;; (setq lsp-bridge-enable-debug nil +;; lsp-bridge-enable-auto-format-code 0 +;; lsp-bridge-python-lsp-server 'pylsp +;; lsp-bridge-disable-backup nil +;; lsp-bridge-enable-org-babel 1 +;; acm-enable-search-file-words 0 +;; lsp-bridge-enable-hover-diagnostic 1) +;; ) + +(setq backup-by-copying-when-linked t) + +;; (use-package dired +;; :ensure nil +;; :commands (dired dired-jump) +;; :bind (("C-x C-j" . dired-jump)) +;; :custom ((dired-listing-switches "-agho --group-directories-first")) +;; :config +;; (evil-collection-define-key 'normal 'dired-mode-map +;; "h" 'dired-single-up-directory +;; "l" 'dired-single-buffer)) + +;; (use-package dired-single) + +;; (use-package nerd-icons-dired +;; :hook +;; (dired-mode . nerd-icons-dired-mode)) +;; (use-package nerd-icons-completion +;; :after nerd-icons) +;; (use-package nerd-icons-ivy-rich) +;; (use-package nerd-icons-ibuffer) +;; ;; more colorful dired +;; (use-package diredfl +;; :hook +;; (dired-mode . diredfl-mode)) + +(use-package dirvish + :init + (dirvish-override-dired-mode) + :config + (dirvish-peek-mode) + (dirvish-side-follow-mode) + :custom + (delete-by-moving-to-trash t) + (dired-listing-switches + "-l --almost-all --human-readable --group-directories-first --no-group") + (dirvish-attributes + '(vc-state subtree-state nerd-icons collapse file-time file-size)) + (dirvish-quick-access-entries + '(("h" "~/" "Home") + ("c" "~/.dotfiles/" "Config") + ("d" "~/Downloads/" "Downloads") + ("D" "~/Documents/" "Documents") + ("p" "~/Documents/GitHub/" "Projects") + ("/" "/" "Root"))) + :bind + ((" d" . 'dirvish) + ("C-=" . 'dirvish-side) + :map dirvish-mode-map + ("h" . dired-up-directory) + ("" . dired-up-directory) + ("l" . dired-find-file) + ("" . dired-find-file) + ("j" . evil-next-visual-line) + ("k" . evil-previous-visual-line) + ("a" . dirvish-quick-access) + ("f" . dirvish-file-info-menu) + ("z" . dirvish-history-last) + ("J" . dirvish-history-jump) + ("y" . dirvish-yank-menu) + ("TAB" . dirvish-subtree-toggle) + ("M-f" . dirvish-history-go-forward) + ("M-b" . dirvish-history-go-backward) + ("M-l" . dirvish-ls-switches-menu) + ("M-m" . dirvish-mark-menu) + ("M-t" . dirvish-layout-toggle) + ("M-s" . dirvish-setup-menu) + ("M-e" . dirvish-emerge-menu) + ("M-j" . dirvish-fd-jump))) + +(use-package pdf-tools + :init + (if (not (boundp 'pdf-tools-directory)) + (pdf-tools-install)) + :mode ("\\.pdf" . pdf-view-mode)) + +(use-package openwith) +(openwith-mode t) +;; (setq openwith-associations '(("\\.pdf\\'" "evince" (file)) ("\\.xopp\\'" "xournalpp" (file)))) +(setq openwith-associations '(("\\.xopp\\'" "xournalpp" (file)))) + ;(setq openwith-associations '(("\\.xopp\\'" "xournalpp" (file)))) + +(use-package ein) + +(use-package obsidian + :ensure t + :demand t + :config + (obsidian-specify-path swarsel-obsidian-vault-directory) + (global-obsidian-mode t) + :custom + ;; This directory will be used for `obsidian-capture' if set. + (obsidian-inbox-directory "Inbox") + (bind-key (kbd "C-c M-o") 'obsidian-hydra/body 'obsidian-mode-map) + :bind (:map obsidian-mode-map + ;; Replace C-c C-o with Obsidian.el's implementation. It's ok to use another key binding. + ("C-c C-o" . obsidian-follow-link-at-point) + ;; Jump to backlinks + ("C-c C-b" . obsidian-backlink-jump) + ;; If you prefer you can use `obsidian-insert-link' + ("C-c C-l" . obsidian-insert-wikilink))) + +(use-package anki-editor + :after org + :bind (:map org-mode-map + ("" . anki-editor-cloze-region-auto-incr) + ("" . anki-editor-cloze-region-dont-incr) + ("" . anki-editor-reset-cloze-number) + ("" . anki-editor-push-tree)) + :hook (org-capture-after-finalize . anki-editor-reset-cloze-number) ; Reset cloze-number after each capture. + :config + (setq anki-editor-create-decks t ;; Allow anki-editor to create a new deck if it doesn't exist + anki-editor-org-tags-as-anki-tags t) + + (defun anki-editor-cloze-region-auto-incr (&optional arg) + "Cloze region without hint and increase card number." + (interactive) + (anki-editor-cloze-region swarsel-anki-editor-cloze-number "") + (setq swarsel-anki-editor-cloze-number (1+ swarsel-anki-editor-cloze-number)) + (forward-sexp)) + (defun anki-editor-cloze-region-dont-incr (&optional arg) + "Cloze region without hint using the previous card number." + (interactive) + (anki-editor-cloze-region (1- swarsel-anki-editor-cloze-number) "") + (forward-sexp)) + (defun anki-editor-reset-cloze-number (&optional arg) + "Reset cloze number to ARG or 1" + (interactive) + (setq swarsel-anki-editor-cloze-number (or arg 1))) + (defun anki-editor-push-tree () + "Push all notes under a tree." + (interactive) + (anki-editor-push-notes '(4)) + (anki-editor-reset-cloze-number)) + ;; Initialize + (anki-editor-reset-cloze-number) + ) + +(require 'anki-editor) + +(defvar swarsel-anki-deck nil) +(defvar swarsel-anki-notetype nil) +(defvar swarsel-anki-fields nil) + +(defun swarsel-anki-set-deck-and-notetype () + (interactive) + (setq swarsel-anki-deck (completing-read "Choose a deck: " + (sort (anki-editor-deck-names) #'string-lessp))) + (setq swarsel-anki-notetype (completing-read "Choose a note type: " + (sort (anki-editor-note-types) #'string-lessp))) + (setq swarsel-anki-fields (progn + (anki-editor--anki-connect-invoke-result "modelFieldNames" `((modelName . ,swarsel-anki-notetype))))) + ) + +(defun swarsel-anki-make-template-string () + (if (not swarsel-anki-deck) + (call-interactively 'swarsel-anki-set-deck-and-notetype)) + (setq swarsel-temp swarsel-anki-fields) + (concat (concat "* %<%H:%M>\n:PROPERTIES:\n:ANKI_NOTE_TYPE: " swarsel-anki-notetype "\n:ANKI_DECK: " swarsel-anki-deck "\n:END:\n** ")(pop swarsel-temp) "\n%?\n** " (mapconcat 'identity swarsel-temp "\n\n** ") "\n\n")) + +(defun swarsel-today() + (format-time-string "%Y-%m-%d")) + +(defun swarsel-obsidian-daily () + (interactive) + (if (not (file-exists-p (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory))) + (write-region "" nil (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory)) + ) + (find-file (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory))) + +(use-package mu4e + :ensure nil + ;; :load-path "/usr/share/emacs/site-lisp/mu4e/" + ;;:defer 20 ; Wait until 20 seconds after startup + :config + + ;; This is set to 't' to avoid mail syncing issues when using mbsync + (setq mu4e-change-filenames-when-moving t) + (setq mu4e-mu-binary (executable-find "mu")) + + ;; Refresh mail using isync every 10 minutes + (setq mu4e-update-interval (* 10 60)) + (setq mu4e-get-mail-command "mbsync -a") + (setq mu4e-maildir "~/Mail") + ;;(setq mu4e t) + + (setq mu4e-drafts-folder "/Drafts") + (setq mu4e-sent-folder "/Sent Mail") + (setq mu4e-refile-folder "/All Mail") + (setq mu4e-trash-folder "/Trash") + + (setq mu4e-maildir-shortcuts + '((:maildir "/leon/Inbox" :key ?1) + (:maildir "/nautilus/Inbox" :key ?2) + (:maildir "/mrswarsel/Inbox" :key ?3) + (:maildir "/Sent Mail" :key ?s) + (:maildir "/Trash" :key ?t) + (:maildir "/Drafts" :key ?d) + (:maildir "/All Mail" :key ?a)))) + +(setq user-mail-address "leon.schwarzaeugl@gmail.com" + user-full-name "Leon Schwarzäugl") + +(let ((mu4epath + (concat + (f-dirname + (file-truename + (executable-find "mu"))) + "/../share/emacs/site-lisp/mu4e"))) + (when (and + (string-prefix-p "/nix/store/" mu4epath) + (file-directory-p mu4epath)) + (add-to-list 'load-path mu4epath))) + +(use-package org-caldav + :init + + (setq org-caldav-url "https://stash.swarsel.win/remote.php/dav/calendars/Swarsele") + (setq org-caldav-calendars + '((:calendar-id "personal" + :inbox "~/Calendars/leon_cal.org"))) + ;; (setq org-caldav-backup-file "~/org-caldav/org-caldav-backup.org") + ;; (setq org-caldav-save-directory "~/org-caldav/") + + :config + (setq org-icalendar-alarm-time 1) + ;; This makes sure to-do items as a category can show up on the calendar + (setq org-icalendar-include-todo t) + ;; This ensures all org "deadlines" show up, and show up as due dates + (setq org-icalendar-use-deadline '(event-if-todo event-if-not-todo todo-due)) + ;; This ensures "scheduled" org items show up, and show up as start times + (setq org-icalendar-use-scheduled '(todo-start event-if-todo event-if-not-todo)) + ) + +(use-package calfw + :ensure nil + :bind ("C-c A" . swarsel/open-calendar) + :init + (use-package calfw-cal + :ensure nil) + (use-package calfw-org + :ensure nil) + (use-package calfw-ical + :ensure nil) + :config + (bind-key "g" 'cfw:refresh-calendar-buffer cfw:calendar-mode-map) + (bind-key "q" 'evil-quit cfw:details-mode-map) + ;; (custom-set-faces + ;; '(cfw:face-title ((t (:foreground "#f0dfaf" :weight bold :height 65)))) + ;; ) + ) + +(defun swarsel/open-calendar () + (interactive) + (unless (eq swarsel-caldav-synced 1) (org-caldav-sync) (setq swarsel-caldav-synced 1)) + ;; (select-frame (make-frame '((name . "calendar")))) ; makes a new frame and selects it + ;; (set-face-attribute 'default (selected-frame) :height 65) ; reduces the font size of the new frame + (cfw:open-calendar-buffer + :contents-sources + (list + (cfw:org-create-source "Purple") ; orgmode source + (cfw:ical-create-source "TISS" "https://tiss.tuwien.ac.at/events/rest/calendar/personal?locale=de&token=4463bf7a-87a3-490a-b54c-99b4a65192f3" "Cyan")))) + +(use-package mu4e-alert) +(mu4e-alert-set-default-style 'libnotify) +(add-hook 'after-init-hook #'mu4e-alert-enable-notifications) + +;;show mail + ;;(mu4e) + +(use-package dashboard + :ensure t + :config + (dashboard-setup-startup-hook) + ;; (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))) + (setq dashboard-display-icons-p t ;; display icons on both GUI and terminal + dashboard-icon-type 'nerd-icons ;; use `nerd-icons' package + dashboard-set-file-icons t + dashboard-items '((recents . 5) + (projects . 5) + (agenda . 5)) + dashboard-set-footer nil + dashboard-banner-logo-title "Welcome to SwarsEmacs!" + dashboard-image-banner-max-height 300 + dashboard-startup-banner "~/.dotfiles/wallpaper/swarsel.png" + dashboard-projects-backend 'projectile + dashboard-set-navigator t + dashboard-navigator-buttons + `(;; line1 + ((,"" + "SwarselSocial" + "Browse Swarsele" + (lambda (&rest _) (browse-url "instagram.com/Swarsele"))) + + (,"" + "SwarselSound" + "Browse SwarselSound" + (lambda (&rest _) (browse-url "sound.swarsel.win")) ) + (,"" + "SwarselSwarsel" + "Browse Swarsel" + (lambda (&rest _) (browse-url "github.com/Swarsel")) ) + (,"" + "SwarselStash" + "Browse SwarselStash" + (lambda (&rest _) (browse-url "stash.swarsel.win")) ) + (,"󰫑" + "SwarselSport" + "Browse SwarselSports" + (lambda (&rest _) (browse-url "social.parkour.wien/@Lenno"))) + ) + ( + (,"󱄅" + "swarsel.win" + "Browse swarsel.win" + (lambda (&rest _) (browse-url "swarsel.win"))) + ) + ))) + (setq dashboard-projects-switch-function 'counsel-projectile-switch-project-by-name) + +(fset 'epg-wait-for-status 'ignore) diff --git a/programs/emacs/init.el~ b/programs/emacs/init.el~ new file mode 100644 index 0000000..4e2b03a --- /dev/null +++ b/programs/emacs/init.el~ @@ -0,0 +1,1824 @@ +;; The default is 800 kilobytes. Measured in bytes. +(setq gc-cons-threshold (* 50 1000 1000)) + +;; use UTF-8 everywhere +(set-language-environment "UTF-8") + +;; set default font size +;; (defvar swarsel/default-font-size 130) +;; (setq swarsel-standard-font "FiraCode Nerd Font Mono" +;; swarsel-alt-font "FiraCode Nerd Font Mono") + +;; ;; se +t Nextcloud directory for journals etc. +(setq swarsel-sync-directory "~/Nextcloud" + swarsel-emacs-directory "~/.emacs.d" + swarsel-dotfiles-directory "~/.dotfiles" + swarsel-projects-directory "~/Documents/GitHub") + +(setq swarsel-emacs-org-filepath (expand-file-name "Emacs.org" swarsel-dotfiles-directory) + swarsel-nix-org-filepath (expand-file-name "Nix.org" swarsel-dotfiles-directory)) + + +;; set Emacs main configuration .org names +(setq swarsel-emacs-org-file "Emacs.org" + swarsel-anki-org-file "Anki.org" + swarsel-tasks-org-file "Tasks.org" + swarsel-archive-org-file "Archive.org" + swarsel-org-folder-name "org" + swarsel-obsidian-daily-folder-name "⭐ Personal/Journal" + swarsel-obsidian-folder-name "Obsidian" + swarsel-obsidian-vault-name "Main") + + +;; set directory paths +(setq swarsel-org-directory (expand-file-name swarsel-org-folder-name swarsel-sync-directory)) ; path to org folder +(setq swarsel-obsidian-directory (expand-file-name swarsel-obsidian-folder-name swarsel-sync-directory)) ; path to obsidian +(setq swarsel-obsidian-vault-directory (expand-file-name swarsel-obsidian-vault-name swarsel-obsidian-directory)) ; path to obsidian vault +(setq swarsel-obsidian-daily-directory (expand-file-name swarsel-obsidian-daily-folder-name swarsel-obsidian-vault-directory)) ; path to obsidian daily folder + +;; filepaths to certain documents +(setq swarsel-org-anki-filepath (expand-file-name swarsel-anki-org-file swarsel-org-directory) ; path to anki export file + swarsel-org-tasks-filepath (expand-file-name swarsel-tasks-org-file swarsel-org-directory) + swarsel-org-archive-filepath (expand-file-name swarsel-archive-org-file swarsel-org-directory)) + +;; set paths to authentication files (forge) +;; (setq auth-source-pass-filename "~/.local/share/password-store" +(setq auth-sources '("~/.emacs.d/.authinfo.gpg") + auth-source-cache-expiry nil) ; default is 2h + +;; set pandoc for markdown compilation +(setq markdown-command "pandoc") + +;; set org-caldav-sync-initalization +(setq swarsel-caldav-synced 0) + +;; Change the user-emacs-directory to keep unwanted things out of ~/.emacs.d +(setq user-emacs-directory (expand-file-name "~/.cache/emacs/") + url-history-file (expand-file-name "url/history" user-emacs-directory)) + +;; Use no-littering to automatically set common paths to the new user-emacs-directory +(use-package no-littering) +(setq custom-file (expand-file-name "programs/emacs/custom.el" swarsel-dotfiles-directory)) +(load custom-file t) + +(defalias 'yes-or-no-p 'y-or-n-p) +;;(setq-default show-trailing-whitespace t) +(add-hook 'before-save-hook 'delete-trailing-whitespace) +(global-hl-line-mode 1) +;; (setq redisplay-dont-pause t) ;; obsolete +(delete-selection-mode 1) +(pixel-scroll-precision-mode 1) +(setq vc-follow-symlinks t) +(setq require-final-newline t) +(winner-mode 1) +;; less noise when compiling elisp +(setq byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local)) +(setq native-comp-async-report-warnings-errors nil) +(setq load-prefer-newer t) + +;; disable a keybind that does more harm than good +(global-set-key [remap suspend-frame] + (lambda () + (interactive) + (message "This keybinding is disabled (was 'suspend-frame')"))) + +;; (scroll-bar-mode -1) +;; (tool-bar-mode -1) +;; (tooltip-mode -1) +;; (menu-bar-mode -1) +(setq visible-bell nil) +(setq initial-major-mode 'fundamental-mode + initial-scratch-message nil) + +(setq-default indent-tabs-mode nil + tab-width 2) + + (setq tab-always-indent 'complete) + +(use-package highlight-indent-guides + :hook (prog-mode . highlight-indent-guides-mode) + :init + (setq highlight-indent-guides-method 'character) + (setq highlight-indent-guides-character "‖") + (setq highlight-indent-guides-responsive 'top) + ) + +(setq scroll-step 1 + scroll-margin 4 + scroll-conservatively 5) + +(defun swarsel/with-buffer-name-prompt-and-make-subdirs () + (let ((parent-directory (file-name-directory buffer-file-name))) + (when (and (not (file-exists-p parent-directory)) + (y-or-n-p (format "Directory `%s' does not exist! Create it? " parent-directory))) + (make-directory parent-directory t)))) + +(add-to-list 'find-file-not-found-functions #'swarsel/with-buffer-name-prompt-and-make-subdirs) + +;; Emulate vim in emacs + (use-package evil + :init + (setq evil-want-integration t) ; loads evil + (setq evil-want-keybinding nil) ; loads "helpful bindings" for other modes + (setq evil-want-C-u-scroll t) ; scrolling using C-u + (setq evil-want-C-i-jump nil) ; jumping with C-i + (setq evil-want-Y-yank-to-eol t) ; give Y some utility + (setq evil-shift-width 2) ; uniform indent + (setq evil-respect-visual-line-mode t) ; i am torn on this one + ; sane splitting + (setq evil-split-window-below t) + (setq evil-vsplit-window-right t) + :config + (evil-mode 1) + (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state) ; alternative for exiting insert mode + (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join) ; dont show help but instead do normal vim delete backwards + + ;; evil undo system + (evil-set-undo-system 'undo-tree) + ;; Use visual line motions even outside of visual-line-mode buffers + ;; (evil-global-set-key 'motion "j" 'evil-next-visual-line) + ;; (evil-global-set-key 'motion "k" 'evil-previous-visual-line) + + ;; Don't use evil-mode in these contexts, or use it in a specific mode + (evil-set-initial-state 'messages-buffer-mode 'emacs) + (evil-set-initial-state 'dashboard-mode 'emacs) + (evil-set-initial-state 'dired-mode 'emacs) + (evil-set-initial-state 'cfw:details-mode 'emacs) + (evil-set-initial-state 'Custom-mode 'emacs) ; god knows why this mode is in uppercase + + ; require a specific evil state + (evil-set-initial-state 'mu4e-headers-mode 'normal) + (evil-set-initial-state 'python-inferior-mode 'normal) + (add-hook 'org-capture-mode-hook 'evil-insert-state) + (add-to-list 'evil-buffer-regexps '("COMMIT_EDITMSG" . insert))) + + ;; Evil configuration for different modes + (use-package evil-collection + :after evil + :config + (evil-collection-init) + (setq forge-add-default-bindings nil)) + + + + (use-package evil-snipe + :after evil + :demand + :config + (evil-snipe-mode +1) + (evil-snipe-override-mode +1)) + +(use-package evil-cleverparens) + + +(use-package evil-surround + :general + (:states 'operator + "s" 'evil-surround-edit + "S" 'evil-Surround-edit) + (:states 'visual + "S" 'evil-surround-region + "gS" 'evil-Surround-region)) + + + + (use-package evil-goggles + :after evil + :demand + :init + (setq evil-goggles-duration 0.05) + :config + (push '(evil-operator-eval + :face evil-goggles-yank-face + :switch evil-goggles-enable-yank + :advice evil-goggles--generic-async-advice) + evil-goggles--commands) + (evil-goggles-mode) + (evil-goggles-use-diff-faces) + ) + +(use-package undo-tree + ;; :init (global-undo-tree-mode) + :bind (:map undo-tree-visualizer-mode-map + ("h" . undo-tree-visualize-switch-branch-left) + ("l" . undo-tree-visualize-switch-branch-left) + ("j" . undo-tree-visualize-redo) + ("k" . undo-tree-visualize-undo)) + :config + (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo"))) + ) +(add-hook 'prog-mode-hook 'undo-tree-mode) +(add-hook 'text-mode-hook 'undo-tree-mode) +(add-hook 'org-mode-hook 'undo-tree-mode) +(add-hook 'latex-mode-hook 'undo-tree-mode) + +(let ((backup-dir "~/tmp/emacs/backups") + (auto-saves-dir "~/tmp/emacs/auto-saves/")) + (dolist (dir (list backup-dir auto-saves-dir)) + (when (not (file-directory-p dir)) + (make-directory dir t))) + (setq backup-directory-alist `(("." . ,backup-dir)) + auto-save-file-name-transforms `((".*" ,auto-saves-dir t)) + auto-save-list-file-prefix (concat auto-saves-dir ".saves-") + tramp-backup-directory-alist `((".*" . ,backup-dir)) + tramp-auto-save-directory auto-saves-dir)) + +(setq backup-by-copying t ; Don't delink hardlinks + delete-old-versions t ; Clean up the backups + version-control t ; Use version numbers on backups, + kept-new-versions 5 ; keep some new versions + kept-old-versions 2) ; and some old ones, too + +;; Make ESC quit prompts +(global-set-key (kbd "") 'keyboard-escape-quit) + +;; Set up general keybindings +(use-package general + :config + (general-create-definer swarsel/leader-keys + :keymaps '(normal insert visual emacs) + :prefix "SPC" + :global-prefix "C-SPC") + + (swarsel/leader-keys + "t" '(:ignore t :which-key "toggles") + "ts" '(hydra-text-scale/body :which-key "scale text") + "tl" '(display-line-numbers-mode :which-key "line numbers") + "to" '(olivetti-mode :wk "olivetti") + "td" '(darkroom-tentative-mode :wk "darkroom") + "tw" '((lambda () (interactive) (toggle-truncate-lines)) :which-key "line wrapping") + "m" '(:ignore m :which-key "modes/programs") + "mm" '((lambda () (interactive) (mu4e)) :which-key "mu4e") + "mg" '((lambda () (interactive) (magit-list-repositories)) :which-key "magit-list-repos") + "mc" '((lambda () (interactive) (swarsel/open-calendar)) :which-key "calendar") + "mp" '(popper-toggle :which-key "popper") + "md" '(dirvish :which-key "dirvish") + "c" '(:ignore c :which-key "capture") + "cj" '((lambda () (interactive) (org-capture nil "jj")) :which-key "journal") + "cs" '(markdown-download-screenshot :which-key "screenshot") + "l" '(:ignore l :which-key "links") + "le" '((lambda () (interactive) (find-file swarsel-emacs-org-filepath)) :which-key "Emacs.org") + "ls" '((lambda () (interactive) (find-file "/smb:Swarsel@192.168.1.3:")) :which-key "Server") + "lo" '(dired swarsel-obsidian-vault-directory :which-key "obsidian") + "la" '((lambda () (interactive) (find-file swarsel-org-anki-filepath)) :which-key "anki") + "ln" '((lambda () (interactive) (find-file swarsel-nix-org-filepath)) :which-key "Nix.org") + "lp" '((lambda () (interactive) (projectile-switch-project)) :which-key "switch project") + "lg" '((lambda () (interactive) (magit-list-repositories)) :which-key "list git repos") + "a" '(:ignore a :which-key "anki") + "ap" '(anki-editor-push-tree :which-key "push new cards") + "an" '((lambda () (interactive) (org-capture nil "a")) :which-key "new card") + "as" '(swarsel-anki-set-deck-and-notetype :which-key "change deck and notetype") + "h" '(:ignore h :which-key "help") + "hy" '(yas-describe-tables :which-key "yas tables") + "hb" '(embark-bindings :which-key "current key bindings") + "h" '(:ignore t :which-key "describe") + "he" 'view-echo-area-messages + "hf" 'describe-function + "hF" 'describe-face + "hl" '(view-lossage :which-key "show command keypresses") + "hL" 'find-library + "hm" 'describe-mode + "hk" 'describe-key + "hK" 'describe-keymap + "hp" 'describe-package + "hv" 'describe-variable + "hd" 'devdocs-lookup + "w" '(:ignore t :which-key "window") + "wl" 'windmove-right + "wh" 'windmove-left + "wk" 'windmove-up + "wj" 'windmove-down + "wr" 'winner-redo + "wd" 'delete-window + "w=" 'balance-windows-area + "wD" 'kill-buffer-and-window + "wu" 'winner-undo + "wr" 'winner-redo + "w/" 'evil-window-vsplit + "w-" 'evil-window-split + "wm" '(delete-other-windows :wk "maximize") + )) + +;; General often used hotkeys +(general-define-key + "C-M-a" (lambda () (interactive) (org-capture nil "a")) ; make new anki card + "C-M-d" 'swarsel-obsidian-daily ; open daily obsidian file and create if not exist + "C-M-S" 'swarsel-anki-set-deck-and-notetype ; switch deck and notetye for new anki cards + "C-M-s" 'markdown-download-screenshot ; wrapper for org-download-screenshot + "C-c d" 'duplicate-line ; duplicate line on CURSOR + "C-M-j" 'consult-buffer + "C-s" 'consult-line + ) + +(setq inhibit-startup-message t) + +;; (set-fringe-mode nil) ; Give some breathing room + +;; Increase undo limit and allow for more fine grained undo, base emacs deletes way too much on undo +(setq undo-limit 80000000 + evil-want-fine-undo t + auto-save-default t + password-cache-expiry nil + ) + +;; (display-time-mode 1) +(global-subword-mode 1) ; Iterate through CamelCase words + +(use-package rainbow-mode + :config (rainbow-mode)) + +(setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; one line at a time +(setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling +(setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse + + +(add-hook 'prog-mode-hook 'display-line-numbers-mode) +(add-hook 'text-mode-hook 'display-line-numbers-mode) + +;; (defun swarsel/font-setup (frame) + ;; (set-face-attribute 'default nil :font swarsel-standard-font :height swarsel/default-font-size) + ;; ;; Set the fixed pitch face - basically normal text + ;; (set-face-attribute 'fixed-pitch nil :font swarsel-standard-font :height 140) + ;; ;; Set the variable pitch face - basically headers etc + ;; (set-face-attribute 'variable-pitch nil :font swarsel-alt-font :height 100 :weight 'regular) + ;; (set-face-attribute 'region nil :foreground "cyan" :background "gray40" :weight 'bold) + ;; ;; (remove-hook 'after-make-frame-functions #'swarsel/font-setup) + ;; ) + + ;; (add-hook 'after-make-frame-functions #'swarsel/font-setup) + +;; (dolist (face '(default fixed-pitch)) +;; (set-face-attribute face nil +;; :font "FiraCode Nerd Font Mono")) +;; (add-to-list 'default-frame-alist '(font . "FiraCode Nerd Font Mono")) + +;; (set-face-attribute 'default nil :height 100) +;; (set-face-attribute 'fixed-pitch nil :height 1.0) + +;; (set-face-attribute 'variable-pitch nil +;; :family "IBM Plex Sans" +;; :weight 'regular +;; :height 1.06) + +;; (use-package doom-themes +;; :init (load-theme 'doom-city-lights t)) + +;; (set-frame-parameter (selected-frame) 'alpha '(95 . 95)) +;; (add-to-list 'default-frame-alist '(alpha . (95 . 95))) +;; (set-frame-parameter (selected-frame) 'fullscreen 'maximized) +;; (add-to-list 'default-frame-alist '(fullscreen . maximized)) + +(use-package mixed-pitch + :custom + (mixed-pitch-set-height nil) + (mixed-pitch-variable-pitch-cursor nil) + :hook + (text-mode . mixed-pitch-mode)) + +(use-package nerd-icons) + +;; Adds a more beautiful modeline with less clutter +(use-package doom-modeline + :init (doom-modeline-mode) + :custom + ((doom-modeline-height 22) + (doom-modeline-indent-info t))) + +;; Generally show line numbers +(column-number-mode) + +;; (unless (string-match-p "^Power N/A" (battery)) ; On laptops... +;; (display-battery-mode 1)) + +(use-package vertico + :custom + (vertico-scroll-margin 0) + (vertico-count 10) + (vertico-resize t) + (vertico-cycle t) + :init + (vertico-mode) + (vertico-mouse-mode)) + + (use-package vertico-directory + :ensure nil + :after vertico + :bind (:map vertico-map + ("RET" . vertico-directory-enter) + ("DEL" . vertico-directory-delete-char) + ("M-DEL" . vertico-directory-delete-word)) + ;; Tidy shadowed file names + :hook (rfn-eshadow-update-overlay . vertico-directory-tidy)) + + (use-package orderless + :custom + (completion-styles '(orderless flex basic)) + (completion-category-overrides '((file (styles . (partial-completion))) + (eglot (styles orderless))))) + + (use-package consult + :config + (setq consult-fontify-max-size 1024) + :bind + ("C-x b" . consult-buffer) + ("C-c " . consult-global-mark) + ("C-c C-a" . consult-org-agenda) + ("C-x O" . consult-outline) + ("M-g M-g" . consult-goto-line) + ("M-g i" . consult-imenu) + ("M-s s" . consult-line) + ("M-s M-s" . consult-line-multi)) + + (use-package embark + :bind + (("C-." . embark-act) + ("M-." . embark-dwim) + ("C-h B" . embark-bindings)) + :custom + (prefix-help-command #'embark-prefix-help-command) + (embark-quit-after-action '((t . nil))) + :config + (add-to-list 'display-buffer-alist + '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" + nil + (window-parameters (mode-line-format . none))))) + + (use-package embark-consult + :after (embark consult) + :demand t ; only necessary if you have the hook below + ;; if you want to have consult previews as you move around an + ;; auto-updating embark collect buffer + :hook + (embark-collect-mode . consult-preview-at-point-mode)) + + (use-package marginalia + :after vertico + :init + (marginalia-mode) + (setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))) + +(use-package nerd-icons-completion + :after (marginalia nerd-icons) + :hook (marginalia-mode . nerd-icons-completion-marginalia-setup) + :init + (nerd-icons-completion-mode)) + +;; (use-package ivy +;; :init (ivy-mode 1) +;; :diminish +;; :bind (("C-s" . swiper) ; call swiper (find tool) +;; :map ivy-minibuffer-map +;; ;("TAB" . ivy-alt-done) ; autocomplete +;; ("C-l" . ivy-alt-done) +;; ("C-" . ivy-alt-done) ; for kyria +;; ("C-h" . counsel-up-directory) ; for kyria +;; ("C-" . counsel-up-directory) ; for kyria +;; ("C-j" . ivy-next-line) ; go up and down in ivy using vim keys +;; ("C-" . ivy-next-line) ; for kyria +;; ("C-k" . ivy-previous-line) +;; ("C-" . ivy-previous-line) ; for kyria +;; :map ivy-switch-buffer-map +;; ("C-k" . ivy-previous-line) +;; ("C-" . ivy-previous-line) ; for kyria +;; ("C-l" . ivy-done) +;; ("C-" . ivy-done) ; for kyria +;; ("C-d" . ivy-switch-buffer-kill) +;; :map ivy-reverse-i-search-map +;; ("C-k" . ivy-previous-line) +;; ("C-" . ivy-previous-line) ; for kyria +;; ("C-d" . ivy-reverse-i-search-kill)) +;; :config +;; (setq ivy-use-virtual-buffers t) +;; (setq ivy-count-format "(%d/%d) ") +;; (setq ivy-wrap t)) + +;; ;; More information about functions in ivy-mode +;; (use-package ivy-rich +;; :init +;; (ivy-rich-mode 1)) + +;; (use-package counsel +;; :init (counsel-mode 1) +;; :bind (("C-M-j" . counsel-switch-buffer) +;; ("M-x" . counsel-M-x) +;; ("C-x b" . counsel-ibuffer) +;; ("C-x C-f" . counsel-find-file) +;; :map minibuffer-local-map +;; ("C-r" . 'counsel-minibuffer-history)) +;; :config +;; (setq ivy-initial-inputs-alist nil)) + +(use-package which-key + :init (which-key-mode) + :diminish which-key-mode + :config + (setq which-key-idle-delay 0.3)) + +;; (use-package helpful +;; :custom +;; (counsel-describe-function-function #'helpful-callable) +;; (counsel-describe-variable-function #'helpful-variable) +;; :bind +;; ([remap describe-function] . counsel-describe-function) +;; ([remap describe-command] . helpful-command) +;; ([remap describe-variable] . counsel-describe-variable) +;; ([remap describe-key] . helpful-key)) + +(use-package helpful + :custom + (help-select-window t) + :bind + (("C-h f" . helpful-callable) + ("C-h v" . helpful-variable) + ("C-h k" . helpful-key) + ("C-h C-." . helpful-at-point))) + +(use-package hydra) + +;; change the text size of the current buffer +(defhydra hydra-text-scale (:timeout 4) + "scale text" + ("j" text-scale-increase "in") + ("k" text-scale-decrease "out") + ("f" nil "finished" :exit t)) + +(use-package ligature + :config + (ligature-set-ligatures 'prog-mode + '("|||>" "<|||" "<==>" "" "---" "-<<" + "<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->" + "<--" "<-<" "<<=" "<<-" "<<<" "<+>" "" "###" "#_(" "..<" + "..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~=" + "~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|" + "[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:" + ">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:" + "<$" "<=" "<>" "<-" "<<" "<+" "" "++" "?:" "?=" + "?." "??" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)" "\\\\" + "://" ";;")) + (global-ligature-mode t)) + +(use-package popper +:bind (("M-[" . popper-toggle)) +:init +(setq popper-reference-buffers + '("\\*Messages\\*" + ("\\*Warnings\\*" . hide) + "Output\\*$" + "\\*Async Shell Command\\*" + "\\*Async-native-compile-log\\*" + help-mode + helpful-mode + "*Occur*" + "*scratch*" + "*julia*" + "*Python*" + ;; ("*tex-shell*" . hide) + (compilation-mode . hide))) +(popper-mode +1) +(popper-echo-mode +1)) + +(use-package shackle +:config +(setq shackle-rules '(("*Messages*" :select t :popup t :align right :size 0.3) + ("*Warnings*" :ignore t :popup t :align right :size 0.3) + ("*Occur*" :select t :popup t :align below :size 0.2) + ("*scratch*" :select t :popup t :align below :size 0.2) + ("*Python*" :select t :popup t :align below :size 0.2) + ("*tex-shell*" :ignore t :popup t :align below :size 0.2) + (helpful-mode :select t :popup t :align right :size 0.35) + (help-mode :select t :popup t :align right :size 0.6))) +(shackle-mode 1)) + +(setq-default indicate-buffer-boundaries t) + +(defun swarsel/org-mode-setup () + (org-indent-mode) + (variable-pitch-mode 1) + ;;(auto-fill-mode 0) + (setq display-line-numbers-type 'relative + display-line-numbers-current-absolute 1 + display-line-numbers-width-start nil + display-line-numbers-width 6 + display-line-numbers-grow-only 1) + (add-hook 'org-tab-first-hook 'org-end-of-line) + (visual-line-mode 1)) +;; (setq evil-auto-indent nil) +;;(diminish org-indent-mode) + +(defun swarsel/org-font-setup () + ;; Replace list hyphen with dot + (font-lock-add-keywords 'org-mode + '(("^ *\\([-]\\) " + (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))) + +(use-package org + ;;:diminish (org-indent-mode) + :hook (org-mode . swarsel/org-mode-setup) + :bind ("C-" . org-fold-outer) + :config + (setq org-ellipsis " ⤵" + org-hide-emphasis-markers t) + (setq org-startup-folded t) + (setq org-support-shift-select t) + (setq org-agenda-start-with-log-mode t) + (setq org-log-done 'time) + (setq org-log-into-drawer t) + (setq org-startup-with-inline-images t) + (setq org-image-actual-width nil) + (setq org-format-latex-options '(:foreground "White" :background default :scale 2.0 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0 :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))) + + ;; (setq org-agenda-files + ;; '(swarsel-org-tasks-filepath + ;; swarsel-org-archive-filepath + ;; swarsel-org-anki-filepath)) + + (setq org-agenda-files + '("~/Calendars/leon_cal.org")) + + (require 'org-habit) + (add-to-list 'org-modules 'org-habit) + (setq org-habit-graph-column 60) + + (setq org-todo-keywords + '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)") + (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANC(k@)"))) + + (setq org-refile-targets + '((swarsel-archive-org-file :maxlevel . 1) + (swarsel-anki-org-file :maxlevel . 1) + (swarsel-tasks-org-file :maxlevel . 1))) + + ;; Configure custom agenda views + (setq org-agenda-custom-commands + '(("d" "Dashboard" + ((agenda "" ((org-deadline-warning-days 7))) + (todo "NEXT" + ((org-agenda-overriding-header "Next Tasks"))) + (tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects"))))) + + ("n" "Next Tasks" + ((todo "NEXT" + ((org-agenda-overriding-header "Next Tasks"))))) + + ("W" "Work Tasks" tags-todo "+work-email") + + ;; Low-effort next actions + ("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0" + ((org-agenda-overriding-header "Low Effort Tasks") + (org-agenda-max-todos 20) + (org-agenda-files org-agenda-files))) + + ("w" "Workflow Status" + ((todo "WAIT" + ((org-agenda-overriding-header "Waiting on External") + (org-agenda-files org-agenda-files))) + (todo "REVIEW" + ((org-agenda-overriding-header "In Review") + (org-agenda-files org-agenda-files))) + (todo "PLAN" + ((org-agenda-overriding-header "In Planning") + (org-agenda-todo-list-sublevels nil) + (org-agenda-files org-agenda-files))) + (todo "BACKLOG" + ((org-agenda-overriding-header "Project Backlog") + (org-agenda-todo-list-sublevels nil) + (org-agenda-files org-agenda-files))) + (todo "READY" + ((org-agenda-overriding-header "Ready for Work") + (org-agenda-files org-agenda-files))) + (todo "ACTIVE" + ((org-agenda-overriding-header "Active Projects") + (org-agenda-files org-agenda-files))) + (todo "COMPLETED" + ((org-agenda-overriding-header "Completed Projects") + (org-agenda-files org-agenda-files))) + (todo "CANC" + ((org-agenda-overriding-header "Cancelled Projects") + (org-agenda-files org-agenda-files))))))) + + (setq org-capture-templates + `( + ("a" "Anki basic" + entry + (file+headline swarsel-org-anki-filepath "Dispatch") + (function swarsel-anki-make-template-string)) + + ("A" "Anki cloze" + entry + (file+headline org-swarsel-anki-file "Dispatch") + "* %<%H:%M>\n:PROPERTIES:\n:ANKI_NOTE_TYPE: Cloze\n:ANKI_DECK: 🦁 All::01 ❤️ Various::00 ✨ Allgemein\n:END:\n** Text\n%?\n** Extra\n") + ("t" "Tasks / Projects") + ("tt" "Task" entry (file+olp swarsel-org-tasks-filepath "Inbox") + "* TODO %?\n %U\n %a\n %i" :empty-lines 1) + + ("j" "Journal Entries") + ("jj" "Journal" entry + (file+olp+datetree swarsel-org-journal-filepath) + "\n* %<%I:%M %p> - Journal :journal:\n\n%?\n\n" + ;; ,(dw/read-file-as-string "~/Notes/Templates/Daily.org") + :clock-in :clock-resume + :empty-lines 1))) + + (swarsel/org-font-setup)) + +;; ;; Set faces for heading levels +;; (with-eval-after-load 'org-faces (dolist (face '((org-level-1 . 1.3) +;; (org-level-2 . 1.2) +;; (org-level-3 . 1.15) +;; (org-level-4 . 1.1) +;; (org-level-5 . 1.1) +;; (org-level-6 . 1.1) +;; (org-level-7 . 1.1) +;; (org-level-8 . 1.1))) +;; (set-face-attribute (car face) nil :font swarsel-alt-font :weight 'regular :height (cdr face))) + +;; ;; Ensure that anything that should be fixed-pitch in Org files appears that way +;; (set-face-attribute 'org-block nil :inherit '(fixed-pitch)) +;; (set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch)) +;; (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch)) +;; (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch)) +;; (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch)) +;; (set-face-attribute 'org-checkbox nil :inherit '(fixed-pitch))) + +;; Show hidden emphasis markers +(use-package org-appear + :hook (org-mode . org-appear-mode) + :init + (setq org-appear-autolinks t) + (setq org-appear-autosubmarkers t) + ) + +(use-package org-bullets + :after org + :hook (org-mode . org-bullets-mode) + :custom + (org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●"))) + +(defun swarsel/org-mode-visual-fill () + (setq visual-fill-column-width 150 + visual-fill-column-center-text t) + (visual-fill-column-mode 1)) + +(use-package visual-fill-column + :hook (org-mode . swarsel/org-mode-visual-fill)) + +(setq org-fold-core-style 'overlays) + +(org-babel-do-load-languages + 'org-babel-load-languages + '((emacs-lisp . t) + (python . t))) + +(push '("conf-unix" . conf-unix) org-src-lang-modes) + +(require 'org-tempo) +(add-to-list 'org-structure-template-alist '("sh" . "src shell")) +(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) +(add-to-list 'org-structure-template-alist '("py" . "src python")) +(add-to-list 'org-structure-template-alist '("nix" . "src nix :tangle")) + +(defun swarsel/org-babel-tangle-config () + (when (string-equal (buffer-file-name) + swarsel-emacs-org-filepath) + ;; Dynamic scoping to the rescue + (let ((org-confirm-babel-evaluate nil)) + (org-babel-tangle))) + (when (string-equal (buffer-file-name) + swarsel-nix-org-filepath) + ;; Dynamic scoping to the rescue + (let ((org-confirm-babel-evaluate nil)) + (org-babel-tangle)))) + +(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'swarsel/org-babel-tangle-config))) + +(add-hook 'markdown-mode-hook + (lambda () + (local-set-key (kbd "C-c C-x C-l") 'org-latex-preview) + (local-set-key (kbd "C-c C-x C-u") 'markdown-toggle-url-hiding) + )) + +(use-package org-download + :after org + :defer nil + :custom + (org-download-method 'directory) + (org-download-image-dir "./images") + (org-download-heading-lvl 0) + (org-download-timestamp "org_%Y%m%d-%H%M%S_") + ;;(org-image-actual-width 500) + (org-download-screenshot-method "grim -g \"$(slurp)\" %s") + :bind + ("C-M-y" . org-download-screenshot) + :config + (require 'org-download)) + +(use-package org-fragtog) +(add-hook 'org-mode-hook 'org-fragtog-mode) +(add-hook 'markdown-mode-hook 'org-fragtog-mode) + +(defun org-fold-outer () + (interactive) + (org-beginning-of-line) + (if (string-match "^*+" (thing-at-point 'line t)) + (outline-up-heading 1)) + (outline-hide-subtree) + ) + +(use-package org-modern + :config (setq org-modern-block-name + '((t . t) + ("src" "»" "∥"))) + :hook (org-mode . org-modern-mode)) + +(use-package nix-mode + :mode "\\.nix\\'") + +;; https://github.com/mooreryan/markdown-dnd-images +(add-to-list 'load-path "~/.emacs.d/packages") +(require 'markdown-dnd-images) +(setq dnd-save-directory "images") + +(setq dnd-save-buffer-name nil) + +(setq dnd-view-inline t) + +(setq dnd-capture-source nil) + +;; these next lines provide an interface for org-download in markdown mode for use with obsidian + +(defvar org-download-markdown-link-format + "![[./%s]]\n" + "Format of the file link to insert.") + +(defcustom org-download-markdown-link-format-function #'org-download-markdown-link-format-function-default + "Function that takes FILENAME and returns a org link." + :type 'function) + +(defun org-download-markdown-link-format-function-default (filename) + "The default function of `org-download-link-format-function'." + (if (and (>= (string-to-number org-version) 9.3) + (eq org-download-method 'attach)) + (format "[[attachment:%s]]\n" + (org-link-escape + (file-relative-name filename (org-attach-dir)))) + (format org-download-markdown-link-format + (org-link-escape + (funcall org-download-abbreviate-filename-function filename))))) + +(defun org-download-markdown-image (link) + "Save image at address LINK to `org-download--dir'." + (interactive "sUrl: ") + (let* ((link-and-ext (org-download--parse-link link)) + (filename + (cond ((and (derived-mode-p 'org-mode) + (eq org-download-method 'attach)) + (let ((org-download-image-dir (org-attach-dir t)) + org-download-heading-lvl) + (apply #'org-download--fullname link-and-ext))) + ((fboundp org-download-method) + (funcall org-download-method link)) + (t + (apply #'org-download--fullname link-and-ext))))) + (setq org-download-path-last-file filename) + (org-download--image link filename) + (when (org-download-org-mode-p) + (when (eq org-download-method 'attach) + (org-attach-attach filename nil 'none)) + (org-download-markdown-insert-link link filename)) + (when (and (eq org-download-delete-image-after-download t) + (not (url-handler-file-remote-p (current-kill 0)))) + (delete-file link delete-by-moving-to-trash)))) + +(defun org-download-markdown-screenshot (&optional basename) + "Capture screenshot and insert the resulting file. + The screenshot tool is determined by `org-download-screenshot-method'." + (interactive) + (let* ((screenshot-dir (file-name-directory org-download-screenshot-file)) + (org-download-screenshot-file + (if basename + (concat screenshot-dir basename) org-download-screenshot-file))) + (make-directory screenshot-dir t) + (if (functionp org-download-screenshot-method) + (funcall org-download-screenshot-method + org-download-screenshot-file) + (shell-command-to-string + (format org-download-screenshot-method + org-download-screenshot-file))) + (when (file-exists-p org-download-screenshot-file) + (org-download-markdown-image org-download-screenshot-file) + (delete-file org-download-screenshot-file)))) + + +(defun org-download-markdown-insert-link (link filename) + (let* ((beg (point)) + (line-beg (line-beginning-position)) + (indent (- beg line-beg)) + (in-item-p (org-in-item-p)) + str) + (if (looking-back "^[ \t]+" line-beg) + (delete-region (match-beginning 0) (match-end 0)) + (newline)) + (insert (funcall org-download-annotate-function link)) + (dolist (attr org-download-image-attr-list) + (insert attr "\n")) + (insert (if (= org-download-image-html-width 0) + "" + (format "#+attr_html: :width %dpx\n" org-download-image-html-width))) + (insert (if (= org-download-image-latex-width 0) + "" + (format "#+attr_latex: :width %dcm\n" org-download-image-latex-width))) + (insert (if (= org-download-image-org-width 0) + "" + (format "#+attr_org: :width %dpx\n" org-download-image-org-width))) + (insert (funcall org-download-markdown-link-format-function filename)) + (org-download--display-inline-images) + (setq str (buffer-substring-no-properties line-beg (point))) + (when in-item-p + (indent-region line-beg (point) indent)) + str)) + +(defun markdown-download-screenshot () + (interactive) + (org-mode) + (org-download-markdown-screenshot) + (markdown-mode)) + +(add-hook 'markdown-mode-hook (lambda () (org-display-inline-images))) + +(use-package olivetti + :init + (setq olivetti-body-width 100) + (setq olivetti-recall-visual-line-mode-entry-state t)) + +(use-package darkroom + :init + (setq darkroom-text-scale-increase 3)) + +(use-package rg) + +;; (setq treesit-language-source-alist +;; '((bash "https://github.com/tree-sitter/tree-sitter-bash") +;; (cmake "https://github.com/uyha/tree-sitter-cmake") +;; (c "https://github.com/tree-sitter/tree-sitter-c") +;; (cpp "https://github.com/tree-sitter/tree-sitter-cpp") +;; (css "https://github.com/tree-sitter/tree-sitter-css") +;; (elisp "https://github.com/Wilfred/tree-sitter-elisp") +;; (go "https://github.com/tree-sitter/tree-sitter-go") +;; (html "https://github.com/tree-sitter/tree-sitter-html") +;; (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src") +;; (json "https://github.com/tree-sitter/tree-sitter-json") +;; (make "https://github.com/alemuller/tree-sitter-make") +;; (markdown "https://github.com/ikatyang/tree-sitter-markdown") +;; (python "https://github.com/tree-sitter/tree-sitter-python") +;; (toml "https://github.com/tree-sitter/tree-sitter-toml") +;; (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src") +;; (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src") +;; (rust "https://github.com/tree-sitter/tree-sitter-rust") +;; (sql "https://github.com/m-novikov/tree-sitter-sql") +;; (yaml "https://github.com/ikatyang/tree-sitter-yaml"))) + +;; (add-hook 'rustic-mode-hook 'tree-sitter-mode) +;; (add-hook 'rustic-mode-hook 'tree-sitter-hl-mode) + +(use-package emacs + :ensure nil + :init + (setq treesit-language-source-alist + '((bash . ("https://github.com/tree-sitter/tree-sitter-bash")) + (c . ("https://github.com/tree-sitter/tree-sitter-c")) + (cmake . ("https://github.com/uyha/tree-sitter-cmake")) + (cpp . ("https://github.com/tree-sitter/tree-sitter-cpp")) + (css . ("https://github.com/tree-sitter/tree-sitter-css")) + (elisp . ("https://github.com/Wilfred/tree-sitter-elisp")) + (go . ("https://github.com/tree-sitter/tree-sitter-go")) + (html . ("https://github.com/tree-sitter/tree-sitter-html")) + (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript")) + (json . ("https://github.com/tree-sitter/tree-sitter-json")) + (julia . ("https://github.com/tree-sitter/tree-sitter-julia")) + (latex . ("https://github.com/latex-lsp/tree-sitter-latex")) + (make . ("https://github.com/alemuller/tree-sitter-make")) + (markdown . ("https://github.com/ikatyang/tree-sitter-markdown")) + (R . ("https://github.com/r-lib/tree-sitter-r")) + (python . ("https://github.com/tree-sitter/tree-sitter-python")) + (typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "typescript/src" "typescript")) + (rust . ("https://github.com/tree-sitter/tree-sitter-rust")) + (sql . ("https://github.com/m-novikov/tree-sitter-sql")) + (toml . ("https://github.com/tree-sitter/tree-sitter-toml")) + (yaml . ("https://github.com/ikatyang/tree-sitter-yaml")))) + ;; :hook (((rustic-mode) . tree-sitter-mode) + ;; ((rustic-mode) . tree-sitter-hl-mode)) + ) + +(use-package treesit-auto + :config + (global-treesit-auto-mode) + (setq treesit-auto-install 'prompt)) + +(use-package direnv + ;; :init (add-hook 'prog-mode-hook #'direnv-update-environment) + :custom (direnv-always-show-summary nil) + :config (direnv-mode)) + +(use-package devdocs) + +(use-package projectile + :diminish projectile-mode + :config (projectile-mode) + :custom ((projectile-completion-system 'ivy)) ;; integrate ivy into completion system + :bind-keymap + ("C-c p" . projectile-command-map) ; all projectile commands under this + :init + ;; NOTE: Set this to the folder where you keep your Git repos! + (when (file-directory-p swarsel-projects-directory) + (setq projectile-project-search-path (list swarsel-projects-directory))) + ;(setq projectile-switch-project-action #'projectile-dired) ;list files + (setq projectile-switch-project-action #'magit-status)) + +;; (use-package counsel-projectile +;; :config (counsel-projectile-mode)) + +;; (use-package project +;; :ensure nil +;; :bind +;; (:map project-prefix-map +;; ("v" . magit-project-status)) +;; :config +;; (add-to-list 'project-switch-commands '(magit-project-status "Magit" "m"))) + +(use-package magit + :config + (setq magit-repository-directories `((,swarsel-projects-directory . 1) + (,swarsel-emacs-directory . 0) + (,swarsel-obsidian-directory . 0))) + :custom + (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)) ; stay in the same window + +(use-package forge + :after magit) + +(with-eval-after-load 'forge + (add-to-list 'forge-alist + '("sgit.iue.tuwien.ac.at" + "sgit.iue.tuwien.ac.at/api/v1" + "sgit.iue.tuwien.ac.at" + forge-gitea-repository))) + +(use-package git-timemachine + :hook (git-time-machine-mode . evil-normalize-keymaps) + :init (setq git-timemachine-show-minibuffer-details t) + :general + (general-nmap "SPC g t" 'git-timemachine-toggle) + (git-timemachine-mode-map + "C-k" 'git-timemachine-show-previous-revision + "C-j" 'git-timemachine-show-next-revision + "q" 'git-timemachine-quit)) + +(use-package rainbow-delimiters + :hook (prog-mode . rainbow-delimiters-mode)) + +(use-package highlight-parentheses + :config + (setq highlight-parentheses-colors nil) + (setq highlight-parentheses-background-colors '("magenta" "blue" "cyan" "green" "yellow" "orange" "red")) + (global-highlight-parentheses-mode t)) + +(electric-pair-mode 1) +(setq electric-pair-preserve-balance nil) +;; don't skip newline when auto-pairing parenthesis +(setq electric-pair-skip-whitespace-chars '(9 32)) + +;; (use-package company +;; :after lsp-mode +;; :hook (lsp-mode . company-mode) +;; :bind (:map company-active-map +;; ("" . company-complete-selection)) +;; (:map lsp-mode-map +;; ("" . company-indent-or-complete-common)) +;; :custom +;; (company-minimum-prefix-length 1) +;; (company-idle-delay 0.7)) + +;; (use-package company-box +;; :hook (company-mode . company-box-mode)) + +;; (use-package corfu + ;; :custom + ;; (corfu-cycle t) + ;; :init + ;; (global-corfu-mode)) + + (use-package corfu + :init + (global-corfu-mode) + (corfu-history-mode) + (corfu-popupinfo-mode) ; Popup completion info + :custom + (corfu-auto t) + (corfu-auto-prefix 3) + (corfu-auto-delay 0.3) + (corfu-cycle t) + (corfu-quit-no-match 'separator) + (corfu-separator ?\s) + (corfu-quit-no-match t) + (corfu-popupinfo-max-height 70) + (corfu-popupinfo-delay '(0.5 . 0.2)) + ;; (corfu-preview-current 'insert) ; insert previewed candidate + (corfu-preselect 'prompt) + (corfu-on-exact-match nil) ; Don't auto expand tempel snippets + ;; Optionally use TAB for cycling, default is `corfu-complete'. + :bind (:map corfu-map + ("M-SPC" . corfu-insert-separator) + ("" . corfu-complete) + ("S-" . corfu-popupinfo-scroll-down) + ("S-" . corfu-popupinfo-scroll-up) + ("C-" . corfu-previous) + ("C-" . corfu-next) + ("" . swarsel/corfu-quit-and-up) + ("" . swarsel/corfu-quit-and-down)) + ) + + ;; dont disrupt file navigation with completions + (defun swarsel/corfu-quit-and-up (&optional arg) + (interactive) + (corfu-quit) + (evil-previous-visual-line)) + + (defun swarsel/corfu-quit-and-down (&optional arg) + (interactive) + (corfu-quit) + (evil-next-visual-line)) + + (use-package nerd-icons-corfu) + + (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter) + + (setq nerd-icons-corfu-mapping + '((array :style "cod" :icon "symbol_array" :face font-lock-type-face) + (boolean :style "cod" :icon "symbol_boolean" :face font-lock-builtin-face) + ;; ... + (t :style "cod" :icon "code" :face font-lock-warning-face))) + +(use-package cape + ;; Bind dedicated completion commands + ;; Alternative prefix keys: C-c p, M-p, M-+, ... + :bind (("C-c p p" . completion-at-point) ;; capf + ("C-c p t" . complete-tag) ;; etags + ("C-c p d" . cape-dabbrev) ;; or dabbrev-completion + ("C-c p h" . cape-history) + ("C-c p f" . cape-file) + ("C-c p k" . cape-keyword) + ("C-c p s" . cape-elisp-symbol) + ("C-c p e" . cape-elisp-block) + ("C-c p a" . cape-abbrev) + ("C-c p l" . cape-line) + ("C-c p w" . cape-dict) + ("C-c p :" . cape-emoji) + ("C-c p \\" . cape-tex) + ("C-c p _" . cape-tex) + ("C-c p ^" . cape-tex) + ("C-c p &" . cape-sgml) + ("C-c p r" . cape-rfc1345)) + :init + ;; Add to the global default value of `completion-at-point-functions' which is + ;; used by `completion-at-point'. The order of the functions matters, the + ;; first function returning a result wins. Note that the list of buffer-local + ;; completion functions takes precedence over the global list. + (add-to-list 'completion-at-point-functions #'cape-dabbrev) + (add-to-list 'completion-at-point-functions #'cape-file) + (add-to-list 'completion-at-point-functions #'cape-elisp-block) + ;;(add-to-list 'completion-at-point-functions #'cape-history) + ;;(add-to-list 'completion-at-point-functions #'cape-keyword) + ;;(add-to-list 'completion-at-point-functions #'cape-tex) + ;;(add-to-list 'completion-at-point-functions #'cape-sgml) + ;;(add-to-list 'completion-at-point-functions #'cape-rfc1345) + ;;(add-to-list 'completion-at-point-functions #'cape-abbrev) + ;;(add-to-list 'completion-at-point-functions #'cape-dict) + ;;(add-to-list 'completion-at-point-functions #'cape-elisp-symbol) + ;;(add-to-list 'completion-at-point-functions #'cape-line) +) + +;; (use-package rustic + ;; :ensure + ;; :bind (:map rustic-mode-map + ;; ("M-j" . lsp-ui-imenu) + ;; ("M-?" . lsp-find-references) + ;; ("C-c C-c l" . flycheck-list-errors) + ;; ("C-c C-c a" . lsp-execute-code-action) + ;; ("C-c C-c r" . lsp-rename) + ;; ("C-c C-c q" . lsp-workspace-restart) + ;; ("C-c C-c Q" . lsp-workspace-shutdown) + ;; ("C-c C-c s" . lsp-rust-analyzer-status)) + ;; :config + + ;; (setq rustic-format-on-save t) + ;; (add-hook 'rustic-mode-hook 'rk/rustic-mode-hook)) + +;; (defun rk/rustic-mode-hook () +;; ;; so that run C-c C-c C-r works without having to confirm, but don't try to +;; ;; save rust buffers that are not file visiting. Once +;; ;; https://github.com/brotzeit/rustic/issues/253 has been resolved this should +;; ;; no longer be necessary. +;; (when buffer-file-name +;; (setq-local buffer-save-without-query t)) +;; (add-hook 'before-save-hook 'lsp-format-buffer nil t)) + +;; (use-package rustic +;; :config +;; (setq rustic-format-on-save t) +;; (setq rustic-lsp-client 'eglot) +;; :custom +;; (lsp-rust-analyzer-cargo-watch-command "clippy") +;; (lsp-rust-analyzer-server-display-inlay-hints t) +;; :mode ("\\.rs" . rustic-mode)) + +(use-package rustic + :config + (setq rustic-format-on-save t) + (setq rustic-lsp-client 'eglot) + :mode ("\\.rs" . rustic-mode)) + +;; run the python inferior shell immediately upon entering a python buffer + (add-hook 'python-mode-hook 'swarsel/run-python) + +(defun swarsel/run-python () + (save-selected-window + (switch-to-buffer-other-window (process-buffer (python-shell-get-or-create-process (python-shell-parse-command)))))) + +;; (use-package cuda-mode) + +;; ;; add path manually; +;; (add-hook 'cuda-mode-hook +;; (lambda () +;; ( setq c-basic-offset 4 +;; flycheck-cuda-include-path (list ".")) +;; )) + +(use-package tramp + :init + (setq vc-ignore-dir-regexp + (format "\\(%s\\)\\|\\(%s\\)" + vc-ignore-dir-regexp + tramp-file-name-regexp)) + (setq tramp-default-method "ssh") + (setq tramp-auto-save-directory + (expand-file-name "tramp-auto-save" user-emacs-directory)) + (setq tramp-persistency-file-name + (expand-file-name "tramp-connection-history" user-emacs-directory)) + (setq password-cache-expiry nil) + (setq tramp-use-ssh-controlmaster-options nil) + (setq remote-file-name-inhibit-cache nil) + :config + (customize-set-variable 'tramp-ssh-controlmaster-options + (concat + "-o ControlPath=/tmp/ssh-tramp-%%r@%%h:%%p " + "-o ControlMaster=auto -o ControlPersist=yes")) +) + +(use-package evil-nerd-commenter + :bind ("M-/" . evilnc-comment-or-uncomment-lines)) + +(use-package yasnippet + :init (yas-global-mode 1) + :config + (yas-reload-all) + ) + + ;; (use-package yasnippet-snippets) + +(use-package yasnippet + :config + (setq wtf/greek-alphabet + '(("a" . "\\alpha") + ("b" . "\\beta" ) + ("g" . "\\gamma") + ("d" . "\\delta") + ("e" . "\\epsilon") + ("z" . "\\zeta") + ("h" . "\\eta") + ("t" . "\\theta") + ("i" . "\\iota") + ("k" . "\\kappa") + ("l" . "\\lambda") + ("m" . "\\mu") + ("n" . "\\nu") + ("x" . "\\xi") + ("p" . "\\pi") + ("r" . "\\rho") + ("s" . "\\sigma") + ("t" . "\\tau") + ("u" . "\\upsilon") + ("f" . "\\phi") + ("c" . "\\chi") + ("v" . "\\psi") + ("g" . "\\omega"))) + + (setq wtf/latex-greek-prefix "'") + + ;; The same for capitalized letters + (dolist (elem wtf/greek-alphabet) + (let ((key (car elem)) + (value (cdr elem))) + (when (string-equal key (downcase key)) + (add-to-list 'wtf/greek-alphabet + (cons + (capitalize (car elem)) + (concat + (substring value 0 1) + (capitalize (substring value 1 2)) + (substring value 2))))))) + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (list (concat wtf/latex-greek-prefix (car elem)) (cdr elem) (concat "Greek letter " (car elem)))) + wtf/greek-alphabet)) + + (setq wtf/english-alphabet + '("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z")) + + (dolist (elem wtf/english-alphabet) + (when (string-equal elem (downcase elem)) + (add-to-list 'wtf/english-alphabet (upcase elem)))) + + (setq wtf/latex-mathbb-prefix "`") + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (list (concat wtf/latex-mathbb-prefix elem) (concat "\\mathbb{" elem "}") (concat "Mathbb letter " elem))) + wtf/english-alphabet)) + + (setq wtf/latex-math-symbols + '(("x" . "\\times") + ("." . "\\cdot") + ("v" . "\\forall") + ("s" . "\\sum_{$1}^{$2}$0") + ("p" . "\\prod_{$1}^{$2}$0") + ("e" . "\\exists") + ("i" . "\\int_{$1}^{$2}$0") + ("c" . "\\cap") + ("u" . "\\cup") + ("0" . "\\emptyset"))) + + (setq wtf/latex-math-prefix "''") + + (yas-define-snippets + 'latex-mode + (mapcar + (lambda (elem) + (let ((key (car elem)) + (value (cdr elem))) + (list (concat wtf/latex-math-prefix key) value (concat "Math symbol " value)))) + wtf/latex-math-symbols)) + ) + +(defun duplicate-line (arg) + "Duplicate current line, leaving point in lower line." + (interactive "*p") + + ;; save the point for undo + (setq buffer-undo-list (cons (point) buffer-undo-list)) + + ;; local variables for start and end of line + (let ((bol (save-excursion (beginning-of-line) (point))) + eol) + (save-excursion + + ;; don't use forward-line for this, because you would have + ;; to check whether you are at the end of the buffer + (end-of-line) + (setq eol (point)) + + ;; store the line and disable the recording of undo information + (let ((line (buffer-substring bol eol)) + (buffer-undo-list t) + (count arg)) + ;; insert the line arg times + (while (> count 0) + (newline) ;; because there is no newline in 'line' + (insert line) + (setq count (1- count))) + ) + + ;; create the undo information + (setq buffer-undo-list (cons (cons eol (point)) buffer-undo-list))) + ) ; end-of-let + + ;; put the point in the lowest line and return + (next-line arg)) + +;; (use-package lsp-mode + ;; :ensure t + ;; :init + ;; ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l") + ;; (setq lsp-keymap-prefix "C-c l") + ;; :hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode) + ;; (python-mode . lsp) + ;; (c++-mode . lsp) + ;; (c-mode . lsp) + ;; (cuda-mode . lsp) + ;; (rustic-mode . lsp) + ;; ;; if you want which-key integration + ;; (lsp-mode . lsp-enable-which-key-integration)) + ;; :commands lsp) + + ;; (use-package lsp-ui + ;; :config + ;; (setq lsp-ui-doc-enable t + ;; lsp-ui-doc-show-with-cursor t + ;; lsp-ui-doc-delay 0.5 + ;; lsp-ui-doc-max-height 70) + ;; ) + + ;; optionally if you want to use debugger + ;; (use-package dap-mode) + +;; (use-package lsp-treemacs +;; :after lsp) + +;; ;; currently there is a bug with the double click behavior that was recently added. Fixed by this +;; (autoload 'treemacs-define-doubleclick-action "treemacs-mouse-interface" nil nil) + +;; ;; (use-package flycheck +;; :hook +;; ((lsp-mode text-mode) . flycheck-mode) +;; :config +;; (define-key flycheck-mode-map flycheck-keymap-prefix nil) +;; ;;(setq flycheck-keymap-prefix (kbd my-flycheck-prefix)) +;; (define-key flycheck-mode-map flycheck-keymap-prefix +;; flycheck-command-map)) + +;; ;; (use-package flycheck-posframe +;; :ensure t +;; :after flycheck +;; :config (add-hook 'flycheck-mode-hook #'flycheck-posframe-mode) +;; :init +;; (setq +;; flycheck-posframe-position 'point-top-left-corner +;; flycheck-posframe-error-prefix "❌ " +;; flycheck-posframe-info-prefix "ℹ️️️ " +;; flycheck-posframe-warning-prefix "⚠️ " +;; flycheck-posframe-prefix "💬 ")) + +(use-package eglot + :ensure nil + :hook + ((python-mode + c-mode + c++-mode + ) . (lambda () (progn + (eglot-ensure) + (add-hook 'before-save-hook 'eglot-format nil 'local)))) + :custom + (eldoc-echo-area-use-multiline-p nil) + (completion-category-defaults nil) + :config + ;; (push '(rustic-ts-mode . eglot-rust-analyzer) eglot-server-programs) + (push '(rustic-mode . eglot-rust-analyzer) eglot-server-programs) + (add-to-list 'eglot-server-programs '((rust-mode) . (eglot-rust-analyzer "rust-analyzer"))) + ;; (add-to-list 'eglot-server-programs '((python-mode) . ("pylsp"))) + ;; (add-to-list 'eglot-server-programs '((c-mode) . ("clangd"))) + :bind (:map eglot-mode-map + ("M-(" . flymake-goto-next-error) + ("C-c ," . eglot-code-actions))) + +(use-package breadcrumb + :config (breadcrumb-mode)) + +;; (use-package lsp-bridge +;; :ensure nil +;; :init +;; (global-lsp-bridge-mode) +;; :config +;; (setq lsp-bridge-enable-debug nil +;; lsp-bridge-enable-auto-format-code 0 +;; lsp-bridge-python-lsp-server 'pylsp +;; lsp-bridge-disable-backup nil +;; lsp-bridge-enable-org-babel 1 +;; acm-enable-search-file-words 0 +;; lsp-bridge-enable-hover-diagnostic 1) +;; ) + +(setq backup-by-copying-when-linked t) + +;; (use-package dired +;; :ensure nil +;; :commands (dired dired-jump) +;; :bind (("C-x C-j" . dired-jump)) +;; :custom ((dired-listing-switches "-agho --group-directories-first")) +;; :config +;; (evil-collection-define-key 'normal 'dired-mode-map +;; "h" 'dired-single-up-directory +;; "l" 'dired-single-buffer)) + +;; (use-package dired-single) + +;; (use-package nerd-icons-dired +;; :hook +;; (dired-mode . nerd-icons-dired-mode)) +;; (use-package nerd-icons-completion +;; :after nerd-icons) +;; (use-package nerd-icons-ivy-rich) +;; (use-package nerd-icons-ibuffer) +;; ;; more colorful dired +;; (use-package diredfl +;; :hook +;; (dired-mode . diredfl-mode)) + +(use-package dirvish + :init + (dirvish-override-dired-mode) + :config + (dirvish-peek-mode) + (dirvish-side-follow-mode) + :custom + (delete-by-moving-to-trash t) + (dired-listing-switches + "-l --almost-all --human-readable --group-directories-first --no-group") + (dirvish-attributes + '(vc-state subtree-state nerd-icons collapse file-time file-size)) + (dirvish-quick-access-entries + '(("h" "~/" "Home") + ("c" "~/.dotfiles/" "Config") + ("d" "~/Downloads/" "Downloads") + ("D" "~/Documents/" "Documents") + ("p" "~/Documents/GitHub/" "Projects") + ("/" "/" "Root"))) + :bind + ((" d" . 'dirvish) + ("C-=" . 'dirvish-side) + :map dirvish-mode-map + ("h" . dired-up-directory) + ("" . dired-up-directory) + ("l" . dired-find-file) + ("" . dired-find-file) + ("j" . evil-next-visual-line) + ("k" . evil-previous-visual-line) + ("a" . dirvish-quick-access) + ("f" . dirvish-file-info-menu) + ("z" . dirvish-history-last) + ("J" . dirvish-history-jump) + ("y" . dirvish-yank-menu) + ("TAB" . dirvish-subtree-toggle) + ("M-f" . dirvish-history-go-forward) + ("M-b" . dirvish-history-go-backward) + ("M-l" . dirvish-ls-switches-menu) + ("M-m" . dirvish-mark-menu) + ("M-t" . dirvish-layout-toggle) + ("M-s" . dirvish-setup-menu) + ("M-e" . dirvish-emerge-menu) + ("M-j" . dirvish-fd-jump))) + +(use-package pdf-tools + :init + (if (not (boundp 'pdf-tools-directory)) + (pdf-tools-install)) + :mode ("\\.pdf" . pdf-view-mode)) + +(use-package openwith) +(openwith-mode t) +;; (setq openwith-associations '(("\\.pdf\\'" "evince" (file)) ("\\.xopp\\'" "xournalpp" (file)))) +(setq openwith-associations '(("\\.xopp\\'" "xournalpp" (file)))) + ;(setq openwith-associations '(("\\.xopp\\'" "xournalpp" (file)))) + +(use-package ein) + +(use-package obsidian + :ensure t + :demand t + :config + (obsidian-specify-path swarsel-obsidian-vault-directory) + (global-obsidian-mode t) + :custom + ;; This directory will be used for `obsidian-capture' if set. + (obsidian-inbox-directory "Inbox") + (bind-key (kbd "C-c M-o") 'obsidian-hydra/body 'obsidian-mode-map) + :bind (:map obsidian-mode-map + ;; Replace C-c C-o with Obsidian.el's implementation. It's ok to use another key binding. + ("C-c C-o" . obsidian-follow-link-at-point) + ;; Jump to backlinks + ("C-c C-b" . obsidian-backlink-jump) + ;; If you prefer you can use `obsidian-insert-link' + ("C-c C-l" . obsidian-insert-wikilink))) + +(use-package anki-editor + :after org + :bind (:map org-mode-map + ("" . anki-editor-cloze-region-auto-incr) + ("" . anki-editor-cloze-region-dont-incr) + ("" . anki-editor-reset-cloze-number) + ("" . anki-editor-push-tree)) + :hook (org-capture-after-finalize . anki-editor-reset-cloze-number) ; Reset cloze-number after each capture. + :config + (setq anki-editor-create-decks t ;; Allow anki-editor to create a new deck if it doesn't exist + anki-editor-org-tags-as-anki-tags t) + + (defun anki-editor-cloze-region-auto-incr (&optional arg) + "Cloze region without hint and increase card number." + (interactive) + (anki-editor-cloze-region swarsel-anki-editor-cloze-number "") + (setq swarsel-anki-editor-cloze-number (1+ swarsel-anki-editor-cloze-number)) + (forward-sexp)) + (defun anki-editor-cloze-region-dont-incr (&optional arg) + "Cloze region without hint using the previous card number." + (interactive) + (anki-editor-cloze-region (1- swarsel-anki-editor-cloze-number) "") + (forward-sexp)) + (defun anki-editor-reset-cloze-number (&optional arg) + "Reset cloze number to ARG or 1" + (interactive) + (setq swarsel-anki-editor-cloze-number (or arg 1))) + (defun anki-editor-push-tree () + "Push all notes under a tree." + (interactive) + (anki-editor-push-notes '(4)) + (anki-editor-reset-cloze-number)) + ;; Initialize + (anki-editor-reset-cloze-number) + ) + +(require 'anki-editor) + +(defvar swarsel-anki-deck nil) +(defvar swarsel-anki-notetype nil) +(defvar swarsel-anki-fields nil) + +(defun swarsel-anki-set-deck-and-notetype () + (interactive) + (setq swarsel-anki-deck (completing-read "Choose a deck: " + (sort (anki-editor-deck-names) #'string-lessp))) + (setq swarsel-anki-notetype (completing-read "Choose a note type: " + (sort (anki-editor-note-types) #'string-lessp))) + (setq swarsel-anki-fields (progn + (anki-editor--anki-connect-invoke-result "modelFieldNames" `((modelName . ,swarsel-anki-notetype))))) + ) + +(defun swarsel-anki-make-template-string () + (if (not swarsel-anki-deck) + (call-interactively 'swarsel-anki-set-deck-and-notetype)) + (setq swarsel-temp swarsel-anki-fields) + (concat (concat "* %<%H:%M>\n:PROPERTIES:\n:ANKI_NOTE_TYPE: " swarsel-anki-notetype "\n:ANKI_DECK: " swarsel-anki-deck "\n:END:\n** ")(pop swarsel-temp) "\n%?\n** " (mapconcat 'identity swarsel-temp "\n\n** ") "\n\n")) + +(defun swarsel-today() + (format-time-string "%Y-%m-%d")) + +(defun swarsel-obsidian-daily () + (interactive) + (if (not (file-exists-p (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory))) + (write-region "" nil (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory)) + ) + (find-file (expand-file-name (concat (swarsel-today) ".md") swarsel-obsidian-daily-directory))) + +(use-package mu4e + :ensure nil + ;; :load-path "/usr/share/emacs/site-lisp/mu4e/" + ;;:defer 20 ; Wait until 20 seconds after startup + :config + + ;; This is set to 't' to avoid mail syncing issues when using mbsync + (setq mu4e-change-filenames-when-moving t) + (setq mu4e-mu-binary (executable-find "mu")) + + ;; Refresh mail using isync every 10 minutes + (setq mu4e-update-interval (* 10 60)) + (setq mu4e-get-mail-command "mbsync -a") + (setq mu4e-maildir "~/Mail") + ;;(setq mu4e t) + + (setq mu4e-drafts-folder "/Drafts") + (setq mu4e-sent-folder "/Sent Mail") + (setq mu4e-refile-folder "/All Mail") + (setq mu4e-trash-folder "/Trash") + + (setq mu4e-maildir-shortcuts + '((:maildir "/leon/Inbox" :key ?1) + (:maildir "/nautilus/Inbox" :key ?2) + (:maildir "/mrswarsel/Inbox" :key ?3) + (:maildir "/Sent Mail" :key ?s) + (:maildir "/Trash" :key ?t) + (:maildir "/Drafts" :key ?d) + (:maildir "/All Mail" :key ?a)))) + +(setq user-mail-address "leon.schwarzaeugl@gmail.com" + user-full-name "Leon Schwarzäugl") + +(let ((mu4epath + (concat + (f-dirname + (file-truename + (executable-find "mu"))) + "/../share/emacs/site-lisp/mu4e"))) + (when (and + (string-prefix-p "/nix/store/" mu4epath) + (file-directory-p mu4epath)) + (add-to-list 'load-path mu4epath))) + +(use-package org-caldav + :init + + (setq org-caldav-url "https://stash.swarsel.win/remote.php/dav/calendars/Swarsele") + (setq org-caldav-calendars + '((:calendar-id "personal" + :inbox "~/Calendars/leon_cal.org"))) + ;; (setq org-caldav-backup-file "~/org-caldav/org-caldav-backup.org") + ;; (setq org-caldav-save-directory "~/org-caldav/") + + :config + (setq org-icalendar-alarm-time 1) + ;; This makes sure to-do items as a category can show up on the calendar + (setq org-icalendar-include-todo t) + ;; This ensures all org "deadlines" show up, and show up as due dates + (setq org-icalendar-use-deadline '(event-if-todo event-if-not-todo todo-due)) + ;; This ensures "scheduled" org items show up, and show up as start times + (setq org-icalendar-use-scheduled '(todo-start event-if-todo event-if-not-todo)) + ) + +(use-package calfw + :bind ("C-c A" . swarsel/open-calendar) + :init + (use-package calfw-cal) + (use-package calfw-org) + (use-package calfw-ical) + :config + (bind-key "g" 'cfw:refresh-calendar-buffer cfw:calendar-mode-map) + (bind-key "q" 'evil-quit cfw:details-mode-map) + ;; (custom-set-faces + ;; '(cfw:face-title ((t (:foreground "#f0dfaf" :weight bold :height 65)))) + ;; ) + ) + +(defun swarsel/open-calendar () + (interactive) + (unless (eq swarsel-caldav-synced 1) (org-caldav-sync) (setq swarsel-caldav-synced 1)) + ;; (select-frame (make-frame '((name . "calendar")))) ; makes a new frame and selects it + ;; (set-face-attribute 'default (selected-frame) :height 65) ; reduces the font size of the new frame + (cfw:open-calendar-buffer + :contents-sources + (list + (cfw:org-create-source "Purple") ; orgmode source + (cfw:ical-create-source "TISS" "https://tiss.tuwien.ac.at/events/rest/calendar/personal?locale=de&token=4463bf7a-87a3-490a-b54c-99b4a65192f3" "Cyan")))) + +(use-package mu4e-alert) +(mu4e-alert-set-default-style 'libnotify) +(add-hook 'after-init-hook #'mu4e-alert-enable-notifications) + +;;show mail + ;;(mu4e) + +(use-package dashboard + :ensure t + :config + (dashboard-setup-startup-hook) + ;; (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))) + (setq dashboard-display-icons-p t ;; display icons on both GUI and terminal + dashboard-icon-type 'nerd-icons ;; use `nerd-icons' package + dashboard-set-file-icons t + dashboard-items '((recents . 5) + (projects . 5) + (agenda . 5)) + dashboard-set-footer nil + dashboard-banner-logo-title "Welcome to SwarsEmacs!" + dashboard-startup-banner "~/.dotfiles/wallpaper/swarsel.png" + dashboard-projects-backend 'projectile + dashboard-image-banner-max-height 300 + dashboard-set-navigator t + dashboard-navigator-buttons + `(;; line1 + ((,"" + "SwarselSocial" + "Browse Swarsele" + (lambda (&rest _) (browse-url "instagram.com/Swarsele"))) + + (,"" + "SwarselSound" + "Browse SwarselSound" + (lambda (&rest _) (browse-url "sound.swarsel.win")) ) + (,"" + "SwarselSwarsel" + "Browse Swarsel" + (lambda (&rest _) (browse-url "github.com/Swarsel")) ) + (,"" + "SwarselStash" + "Browse SwarselStash" + (lambda (&rest _) (browse-url "stash.swarsel.win")) ) + (,"󰫑" + "SwarselSport" + "Browse SwarselSports" + (lambda (&rest _) (browse-url "social.parkour.wien/@Lenno"))) + ) + ( + (,"󱄅" + "swarsel.win" + "Browse swarsel.win" + (lambda (&rest _) (browse-url "swarsel.win"))) + ) + ))) + (setq dashboard-projects-switch-function 'counsel-projectile-switch-project-by-name) + +(fset 'epg-wait-for-status 'ignore) diff --git a/scripts/checkconfigstatus.sh b/scripts/checkconfigstatus.sh new file mode 100755 index 0000000..2e6a998 --- /dev/null +++ b/scripts/checkconfigstatus.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# CFG=$(git --git-dir=$HOME/.cfg/ --work-tree=$HOME diff --numstat | wc -l) +CFG=$(git --git-dir=$HOME/.cfg/ --work-tree=$HOME status -s | wc -l) +CSE=$(git --git-dir=$HOME/Documents/GitHub/CSE_TUWIEN/.git --work-tree=$HOME/Documents/GitHub/CSE_TUWIEN/ status -s | wc -l) +PASS=$(git --git-dir=$HOME/.local/share/password-store/.git --work-tree=$HOME/.local/share/password-store/ status -s | wc -l) + +if [ $CFG != 0 ]; then + CFG_STR='CONFIG' +else + CFG_STR='' +fi + +if [ $CSE != 0 ]; then + CSE_STR=' CSE' +else + CSE_STR='' +fi + +if [ $PASS != 0 ]; then + PASS_STR=' PASS' +else + PASS_STR='' +fi + +OUT="$CFG_STR""$CSE_STR""$PASS_STR" +echo "$OUT" diff --git a/scripts/checkdiscord.sh b/scripts/checkdiscord.sh new file mode 100755 index 0000000..5da9ff5 --- /dev/null +++ b/scripts/checkdiscord.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +STR=$(swaymsg -t get_tree | grep discord) +if [ "$STR" == "" ]; then + exec discord + #exec swaymsg '[class=discord]' move container to scratchpad; scratchpad show +else + exec swaymsg '[app_id=discord]' kill +fi +exit 0 diff --git a/scripts/checkgomuks.sh b/scripts/checkgomuks.sh new file mode 100755 index 0000000..f900db2 --- /dev/null +++ b/scripts/checkgomuks.sh @@ -0,0 +1,12 @@ +#!/bin/bash +STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep gomuksterm) +CHECK=$(swaymsg -t get_tree | grep gomuksterm) +if [ "$CHECK" == "" ]; then + exec kitty -T gomuksterm -o confirm_os_window_close=0 gomuks & sleep 1 +fi +if [ "$STR" == "" ]; then + exec swaymsg '[title="gomuksterm"]' scratchpad show +else + exec swaymsg '[title="gomuksterm"]' scratchpad show +fi +exit 0 diff --git a/scripts/checkkitty.sh b/scripts/checkkitty.sh new file mode 100755 index 0000000..c5327ee --- /dev/null +++ b/scripts/checkkitty.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep kittyterm) +CHECK=$(swaymsg -t get_tree | grep kittyterm) +if [ "$CHECK" == "" ]; then + exec kitty -T kittyterm & sleep 1 +fi +if [ "$STR" == "" ]; then + exec swaymsg '[title="kittyterm"]' scratchpad show +else + exec swaymsg '[title="kittyterm"]' scratchpad show +fi +exit 0 diff --git a/scripts/checkschildi.sh b/scripts/checkschildi.sh new file mode 100755 index 0000000..1bea71d --- /dev/null +++ b/scripts/checkschildi.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +STR=$(swaymsg -t get_tree | grep SchildiChat) +if [ "$STR" == "" ]; then + exec schildichat-desktop + #exec swaymsg '[app_id=SchildiChat]' move container to scratchpad; scratchpad show +else + exec swaymsg '[app_id=SchildiChat]' kill +fi +exit 0 diff --git a/scripts/checkspotify.sh b/scripts/checkspotify.sh new file mode 100755 index 0000000..b2779c5 --- /dev/null +++ b/scripts/checkspotify.sh @@ -0,0 +1,7 @@ +#!/bin/bash + + +# this is a crutch script that is to be used until spotify +# properly sets an app_id upon launch +swaymsg '[app_id="^$"]' scratchpad show +# exec spotify diff --git a/scripts/checkspotify_actual.sh b/scripts/checkspotify_actual.sh new file mode 100755 index 0000000..c94a93d --- /dev/null +++ b/scripts/checkspotify_actual.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +STR=$(swaymsg -t get_tree | grep spotify) +if [ "$STR" == "" ]; then + exec spotify & sleep 2 + exec swaymsg '[class="Spotify"]' scratchpad show +else + exec swaymsg '[class="Spotify"]' scratchpad show +fi +exit 0 diff --git a/scripts/checkspotifytui.sh b/scripts/checkspotifytui.sh new file mode 100755 index 0000000..880f526 --- /dev/null +++ b/scripts/checkspotifytui.sh @@ -0,0 +1,12 @@ +#!/bin/bash +STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep spotifytui) +CHECK=$(swaymsg -t get_tree | grep spotifytui) +if [ "$CHECK" == "" ]; then + exec kitty -T spotifytui -o confirm_os_window_close=0 spt & sleep 1 +fi +if [ "$STR" == "" ]; then + exec swaymsg '[title="spotifytui"]' scratchpad show +else + exec swaymsg '[title="spotifytui"]' scratchpad show +fi +exit 0 diff --git a/scripts/devShell/benchmark b/scripts/devShell/benchmark new file mode 100755 index 0000000..2818314 --- /dev/null +++ b/scripts/devShell/benchmark @@ -0,0 +1,5 @@ +#!/bin/sh +rm -rf build +cmake -S . -B build -D CMAKE_BUILD_TYPE=Release +cmake --build build --target benchmark +./build/benchmark/benchmark \ No newline at end of file diff --git a/scripts/devShell/compile b/scripts/devShell/compile new file mode 100755 index 0000000..ca7ec19 --- /dev/null +++ b/scripts/devShell/compile @@ -0,0 +1,5 @@ +#!/bin/sh +rm -rf build +cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug +cmake --build build --target all +ctest --test-dir build diff --git a/scripts/editor.sh b/scripts/editor.sh new file mode 100755 index 0000000..cb4f495 --- /dev/null +++ b/scripts/editor.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep kittyterm) +if [ "$STR" == "" ]; then + VAR="1" + swaymsg '[title="kittyterm"]' scratchpad show +else + VAR="0" +fi +emacsclient -c -a "" "$@" +if [ "$VAR" == "1" ] +then + swaymsg '[title="kittyterm"]' scratchpad show +fi +exit 0 diff --git a/scripts/editor_nowait.sh b/scripts/editor_nowait.sh new file mode 100755 index 0000000..f510733 --- /dev/null +++ b/scripts/editor_nowait.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +STR=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]) | select(.name == "__i3_scratch")' | grep kittyterm) +if [ "$STR" == "" ]; then + VAR="1" + swaymsg '[title="kittyterm"]' scratchpad show + emacsclient -c -a "" "$@" +else + VAR="0" + emacsclient -n -c -a "" "$@" +fi +if [ "$VAR" == "1" ] +then + swaymsg '[title="kittyterm"]' scratchpad show +fi +exit 0 diff --git a/secrets/general/secrets.yaml b/secrets/general/secrets.yaml new file mode 100644 index 0000000..b5b96b8 --- /dev/null +++ b/secrets/general/secrets.yaml @@ -0,0 +1,55 @@ +mrswarsel: ENC[AES256_GCM,data:d87RitiYFsLpuxdOaI1xLVW6dA==,iv:MX+IDLr6H5lOmbq0RZc7cFPLfuSDoQKxDljKjeZRppA=,tag:QvuoRtS5EbZV9bKr/URnhw==,type:str] +nautilus: ENC[AES256_GCM,data:p0qGJuaNBKbZGRqGzV33SDh4jA==,iv:+EGI9GWsBPIwFz1RK3Hth2PV9OKiWzba9VsRUjUs1Cs=,tag:W+fCUPnFqoR0ggv9j2qafg==,type:str] +leon: ENC[AES256_GCM,data:NdHUj00/cdq1+hKes3irtMEGcA==,iv:jfMyTOznA+bTVBXvrN6Prq0Z0jvLNcm/7x0iauaSvw0=,tag:74c7l5sRjYphQGG8ky+3CQ==,type:str] +caldav: ENC[AES256_GCM,data:cmgO/btKdGG4I6B4MMDMrwFvZuSpAYJZZkw6XJ5qd/qxYaMnvKYzQ1VQUaoxYsxCgunm2/d/76NK3/ZojAaIqFVeN3gnd5wRmFty1g==,iv:nBXUBtfabaAeK5bs9wmEwkeGOK7UUL+kALd3W4qRvc0=,tag:oQaNH8Kdn62T+EVVOgfR8Q==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1zdjm8qa5t25mca0xxhhkpuh85mgg4l267mqjj2pdttksq7zg4unqdmqyp4 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZQU5MS2FxTEg3SGwxNDZq + SmJvbi9tZWtCL3kxVTYydk1YeURWVTBJWkZFCjQyUHRuU2U4ZWVGekpDOUFqTlQ1 + SlNxZTVXZWZ6dVJZQ0QvcG5yNTNPazAKLS0tIG1RTjcvRk5KN3FuakhkdUdYM2Qv + MnJpRGdkZ0dIZ1dEOFF1ZVVXbmdPT3MKBQSQiVjvTvBOdSciHkWoLRaHetw5m200 + SG7+K345GT4pWnQSzSGN26eKDvWNES0tZFIpUB9mpCslgIjpCpvl5Q== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2023-12-08T21:04:26Z" + mac: ENC[AES256_GCM,data:NDRcclJRrK7RjRCfP8jLJ2aXa5LtttIE20i1Her70AqOca9pcb7UV+DD3/lIb/NRM8wbIQMuOw4T7CnAnPTrokzqDTiPkafh3zM+qjV5FFSucktkMtJCKwYePGdS7RZOkydISTWPFVoo7FPX0i51+mGRtzMPhm9lufluITeZ46w=,iv:rxGIUaeEaOGYL5Vp9aB8UXBxX2U+H/Dtm+PEPLMaYis=,tag:0pI11GBOVtiRzcsmQtYRHg==,type:str] + pgp: + - created_at: "2023-12-08T07:40:01Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hQIMAwDh3VI7VctTARAAq7uFn44YEG6/af/V1OyoMrgZ1KGGOmRITE7j1+PHJWmq + wBUwAKXyuSTo5bzRUdynEWdKwYD/7YY+jqO57orcWVql6MJUoxYXNEK3ZF7lDXdL + q1SOnb0FjdNPhPCR2pUByyi/KmvnFBX/OQ8tc16nQ6nZ7KkRdUFPtOFNqX6cGARV + jIu3BoYJn1Aitax2c6Gt8K/OH31o24wp38F7O9tQTImezOjArsfzgTR+aL9UOv1B + uYgDtnKXqSaY20h8nSnBgE3+pxWM75rp8a1JFkbQCWn1dDRWhmfCcdS4GHXfHeKP + jezlNQvi7DfIgN0QxyrMd97MW4bOAMQ7HNT7bH28L3pXRU2OfJdgUFmVG6Iakubh + 2PXyO8vh+KIiZNGhGPCLVOtHiL6UhjZuULCE65Kh4AAm5PsUcbV1vTGi+Vnoq1Ed + 3DAYNjIkXx0pv1RB+d1T4Ym+I6xnm7HKtnY4CZCDeszyi9fluok/a8FbaaNK5qpd + YfS4S+eNymUtz9nEKKFvF5dYM7cqTkVRo0rsBB5gxvaWVxt4iveWHNelYWgfbfAe + bc2gWdZ3vpHjdjxVAISeClqwPKF+ZpZLuwSMoSQxWSMSMC7V6kUl3CF32zdsJT6E + ob0uJ2DILcQj91rd1EDH6RW4eZfvfglV+WlpEH7GkYa413TNem3vsGKYLIe95rSF + AgwDC9FRLmchgYQBD/9UlyxDh7ehiGxf7iX2d//TJLNtDb8yAk4nNb49VEJRq1D2 + +/qaST4dtwIfFR9uqiQVKo6lIk4q3vk9QXUJQsGPIj7GpXiHb+2gxBOqdz7GFihD + 3bXDcVGFRwynz2FWmydwS+NFFaqOe/HBIF9TYE64sxXu8RXDOyLI6cv8zFIv1DqQ + ogZfSJNAqEFjUehWUcW7KA3fFs5/FEPEK07rJu6PVkyi4lWl7AtvZpTNFX7wKY1t + EKzhtpPiPjKR8iMGcEG/S1jf9r7MKzpFlu7QAmONdxQLjWgKV71clHIXt39PVOdP + 6rz/QtWu2nZUBwNZSxiPPssTpONG0iiX4N5u6Pb9hrgw1WLyObwRK9cOeCqEuLMt + LCpVeIt2PV4ozMMfQC6v9PlR3aQcaWLOH9E7ogbXU642kVAIcCv/nsFJtU8QkxwN + JFAU9UBLNa4FssBjeBJx7HyUN8V3jDzmXYZnjcEalH1hzXw4Nl0rkUpiZTPUeCBP + qt2QJQFT4Hn6bUOnM0yzNcwJzXwTMxrjYSs1Kj6Lm6CdelBBnccXqDV/Hc9JR1kc + BM+u8BtUNvTRKSE5sfl93FwYqFgSKJWfmBB6YsgVN6up2lEzUez4kgh9KXlal0Mv + 8ENUKEdIENfU8IPAn8Kyc7SIiW9yugp6g+PoEBc5/aEWiguS+CReCwiM6t6XktJe + Abf3/jzpDVs/X0Y9M70+OxAe//dUoVj0jd52l8uTA4v7s++sfB2vv6DVvW6y3Vrw + l8+JPgcfDXVe4it7pYxCY+EzU1y+g2d3t6XolGqyHJ88d23XRXDQ5Uz/IJhbpw== + =zTtX + -----END PGP MESSAGE----- + fp: 4BE7925262289B476DBBC17B76FD3810215AE097 + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/secrets/keys/gpg-owner-trust.txt b/secrets/keys/gpg-owner-trust.txt new file mode 100644 index 0000000..38a0f53 --- /dev/null +++ b/secrets/keys/gpg-owner-trust.txt @@ -0,0 +1,3 @@ +# List of assigned trustvalues, created So 17 Sep 2023 03:37:14 CEST +# (Use "gpg --import-ownertrust" to restore them) +4BE7925262289B476DBBC17B76FD3810215AE097:6: diff --git a/secrets/keys/gpg-public-key-0x76FD3810215AE097.asc b/secrets/keys/gpg-public-key-0x76FD3810215AE097.asc new file mode 100644 index 0000000..7ced3de --- /dev/null +++ b/secrets/keys/gpg-public-key-0x76FD3810215AE097.asc @@ -0,0 +1,109 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGUGVBIBEADDpv7vQpXqxKU1xIo//KtTHpeLxQ0V1KYGRA8uKJCsu5SUgCza +R1CaSfPZ0lIikpXJ6G4Mi7l9orLZUvidfCq6pvdje6kJjv9IEp41bcdYrhMQVfm8 +jeqFGJhMxobUY6Ca3gx+6gXVjchMFS3fGcGxvHSjkiVeeLEcilZ9oYQu/fvcDhqz +GVNB1dlNH/ddECtp5mKMeYVuou8rWKUIO2YkTwj/mRjgoggZZyifYMMFIfYRGKHS +wNakmcduTCGpgO5rnD61Q+m3zbtu6oxJb1gqvKiJ1a8ZdtGs6e5jWh0ob0oNxeo0 +iJby2RKDtVSlJ0vXEc9vVxemHH2xBMkd46sy+6UZx33Kuy09DL12KioM48CGNBbT +Z2kcRoTY8zCV7XCpAnMuPEqDtARUZhtSwReXKgQxbjYYesQeO3KrpDO8yaAaBXJu +PWeb4UzE+d0JcfzfuW0mAvGre5nozHfXXc2AmX8iI3dXB5jkO4YyP7tdvcvbq5PZ +73ocbLsHijreR1tfwXquP5QfDHgfkl+gKIxi2X8LL/6DrhAARzd7xHtBBAVoQbWB +AxhhezjjDi4Oy4WyO7rZuFstWgmYWEN6S6MHnpMmORRM8GyLKcVW+VUkws6oqhuW +rIqULVWvZyWh9Rcz9Pawv6V6v8u58eWQYdQLhx425T2IM9ci5IOF5pJlJQARAQAB +tC9MZW9uIFNjaHdhcnrDpHVnbCA8bGVvbi5zY2h3YXJ6YWV1Z2xAZ21haWwuY29t +PokCTAQTAQoANhYhBEvnklJiKJtHbbvBe3b9OBAhWuCXBQJlBlQSAhsBBAsJCAcE +FQoJCAUWAgMBAAIeBQIXgAAKCRB2/TgQIVrgl6cmEACnlMgjXfjbwMuj68n5KBv3 +oFbfEyfJZ1nC6jwBcwaY4Mp5qT6JJPO/q8v+Px6hdmugKVUitbmlQASFP6/yOR3I +/mGnnG5GoTVcO7xWA+DqfDnac/br1vj54wxY9m9l7bcCbkFZ8wF4u2C67EfBLCcv +pIIIkjLec1vCoOBubeVIMx9A6GJ032XlYre6d7kPW61QbBAIHcsiM5Beho1RXdK4 +mC/dyaqQk1/Ucke1t27cl8GXcQnpEtzx1pB8KJEDv4DyGNZHPO7c7N1dJopNwSf9 +jA35Mw90PUb2BV0+tiM/3rx3/QCSuWTplmje4NvrVIcQjtjYK2UjpJzOlKS4/cMg +P32KEBVFW9Qzq1JSmd0ZnMZPljIuXX3HLe8MD0MJFcj1KqEGPBG+Ifp5uLbxyPFb +FeA5guCJ4SPAtkLnUhEv493+yHrB4jngCg1mdtYGZs+3vVuhEI0dENbkC9ymHz3e +xEXBBC7/5jCTa7BdKpTEcl/49VyLixPI0NSQ3tQXmuEzFNPE/bHlYNlTTkTw+8fx +WsAJveZxsTk7yu/s4T3VmaYVIF7YBzOLeh1MuABm7cLy1JCURIRiPsk4wKzIBOyt +b5qyVUPCoLSbpxlyF2w23O2rX4bkKUlWAv1iHWlBNS4vsMwUD4xELd9FeJLPO5uU +g2aDaeChd1LsDw9sTwXHObkCDQRlBlRgARAAtLXcd/2I3gD6PoSRI4RRVwCmjM+q +Yw0o+lWSMUWrHO2rNgiffbQ16ivK7Fg7IUdCiVlE6gCRPe77T3VyUe4gmyW/+eI7 +9LLXIRQett1j7lSTasHm8fvp436OXlzRDjaz0UNj26NCqoRXkp3rWcfhdGmCbmy8 +D3KZXPC8za1HafHk+YajI8Sqe4qQ5FxFEycQjDCRzC+CQ7VtPmQR7Hov9VbrpDtL +30eTBDJ7PR2sUJeBZrgOyEAtjN/0x0jCaaXp4JYnVO7Y2qNeJYZhhdjs+rzlWfT2 +wxXlTYCpHk3FlBp+H0yDblPUcwJSukxDDiGafs2O7s7zvVMyjyW6GLaCbGJeyT7G +b+m2zQdPc37bRFPfQ4nyhecf3jWVQRkU6zgC/eFtxOd6QPSLbmEo1Rmbpvf1uH1K +VZ7t4Zr+KgbK8dKC2mI9SQxIhas3AwTyzo4+/p5mUBDOpfa9/xyn46KEs+YAaHBp +05rtPxAxkcU6AGVWIMdxgrfL2GtR2Xy//Z9sOGMxF5GwEeEXDob/chU8QfBXeony +veWHFBTU8TRB5ePVYrQvTBBWCAsKwIly468tJgXmnnFHWrgw2ONWVgYOcnfAP45Y +HywRAVCP5EZ/NEQs0k/rqkUvVsOiBIW76bsBqTZVmJxdJ/tcFTxTyerYQZe4MA2R +V8XqaZiKXKAp2FEAEQEAAYkEbAQYAQoAIBYhBEvnklJiKJtHbbvBe3b9OBAhWuCX +BQJlBlRgAhsCAkAJEHb9OBAhWuCXwXQgBBkBCgAdFiEEENk/FW6JNZXEHmL2JqVM +MfKk/YQFAmUGVGAACgkQJqVMMfKk/YQlxw//RAyw+cvWDw6F/gmtxuLpXrRdGymo +ruG4lV5Z2HWX2KPWu5gvjz0X0rd0CajEvDzoWNnNbq/eIe4/nABdBjChvxhlEiJH +nDE3MUl5gujvsixix1iBq50XTmusGZQsj7VnDw2GuASpoBstUXQKOZrdMOkLW28j +601EdDWDPkGGBAh2rT7mfQmFQYORb8rlskcn/fEHwC4p7T0ntLIi6u92ts+gnqPx +gusYP728sR7lPukGxC1Y7MlXQY/BEIxiDkLYrqfFSMI4RxtDmiPMS+8Si9usIyNU +2H55D0P4dYNVDnyGw1oBlzK6oLakMDxrfHuSfApUBKURrM3scItn/4UWCqXyUJAl +s72LWLAuDNAMTESWaZJJul1v2gk/6HPm7SuMllL0KPZ4NbIZRsKjUUSHTnK97gXL +PsVJ699DcEJr9IQ+KIGEwVA7OyXCzB7y88NHvtPCXmm4Jb6Qv6dd0P9Si+D10bSu +44eonoCVDuJtjkASo42chJnyJC2SSxMcb6tCxnsNlZf/LyKDnUU1SnvsCTrb4vKh +HJGKUFpmya0rqqEj4YAPswl3gPLRFIOST4Yg89ErP6QqqC56+rr56NbEYRHhAtg2 +kdfCPO0RvAekg5dAtnKH9+e/MLf9AKIf1bJbS+QQrxZVySRUxH/rAZ1OU1myTU9r +YbAU+RZkqqr9r+jJMA//cSSVA49vZnSdNCyJbXDJ9sENRUcPSFm7QGE1TninG2Tq +XDDgUIMulzuFeZBa9KmSeJ+19T3LWNsXtOJlZ39l8qIu3V8r2GIjqmG3VHl2dNpp +uOug2Cq/lPOsP2TC9eSq2tMKgeU4XWf2s6Ux1c0Y3t5laRQgSZVHXABJUCcYZ/kn +Xk+GfW208cE5EZhowxanebfABs7Apc7+10m17Ki9juh3kUBXvJtk/zDZ84wwmC2M +SxrYpY7mucL/smu4eq2igu21e7ndKqsb4qUWAPytriWUzFxowyktdMRA6bWHafRk +I+kUdDLaNkdmFNK4Hq/On54oAYzs+xQftSj5ppNm/yfVgLtfQzgIWvXjhchAznqc +8u3LJZ70dw1AwDSQvQdmIBSIM+/Y+6QWwuxgONpyXdFVf6/R3+GQoj7EVieHMUkC +rEfr97JIrt78iwLOD1TmdGxwcmW98zvvGVnuSmTDPK0JQ9R6vI7fhc2Jban0VDW5 +hEbiXC79R3a+0r3/Ks9pnxfXuJq8nqEKkoL7g5yQ0Jz59ZIG5EiPemmrY4Lz6R6/ +uNLiXYkbu7rBippkSFVn6+ih51aJsRGerjDl2YBhWq3SwvgEOtNyw0aWAm12gOb/ +OntB//C7tccgM+IRLuHeVvyPZOQNZLIeOofe200eNtRtKVEiqSk7uSse74yVaey5 +Ag0EZQZUbwEQAMw+yGZhHMIQP24F/bKI9GJwsJIzLtzKFiobpaDeKp8hKf06oicV +lC0Hf6oBF6l+4QDzu+vBN2IilY+RovatrwI96iUZ6xw9KfmNeGuWVudmMmzkIcIW +PFoc5T04J28M0kPHPgyh0a29Mcqzsn6BCLTjQP/kTFkSI3NzoDP6RcTPThYlase7 +PeMqJh9MJLqCR++YDoZMm/nj2jXKPyXfucicyonIl1Qdf/+nPC2vROR8bv41qKT5 +hoh5hrvA8jhWlJ3SyHvB2SnqObOsJPaGj9ofFYih0SKyVQOlJyfFrACQD5pl/1AX +9op0ZImkrpGFRd4CoEeOQS2Sr5UZuFowGGUngnoDgT6qJPWNui4TjlekJdFTFQ8r +kjtVGeVI4USQ0XCDqYFycpCittH2BdgqYRTZfb/fSPetUFOoAG7R0WcWloEMunHL +47BEEdDWJOLta8nuJPsUWMUnPJMR+wRprIdOQsL+OaKy7IO11k8vLRaRnHewCHTi +tfArNTLYUzUdA4Nt4hZHCD1PZvRB3dHgDeldLLvhUPyE8csREuT8IEAWsYhfubFr +HAkFd9PJtUBKg1q3hlyWuaRSCjXhkyEUXRTOw94eyH5q2hWZIGJTmWOxSKUp8erq +P1Emi1gl5/hI1HZJWhcYeCAWkN0zKLKYvQbDtb5kW+kO0Vb1H/ECwphHABEBAAGJ +AjYEGAEKACAWIQRL55JSYiibR227wXt2/TgQIVrglwUCZQZUbwIbDAAKCRB2/TgQ +IVrglzrYEACkejMr595fzBqNKWePfNB9Dx3OXrt+uAjviPc6e5taEmH1wVNIhcPz +P2SVKUjyZXxXo7gs6jvA6s+d65WWjGaKWEcrj6KtEDV5iHVqvYAU/A1+wch+XCEK +gDm4teIROLp2VgXvcHXheaxgh4UCnNKPPi9HrIqeOBfkMITrJe512NWSOKidlDpy +9J5DZiC4/+8ITCSrCXGvsTNx7n6HLhpym2NC9xqVKv+FwiLPdnHGGVONcOE/WCpS +gXbhoY/5ClrdiS6E2hIKoi+YUc/+IBuBSRMyo2sur8Js4vCAg0mdd/2Deu0kW4Ld +0ku4J6WEEUOq3Kjuq9bpQ+O5ZPh+JdQL5gndnzqiC2q0XxC+ZcFWCeXoZVnD31Y8 +wXt681xV3gyFZ34dlAMc1+WnT8E1gwJXSYyHyXWmp+gD64gScBuXrXVjFsInWTBf +zdR8G4Nl5FjhNdYRejGcOyTOSuRW3XPhUBruh8edpy6DXSnXk2Q2oKBnTfWa+lN5 +eiulIOBxz0lh7IPzaepoXi8SGg7v5Muve9shRXoByJCIvheiV1i22/6iURIZTFIu +Vz1puI2u22BElyvdIqWPZXR/vlFOh/2N39WrPttjPsq0mPz4XNLQz5BCvt6JyyUK +AhKHf5C01wbtmv7WvlbwM+MOyrjeU5YZyEPuLegC2BMklVsffTJRiLkCDQRlBlSA +ARAA3dF16C30RNAMmrMbHBAcDKjpy1j6sM/nrRqs1TXksP0XIJ8TovdN5pVYwh/o +81jEnthlUoM4DNtI/6/bHxNj9c/sKv0TgxUtOCTNJbVKBZJJvyA2V0NqYjpOwKFY +uWo3ceBIgZ12PO478YeXAoEJbZI96LjxexVTfzGjdtSIFmAfDYJGlRn7f/zqZaHZ +Q0DaLde3NLBTIm2NB3KrsJh4aijrSjNYE/fPo2ZdK3dawqlxTr5HrFuhTwuJ84qz +2ovh4s6eYJ3K5CTmZiy6q41cej36UM6syIaFJ9WEuQqcn15ymVIMdjovEhDZljmf +Q8WLw5JYBLbaG9+xNmyF21ITsP7uCN6JRhYArCi+o4NDfnebXhGgmRZ85TqdFDFo +lKO5VaquwcJd6zZGtqcRHWfb/9fpvXCYj+4eqZypnHFRpLue4hiA57J6E65qNamw +I3vhLJj2G3PqjJ0w7znUh0zl547Mk3fgA5JbzBwlALn+pLuJLUBIZWcVNz72Lyh2 +tXEwhF8S1o8rSIB4E4Gm/TOSB9vUOeS0kUUAc1HZMIzhuiobKhvsRBOtN/BG169D +Bik5tNQBZnlWVnsJpEi7tlHaDjIsPJk0kIUBX6dkK7mB54e6CQqO7bSk9bC6EV/k +34EJta8p/6K4UXoNhhX5m4ixsWiRlTb46gsaqyBUF8eGQx8AEQEAAYkCLQQYAQoA +IRYhBEvnklJiKJtHbbvBe3b9OBAhWuCXBQJlBlSAAxsgBAAAoKoQALCyOgo+lCnn +uX6lriqs+qhqvRDjkGpVUwm810bHB87DB1kRuJ9KKf2JImu5RJkxHnrubj6Kik+w +0pJrsLR5fcvRymPM3jncN4kDYWptbnh5EaFxQg4252aRxTiDqL4srBblGRalFU2c +z1pJSgSjp4JItS94I3v9cxqsZ+vGUd4tgDK99HkwjS0vMsHjBWQudGxDM4NAeip5 +X12t5LI7GfYeR7yE8a1xSp45P8AwRz5GnSVuwh0ti6ocCylUzpPSrkjM/eA+TwRT +9+ws656tlI8aIiXKA1RrAcRfMosTYqbhHWn32SVUoOrEsnVNcZ0k7gpAKQ9aqJee +vsNVq/djTu/+QchvAS65RZpSG5VuKs13cnU6ljcuExlNDbaUrHwNSbXrIqLHhaWz +Hzo2KRn9/6ObWyEcdscVGxvPjyvPLxl2VLTMB3JMT+Z9gPStgm98mb7D5dvQbrLB +R5PJ209Mr4Ej2ci+UwZQ8DSLK6aFDm2Xz3+FRJAZHtx1160fRTNfBW9SeqGwa76c +Im6xUj2snmYubUBDhF7NyRGzM9rddO97F/gWOORknE+Dw8MyEFyizk7Gmtu4fAH7 +478GJars358WWC5stvK62OudLonSw73aL7DrXRZ28aDpOZRtvnhH5+dQ4CmiyEEC +dF/fBNFmNC2yUJ6dc2F1iU9S7jY4TiCv +=KpA6 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/secrets/keys/nixos.pub b/secrets/keys/nixos.pub new file mode 100644 index 0000000..d6f1842 --- /dev/null +++ b/secrets/keys/nixos.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGPg63pYhrS2UAzFvcmqGrCkp/DG/NihDO/JS3kBs/J+ swarsel@nixos diff --git a/secrets/keys/stand.pub b/secrets/keys/stand.pub new file mode 100644 index 0000000..c7fb866 --- /dev/null +++ b/secrets/keys/stand.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMr0iwKZtJDYfs4WJ1PfgDHcP1/9KqQOoqTSKWrZerUu stand sops diff --git a/secrets/keys/surface.pub b/secrets/keys/surface.pub new file mode 100644 index 0000000..e246dde --- /dev/null +++ b/secrets/keys/surface.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA0GIpY0NvYTKS9BWwl3G9qZtq65LqsrcVDMJzctzB2G surface sops diff --git a/templates/cpp_flake.nix b/templates/cpp_flake.nix new file mode 100644 index 0000000..58f9dd4 --- /dev/null +++ b/templates/cpp_flake.nix @@ -0,0 +1,38 @@ +# flake.nix +{ + description = "C/C++ environment"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = {nixpkgs, ...}: let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + llvm = pkgs.llvmPackages_latest; + in { + devShells.${system}.default = pkgs.mkShell { + + packages = with pkgs; [ + gcc + #builder + cmake + gnumake + #headers + clang-tools + #lsp + llvm.libstdcxxClang + #tools + cppcheck + valgrind + doxygen + ]; + hardeningDisable = ["all"]; + # direnv does not allow aliases, use scripts as a workaround + shellHook = '' + PATH_add ~/.dotfiles/scripts/devShell + ''; + # ... + + }; + }; +} diff --git a/templates/cu_flake.nix b/templates/cu_flake.nix new file mode 100644 index 0000000..931ed32 --- /dev/null +++ b/templates/cu_flake.nix @@ -0,0 +1,46 @@ +# flake.nix +{ + description = "CUDA environment"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = {nixpkgs, ...}: let + system = "x86_64-linux"; + pkgs = import nixpkgs { system = "x86_64-linux"; config.allowUnfree = true; }; + llvm = pkgs.llvmPackages_latest; + in { + devShells.${system}.default = pkgs.mkShell { + + packages = with pkgs; [ + # gcc + #builder + # cmake + # gnumake + #headers + clang-tools + #lsp + # llvm.libstdcxxClang + # cudaPackages.cuda_nvcc + #tools + cppcheck + valgrind + doxygen + cudatoolkit + + (pkgs.python3.withPackages (python-pkgs: [ + python-pkgs.numpy + python-pkgs.pandas + python-pkgs.scipy + python-pkgs.matplotlib + python-pkgs.requests + python-pkgs.debugpy + python-pkgs.python-lsp-server + ])) + ]; + hardeningDisable = ["all"]; + # ... + + }; + }; +} diff --git a/templates/py_flake.nix b/templates/py_flake.nix new file mode 100644 index 0000000..5664ef9 --- /dev/null +++ b/templates/py_flake.nix @@ -0,0 +1,28 @@ +{ + description = "Python Flake"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = {nixpkgs, ...}: let + system = "x86_64-linux"; + pkgs = nixpkgs.legacyPackages.${system}; + in { + devShells.${system}.default = pkgs.mkShell { + + packages = [ + (pkgs.python3.withPackages (python-pkgs: [ + python-pkgs.numpy + python-pkgs.pandas + python-pkgs.scipy + python-pkgs.matplotlib + python-pkgs.requests + python-pkgs.debugpy + python-pkgs.flake8 + python-pkgs.gnureadline + python-pkgs.python-lsp-server + ])) + ]; + }; + }; +} diff --git a/templates/rust_flake.nix b/templates/rust_flake.nix new file mode 100644 index 0000000..eb6ff27 --- /dev/null +++ b/templates/rust_flake.nix @@ -0,0 +1,36 @@ +# flake.nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + rust-overlay.url = "github:oxalica/rust-overlay"; + }; + + outputs = {self, nixpkgs, rust-overlay, ...}: let + system = "x86_64-linux"; + pkgs = import nixpkgs { + inherit system; + overlays = [rust-overlay.overlays.default]; + }; + toolchain = pkgs.rust-bin.fromRustupToolchainFile ./toolchain.toml; + in { + devShells.${system}.default = pkgs.mkShell { + + packages = with pkgs; [ + cargo + clippy + rustc + rustfmt + toolchain + rust-analyzer-unwrapped + rust-analyzer + ]; + env = { + RUST_BACKTRACE = "full"; + }; + RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library"; + + # ... + + }; + }; +} diff --git a/templates/tex_standard.tex b/templates/tex_standard.tex new file mode 100644 index 0000000..293e1b3 --- /dev/null +++ b/templates/tex_standard.tex @@ -0,0 +1,29 @@ +\documentclass[11pt]{article} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{graphicx} +\usepackage{longtable} +\usepackage{wrapfig} +\usepackage{rotating} +\usepackage[normalem]{ulem} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{capt-of} +\usepackage{hyperref} +\usepackage{verbatim} +\usepackage{listings} +\author{Leon Schwarzäugl} +\date{\today} +\title{--NAME--} +\hypersetup{ + pdfauthor={Leon Schwarzäugl}, + pdftitle={--METADATA-NAME--}, + pdfkeywords={}, + pdfsubject={}, + pdfcreator={Emacs 30.0.50 (Org mode 9.6.12)}, + pdflang={English}} +\begin{document} + + + +\end{document} diff --git a/templates/toolchain.toml b/templates/toolchain.toml new file mode 100644 index 0000000..e27fc5d --- /dev/null +++ b/templates/toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +channel = "stable" +components = [ + "rust-src" + # ... +] diff --git a/wallpaper/lenovowp.png b/wallpaper/lenovowp.png new file mode 100644 index 0000000..53a7716 Binary files /dev/null and b/wallpaper/lenovowp.png differ diff --git a/wallpaper/serverwp.png b/wallpaper/serverwp.png new file mode 100644 index 0000000..f5a4fe3 Binary files /dev/null and b/wallpaper/serverwp.png differ diff --git a/wallpaper/standwp.png b/wallpaper/standwp.png new file mode 100644 index 0000000..8e0b1ea Binary files /dev/null and b/wallpaper/standwp.png differ diff --git a/wallpaper/surfacewp.png b/wallpaper/surfacewp.png new file mode 100644 index 0000000..fc21650 Binary files /dev/null and b/wallpaper/surfacewp.png differ diff --git a/wallpaper/swarsel.png b/wallpaper/swarsel.png new file mode 100644 index 0000000..713bc09 Binary files /dev/null and b/wallpaper/swarsel.png differ diff --git a/wallpaper/swarsel.yaml b/wallpaper/swarsel.yaml new file mode 100644 index 0000000..772524b --- /dev/null +++ b/wallpaper/swarsel.yaml @@ -0,0 +1,35 @@ +# scheme: "better-contrast" +author: "Swarsel" +base00: "1D252C" # #1d252c passt +base01: "171D23" # #171d23 +base02: "5EC4FF" # #5EC4FF +base03: "566C7D" # #566C7D passt +base04: "5EC4FF" # #5EC4FF passt +base05: "A0B3C5" # #A0B3C5 passt +base06: "C06ECE" # #C06ECE passt +base07: "A0B3C5" # #A0B3C5 passt +base08: "D95468" # #D95468 passt +base09: "FFA880" # #ffA880 passt +base0A: "5EC4FF" # #5EC4FF +base0B: "8BD49C" # #8BD49C +base0C: "008B94" # #008B94 passt +base0D: "5EC4FF" # #5EC4FF passt +base0E: "C06ECE" # #C06ECE passt +base0F: "5EC4FF" # #5EC4FF passt + +# base00 - Default Background +# base01 - Lighter Background (Used for status bars) +# base02 - Selection Background +# base03 - Comments, Invisibles, Line Highlighting +# base04 - Dark Foreground (Used for status bars) +# base05 - Default Foreground, Caret, Delimiters, Operators +# base06 - Light Foreground (Not often used) +# base07 - Light Background (Not often used) +# base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted +# base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url +# base0A - Classes, Markup Bold, Search Text Background +# base0B - Strings, Inherited Class, Markup Code, Diff Inserted +# base0C - Support, Regular Expressions, Escape Characters, Markup Quotes +# base0D - Functions, Methods, Attribute IDs, Headings +# base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed +# base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. diff --git a/wallpaper/user.png b/wallpaper/user.png new file mode 100644 index 0000000..86d9a1b Binary files /dev/null and b/wallpaper/user.png differ