Dotfiles

This is my setup script for Linux Mint 22.1:

sudo apt update
sudo apt install emacs git homebank keepassxc

sudo locale-gen 'de_DE.UTF-8'

git clone https://github.com/fwinkelbauer/chunkyard ~/Projects/chunkyard
git clone https://github.com/fwinkelbauer/fwinkelbauer.github.io.git ~/Projects/website

emacs -Q --batch -l org --eval '(org-babel-tangle-file "~/Projects/website/content/notes/dotfiles.org")'

Git

[user]
  email = mail@florianwinkelbauer.com
  name = Florian Winkelbauer
  signingKey = ~/.ssh/git-commit.ed25519.pub

[gpg]
  format = ssh

[commit]
  gpgSign = true

[tag]
  gpgSign = true

[fetch]
  prune = true
  pruneTags = true

[push]
  followTags = true

[merge]
  ff = only
  conflictStyle = zdiff3

[tag]
  sort = version:refname

[log]
  date = iso

[init]
  defaultBranch = main

[url "git@github.com:fwinkelbauer/"]
  insteadOf = "https://github.com/fwinkelbauer/"

Chunkyard

A utility script to access my backup:

chunkyard "$@" --repository ~/.chunkyard --password 'Libsecret'

Create new backup:

directories=(
    ~/.local/share/fonts
    ~/.ssh
    ~/Documents
    ~/Music
    ~/Pictures
    ~/Videos
)

includes=(
    '!\~$'
    '!\.uuid$'
    '!authorized_keys$'
)

chunkyard store --directory "${directories[@]}" --include "${includes[@]}" --repository ~/.chunkyard --password 'Libsecret' "$@"

Restore the latest backup:

chunkyard restore --repository ~/.chunkyard --directory ~/ --password 'Libsecret' "$@"

