summaryrefslogtreecommitdiff
path: root/.config
diff options
context:
space:
mode:
Diffstat (limited to '.config')
-rw-r--r--.config/alacritty/alacritty.toml8
-rw-r--r--.config/emacs/init.el1275
-rw-r--r--.config/sway/config273
-rw-r--r--.config/waybar/config123
-rw-r--r--.config/waybar/style.css74
5 files changed, 1753 insertions, 0 deletions
diff --git a/.config/alacritty/alacritty.toml b/.config/alacritty/alacritty.toml
new file mode 100644
index 0000000..327ef67
--- /dev/null
+++ b/.config/alacritty/alacritty.toml
@@ -0,0 +1,8 @@
+[window]
+opacity = 0.9
+
+[colors]
+primary.background="#0C0C0C"
+
+[font]
+normal={family="Jetbrains Mono", style="Regular"}
diff --git a/.config/emacs/init.el b/.config/emacs/init.el
new file mode 100644
index 0000000..a80febc
--- /dev/null
+++ b/.config/emacs/init.el
@@ -0,0 +1,1275 @@
+;;; init.el --- Emacs configuration -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023 Thanos Apollo
+
+;; Author: Thanos Apollo <[email protected]>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;; ╭━━━━┳╮╱╱╱╱╱╱╱╱╱╱╱╱╱╱╭━━━╮╱╱╱╱╱╭╮╭╮╱╱╱╱╱╱╱╱╭━━━╮
+;; ┃╭╮╭╮┃┃╱╱╱╱╱╱╱╱╱╱╱╱╱╱┃╭━╮┃╱╱╱╱╱┃┃┃┃╱╱╱╱╱╱╱╱┃╭━━╯
+;; ╰╯┃┃╰┫╰━┳━━┳━╮╭━━┳━━╮┃┃╱┃┣━━┳━━┫┃┃┃╭━━╮╱╱╱╱┃╰━━┳╮╭┳━━┳━━┳━━╮
+;; ╱╱┃┃╱┃╭╮┃╭╮┃╭╮┫╭╮┃━━┫┃╰━╯┃╭╮┃╭╮┃┃┃┃┃╭╮┃╭━━╮┃╭━━┫╰╯┃╭╮┃╭━┫━━┫
+;; ╱╱┃┃╱┃┃┃┃╭╮┃┃┃┃╰╯┣━━┃┃╭━╮┃╰╯┃╰╯┃╰┫╰┫╰╯┃╰━━╯┃╰━━┫┃┃┃╭╮┃╰━╋━━┃
+;; ╱╱╰╯╱╰╯╰┻╯╰┻╯╰┻━━┻━━╯╰╯╱╰┫╭━┻━━┻━┻━┻━━╯╱╱╱╱╰━━━┻┻┻┻╯╰┻━━┻━━╯
+;; ╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱┃┃
+;; ╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╱╰╯
+;;; Code:
+
+(setf user-full-name "Thanos Apollo"
+ user-mail-address "[email protected]")
+
+(defvar is-zeus (equal (system-name) "zeus"))
+(defvar is-hermes (equal (system-name) "hermes"))
+(defvar is-phone (equal (system-name) "localhost"))
+
+;; Autoinsert
+(auto-insert-mode 1)
+
+(setq auto-insert-alist '((python-mode . "python.template"))
+ auto-insert-directory (locate-user-emacs-file "insert"))
+
+(add-to-list 'completion-styles 'initials t)
+
+(setf tab-always-indent 'complete)
+
+;; xref
+(setf xref-show-xrefs-function #'consult-xref
+ xref-show-definitions-function #'consult-xref)
+
+;; Set and load custom.el
+(setf custom-file (locate-user-emacs-file "custom.el"))
+(load custom-file 'noerror)
+
+;; Enable use-package support for imenu
+(setf use-package-enable-imenu-support t)
+
+;; Install straight.el
+(defvar bootstrap-version)
+
+(let ((bootstrap-file
+ (expand-file-name
+ "straight/repos/straight.el/bootstrap.el"
+ (or (bound-and-true-p straight-base-dir)
+ user-emacs-directory)))
+ (bootstrap-version 7))
+ (unless (file-exists-p bootstrap-file)
+ (with-current-buffer
+ (url-retrieve-synchronously
+ "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
+ 'silent 'inhibit-cookies)
+ (goto-char (point-max))
+ (eval-print-last-sexp)))
+ (load bootstrap-file nil 'nomessage))
+
+(setq package-enable-at-startup nil)
+
+(require 'straight)
+
+(setf straight-use-package-by-default t)
+
+(setf straight-recipe-overrides
+ '((transmission :type git :host nil :repo "[email protected]:/var/git/transmission.git")
+ ;; (yeetube :type git :host nil :repo "[email protected]:/var/git/yeetube.git")
+ (gnosis :type git :host nil :repo "[email protected]:/var/git/gnosis.git")
+ (pcmpl-emerge :type git :host nil :repo "[email protected]:/var/git/pcmpl-emerge.git")
+ (pcmpl-rc :type git :host nil :repo "[email protected]:/var/git/pcmpl-rc.git")))
+
+(use-package emacs
+ :straight nil
+ :ensure t
+ :config
+
+ (setf browse-url-browser-function 'browse-url-generic
+ browse-url-generic-program "icecat"
+ backup-directory-alist '((".*" . "~/.Trash"))
+ sentence-end-double-space t
+ default-input-method "bulgarian-phonetic"
+ gc-cons-threshold 5000000
+ disabled-command-function nil ;; Enable all commands
+ url-privacy-level 'high
+ calendar-date-style 'european)
+ (if is-zeus
+ (display-battery-mode 0)
+ (display-battery-mode 1))
+
+ ;; use ssh for tramp, faster for small files
+ (setf tramp-default-method "ssh")
+
+ (savehist-mode)
+ (save-place-mode 1)
+ (recentf-mode 1)
+ (electric-pair-mode 1)
+ :bind (("M-<backspace>" . 'backward-kill-sexp)
+ ("C-c L" . 'display-line-numbers-mode)
+ ("C-z" . nil)
+ ("C-c r" . 'rename-visited-file))
+ :hook ((emacs-lisp-mode . prettify-symbols-mode)
+ (lisp-mode . prettify-symbols-mode)))
+
+(use-package dired
+ :straight nil
+ :ensure nil
+ :config
+ (defun dired-watch-video ()
+ "Watch play file with mpv."
+ (interactive)
+ (call-process-shell-command
+ (format "mpv \"%s\"" (dired-get-filename)) nil 0))
+
+ (defun dired-set-wallpaper ()
+ "Set NAME as wallpaper using feh."
+ (interactive)
+ (let ((command (if is-zeus "swaybg -o DP-2 -i" "feh --bg-scale")))
+ (call-process-shell-command
+ (format "%s %s" command (dired-get-filename)) nil 0)))
+
+ (defun dired-delete-files-except ()
+ "Delete all files inside directory except match."
+ (interactive)
+ (let* ((directory (read-directory-name "Select directory: "))
+ (files (directory-files directory t))
+ (except-match (read-string "Except the ones that have: ")))
+ (dolist (file files)
+ (unless (or (string= "." (substring file -1))
+ (string= ".." (substring file -2))
+ (string-match except-match file))
+ (dired-delete-file file t)))))
+
+ (defun dired-delete-file-match ()
+ "Delete all files inside directory except match."
+ (interactive)
+ (let* ((directory (read-directory-name "Select directory: "))
+ (files (directory-files directory t))
+ (match (read-string "Delete files that match: ")))
+ (dolist (file files)
+ (when (string-match-p match file)
+ (dired-delete-file file t)))))
+
+ (defun dired-rename-capitalize-file ()
+ "Capitalize the base name of the file at point in a Dired buffer."
+ (interactive)
+ (let* ((file (dired-get-file-for-visit))
+ (new-file (capitalize (file-name-nondirectory file))))
+ (if (string-prefix-p "." file)
+ (message "Skipping file starting with '.'")
+ (progn
+ (rename-file file (concat (file-name-directory file) new-file))
+ (revert-buffer)
+ (message "Renamed %s to %s" file new-file)))))
+ :bind ((:map
+ dired-mode-map
+ ("b" . 'dired-up-directory)
+ ("v" . 'dired-watch-video)
+ ("z" . 'wdired-change-to-wdired-mode)
+ ("C-c w" . 'dired-set-wallpaper)
+ ("C-c d" . 'dired-delete-files-except)
+ ("C-c r" . 'dired-do-query-replace-regexp))))
+
+(defun theme-invisible-dividers (_theme)
+ "Make window dividers for THEME invisible."
+ (let ((bg (face-background 'default)))
+ (custom-set-faces
+ `(fringe ((t :background ,bg :foreground ,bg)))
+ `(window-divider ((t :background ,bg :foreground ,bg)))
+ `(window-divider-first-pixel ((t :background ,bg :foreground ,bg)))
+ `(window-divider-last-pixel ((t :background ,bg :foreground ,bg))))))
+
+(add-hook 'enable-theme-functions #'theme-invisible-dividers)
+
+;;;; Theming ;;;;
+(setf inhibit-startup-message t
+ initial-scratch-message nil)
+
+(blink-cursor-mode -1)
+(global-visual-line-mode 0)
+
+(setf visible-bell nil
+ display-line-numbers-type 'relative)
+
+(column-number-mode)
+(global-display-line-numbers-mode 1)
+
+;; Transparency
+(add-to-list 'default-frame-alist '(alpha-background . 85))
+
+;; theming
+;; (global-hl-line-mode)
+(global-visual-line-mode)
+
+(defun thanos/terminal-theming ()
+ "Customize theming when laucning Emacs as TUI."
+ (unless (display-graphic-p (selected-frame))
+ (set-face-background 'default "unspecified-bg" (selected-frame))
+ (global-hl-line-mode 0)))
+
+(add-hook 'window-setup-hook 'thanos/terminal-theming)
+
+(when (equal is-phone nil)
+ (scroll-bar-mode -1)
+ (set-fringe-mode 10))
+
+(tool-bar-mode -1)
+(tooltip-mode -1)
+(menu-bar-mode -1)
+
+;; (when is-zeus
+;; (guix-emacs-autoload-packages))
+
+(use-package org
+ :ensure t
+ :config
+ (setf org-directory "~/org/"
+ org-agenda-files '("~/org/seminars.org" "~/org/lectures.org")
+ org-default-notes-file (expand-file-name "notes.org" org-directory)
+ org-ellipsis " ▼ "
+ org-log-done 'time
+ org-hide-emphasis-markers nil ;;change to t to hide emphasis markers
+ org-table-convert-region-max-lines 20000
+ org-log-done 'time
+ org-todo-keywords '((sequence "TODO(t)" "SEMINAR(s)" "LECTURE(l)" "DONE(d)")))
+
+ (setf org-structure-template-alist
+ '(("e" . "src emacs-lisp")
+ ("p" . "src python")
+ ("l" . "src lisp")
+ ("b" . "src bash")
+ ("q" . "QUOTE")))
+
+ :hook ((org-mode . org-auto-tangle-mode)
+ (org-mode . (lambda () (display-line-numbers-mode -1) (flyspell-mode))))
+ :bind (:map org-mode-map
+ (("C-c l" . org-store-link)
+ ("C-c M-t" . org-todo))))
+
+(defun org-insert-book ()
+ "Insert org-link from ~/Library for book."
+ (interactive)
+ (let* ((book-path (read-file-name "Book: " "~/Library/")))
+ (org-insert-link nil book-path (file-name-base book-path))))
+
+(use-package org-modern
+ :ensure t
+ :config
+ (setf org-modern-table nil
+ org-modern-todo nil
+ org-modern-tag nil)
+ :hook ((org-mode . org-modern-mode)))
+
+;; Create notes directory for org-roam
+(unless (file-exists-p "~/Notes")
+ (make-directory "~/Notes"))
+
+(use-package org-roam
+ :defer t
+ :init
+ (define-prefix-command 'thanos/notes-map)
+ :config
+ (setf org-roam-directory "~/Notes"
+ org-roam-dailies-directory "daily/")
+
+ (org-roam-db-autosync-enable)
+
+ (setf org-roam-node-display-template
+ (concat "${title:50} "(propertize "${tags:30}" 'face 'org-tag)))
+
+ (setf org-roam-db-node-include-function
+ (lambda ()
+ (not (or (member "journal" (org-get-tags))
+ (member "dailies" (org-get-tags))))))
+ ;; Templates
+ (setf org-roam-capture-templates
+ '(("d" "default" plain
+ "%?"
+ :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+startup: overview\n")
+ :unnarrowed t)
+ ("p" "MUS" plain "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n"
+ :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+filetags: MUS")
+ :unnarrowed t))
+ org-roam-dailies-capture-templates
+ '(("d" "default" entry
+ "* %?"
+ :target (file+head "%<%Y-%m-%d>.org"
+ "#+title: %<%Y-%m-%d>\n#+filetags: :journal:\n"))
+ ("j" "journal" plain
+ "\n* Daily Notes\n\n* Goals\n+ []\n\n* Extras %?"
+ :target (file+head "%<%Y-%m-%d>.org"
+ "#+title: %<%Y-%m-%d>\n#+filetags: :journal:\n"))))
+
+ (defun org-roam-ref-add-book ()
+ "Insert org-link from Library."
+ (interactive)
+ (let ((book (format "file:%s" (read-file-name "Book: " (if is-zeus "/hdd/Library/" "~/Library/")))))
+ book))
+
+ (defun org-roam-sync-notes ()
+ "Sync org-oram notes"
+ (interactive)
+ (let ((git (executable-find "git"))
+ (default-directory org-roam-directory))
+ (message "Synching org-roam notes %s" org-roam-directory)
+ (unless git
+ (error "Git not found, please install `git'"))
+ (unless (file-exists-p (expand-file-name ".git" gnosis-dir))
+ (message "Creating git repository")
+ (vc-create-repo 'Git))
+ (shell-command "git pull")
+ (shell-command (format "%s %s" git "add ."))
+ (shell-command (format "%s %s %s" git "commit -m" (shell-quote-argument "Update org-roam notes")))
+ (vc-git-push nil))
+ (funcall 'org-roam-db-sync))
+
+ :bind (("C-c n" . thanos/notes-map)
+ :map thanos/notes-map
+ ("t" . org-roam-buffer-toggle)
+ ("f" . org-roam-node-find)
+ ("i" . org-roam-node-insert)
+ ("d" . org-roam-dailies-goto-today)
+ ("D" . org-roam-dailies-goto-date)
+ :map org-mode-map
+ ("C-c C-." . org-roam-tag-add)
+ ("C-c i" . org-id-get-create)))
+
+(use-package org-roam-ui
+ :defer t)
+
+;; (use-package jabber
+;; :defer t)
+
+(use-package modus-themes
+ :straight t
+ :config
+ (setf modus-themes-italic-constructs nil
+ modus-themes-bold-constructs nil
+ modus-themes-mixed-fonts nil
+ modus-themes-variable-pitch-ui nil
+ modus-themes-custom-auto-reload t
+ modus-themes-disable-other-themes t
+ modus-themes-prompts '(italic)
+ modus-themes-completions '((matches . (extrabold))
+ (selection . (semibold italic text-also underline)))
+ modus-themes-org-blocks 'tinted-background)
+ ;; Palette overrides
+ (setf modus-themes-common-palette-overrides
+ '(;; (fg-line-number-inactive "gray40")
+ (fg-line-number-active cyan-intense)
+ ;; (bg-main "#1d2021") ;;grubox-hard
+ ;; (bg-main "#191919") ;; 1337
+ ;; (bg-main "#1d1f21") ;; tomorrow night
+ ;; (bg-main "#151515") ;; jazz
+ (bg-main "#0C0C0C") ;; random black
+ ;; (bg-main "#171717") ;; badger
+ ;; (overline-heading-1 gold)
+ (fg-heading-1 red-warmer)
+ ;; (bg-heading-1 bg-blue-nuanced)
+ (bg-line-number-inactive unspecified)
+ (bg-line-number-active unspecified)
+ (bg-paren-match bg-magenta-intense)
+ (underline-paren-match fg-main)
+ (underline-err red-intense)
+ (underline-warning yellow-faint)
+ (underline-note cyan-faint)
+ (string "#86B187")
+ (border-mode-line-active unspecified)
+ (border-mode-line-inactive unspecified)
+ (bg-mode-line-active "#433F4f") ;; subtle lavender
+ (bg-mode-line-inactive "#1D1D1D")
+ ;; set fg from badger theme
+ (fg-mode-line-active "#F6F3E8")
+ (bg-hl-line bg-dim)
+ (cursor slate)
+ (prose-todo green-intense)
+ (prose-done bg-term-white)
+ (fg-prompt yellow-faint)
+ ,@modus-themes-preset-overrides-intense))
+ ;; Headings
+ (setf modus-themes-headings
+ '((1 . (ultrabold 1.35))
+ (2 . (semibold 1.2))
+ (agenda-date . (1.3))
+ (agenda-structure . (variable-pitch light 1.8))
+ (t . (1.15))))
+ ;; Load modus
+ (load-theme 'modus-vivendi t))
+
+(use-package vertico
+ :ensure t
+ :config
+ (vertico-mode))
+
+(use-package marginalia
+ :ensure t
+ :config
+ (marginalia-mode))
+
+(use-package consult
+ :ensure t
+ :init (define-prefix-command 'thanos/search)
+ :bind (("C-x r d" . 'bookmark-delete)
+ ("C-x r C-r" . 'bookmark-rename)
+ ("C-x r C-j" . 'consult-register)
+ ("C-x r SPC" . 'consult-register-store)
+ ("C-x r b" . 'consult-bookmark)
+ ("C-c m" . 'consult-imenu)
+ ("C-x b" . 'consult-buffer)
+ ("M-y" . 'consult-yank-from-kill-ring)
+ ("C-s" . 'thanos/search)
+ :map thanos/search
+ ("f" . 'isearch-forward)
+ ("r" . 'isearch-backward)
+ ("s" . 'consult-line)
+ ("i" . 'change-inner)
+ ("C-f" . 'consult-find)
+ ("C-g" . 'consult-grep)
+ ("C-i" . 'consult-info)
+ ("C-l" . 'consult-locate)
+ :map project-prefix-map
+ ("b" . 'consult-project-buffer)))
+
+(use-package which-key
+ :ensure t
+ :config
+ (which-key-mode 1))
+
+(defun elfeed-mpv (&optional use-generic-p)
+ "Play video link with mpv."
+ (interactive "P")
+ (let ((entries (elfeed-search-selected)))
+ (cl-loop for entry in entries
+ do (elfeed-untag entry 'unread)
+ when (elfeed-entry-link entry)
+ do (start-process-shell-command "elfeed-video" nil (format "mpv \"%s\"" it)))
+ (mapc #'elfeed-search-update-entry entries)
+ (unless (use-region-p) (forward-line))))
+
+(use-package elfeed
+ :defer t
+ :config
+ (setf elfeed-search-filter "@1-week-ago +unread -hackernoon"
+ browse-url-browser-function #'browse-url-default-browser)
+ ;; Feeds
+ (setf elfeed-feeds
+ '(("https://hackaday.com/blog/feed/"
+ hackaday linux)
+ ("https://thanosapollo.org/index.xml"
+ thanos)
+ ("http://wikileaks.org/feed"
+ wikileaks)
+ ("https://hackernoon.com/feed"
+ hackernoon)
+ ("https://torrentfreak.com/feed"
+ torrentfreak piracy)
+ ("https://www.science.org/action/showFeed?type=etoc&feed=rss&jc=sciimmunol"
+ science)
+ ("https://rss-bridge.thanosapollo.org/?action=display&bridge=CssSelectorBridge&home_page=https%3A%2F%2Fwww.medscape.com%2Findex%2Flist_13470_0&url_selector=a.title&url_pattern=viewarticle%2F.*&content_selector=div.article__main-content&content_cleanup=&title_cleanup=+-+Index&limit=&format=Atom" medscape med)
+ ("http://rss-bridge.thanosapollo.org/?action=display&bridge=CssSelectorBridge&home_page=https%3A%2F%2Fmedfac.mu-sofia.com%2Fen%2Fnews%2F&url_selector=div.news-card&url_pattern=%2F*&content_selector=article.richtext-area&content_cleanup=&title_cleanup=&limit=&format=Atom" musofia med)
+ ("http://rss-bridge.thanosapollo.org/?action=display&bridge=CssSelectorBridge&home_page=https%3A%2F%2Fedition.cnn.com%2Fworld%2Feurope&url_selector=a.container__link--type-article&url_pattern=&content_selector=div.article__content&content_cleanup=&&title_cleanup=-+breaking+news%2C+video%2C+headlines+and+opinion&limit=&format=Atom" news cnn europe)
+ ("http://rss-bridge.thanosapollo.org/?action=display&bridge=CssSelectorBridge&home_page=https%3A%2F%2Fedition.cnn.com%2Fworld%2Famericas&url_selector=a.container__link--type-article&url_pattern=&content_selector=div.article__content&content_cleanup=div.data-uri&title_cleanup=-+breaking+news%2C+video%2C+headlines+and+opinion&limit=&format=Atom" news cnn americas)
+ ("https://annas-blog.org/rss.xml"
+ anna piracy)
+ ("https://rss-bridge.thanosapollo.org/?action=display&bridge=CssSelectorBridge&home_page=https%3A%2F%2Fwww.theguardian.com%2Feurope&url_selector=a.dcr-lv2v9o&url_pattern=&content_selector=div.article-body-commercial-selector&content_cleanup=figure.dcr-173mewl%2C+div.dcr-ut4tvs&title_cleanup=News%2C+sport+and+opinion+from+the+Guardian%27s+Europe+edition+%7C&limit=&format=Atom" news guardian europe)
+ ("https://planet.emacslife.com/atom.xml" emacs emacslife)
+ ("https://localmonero.co/static/rss/the-monero-standard/feed.xml" monero)
+ ("https://devonzuegel.com/feed" devon)
+ ("https://www.addtoany.com/add_to/feed?linkurl=http%3A%2F%2Fwww.thelancet.com%2Frssfeed%2Flancet_online.xml&type=feed&linkname=The%20Lancet%20Online%20First&linknote=" lancet med)
+ ("http://tools.cdc.gov/podcasts/feed.asp?feedid=183" cdc med)
+ ("http://planet.lisp.org/rss20.xml" lisp planetlisp)
+ ("https://guix.gnu.org/feeds/blog.atom" guix)))
+ :bind (("C-x f" . elfeed)
+ :map elfeed-search-mode-map
+ ("v" . 'elfeed-mpv)
+ ("U" . 'elfeed-update))
+ :hook ((elfeed-search-mode . (lambda () (display-line-numbers-mode 0)))))
+
+;; Python
+(use-package python-mode
+ :defer t
+ :config
+ (add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode)))
+
+(use-package pyenv
+ :defer t)
+
+(use-package elpy
+ :straight nil
+ :ensure nil
+ :init
+ (elpy-enable))
+
+;; Clojure
+(use-package cider
+ :defer t)
+
+(use-package clojure-mode
+ :defer t)
+
+(use-package rainbow-delimiters
+ :defer t
+ :hook ((emacs-lisp-mode . rainbow-delimiters-mode)
+ (lisp-mode . rainbow-delimiters-mode)
+ (clojure-mode . rainbow-delimiters-mode)
+ (scheme-mode . rainbow-delimiters-mode)))
+
+;; (use-package paredit
+;; :ensure t
+;; :hook ((emacs-lisp-mode . paredit-mode)
+;; (lisp-mode . paredit-mode)
+;; (clojure-mode . paredit-mode)
+;; (scheme-mode . paredit-mode)))
+
+(use-package sly
+ :init (setf inferior-lisp-program "sbcl")
+ :defer t)
+
+(use-package helpful
+ :defer t
+ :bind (("C-h f" . 'helpful-callable)
+ ("C-h v" . 'helpful-variable)
+ ("C-h k" . 'helpful-key)
+ ("C-h x" . 'helpful-command)
+ ("C-h ." . 'helpful-at-point)
+ ("C-h F" . 'helpful-function)
+ ("C-h C-k" . 'helpful-kill-buffers)
+ ("C-h a" . 'apropos)
+ ("C-h C-m" . 'info-apropos)))
+
+(use-package ox-hugo
+ :ensure t
+ :config
+ (setf org-hugo-section "post"))
+
+(use-package json-mode
+ :defer t
+ :config
+ (add-to-list 'auto-mode-alist '("\\.json'" . json-mode)))
+
+(defun project-magit ()
+ "Run magit-status in the current project's root."
+ (interactive)
+ (magit-status-setup-buffer (project-root (project-current t))))
+
+(use-package magit
+ :defer t
+ :config
+ (setf magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
+ :bind (:map project-prefix-map ("g" . 'project-magit)))
+
+(use-package corfu
+ :ensure t
+ :config
+ (global-corfu-mode)
+ (corfu-popupinfo-mode)
+ (setf corfu-auto t
+ corfu-auto-delay 0.1
+ corfu-auto-prefix 2
+ corfu-cycle t
+ corfu-popupinfo-delay 0.3
+ corfu-quit-at-boundary 'separator
+ corfu-quit-no-match t
+ corfu-preselect 'first
+ corfu-preview-current t
+ corfu-echo-mode t)
+ (setf indent-tabs-mode nil))
+
+(defun insert-brackets (&optional arg)
+ "Insert ARG brackets."
+ (interactive "P")
+ (insert-pair arg ?\[ ?\]))
+
+(global-set-key (kbd "C-x M-[") 'insert-brackets)
+
+
+(use-package orderless
+ :init (add-to-list 'completion-styles 'initials t)
+ :ensure t
+ :config
+ (setf completion-category-overrides '((file (style basic partial-completion)))
+ completion-styles '(orderless)
+ completion-cycle-threshold 2))
+
+(use-package pdf-tools
+ :straight nil
+ :ensure nil
+ :config
+ (add-to-list 'auto-mode-alist '("\\.pdf\\'" . pdf-view-mode))
+ :hook
+ ((pdf-view-mode . (lambda ()
+ (display-line-numbers-mode 0)
+ ;; Guix package emacs-pdf-tools does not enable
+ ;; minor modes automatically
+ (pdf-tools-enable-minor-modes)))))
+
+(use-package markdown-mode
+ :defer t
+ :config
+ (setq markdown-header-scaling t
+ markdown-command "multimarkdown")
+ (add-to-list 'auto-mode-alist '("\\.md\\'" . gfm-mode))
+ :hook ((markdown-mode . flyspell-mode)))
+
+(use-package org-auto-tangle
+ :defer t)
+
+(use-package org-present
+ :defer t)
+
+(use-package expand-region
+ :defer t)
+
+(use-package change-inner
+ :after expand-region
+ :bind ((:map thanos/search ("i" . 'change-inner))))
+
+(use-package nov
+ :straight nil
+ :defer t
+ :config
+ (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)))
+
+(use-package eshell-syntax-highlighting
+ :defer t)
+
+(use-package emojify
+ :ensure t
+ :hook (erc-mode . emojify-mode)
+ :commands emojify-mode)
+
+(use-package flycheck-package
+ :ensure t
+ :after flycheck)
+
+(use-package flycheck
+ :ensure t
+ :config
+ (setf flycheck-emacs-lisp-load-path 'inherit)
+ (global-flycheck-mode)
+ :hook ((emacs-lisp-mode . (lambda () (flycheck-mode) (flycheck-package-setup)))))
+
+;; Shells
+(use-package vterm
+ :straight nil
+ :ensure nil
+ :bind (("C-c v" . vterm)
+ :map vterm-mode-map
+ ("M-&" . 'async-shell-command)
+ ("C-c C-y" . 'vterm-copy-mode))
+ :hook
+ ((vterm-mode . (lambda () (display-line-numbers-mode -1)))))
+
+(use-package shell
+ :defer t
+ :bind (("C-c V" . shell)
+ :map shell-mode-map
+ ("C-l" . 'comint-clear-buffer))
+ :hook ((shell-mode . (lambda () (display-line-numbers-mode -1)))))
+
+(defvar thanos/aliases
+ '((g . magit)
+ (gl . magit-log)
+ (gc . magit-clone)
+ (d . dired)
+ (o . find-file)
+ (oo . find-file-other-window)
+ (ll . (lambda () (eshell/ls '-lha)))
+ (eshell/clear . eshell/clear-scrollback)))
+
+(defun thanos/set-eshell-aliases (aliases)
+ "Set ALIASES as eshell aliases."
+ (mapc (lambda (alias)
+ (defalias (car alias) (cdr alias)))
+ aliases))
+
+(use-package eshell
+ :config
+ (setf eshell-highlight-prompt t)
+ (eshell-syntax-highlighting-global-mode 1)
+ :bind (("C-c e" . eshell)
+ :map eshell-mode-map
+ ("C-l" . eshell/clear-scrollback))
+ :hook ((eshell-mode . (lambda ()
+ (thanos/set-eshell-aliases thanos/aliases)
+ (display-line-numbers-mode -1)))))
+
+(use-package eat
+ :after 'eshell
+ :config
+ (add-hook 'eshell-load-hook #'eat-eshell-mode)
+ (setf eat-term-name "xterm-256color"))
+
+(use-package eshell-git-prompt
+ :config
+ (defun eshell-git-prompt-multiline ()
+ "Eshell Git prompt inspired by spaceship-prompt."
+ (let (separator hr dir git git-dirty time sign command)
+ (setq separator (with-face " | " 'eshell-git-prompt-multiline-secondary-face))
+ (setq hr (with-face (concat "\n" (make-string (/ (window-total-width) 2) ?─) "\n") 'eshell-git-prompt-multiline-secondary-face))
+ (setq dir
+ (concat
+ (with-face "" 'eshell-git-prompt-directory-face)
+ (concat (abbreviate-file-name (eshell/pwd)))))
+ (setq git
+ (concat (with-face "⎇" 'eshell-git-prompt-exit-success-face)
+ (concat (eshell-git-prompt--branch-name))))
+ (setq git-dirty
+ (when (eshell-git-prompt--branch-name)
+ (if (eshell-git-prompt--collect-status)
+ (with-face " ✎" 'eshell-git-prompt-modified-face)
+ (with-face " ✔" 'eshell-git-prompt-exit-success-face))))
+ (setq time (with-face (format-time-string "%I:%M:%S %p") 'eshell-git-prompt-multiline-secondary-face))
+ (setq sign
+ (if (= (user-uid) 0)
+ (with-face "\n#" 'eshell-git-prompt-multiline-sign-face)
+ (with-face "\nλ" 'eshell-git-prompt-multiline-sign-face)))
+ (setq command (with-face " " 'eshell-git-prompt-multiline-command-face))
+
+ ;; Build prompt
+ (eshell-git-prompt---str-read-only
+ (concat hr dir separator git git-dirty separator time sign command))))
+
+ (eshell-git-prompt-use-theme 'multiline))
+
+;; Chat
+(use-package jabber
+ :defer t
+ :config
+ (defun jabber-buffers-formats (&optional buffer-formats)
+ "Return jabber BUFFER-FORMATS without the format specifiers.
+
+By default, returns all jabber related buffers format."
+ (let ((buffer-formats (or buffer-formats '(jabber-chat-buffer-format
+ jabber-browse-buffer-format
+ jabber-roster-buffer
+ jabber-groupchat-buffer-format
+ jabber-muc-private-buffer-format))))
+ (cl-loop for var in buffer-formats
+ for str = (symbol-value var)
+ for formatted-str = (when (stringp str)
+ ;; Remove format specifier and
+ ;; the following 2 char, or 1 if
+ ;; there is not second.
+ (replace-regexp-in-string "%.?" "" str))
+ collect formatted-str)))
+
+ (defun jabber-switch-to-buffer ()
+ "Prompt the user to select a buffer whose name matches a list of strings."
+ (interactive)
+ (let* ((string-list (jabber-buffers-formats))
+ (buffers-matching-strings
+ (cl-loop for buf in (buffer-list)
+ when (cl-loop for str in string-list
+ thereis (string-match-p str (buffer-name buf)))
+ collect (buffer-name buf))))
+ (if buffers-matching-strings
+ (switch-to-buffer
+ (completing-read "Select jabber buffer: " buffers-matching-strings)))
+ (error "No jabber buffer found")))
+ :bind (:map jabber-global-keymap
+ ("C-b" . 'jabber-switch-to-buffer)))
+
+(use-package erc
+ :defer t
+ :config
+ (unless (expand-file-name "erc" user-emacs-directory)
+ (make-directory (expand-file-name "erc" user-emacs-directory)))
+ (setf erc-modules
+ '(sasl netsplit fill button match track completion readonly
+ networks ring autojoin noncommands irccontrols move-to-prompt stamp
+ menu list log notifications)
+ erc-log-channels-directory (expand-file-name "erc" user-emacs-directory))
+ :bind (("C-c E" . 'erc-libera)
+ :map erc-mode-map
+ ("C-c RET" . 'erc-cmd-QUERY)))
+
+;; (use-package erc-image
+;; :ensure t
+;; :after erc
+;; :config
+;; (setq erc-image-inline-rescale 300)
+;; (add-to-list 'erc-modules 'image))
+
+(use-package transmission
+ :defer t)
+
+(use-package sudo-edit
+ :defer t
+ :config
+ (setf sudo-edit-local-method "sudo"))
+
+(use-package dabbrev
+ :defer t
+ :config
+ (setf dabbrev-ignored-buffer-regexps '("\\.\\(?:pdf\\|jpe?g\\|png\\)\\'")))
+
+(use-package xref
+ :defer t
+ :config
+ (setf xref-show-xrefs-function #'consult-xref
+ xref-show-definitions-function #'consult-xref))
+
+(use-package moc-player
+ :defer t
+ :straight '(moc-player :local-repo "~/Dev/emacs-lisp/moc-player")
+ :init (define-prefix-command 'thanos/mocp)
+ :bind (("C-z" . thanos/mocp)
+ :map thanos/mocp
+ ("SPC" . 'mocp-toggle-pause)
+ ("n" . 'mocp-next)
+ ("p" . 'mocp-previous)))
+
+;; My packages
+(when (or is-zeus is-hermes)
+ (use-package yeetube
+ :init (define-prefix-command 'thanos/yeetube-map)
+ :straight nil
+ :ensure t
+ :config
+ (setf yeetube-results-limit 20
+ yeetube-mpv-disable-video t
+ yeetube-display-thumbnails nil
+ yeetube-play-function #'yeetube-mpv-play)
+
+ (defun yeetube-download-videos-ffmpeg ()
+ "Download videos using ffmpeg."
+ (interactive)
+ (let ((url "")
+ (name "")
+ (download-counter 1)
+ (stored-contents nil))
+ ;; Read links and names until "q" is entered
+ (while (not (string= url "q"))
+ (setf url (read-string "Enter URL (q to quit): "))
+ (unless (string= url "q")
+ (setf name (read-string (format "Custom name (download counter: %d) " download-counter)))
+ (push (cons url name) stored-contents)
+ (setf download-counter (1+ download-counter))))
+ ;; Process the collected links and names
+ (dolist (pair stored-contents)
+ (let ((url (car pair))
+ (name (cdr pair)))
+ (async-shell-command
+ (format
+ "ffmpeg -protocol_whitelist file,crypto,data,https,tls,tcp -stats -i '%s' -codec copy '%s.mp4'"
+ url name))))))
+
+ (defun yeetube-download-vimeo-videos ()
+ "Download videos from vimeo services."
+ (interactive)
+ (let ((url "")
+ (name "")
+ (download-counter 1))
+ (while (not (string= url "q"))
+ (setf url (read-string "Enter URL (q to quit): "))
+ (unless (string= url "q")
+ (setf name (read-string (format "Custom name (download counter: %d) " download-counter)))
+ (setf download-counter (1+ download-counter))
+ (call-process-shell-command
+ (format
+ "yt-dlp '%s' -o '%s'"
+ (replace-regexp-in-string "\\.json" ".m3u8" url) name)
+ nil 0)))))
+
+ :bind (("C-c y" . 'thanos/yeetube-map)
+ :map thanos/yeetube-map
+ ("s" . 'yeetube-search)
+ ("b" . 'yeetube-play-saved-video)
+ ("d" . 'yeetube-download-videos)
+ ("C-d" . 'yeetube-download-vimeo-videos)
+ ("p" . 'yeetube-mpv-toggle-pause)
+ ("v" . 'yeetube-mpv-toggle-video)
+ ("V" . 'yeetube-mpv-toggle-no-video-flag)
+ ("C-p" . 'yeetube-mpv-toggle-video)
+ ("k" . 'yeetube-remove-saved-video)))
+
+ (use-package gnosis
+ :straight (gnosis :local-repo "~/Dev/emacs-lisp/gnosis")
+ :ensure t
+ :init (define-prefix-command 'thanos/gnosis-map)
+ :config
+ (setf gnosis-vc-auto-push t
+ gnosis-mcq-display-choices nil
+ gnosis-image-width nil
+ gnosis-image-height nil)
+ (gnosis-modeline-mode)
+ :bind (("C-r" . thanos/gnosis-map)
+ :map thanos/gnosis-map
+ ("r" . 'gnosis-review)
+ ("a" . 'gnosis-add-note)
+ ("C-d" . 'gnosis-dashboard)
+ ("d" . 'gnosis-add-deck)
+ ("t" . 'gnosis-test-start)))
+
+ ;; Run vc-pull on startup
+ (gnosis-vc-pull)
+
+ (use-package pcmpl-emerge
+ :defer t
+ :straight (pcmpl-emerge :local-repo "~/Dev/emacs-lisp/pcmpl-emerge"))
+
+ (use-package pcmpl-rc
+ :straight (pcmpl-rc :local-repo "~/Dev/emacs-lisp/pcmpl-rc")
+ :defer t)
+
+ (use-package pcmpl-tailscale
+ :straight (pcmpl-tailscale :local-repo "~/Dev/emacs-lisp/pcmpl-taiscale")
+ :defer t))
+
+;; Emacs dev
+
+(use-package package-lint
+ :defer t)
+
+;; AI tools
+(use-package gptel
+ :defer t
+ :config
+ (setf gptel-api-key (password-store-get-field "openai/[email protected]" "api")
+ gptel-default-mode 'org-mode)
+ (setq-default gptel-model "ChatGPT:gpt-4"
+ gptel-backend (gptel-make-ollama "Ollama"
+ :host "zeus:11434"
+ :stream t
+ :models '("llama2:latest" "zephyr:latest" "codellama:latest"
+ "mistral:latest" "mixtral:latest" "neural-chat:latest"
+ "dolphin-mixtral:latest"))
+ gptel-directives '((default . "You are a large language model living in Emacs and a helpful assistant. Respond concisely.")
+ (programming . "You are a large language model and a careful programmer. Provide code and only code as output without any additional text, prompt or note.")
+ (epictetus . "You are Epictetus, the stoic philosopher from Nicopolis. Respond concisely as Epictetus.")
+ (med . "You are a medical professor within the Emacs. Respond concisely.")
+ (code-review . "You are an expert programmer within Emacs reviewing code. Respond concisely")
+ (writer . "You are an expert writer and FOSS enthusiast. Improve only the article sections provided as a hacker, do not add extra paragraphs.")))
+ :bind (("C-c g" . 'gptel-send)
+ :map gptel-mode-map
+ ("C-c h" . 'gptel-menu)))
+
+;; (use-package copilot
+;; :straight (copilot :host github :repo "zerolfx/copilot.el" :files ("dist" "*.el"))
+;; :bind (:map copilot-mode-map
+;; ("M-TAB" . 'copilot-accept-completion-by-line)
+;; ("C-M-<tab>" . 'copilot-accept-completion-by-word)
+;; ("C-M-n" . 'copilot-next-completion)
+;; ("C-M-p" . 'copilot-previous-completion)))
+
+
+;; Password-store
+(use-package password-store
+ :init (define-prefix-command 'thanos/pass)
+ :defer t
+ :config
+ (setf password-store-password-length (+ 20 (random 20)))
+ :bind (("C-c p" . 'thanos/pass)
+ :map thanos/pass
+ ("i" . 'password-store-insert)
+ ("e" . 'password-store-edit)
+ ("g" . 'password-store-generate)
+ ("c" . 'password-store-copy)
+ ("s" . 'smtp-get-pass)))
+
+(defun thanos/pass-launcher ()
+ "Launch Emacs as a front-end for pass."
+ (interactive)
+ (unwind-protect
+ (with-selected-frame
+ (make-frame '((name . "thanos/pass-launcher")
+ (fullscreen . 0)
+ (undecorated . t)
+ (minibuffer . only)
+ (width . 70)
+ (height . 15)))
+ (let* ((choice (completing-read "Choose an action: "
+ '("AUTO" "COPY PASS" "COPY USERNAME" "EDIT" "GENERATE")))
+ (action (pcase choice
+ ("AUTO" #'(lambda (entry) (let ((user (password-store-get-field entry "user"))
+ (pass (password-store-get entry)))
+ (start-process-shell-command
+ "wtype" nil
+ (format "sleep 0.3 && wtype %s -P tab %s"
+ (shell-quote-argument (if user user "thanosapollo"))
+ (shell-quote-argument pass))))))
+ ("COPY PASS" #'password-store-copy)
+ ("COPY USERNAME" #'(lambda (entry) (password-store-copy-field entry "user")))
+ ("EDIT" #'password-store-edit)
+ ("GENERATE" #'password-store-generate))))
+ (funcall action (completing-read "Search: " (password-store-list)))
+ (delete-frame)))))
+
+(defun smtp-get-pass ()
+ "Get password for smtp."
+ (interactive)
+ (password-store-copy-field "fastmail.com/[email protected]" "smtp"))
+
+(use-package package-lint
+ :defer t)
+
+(use-package consult-mu
+ :straight (consult-mu :type git :host github :repo "armindarvish/consult-mu" :files (:defaults "extras/*.el"))
+ :after (mu4e consult)
+ :bind (:map mu4e-main-mode-map
+ ("M-s" . 'consult-mu)
+ :map mu4e-view-mode-map
+ ("M-s" . 'consult-mu)
+ :map mu4e-headers-mode-map
+ ("M-s" . 'consult-mu)))
+
+;; Guix Setup
+;; Yasnippet configuration
+(with-eval-after-load 'yasnippet
+ (add-to-list 'yas-snippet-dirs "~/Dev/guile/guix/etc/snippets/yas"))
+;; ;; Tempel configuration
+;; (with-eval-after-load 'tempel
+;; ;; Ensure tempel-path is a list -- it may also be a string.
+;; (unless (listp 'tempel-path)
+;; (setq tempel-path (list tempel-path)))
+;; (add-to-list 'tempel-path "~/Dev/guile/guix/etc/snippets/tempel/*"))
+
+(use-package yaml-mode
+ :defer t)
+
+;(load-file "~/Dev/guile/guix/etc/copyright.el")
+
+(setq copyright-names-regexp
+ (format "%s <%s>" user-full-name user-mail-address))
+
+(when (or is-zeus is-hermes)
+ (use-package mu4e
+ :straight nil
+ :ensure nil
+ :init
+
+ :config
+ (require 'server)
+ (require 'mu4e)
+
+ (setf mu4e-get-mail-command "mbsync -a")
+
+ (when (and is-zeus (server-running-p))
+ (setf mu4e-update-interval (* 10 60)))
+
+ (defun set-mu4e-context (context-name full-name mail-address signature)
+ "Return a mu4e context named CONTEXT-NAME with :match-func matching
+ folder name CONTEXT-NAME in Maildir. The context's `user-mail-address',
+ `user-full-name' and `mu4e-compose-signature'`smtpmail-smpt-server' is set to MAIL-ADDRESS
+ FULL-NAME SIGNATURE and SERVER respectively.
+ Special folders are set to context specific folders."
+ (let ((dir-name (concat "/" context-name)))
+ (make-mu4e-context
+ :name context-name
+ ;; we match based on the maildir of the message
+ :match-func
+ `(lambda (msg)
+ (when msg
+ (string-match-p
+ ,(concat "^" dir-name)
+ (mu4e-message-field msg :maildir))))
+ :vars
+ `((user-mail-address . ,mail-address)
+ (user-full-name . ,full-name)
+ (mu4e-sent-folder . ,(concat dir-name "/Sent"))
+ (mu4e-drafts-folder . ,(concat dir-name "/Drafts"))
+ (mu4e-trash-folder . ,(concat dir-name "/Trash"))
+ (mu4e-trash-folder . ,(concat dir-name "/Starred"))
+ (mu4e-refile-folder . ,(concat dir-name "/Archive"))
+ (mu4e-compose-signature . ,signature)))))
+
+ ;;Fixing duplicate UID errors when using mbsync and mu4e
+ (setf mu4e-change-filenames-when-moving t
+ mu4e-maildir-shortcuts
+ '(("/Fastmail/Inbox" . ?i)
+ ("/Drafts" . ?d)
+ ("/Sent" . ?s)
+ ("/Fastmail/Emacs/dev" . ?e)
+ ("/MUSofia/[Gmail]/All Mail" . ?u)
+ ("/Fastmail/Gentoo" . ?g)))
+
+ (setf mu4e-contexts
+ (list
+ (make-mu4e-context
+ :name "Public"
+ :match-func
+ (lambda (msg)
+ (when msg
+ (string-prefix-p "/Fastmail" (mu4e-message-field msg :maildir))))
+ :vars '((user-mail-address . "[email protected]")
+ (user-full-name . "Thanos Apollo")
+ (smtpmail-smtp-server . "smtp.fastmail.com")
+ (smtpmail-smtp-service . 465)
+ (smtpmail-stream-type . ssl)
+ (mu4e-drafts-folder . "/Drafts")
+ (mu4e-sent-folder . "/Sent")
+ (mu4e-refile-folder . "/Archive")
+ (mu4e-trash-folder . "/Trash")))
+ (make-mu4e-context
+ :name "MUSofia"
+ :match-func
+ (lambda (msg)
+ (when msg
+ (string-prefix-p "/MUSofia" (mu4e-message-field msg :maildir))))
+ :vars '((user-mail-address . "[email protected]")
+ (user-full-name . "Thanos Apollo")
+ (smtpmail-smtp-server . "smtp.gmail.com")
+ (smtpmail-smtp-service . 465)
+ (smtpmail-stream-type . ssl)))))
+
+ (setf message-send-mail-function 'smtpmail-send-it
+ mu4e-compose-signature "\nThanos Apollo\n \nhttps://thanosapollo.org\n
+62B7 58D0 F671 9938 BC09 CECA 339F 736C 3A72 0928\n"
+ mu4e-compose-context-policy 'ask)
+
+ (setf mu4e-view-actions
+ (delete-dups
+ (append
+ '(("gapply git patches" . mu4e-action-git-apply-patch)
+ ("mgit am patch" . mu4e-action-git-apply-mbox)
+ ("bb4 am patch" . mu4e-action-git-apply-b4)
+ ("ssetup reword list with b4" . mu4e-action-setup-reword-b4)
+ ("crun checkpatch script" . my-mu4e-action-run-check-patch)
+ ("MCheck if merged" . my-mu4e-action-check-if-merged)))))
+
+ :bind (("C-x m" . 'mu4e))
+ :hook
+ ;; Sign messages
+ ((message-send . 'mml-secure-message-sign-pgpmime)
+ ;; Disable line numbers & autosave
+ (mu4e-main-mode . (lambda () (display-line-numbers-mode -1) (auto-save-mode -1))))))
+
+;;; Random commands ;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Virtual machines
+(defvar vm-directory "~/Virtual/")
+
+(defun vm-create-image ()
+ "Create qcow2 image."
+ (interactive)
+ (let ((name (format "%s%s.qcow2" vm-directory (read-string "Name: ")))
+ (size (format "%s" (read-string "Size(G): "))))
+ (shell-command
+ (format "qemu-img create -f qcow2 %s %sG" name size))))
+
+
+(defun vm-run ()
+ "Spawn Virtual Machine."
+ (interactive)
+ (let ((memory (format "%sG" (read-string "Memory(G): ")))
+ (cores (read-string "Cores: "))
+ (image (read-file-name "Image: " vm-directory))
+ (iso (if (y-or-n-p "Load iso? ")
+ (read-file-name "ISO: ")
+ nil)))
+ (async-shell-command
+ (format "qemu-system-x86_64 -enable-kvm -m %s -smp %s -hda %s -vga virtio -device virtio-serial-pci -netdev user,id=vmnic,hostfwd=tcp::2222-:22 -device e1000,netdev=vmnic %s"
+ memory cores image (if iso (concat "-cdrom " iso) "")))))
+
+;; misc
+(defun thanos/run-in-background (command)
+ "Run COMMAND in the background."
+ (let ((command-parts (split-string command "[ ]+")))
+ (apply #'call-process `(,(car command-parts) nil 0 nil ,@(cdr command-parts)))))
+
+(defun create-text-scratch ()
+ "Create a scratch buffer."
+ (interactive)
+ (switch-to-buffer (get-buffer-create "*Text Scratch*"))
+ (org-mode))
+
+(defun create-scratch ()
+ "Create scratch buffer."
+ (interactive)
+ (switch-to-buffer (get-buffer-create "*scratch*"))
+ (emacs-lisp-mode))
+
+(defvar-keymap thanos/create-map
+ :doc "Create custom buffers"
+ "t" #'create-text-scratch
+ "e" #'create-scratch)
+
+;; Theming
+
+(defvar wallpapers-dir "~/wallpapers/")
+
+(defun thanos/load-theme (&optional theme)
+ "Disable current theme and load a new THEME."
+ (interactive)
+ (let ((theme (or theme (intern (completing-read "Theme: " (custom-available-themes))))))
+ (disable-theme (car custom-enabled-themes))
+ (load-theme theme t)))
+
+(defun thanos/wallpaper-set (image)
+ "Set IMAGE as wallpaper, using feh."
+ (let ((command (if is-zeus "swaybg -o '*' -i" "feh --bg-scale")))
+ ;; Kill previous swaybg
+ (call-process-shell-command "kill -15 $(pgrep swaybg | tail -n 1)")
+ ;; Set wallpaper
+ (call-process-shell-command
+ (format "%s %s%s -m stretch" command wallpapers-dir image)
+ nil 0)))
+
+(defun thanos/wallpaper-random ()
+ "Set random wallpaper."
+ (interactive)
+ (let ((wallpapers (directory-files "~/wallpapers" nil "^[^.].*")))
+ (thanos/wallpaper-set (nth (random (length wallpapers)) wallpapers))))
+
+(defun thanos/wallpaper-select ()
+ "Set wallpaper."
+ (interactive)
+ (let ((wallpaper (completing-read "Choose wallpaper: " (directory-files wallpapers-dir nil "^[^.].*"))))
+ (thanos/wallpaper-set wallpaper)))
+
+(defvar-keymap thanos/applications-map
+ :doc "Thanos commonly used programs"
+ "t" #'thanos/load-theme
+ "w" #'thanos/wallpaper-select
+ "C-c" thanos/create-map)
+
+(define-key global-map (kbd "C-c a") thanos/applications-map)
+
+(defun thanos/iimage-mode-buffer (arg)
+ "Display images if ARG is non-nil, undisplay them otherwise."
+ (let ((image-path (cons default-directory iimage-mode-image-search-path))
+ (edges (window-inside-pixel-edges (get-buffer-window)))
+ file)
+ (with-silent-modifications
+ (save-excursion
+ (dolist (pair iimage-mode-image-regex-alist)
+ (goto-char (point-min))
+ (while (re-search-forward (car pair) nil t)
+ (when (and (setq file (match-string (cdr pair)))
+ (setq file (locate-file file image-path)))
+ (if arg
+ (add-text-properties
+ (match-beginning 0) (match-end 0)
+ `(display
+ ,(create-image file nil nil
+ :max-width 120
+ :max-height 120)
+ keymap ,image-map
+ modification-hooks
+ (iimage-modification-hook)))
+ (remove-list-of-text-properties
+ (match-beginning 0) (match-end 0)
+ '(display modification-hooks))))))))))
+
+(define-minor-mode thanos/iimage-mode nil
+ :group 'iimage :lighter " iImg"
+ (thanos/iimage-mode-buffer thanos/iimage-mode))
+
+;; Font
+(custom-set-faces
+ (if is-hermes '(default ((t (:inherit nil :height 120 :family "Jetbrains Mono"))))
+ '(default ((t (:inherit nil :height 130 :family "Jetbrains Mono")))))
+ '(variable-pitch ((t (:inherit t :family "Iosevka Aile"))))
+ '(org-modern-symbol ((t (:inherit t :family "Iosevka Aile")))))
+
+;;; init.el ends here
diff --git a/.config/sway/config b/.config/sway/config
new file mode 100644
index 0000000..8eaa6d6
--- /dev/null
+++ b/.config/sway/config
@@ -0,0 +1,273 @@
+## Mod key
+set $mod Mod4
+
+exec sudo /home/thanos/.local/bin/tailscaled
+exec waybar
+bindsym $mod+z exec waybar
+bindsym $mod+o exec killall -SIGUSR1 waybar
+
+# Workspace switch
+bindsym $mod+period workspace back_and_forth
+
+bindsym $mod+slash workspace next
+bindsym $mod+comma workspace prev
+## Setup monitors & wallpapers
+output DP-2 pos 0 0 res 2560x1440 bg ~/wallpapers/colors-fantasy.jpg stretch
+output HDMI-A-1 pos 2560 0 res 2560x1440 bg ~/wallpapers/colors-fantasy.jpg fill transform 270
+
+default_border pixel 3
+default_floating_border pixel 3
+gaps inner 5
+gaps outer 0
+bindsym $mod+shift+g exec swaymsg gaps outer all set 0 && swaymsg gaps inner all set 5
+bindsym $mod+g exec swaymsg gaps outer all set 0 && swaymsg gaps inner all set 0
+
+# Activate smart borders (always)
+smart_borders on
+#smart_gaps on
+
+# Always float certain windows #
+#swaymsg -t get_tree | grep app_id
+ for_window [app_id="pop-up"] floating enable
+ for_window [app_id="thanos/pass-launcher"] floating enable
+ for_window [app_id="bubble"] floating enable
+ for_window [app_id="task_dialog"] floating enable
+ for_window [app_id="Preferences"] floating enable
+ for_window [app_id="dialog"] floating enable
+ for_window [app_id="menu"] floating enable
+ for_window [app_id="Organizer"] floating enable
+ for_window [app_id="About"] floating enable
+ for_window [app_id="toolbox"] floating enable
+ for_window [app_id="page-info"] floating enable
+ for_window [app_id="webconsole"] floating enable
+ for_window [app_id="Authy"] floating enable
+ for_window [app_id="termfloat"] floating enable
+ for_window [app_id="termfloat"] resize set height 540
+ for_window [app_id="termfloat"] resize set width 960
+ for_window [app_id="mpv"] floating enable
+ for_window [app_id="mpv"] resize set height 540
+ for_window [app_id="mpv"] resize set width 960
+ for_window [app_id="Nautilus"] floating enable
+ for_window [app_id="Nautilus"] resize set height 540
+ for_window [app_id="Nautilus"] resize set width 960
+
+# Sticky floating windows(sticky enable|disable|toggle)
+ for_window [app_id="danmufloat"] floating enable
+ for_window [app_id="danmufloat"] sticky enable
+ for_window [app_id="danmufloat"] resize set height 540
+ for_window [app_id="danmufloat"] resize set width 960
+
+# Program Opacity
+ for_window [app_id="telegram"] opacity 0.95
+ for_window [app_id="danmufloat"] opacity 0.80
+ # for_window [app_id="icalingua"] opacity 0.95
+ # for_window [class="netease-cloud-music"] opacity 0.90
+
+# Focus follows mouse
+focus_follows_mouse yes
+
+# Autostart #
+
+#exec_always --no-startup-id dunst &
+
+## Keyboard setup
+
+# NOTE: for bg phonetic use ,bg(phonetic)
+ input "type:keyboard" {
+ xkb_layout us,gr
+ xkb_options grp:win_space_toggle
+ }
+
+
+# set gtk+ theme
+set $gnome-schema org.gnome.desktop.interface
+
+# Window colours: border background text
+ # client.unfocused #2e3440 #1f222d #888888
+ # client.focused_inactive #2e3440 #1f222d #888888
+ # client.placeholder #2e3440 #1f222d #888888
+ # client.urgent #D08770 #D08770 #ffffff
+ # client.background #242424
+client.focused #2D2D2D #2D2D2D #ffffff #ffffff #c6c6c6
+client.focused_inactive #0f1212 #0f1212 #ffffff #0f1212 #0f1212
+client.unfocused #2D2D2D #000000 #c6c6c6 #000000 #000000
+client.urgent #0f1212 #FF5555 #F8F8F2 #FF5555 #FF5555
+client.placeholder #000000 #000000 #F8F8F2 #000000 #000000
+
+# TODO Direction keys, like Emacs
+ set $left h
+ set $down j
+ set $up k
+ set $right l
+
+#----------------------------------#
+# Your preferred terminal emulator #
+#----------------------------------#
+ set $term emacsclient -c
+
+# Control volume,monitor brightness,media players #
+ bindsym XF86AudioRaiseVolume exec pactl set-sink-volume @DEFAULT_SINK@ +5%
+ bindsym XF86AudioLowerVolume exec pactl set-sink-volume @DEFAULT_SINK@ -5%
+ bindsym XF86AudioMute exec pactl set-sink-mute @DEFAULT_SINK@ toggle
+ bindsym XF86AudioMicMute exec pactl set-source-mute @DEFAULT_SOURCE@ toggle
+ bindsym XF86MonBrightnessUp exec light -A 5
+ bindsym XF86MonBrightnessDown exec light -U 5
+ bindsym XF86AudioPlay exec playerctl play-pause
+ bindsym XF86AudioNext exec playerctl next
+ bindsym XF86AudioPrev exec playerctl previous
+
+# Key bindings --#
+ bindsym $mod+Return exec $term
+ bindsym $mod+Shift+Return exec kitty --class="termfloat"
+ bindsym $mod+Shift+m exec kitty --class="musicfox" --hold sh -c "musicfox"
+ bindsym $mod+Shift+d exec kitty --class="danmufloat" --hold sh -c "cd /home/ruixi/Codelearning/go/src/bilibili_live_tui/ && export TERM=xterm-256color && ./main"
+
+ bindsym $mod+Shift+x exec --no-startup-id ~/.config/sway/swaylock.sh
+ bindsym $mod+t exec --no-startup-id telegram-desktop
+ bindsym $mod+bracketleft exec --no-startup-id grimshot --notify save area ~/Pictures/$(date "+%Y-%m-%d"T"%H:%M:%S_no_watermark").png
+ bindsym $mod+bracketright exec --no-startup-id grimshot --notify copy area
+ bindsym $mod+a exec --no-startup-id ~/.config/sway/grimshot_watermark.sh
+
+
+ # Kill focused window
+ bindsym $mod+q kill
+
+ # Start your launcher
+ bindsym $mod+r exec fuzzel
+
+ # Reload the configuration file
+ bindsym $mod+Shift+r reload
+
+ # Exit sway (logs you out of your Wayland session)
+ bindsym $mod+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'
+
+ # Drag floating windows by holding down $mod and left mouse button.
+ # Resize them with right mouse button + $mod.
+ # Despite the name, also works for non-floating windows.
+ # Change normal to inverse to use left mouse button for resizing and right
+ # mouse button for dragging.
+ floating_modifier $mod normal
+
+# Moving around: #
+ # Move your focus around
+ bindsym $mod+$left focus left
+ bindsym $mod+$down focus down
+ bindsym $mod+$up focus up
+ bindsym $mod+$right focus right
+ # Or use $mod+[up|down|left|right]
+ bindsym $mod+Left focus left
+ bindsym $mod+Down focus down
+ bindsym $mod+Up focus up
+ bindsym $mod+Right focus right
+
+ # Move the focused window with the same, but add Shift
+ bindsym $mod+Shift+$left move left
+ bindsym $mod+Shift+$down move down
+ bindsym $mod+Shift+$up move up
+ bindsym $mod+Shift+$right move right
+ # Ditto, with arrow keys
+ bindsym $mod+Shift+Left move left
+ bindsym $mod+Shift+Down move down
+ bindsym $mod+Shift+Up move up
+ bindsym $mod+Shift+Right move right
+
+# Workspaces:
+ # Switch to workspace
+ bindsym $mod+1 workspace number 1
+ bindsym $mod+2 workspace number 2
+ bindsym $mod+3 workspace number 3
+ bindsym $mod+4 workspace number 4
+ bindsym $mod+5 workspace number 5
+ bindsym $mod+6 workspace number 6
+ bindsym $mod+7 workspace number 7
+ bindsym $mod+8 workspace number 8
+ bindsym $mod+9 workspace number 9
+ bindsym $mod+0 workspace number 10
+ # Move focused container to workspace
+ bindsym $mod+Shift+1 move container to workspace number 1
+ bindsym $mod+Shift+2 move container to workspace number 2
+ bindsym $mod+Shift+3 move container to workspace number 3
+ bindsym $mod+Shift+4 move container to workspace number 4
+ bindsym $mod+Shift+5 move container to workspace number 5
+ bindsym $mod+Shift+6 move container to workspace number 6
+ bindsym $mod+Shift+7 move container to workspace number 7
+ bindsym $mod+Shift+8 move container to workspace number 8
+ bindsym $mod+Shift+9 move container to workspace number 9
+ bindsym $mod+Shift+0 move container to workspace number 10
+ # move focused container to workspace(follow)
+ bindsym $mod+Ctrl+1 move container to workspace number 1, workspace 1
+ bindsym $mod+Ctrl+2 move container to workspace number 2, workspace 2
+ bindsym $mod+Ctrl+3 move container to workspace number 3, workspace 3
+ bindsym $mod+Ctrl+4 move container to workspace number 4, workspace 4
+ bindsym $mod+Ctrl+5 move container to workspace number 5, workspace 5
+ bindsym $mod+Ctrl+6 move container to workspace number 6, workspace 6
+ bindsym $mod+Ctrl+7 move container to workspace number 7, workspace 7
+ bindsym $mod+Ctrl+8 move container to workspace number 8, workspace 8
+ bindsym $mod+Ctrl+9 move container to workspace number 9, workspace 9
+ bindsym $mod+Ctrl+0 move container to workspace number 10, workspace 10
+ # Note: workspaces can have any name you want, not just numbers.
+ # We just use 1-10 as the default.
+# Layout stuff:
+ # You can "split" the current object of your focus with
+ # $mod+semicolon or $mod+apostrophe, for horizontal and vertical splits
+ # respectively.
+ bindsym $mod+semicolon splitv
+ bindsym $mod+apostrophe splith
+
+ # Switch the current container between different layout styles
+ bindsym $mod+s layout stacking
+ bindsym $mod+w exec emacsclient -e '(thanos/pass-launcher)'
+ bindsym $mod+e layout toggle split
+
+ # Make the current focus fullscreen
+ bindsym $mod+f fullscreen
+
+ # Toggle the current focus between tiling and floating mode
+ bindsym $mod+Shift+space floating toggle
+
+ # Swap focus between the tiling area and the floating area
+ bindsym $mod+space focus mode_toggle
+
+ # Move focus to the parent container
+ bindsym $mod+p focus parent
+ # Move focus the child container
+ bindsym $mod+c focus child
+
+# Scratchpad: #
+## hide | show window(minus is "-" and plus is "+".)
+bindsym $mod+minus move scratchpad
+bindsym $mod+equal scratchpad show
+
+#----------------------#
+# Resizing containers: #
+#----------------------#
+#bindsym $mod+r mode "resize"
+mode "resize" {
+ # left will shrink the containers width
+ # right will grow the containers width
+ # up will shrink the containers height
+ # down will grow the containers height
+ bindsym $left resize shrink width 10px
+ bindsym $up resize grow height 10px
+ bindsym $down resize shrink height 10px
+ bindsym $right resize grow width 10px
+
+ # Ditto, with arrow keys
+ bindsym Left resize shrink width 10px
+ bindsym Up resize grow height 10px
+ bindsym Down resize shrink height 10px
+ bindsym Right resize grow width 10px
+
+ # Return to default mode
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+}
+## Better to resize window
+bindsym Shift+Ctrl+h resize shrink width 5 px or 5 ppt
+bindsym Shift+Ctrl+k resize grow height 5 px or 5 ppt
+bindsym Shift+Ctrl+j resize shrink height 5 px or 5 ppt
+bindsym Shift+Ctrl+l resize grow width 5 px or 5 ppt
+bindsym Shift+Ctrl+Left resize shrink width 5 px or 5 ppt
+bindsym Shift+Ctrl+Up resize grow height 5 px or 5 ppt
+bindsym Shift+Ctrl+Down resize shrink height 5 px or 5 ppt
+bindsym Shift+Ctrl+Right resize grow width 5 px or 5 ppt
diff --git a/.config/waybar/config b/.config/waybar/config
new file mode 100644
index 0000000..66599a9
--- /dev/null
+++ b/.config/waybar/config
@@ -0,0 +1,123 @@
+// -*- mode: json -*-
+
+{
+ "layer": "top",
+ "position": "top",
+
+ "modules-left": [
+ "sway/workspaces",
+ "custom/right-arrow-dark"
+ ],
+ "modules-center": [
+ "custom/left-arrow-dark",
+ "clock#1",
+ "custom/left-arrow-light",
+ "custom/left-arrow-dark",
+ "clock#2",
+ "custom/right-arrow-dark",
+ "custom/right-arrow-light",
+ "clock#3",
+ "custom/right-arrow-dark"
+ ],
+ "modules-right": [
+ "custom/left-arrow-dark",
+ "pulseaudio",
+ "custom/left-arrow-light",
+ "custom/left-arrow-dark",
+ "memory",
+ "custom/left-arrow-light",
+ "custom/left-arrow-dark",
+ "cpu",
+ "custom/left-arrow-light",
+ "custom/left-arrow-dark",
+ "battery",
+ "custom/left-arrow-light",
+ "custom/left-arrow-dark",
+ "disk",
+ "custom/left-arrow-light",
+ "custom/left-arrow-dark",
+ "tray"
+ ],
+
+ "custom/left-arrow-dark": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/left-arrow-light": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right-arrow-dark": {
+ "format": "",
+ "tooltip": false
+ },
+ "custom/right-arrow-light": {
+ "format": "",
+ "tooltip": false
+ },
+
+ "sway/workspaces": {
+ "disable-scroll": true,
+ "format": "{name}"
+ },
+
+ "clock#1": {
+ "format": "{:%a}",
+ "tooltip": false
+ },
+ "clock#2": {
+ "format": "{:%H:%M}",
+ "tooltip": false
+ },
+ "clock#3": {
+ "format": "{:%Y-%m-%d}",
+ "tooltip": false
+ },
+
+ "pulseaudio": {
+ "format": "VOL: {volume:2}%",
+ "format-bluetooth": "{icon} {volume}%",
+ "format-muted": "MUTE",
+ "format-icons": {
+ "headphones": "",
+ "default": [
+ "",
+ ""
+ ]
+ },
+ "scroll-step": 5,
+ "on-click": "pamixer -t",
+ "on-click-right": "pavucontrol"
+ },
+ "memory": {
+ "interval": 5,
+ "format": "Mem {}%"
+ },
+ "cpu": {
+ "interval": 5,
+ "format": "CPU {usage:2}%"
+ },
+ "battery": {
+ "states": {
+ "good": 95,
+ "warning": 30,
+ "critical": 15
+ },
+ "format": "{icon} {capacity}%",
+ "format-icons": [
+ "",
+ "",
+ "",
+ "",
+ ""
+ ]
+ },
+ "disk": {
+ "interval": 5,
+ "format": "Disk {percentage_used:2}%",
+ "path": "/"
+ },
+ "tray": {
+ "icon-size": 10
+ }
+}
diff --git a/.config/waybar/style.css b/.config/waybar/style.css
new file mode 100644
index 0000000..4c6cbf0
--- /dev/null
+++ b/.config/waybar/style.css
@@ -0,0 +1,74 @@
+* {
+ font-size: 15px;
+ font-family: monospace;
+}
+
+window#waybar {
+ background: #292b2e;
+ color: #fdf6e3;
+}
+
+#custom-right-arrow-dark,
+#custom-left-arrow-dark {
+ color: #1a1a1a;
+}
+#custom-right-arrow-light,
+#custom-left-arrow-light {
+ color: #292b2e;
+ background: #1a1a1a;
+}
+
+#workspaces,
+#clock.1,
+#clock.2,
+#clock.3,
+#pulseaudio,
+#memory,
+#cpu,
+#battery,
+#disk,
+#tray {
+ background: #1a1a1a;
+}
+
+#workspaces button {
+ padding: 0 2px;
+ color: #fdf6e3;
+}
+#workspaces button.focused {
+ color: #268bd2;
+}
+#workspaces button:hover {
+ box-shadow: inherit;
+ text-shadow: inherit;
+}
+#workspaces button:hover {
+ background: #1a1a1a;
+ border: #1a1a1a;
+ padding: 0 3px;
+}
+
+#pulseaudio {
+ color: #268bd2;
+}
+#memory {
+ color: #2aa198;
+}
+#cpu {
+ color: #6c71c4;
+}
+#battery {
+ color: #859900;
+}
+#disk {
+ color: #b58900;
+}
+
+#clock,
+#pulseaudio,
+#memory,
+#cpu,
+#battery,
+#disk {
+ padding: 0 10px;
+}