chmod 700 ~/.ssh
chmod 600 ~/.ssh/*

Copy local backup data from/to external devices:

local=~/.chunkyard

remotes=(
    /media/florian/Backup1/Florian/main.chunkyard
    /media/florian/Backup2/Florian/main.chunkyard
    /media/florian/DORA1/main.chunkyard
)

for remote in "${remotes[@]}"; do
    if ! [ -d "$remote" ]; then
        echo "Missing: $remote"
        continue
    fi

    if ! [ -x "$(command -v chunkyard)" ]; then
        cp "$remote/chunkyard" ~/.local/bin/
        chmod +x ~/.local/bin/chunkyard
    fi

    echo "Synchronizing with: $remote"
    chunkyard copy --repository "$local" --destination "$remote" --password 'Libsecret' --last 20 "$@"
    chunkyard copy --repository "$remote" --destination "$local" --password 'Libsecret' --last 20 "$@"
done

Homebank

A script to turn my bank statements into csv files that I can import into Homebank:

input=$(find ~/Downloads -name 'meinElba*.csv')
output=~/Downloads/homebank.csv

awk '{ FS=";"; gsub("\"", ""); print $1 ";8;;;" $2 ";" $4 ";;" }' "$input" > "$output"
rm "$input"
read -rp "Press Enter to delete $output: "
rm "$output"

Emacs

(require 'package)

(package-initialize)

(setq package-selected-packages '(magit vertico orderless embark consult embark-consult modus-themes)
      global-auto-revert-non-file-buffers t
      gc-cons-threshold (* 64 1024 1024)
      use-short-answers t
      backup-inhibited t
      auto-save-default nil
      create-lockfiles nil
      visible-bell t
      inhibit-startup-message t
      initial-scratch-message nil
      column-number-mode t
      sentence-end-double-space nil
      require-final-newline t)

(setq-default fill-column 80
              indent-tabs-mode nil)

(add-to-list 'initial-frame-alist '(fullscreen . maximized))
(pixel-scroll-precision-mode)
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(blink-cursor-mode -1)
(set-face-attribute 'default nil :family "JetBrains Mono" :foundry "JB" :slant 'normal :weight 'medium :height 120 :width 'normal)
(global-auto-revert-mode t)
(delete-selection-mode t)
(add-hook 'before-save-hook #'delete-trailing-whitespace)
(show-paren-mode t)

(defun fw/split-window-vertically ()
  "Split the selected window into two vertical windows."
  (interactive)
  (split-window-vertically)
  (other-window 1))

(defun fw/split-window-horizontally ()
  "Split the selected window into two horizontal windows."
  (interactive)
  (split-window-horizontally)
  (other-window 1))

(use-package dired
  :hook (dired-mode . dired-hide-details-mode)
  :custom
  (dired-auto-revert-buffer t)
  (dired-dwim-target t)
  (dired-listing-switches "-alhv --time-style=+%Y-%m-%d --group-directories-first"))

(use-package org
  :hook (org-mode . (lambda () (electric-indent-local-mode -1)))
  :config
  (setq org-directory "~/Documents/org/"
        org-default-notes-file (concat org-directory "inbox.org")
        org-agenda-files (list org-directory)
        org-edit-src-content-indentation 0)

  (setq org-capture-bookmark nil
        org-capture-templates '(("i" "Inbox" entry (file org-default-notes-file)
                                 "* %?" :empty-lines-before 1)))

  (setq org-agenda-custom-commands
        '(("." "Overview"
           ((agenda ""
                    ((org-agenda-overriding-header "Kalender\n")
                     (org-agenda-prefix-format " %-11c%?-12t")
                     (org-agenda-time-grid '((daily today require-timed)
                                             (800 1000 1200 1400 1600 1800 2000)
                                             " ....."
                                             "----------------"))
                     (org-agenda-time-leading-zero t)
                     (org-agenda-show-future-repeats nil)
                     (org-agenda-current-time-string "<<<<<<<<<<<<<<<<")
                     (org-agenda-scheduled-leaders '("" ""))
                     (org-agenda-skip-deadline-prewarning-if-scheduled t)))
            (todo "*"
                  ((org-agenda-overriding-header "\nSonstiges\n")
                   (org-agenda-block-separator nil)
                   (org-agenda-prefix-format "%-11c%?-12t")
                   (org-agenda-sorting-strategy '(todo-state-up))
                   (org-agenda-todo-ignore-deadlines 'all)
                   (org-agenda-todo-ignore-scheduled 'all)))))))

  (setq calendar-week-start-day 1
        calendar-day-header-array ["So" "Mo" "Di" "Mi" "Do" "Fr" "Sa"]
        calendar-day-name-array ["Sonntag" "Montag" "Dienstag" "Mittwoch" "Donnerstag" "Freitag" "Samstag"]
        calendar-month-name-array ["Jänner" "Februar" "März" "April" "Mai" "Juni" "Juli" "August" "September" "Oktober" "November" "Dezember"]
        calendar-holidays '((holiday-fixed 1 1 "Neujahr (frei)")
                            (holiday-fixed 1 6 "Heilige Drei Könige (frei)")
                            (holiday-fixed 2 14 "Valentinstag")
                            (holiday-easter-etc 1 "Ostermontag (frei)")
                            (holiday-easter-etc -46 "Aschermittwoch")
                            (holiday-easter-etc -2 "Karfreitag")
                            (holiday-fixed 5 1 "Österreichischer Staatsfeiertag (frei)")
                            (holiday-easter-etc 39 "Christi Himmelfahrt (frei)")
                            (holiday-easter-etc 50 "Pfingstmontag (frei)")
                            (holiday-easter-etc 60 "Fronleichnam (frei)")
                            (holiday-float 5 0 2 "Muttertag")
                            (holiday-float 6 0 2 "Vatertag")
                            (holiday-fixed 8 15 "Mariä Himmelfahrt (frei)")
                            (holiday-fixed 10 26 "Nationalfeiertag (frei)")
                            (holiday-fixed 11 1 "Allerheiligen (frei)")
                            (holiday-fixed 12 8 "Maria Empfängnis (frei)")
                            (holiday-fixed 12 24 "Heiliger Abend")
                            (holiday-fixed 12 25 "Erster Weihnachtstag (frei)")
                            (holiday-fixed 12 26 "Zweiter Weihnachtstag (frei)"))
        parse-time-weekdays '(("so" . 0) ("mo" . 1) ("di" . 2) ("mi" . 3) ("do" . 4) ("fr" . 5) ("sa" . 6)))

  (defun fw/org-capture-inbox ()
    "Opens my `org-capture' inbox template."
    (interactive)
    (org-capture nil "i"))

  (defun fw/org-overview ()
    "Show my inbox and custom org-agenda."
    (interactive)
    (delete-other-windows)
    (find-file org-default-notes-file)
    (org-agenda nil ".")))

(use-package magit
  :ensure t
  :custom
  (magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)
  (magit-save-repository-buffers 'dontask)
  (magit-repository-directories '(("~/Projects" . 1))))

(use-package vertico
  :ensure t
  :config
  (vertico-mode)
  (keymap-set vertico-map "DEL" #'vertico-directory-delete-char))

(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles partial-completion)))))

(use-package embark
  :ensure t
  :custom
  (prefix-help-command #'embark-prefix-help-command))

(use-package consult
  :ensure t
  :config
  (defun fw/find-file ()
    "Find files in current project or directory."
    (interactive)
    (if (project-current)
        (project-find-file)
      (consult-find)))

  (defun fw/grep ()
    "Run grep in current project or directory."
    (interactive)
    (if (project-current)
        (consult-git-grep)
      (consult-grep))))

(use-package embark-consult
  :ensure t)

(use-package modus-themes
  :ensure t
  :config
  (load-theme 'modus-operandi-tinted t))

(bind-keys :prefix "<menu>"
           :prefix-map fw/main-map
           ("RET" . embark-act)
           ("w" . save-buffer)
           ("f" . find-file)
           ("s" . consult-line)
           ("q" . query-replace)
           ("l" . consult-goto-line)
           ("k" . kill-current-buffer)
           ("b" . consult-buffer)
           ("h" . mark-whole-buffer)
           ("0" . delete-window)
           ("1" . delete-other-windows)
           ("2" . fw/split-window-vertically)
           ("3" . fw/split-window-horizontally)
           ("o" . other-window)
           ("." . highlight-symbol-at-point)
           ("r" . highlight-regexp)
           ("u" . unhighlight-regexp)
           ("SPC" . rectangle-mark-mode)
           ("t" . string-rectangle)
           ("d" . delete-rectangle)
           ("?" . count-words-region)
           ("DEL" . save-buffers-kill-terminal))

(bind-keys :prefix "<menu> g"
           :prefix-map fw/project-map
           ("f" . fw/find-file)
           ("s" . fw/grep)
           ("d" . magit-file-dispatch)
           ("g" . magit-status))

(bind-keys :prefix "<menu> c"
           :prefix-map fw/org-map
           ("c" . fw/org-overview)
           ("i" . fw/org-capture-inbox)
           ("l" . org-insert-link)
           ("t" . org-todo)
           ("s" . org-schedule)
           ("d" . org-deadline)
           ("." . org-time-stamp)
           (":" . org-time-stamp-inactive)
           ("m" . org-insert-structure-template)
           ("b" . org-babel-tangle))

(bind-key* "C-z" 'undo)