summaryrefslogtreecommitdiff
path: root/org
diff options
context:
space:
mode:
Diffstat (limited to 'org')
-rwxr-xr-xorg/Qtile.org511
-rwxr-xr-xorg/README.org54
-rwxr-xr-xorg/emacs.org1342
-rwxr-xr-xorg/shells.org148
4 files changed, 2055 insertions, 0 deletions
diff --git a/org/Qtile.org b/org/Qtile.org
new file mode 100755
index 0000000..064311f
--- /dev/null
+++ b/org/Qtile.org
@@ -0,0 +1,511 @@
+#+TITLE: Qtile Configuration
+#+auto_tangle: t
+
+* Colors
+#+begin_src python :tangle ../.config/qtile/colors.by
+ """
+ My Favorite Color Themes For Qtile |
+
+ Feel free to change them as you like
+ """
+
+ # Dracula theme
+ dracula = {
+ "bg": "#282a36",
+ "fg": "#f8f8f2",
+ "curr": "#44475a",
+ "cyan": "#8be9fd",
+ "green": "#50fa7b",
+ "orange": "#ffb86c",
+ "purple": "#bd93f9",
+ "red": "#ff5555",
+ }
+
+ # Gruvbox theme
+ gruvbox = {
+ 'bg': '#282828',
+ 'fg': '#d4be98',
+ 'dark-red': '#ea6962',
+ 'red': '#ea6962',
+ 'dark-green': '#a9b665',
+ 'green': '#a9b665',
+ 'dark-yellow': '#e78a4e',
+ 'yellow': '#d8a657',
+ 'dark-blue': '#7daea3',
+ 'blue': '#7daea3',
+ 'dark-magenta': '#d3869b',
+ 'magenta': '#d3869b',
+ 'dark-cyan': '#89b482',
+ 'cyan': '#89b482',
+ 'dark-gray': '#665c54',
+ 'gray': '#928374',
+
+ 'fg4': '#766f64',
+ 'fg3': '#665c54',
+ 'fg2': '#504945',
+ 'fg1': '#3c3836',
+ 'bg0': '#32302f',
+ 'fg0': '#1d2021',
+ 'fg9': '#ebdbb2'
+ }
+
+ # Custom version of arcolinux theme
+ my_colors = {
+ "black": "#000000",
+ "black2": "#2F343F",
+ "blue": "#3384d0",
+ "red": "#ff0000",
+ "grey": "#a9a9a9",
+ "grey2": "#C0C5CE",
+ "cyan": "#6790EB",
+ "green": "#62FF00",
+ "white": "#F3F4F5",
+ "orange": "#FBA922",
+ }
+#+end_src
+* Keys
+#+begin_src python :tangle ../.config/qtile/config.py
+ from libqtile.config import Key
+ from libqtile.command import lazy
+ from libqtile.config import Click, Drag
+
+
+ mod = "mod4"
+ mod = "mod4"
+ browser = "firefox"
+ term = "emacsclient -c"
+ editor = "emacsclient -c -a 'emacs'"
+
+ keys = [
+ Key([mod], "Return",
+ lazy.spawn(term),
+ ),
+ Key([mod, "shift"], "a",
+ lazy.spawn('anki'),
+ ),
+ Key([mod, "shift"], "m",
+ lazy.spawn("spotify"),
+ ),
+ Key([mod], "Tab",
+ lazy.spawn("rofi -show drun"),
+ ),
+ Key([mod], "r",
+ lazy.spawn("rofi -show run"),
+ ),
+ Key([mod], "w",
+ lazy.spawn("rofi -show window"),
+ ),
+ Key([mod], "p",
+ lazy.spawn("passmenu -p 'Password for: '"),
+ ),
+ Key([mod], "b",
+ lazy.spawn(browser),
+ ),
+ Key([mod, "shift"], "c",
+ lazy.next_layout(),
+ ),
+ Key([mod], "q",
+ lazy.window.kill(),
+ ),
+ Key([mod, "shift"], "r",
+ lazy.restart(),
+ ),
+ Key([mod, "shift"], "0",
+ lazy.shutdown(),
+ ),
+ Key([mod, "shift"], "e",
+ lazy.spawn(editor),
+ ),
+ # Switch focus of monitors
+ Key([mod], "period",
+ lazy.next_screen(),
+ ),
+ # Treetab controls
+ Key([mod, "shift"], "h",
+ lazy.layout.move_left(),
+ ),
+ Key([mod, "shift"], "l",
+ lazy.layout.move_right(),
+ ),
+ # Window controls
+ Key([mod], "n",
+ lazy.layout.down(),
+ ),
+ Key([mod], "p",
+ lazy.layout.up(),
+ ),
+ Key([mod, "shift"], "n",
+ lazy.layout.shuffle_down(),
+ lazy.layout.section_down(),
+ ),
+ Key([mod, "shift"], "p",
+ lazy.layout.shuffle_up(),
+ lazy.layout.section_up(),
+ ),
+ Key([mod], "s",
+ lazy.layout.shrink(),
+ lazy.layout.decrease_nmaster(),
+ ),
+ Key([mod], "l",
+ lazy.layout.grow(),
+ lazy.layout.increase_nmaster(),
+ ),
+ Key([mod], "o",
+ lazy.layout.normalize(),
+ ),
+ Key([mod], "m",
+ lazy.layout.maximize(),
+ ),
+ Key([mod, "shift"], "f",
+ lazy.window.toggle_floating(),
+ ),
+ Key([mod], "f",
+ lazy.window.toggle_fullscreen(),
+ ),
+ # Stack controls
+ Key([mod, "shift"], "Tab",
+ lazy.layout.rotate(),
+ lazy.layout.flip(),
+ ),
+ Key([mod, "shift"], "space",
+ lazy.layout.toggle_split(),
+ ),
+ # Volume controls
+ Key([], "XF86AudioLowerVolume",
+ lazy.spawn('amixer sset Master 5%-'),
+ ),
+ Key([], "XF86AudioRaiseVolume",
+ lazy.spawn('amixer sset Master 5%+'),
+ ),
+ # I use mod+F[key] to change volume in my thinkpad,
+ # as I dislike using "fn" key in laptops
+ Key([mod], "F11",
+ lazy.spawn('amixer sset Master 5%-'),
+ ),
+ Key([mod], "F12",
+ lazy.spawn('amixer sset Master 5%+'),
+ ),
+ # Music controls | MOC
+ Key([mod], "u",
+ lazy.spawn("mocp -G "),
+ ),
+ Key([mod], "o",
+ lazy.spawn("mocp -f"),
+ ),
+ Key([mod], "i",
+ lazy.spawn("mocp -r"),
+ ),
+ # Change languages
+ Key([], "F1",
+ lazy.spawn("setxkbmap us -option ctrl:swapcaps"),
+ ),
+ Key([], "F2",
+ lazy.spawn("setxkbmap gr"),
+ ),
+ ]
+
+
+ mouse = [
+ Drag([mod], "Button1", lazy.window.set_position_floating(),
+ start=lazy.window.get_position()),
+ Drag([mod], "Button3", lazy.window.set_size_floating(),
+ start=lazy.window.get_size()),
+ Click([mod], "Button2",
+ lazy.window.bring_to_front()),
+ ]
+
+
+
+#+end_src
+
+* Base
+#+begin_src python :tangle ../.config/qtile/config.py
+ """Configuration for qtile."""
+
+ import os
+ import subprocess
+ from libqtile import layout, bar, widget, hook
+ from libqtile.config import Group, Screen
+ from libqtile.dgroups import simple_key_binder
+ from colors import dracula
+ import keys
+
+
+ @hook.subscribe.startup_once
+ def start_once():
+ """Set your autostart script."""
+ autostart_path = os.path.expanduser('~/.config/autostart/autostart.sh')
+ subprocess.run([autostart_path])
+
+
+
+
+ # Use this to change between workspaces
+ dgroups_key_binder = simple_key_binder("mod4")
+
+
+
+ # Groups and layouts
+ groups = []
+ group_names = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ]
+ group_labels = ["Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ", "Ⅴ", "Ⅵ", "Ⅶ", "Ⅷ", "Ⅸ", "Ⅹ", ]
+ group_layouts = ["monadtall", "monadtall", "monadtall", "monadtall",
+ "monadtall", "monadtall", "monadtall", "monadtall",
+ "monadtall", "monadtall", ]
+
+ for i in range(len(group_names)):
+ groups.append(
+ Group(
+ name=group_names[i],
+ layout=group_layouts[i].lower(),
+ label=group_labels[i],
+ ))
+
+
+ def init_layout_theme():
+ """Layout default theme."""
+ return {"margin": 5,
+ "border_width": 2,
+ "border_focus": dracula["cyan"],
+ "border_normal": dracula["bg"],
+ }
+
+
+ layout_theme = init_layout_theme()
+
+
+ layouts = [
+ layout.MonadTall(**layout_theme),
+ # layout.MonadWide(**layout_theme),
+ # layout.Matrix(**layout_theme),
+ # layout.Bsp(**layout_theme),
+ layout.Floating(**layout_theme),
+ # layout.RatioTile(**layout_theme),
+ # layout.Max(**layout_theme),
+ # layout.Spiral(**layout_theme),
+ layout.TreeTab(bg_color=dracula["bg"],
+ active_bg=dracula["purple"],
+ active_fg=dracula["fg"],
+ inactive_fg=dracula["fg"],
+ inactive_bg=dracula["bg"],
+ font="JetBrains Mono",
+ fontshadow=None,
+ section_fontsize=14,
+ panel_width=135,),
+ # layout.Zoomy(**layout_theme),
+ ]
+
+ # Widgets
+
+
+ def init_widgets_defaults():
+ """Set widget default settings."""
+ return dict(font="JetBrains Mono",
+ fontsize=12,
+ padding=2,
+ foreground=dracula["fg"],
+ background=dracula["bg"]
+ )
+
+
+ widget_defaults = init_widgets_defaults()
+
+
+ def init_widgets_list():
+ """My widget list."""
+ widgets_list = [
+ widget.Spacer(
+ length=7,
+ ),
+ widget.Image(
+ filename="~/.config/qtile/rms.png",
+ scale="True",
+ margin=2,
+ ),
+ widget.Spacer(
+ length=7,
+ ),
+ widget.GroupBox(
+ font="FontAwesome",
+ fontsize=20,
+ padding=3,
+ margin=4,
+ borderwidth=1,
+ active=dracula["cyan"],
+ inactive=dracula["curr"],
+ rounded=False,
+ highlight_method="line",
+ this_current_screen_border=dracula["red"],
+ other_current_screen_border=dracula["curr"],
+ ),
+ widget.CurrentLayout(
+ font="Noto Sans Bold",
+ foreground=dracula["fg"],
+ background="#5B4B8A",
+ ),
+ widget.Spacer(
+ length=5
+ ),
+ widget.WindowName(
+ font="JetBrains Mono Bold",
+ fontsize=12,
+ foreground=dracula["green"],
+ background=dracula["bg"],
+ ),
+ # widget.Image(
+ # filename = "~/.config/qtile/spotify2.png",
+ # scale = True,
+ # ),
+ # Spotify(
+ # fontsize = 12,
+ # background = dracula["bg"],
+ # color = dracula["green"],
+ # fmt = '{}',
+ # font = "JetBrains Mono Bold"
+ # ),
+ # widget.Moc(
+ # font = "JetBrains Mono",
+ # fontsize= 13,
+ # play_color=dracula["green"],
+ # paddig = 10,
+ # ),
+ widget.Pomodoro(
+ color_active=dracula["cyan"],
+ color_break=dracula["orange"],
+ color_inactive=dracula["curr"],
+ lenghth_pomodori=30,
+ fontsize=17,
+ ),
+ widget.Spacer(
+ length=10,
+ ),
+ widget.Image(
+ filename="~/.config/qtile/volume1.png",
+ scale=True,
+ ),
+ widget.Spacer(
+ length=7,
+ padding=10,
+ ),
+ widget.Volume(
+ fontsize=15,
+ fmt='{} ',
+ background=dracula["bg"],
+ foreground=dracula['orange'],
+ font="JetBrains Mono",
+ margin=10,
+ ),
+ # widget.Mpris2(
+ # fontsize= 16,
+ # background = my_colors["red"],
+ # objname="org.mpris.MediaPlayer2.spotify"
+ # ),
+ widget.Spacer(
+ length=7,
+ padding=10,
+ ),
+ widget.Image(
+ filename="~/.config/qtile/ram2.png",
+ scale=True,
+ ),
+ widget.Memory(
+ measure_mem="G",
+ fontsize=15,
+ foreground=dracula["cyan"],
+ background=dracula["bg"],
+ font='JetBrains Mono Bold',
+ ),
+ widget.MemoryGraph(
+ type='box',
+ graph_color=dracula["cyan"],
+ foreground=dracula["fg"],
+ background=dracula["bg"],
+ ),
+ widget.Spacer(
+ length=7
+ ),
+ widget.Image(
+ filename="~/.config/qtile/cpu1.png",
+ scale=True,
+ ),
+ widget.ThermalSensor(
+ threshold=50,
+ fontsize=15,
+ font='JetBrains Mono Bold',
+ foreground=dracula["cyan"],
+ background=dracula["bg"],
+ ),
+ widget.CPUGraph(
+ type='box',
+ graph_color=dracula["cyan"],
+ background=dracula["bg"],
+ ),
+ widget.Spacer(
+ length=5
+ ),
+ widget.TextBox(
+ font="FontAwesome",
+ text="  ",
+ foreground=dracula["orange"],
+ background=dracula["bg"],
+ padding=2,
+ fontsize=18
+ ),
+ widget.Clock(
+ font='JetBrains Mono Bold',
+ foreground=dracula["cyan"],
+ background=dracula["bg"],
+ fontsize=18,
+ format="%d-%m-%Y | %H:%M"
+ ),
+ widget.Spacer(
+ length=6
+ ),
+ widget.Systray(
+ background=dracula["bg"],
+ icon_size=20,
+ padding=10,
+ margin=10,
+ ),
+ widget.Spacer(
+ length=5
+ ),
+ ]
+ return widgets_list
+
+
+ widgets_list = init_widgets_list()
+
+
+ def init_widgets_screen1():
+ """Init every widget for primary screen."""
+ widgets_screen1 = init_widgets_list()
+ return widgets_screen1
+
+
+ def init_widgets_screen2():
+ """Remove systray and spacer for second screen."""
+ widgets_screen2 = init_widgets_list()
+ return widgets_screen2[:-2]
+
+
+ widgets_screen1 = init_widgets_screen1()
+ widgets_screen2 = init_widgets_screen2()
+
+
+ def init_screens():
+ """Panel settings."""
+ return [Screen(top=bar.Bar(widgets=init_widgets_screen1(), size=33,
+ margin=11),),
+ Screen(top=bar.Bar(widgets=init_widgets_screen2(), size=28,
+ margin=7))]
+
+
+ screens = init_screens()
+ follow_mouse_focus = True
+ bring_front_click = False
+ cursor_warp = True
+ auto_fullscreen = True
+ focus_on_window_activation = "smart" # or focus
+ wmname = "Qtile-Apo11o"
+#+end_src
diff --git a/org/README.org b/org/README.org
new file mode 100755
index 0000000..42d4920
--- /dev/null
+++ b/org/README.org
@@ -0,0 +1,54 @@
+#+title: Dotfiles | My Linux setup
+#+OPTIONS: num:nil toc:nil
+#+STARTUP: overview
+* About
+
+Welcome to my dotfiles repository!
+
+Here you will find my custom configuration files for a variety of applications and utilities. All of which are written in org-mode literate configuration format.
+
+All of the configurations in this repository are managed using [[https://www.gnu.org/software/stow/][GNU Stow]], which allows me to easily manage and switch between different configurations for different systems or environments.
+
+- Hosted at [[https://git.sr.ht/~thanos_apollo/dotfiles][sourcehut]]
+
+* Configurations
++ [[file:emacs.org][Emacs]]
++ [[file:shells.org][Shells]]
++ [[file:Qtile.org][Qtile]]
+
+/Qtile with emacs/
+ [[file:pictures/showcase2.png]]
+
+Themes I'm using:
++ [[https://github.com/dracula/rofi][Dracula for rofi]]
++ [[https://github.com/dracula/nyxt][Dracula for nyxt]]
++ [[https://github.com/dracula/qutebrowser][Dracula for Qutebrowser]]
++ [[https://github.com/wimstefan/mocp-themes][mocp-themes]] collection
+
+* Installation
++ clone repository
+
+#+begin_src bash
+ git clone https://github.com/ThanosApollo/dotfiles.git ~/dotfiles
+#+end_src
++ Install [[https://www.gnu.org/software/stow/][GNU stow]]
+
+#+begin_src bash
+ guix install stow # use the package manager of your distro if not guix
+#+end_src
++ Use stow
+#+begin_src bash
+ cd ~/dotfiles
+ stow .
+#+end_src
+If you get any errors due to existing files, rename them with ~_backup~ at the end
+
+e.g ~mv ~/.bashrc ~/.bashrc_backup~
+* WARNING!
+It's important to note that my dotfiles in this repository are constantly evolving, as I am constantly experimenting with new configurations and settings.
+
+While I am happy to share my configurations, *I do not recommend using them as-is on your own system* without careful review and testing.
+
+It's possible that some configurations may not work as expected or may cause issues on your system. Therefore, I strongly recommend taking caution and reviewing any changes carefully before applying them to your own system.
+
+
diff --git a/org/emacs.org b/org/emacs.org
new file mode 100755
index 0000000..9dfd3b6
--- /dev/null
+++ b/org/emacs.org
@@ -0,0 +1,1342 @@
+#+TITLE: Emacs Configuration
+#+PROPERTY: header-args :tangle ../.emacs.d/init.el
+#+auto_tangle: t
+#+STARTUP: overview
+
+* System information
+Check the ~$HOSTNAME~, if it's one of my devices running GuixSD.
+#+begin_src emacs-lisp
+ (defvar is-zeus (equal (system-name) "zeus"))
+ (defvar is-hephaestus (equal (system-name) "hephaestus"))
+#+end_src
+* Setting up Packages
+** Setup for GuixSD machines
+#+begin_src emacs-lisp
+ ;; When guix t, load emacs packages
+ (when (or is-zeus
+ is-hephaestus
+ (add-to-list 'load-path "~/.guix-profile/share/emacs/site-lisp")
+ (guix-emacs-autoload-packages)))
+
+ (with-eval-after-load 'geiser-guile
+ (add-to-list 'geiser-guile-load-path "~/dotfiles/.config/guix"))
+
+ ;; Personal Information
+ (setq user-full-name "Thanos Apollo"
+ user-mail-address "[email protected]")
+
+ (setq copyright-names-regexp
+ (format "%s <%s>" user-full-name user-mail-address))
+#+end_src
+** Define and install packages
+*** List of required packages
+Request the following packages:
+#+begin_src emacs-lisp
+ (defconst my-package-list '(org-snooze
+ all-the-icons
+ all-the-icons-dired
+ all-the-icons-ivy-rich
+ dap-mode
+ toc-org
+ emojify
+ general
+ doom-themes
+ doom-modeline
+ counsel
+ which-key
+ ivy
+ ivy-rich
+ helpful
+ password-store
+ org
+ org-modern
+ visual-fill-column
+ rainbow-delimiters
+ flycheck
+ lsp-mode
+ lsp-ui
+ json-mode
+ rjsx-mode
+ typescript-mode
+ python-mode
+ pyvenv
+ company
+ company-box
+ magit
+ elfeed
+ elfeed-goodies
+ paredit
+ corfu
+ monkeytype
+ sudo-edit
+ exwm
+ exwm-mff
+ ;; exwm-firefox-core
+ consult
+ alsamixer
+ simple-httpd
+ circe
+ eshell-syntax-highlighting
+ ; pdf-tools
+ org-superstar
+ mastodon
+ dashboard
+ org-auto-tangle))
+#+end_src
+*** Installation & activation
+Set our ~package-archives~, and install our packages
+#+begin_src emacs-lisp
+ (setq package-archives '(("melpa" . "https://melpa.org/packages/")
+ ("org" . "https://orgmode.org/elpa/")
+ ("elpa" . "https://elpa.gnu.org/packages/")))
+ (package-initialize)
+ (unless package-archive-contents
+ (package-refresh-contents))
+
+ (defvar my-missing-packages '()
+ "List populated at each startup.
+ Contains the list of packages that need to be installed.")
+
+ (dolist (p my-package-list)
+ (when (not (package-installed-p p))
+ (add-to-list 'my-missing-packages p)))
+
+ (when my-missing-packages
+ (message "Emacs is now refreshing its package database...")
+ (package-refresh-contents)
+ ;; Install the missing packages
+ (dolist (p my-missing-packages)
+ (message "Installing `%s' .." p)
+ (package-install p))
+ (setq my-missing-packages '()))
+
+ (unless (package-installed-p 'use-package)
+ (package-install 'use-package))
+
+ ;; set and load custom.el
+ (setq custom-file (concat user-emacs-directory "custom.el"))
+ (load custom-file 'noerror)
+#+end_src
+
+* UI Settings
+** Basic UI
+Fonts and basic appearance settings
+#+begin_src emacs-lisp
+ (setq inhibit-startup-message nil)
+ ;; Transparency
+ (set-frame-parameter (selected-frame) 'alpha '(90 95))
+ (add-to-list 'default-frame-alist '(alpha 90 90))
+
+ (add-hook 'dired-mode-hook 'all-the-icons-dired-mode)
+ (when is-hephaestus
+ (display-battery-mode 1))
+
+ (scroll-bar-mode -1)
+ (tool-bar-mode -1)
+ (tooltip-mode -1)
+ (set-fringe-mode 10)
+ (menu-bar-mode -1)
+ (which-key-mode 1)
+ (blink-cursor-mode -1)
+ (menu-bar--visual-line-mode-enable)
+ (global-visual-line-mode 1)
+
+ (require 'emojify)
+ (global-emojify-mode 1)
+
+ (setq visible-bell t)
+
+
+ (column-number-mode)
+ (global-display-line-numbers-mode 0)
+ (menu-bar--display-line-numbers-mode-relative)
+ ;;Disable line numbers for some modes
+ (dolist (mode '(pdf-view-mode-hook
+ org-mode-hook
+ term-mode-hook
+ shell-mode-hook
+ eshell-mode-hook
+ vterm-mode-hook
+ elfeed))
+ (add-hook mode (lambda () (display-line-numbers-mode 0))))
+
+ (defvar apollo/default-font-size 140)
+
+ (set-face-attribute 'default nil
+ :font "JetBrains Mono"
+ :height apollo/default-font-size)
+
+ (set-face-attribute 'fixed-pitch nil
+ :font "JetBrains Mono"
+ :height apollo/default-font-size)
+
+ (set-face-attribute 'variable-pitch nil
+ :font "JetBrains Mono"
+ :height apollo/default-font-size
+ :weight 'regular)
+
+#+end_src
+** Dashboard
+#+begin_src emacs-lisp
+ (require 'dashboard)
+ (require 'all-the-icons)
+
+ (dashboard-setup-startup-hook)
+ (setq dashboard-items '((recents . 5)
+ (bookmarks . 5)))
+
+ (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))
+ dashboard-item-names '(("Recent Files:" . "Recent Files:")
+ ("Bookmarks:" . "Study:")))
+ ;; Set the banner
+ (setq dashboard-startup-banner "~/dotfiles/pictures/medicine/plague-doctor-s.png")
+ ;; Set the title
+ (setq dashboard-banner-logo-title "Is that a flying flower?")
+ ;; (setq dashboard-init-info "Bring me your sick and wounded!")
+
+ (setq dashboard-set-init-info t
+ dashboard-center-content t
+ dashboard-set-navigator t
+ dashboard-set-heading-icons t
+ dashboard-set-file-icons t
+ dashboard-show-shortcuts nil
+ dashboard-set-footer t
+ dashboard-footer-messages '("Welcome to the Church Of Emacs")
+ dashboard-footer-icon (all-the-icons-octicon "broadcast"
+ :height 1.15
+ :v-adjust -0.05
+ :face 'font-lock-keyword-face))
+#+end_src
+** Theme & modeline
+#+begin_src emacs-lisp
+(load-theme 'doom-ayu-dark t)
+(doom-modeline-mode 1)
+
+(setq doom-modeline-height 35)
+#+end_src
+** Ivy
+#+begin_src emacs-lisp
+ (use-package ivy
+ :diminish
+ :bind (("C-s" . swiper)
+ :map ivy-minibuffer-map
+ ("TAB" . ivy-alt-done)
+ ("C-l" . ivy-alt-done)
+ ("C-j" . ivy-next-line)
+ ("C-k" . ivy-previous-line)
+ :map ivy-switch-buffer-map
+ ("C-k" . ivy-previous-line)
+ ("C-l" . ivy-done)
+ ("C-d" . ivy-switch-buffer-kill)
+ :map ivy-reverse-i-search-map
+ ("C-k" . ivy-previous-line)
+ ("C-d" . ivy-reverse-i-search-kill))
+ :config
+ (ivy-mode 1)
+ (setq ivy-use-selectable-prompt t))
+
+ (ivy-rich-mode 1)
+ (all-the-icons-ivy-rich-mode 1)
+#+end_src
+** Helpful
+#+begin_src emacs-lisp
+(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))
+#+end_src
+* Dired
+** Keys
+#+begin_src emacs-lisp
+(define-key dired-mode-map "b" 'dired-up-directory)
+#+end_src
+** All-the-icons.el
+#+begin_src emacs-lisp
+;;; all-the-icons-dired.el --- Shows icons for each file in dired mode -*- lexical-binding: t; -*-
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'dired)
+(require 'all-the-icons)
+
+(defface all-the-icons-dired-dir-face
+ '((((background dark)) :foreground "white")
+ (((background light)) :foreground "black"))
+ "Face for the directory icon"
+ :group 'all-the-icons-faces)
+
+(defcustom all-the-icons-dired-v-adjust 0.01
+ "The default vertical adjustment of the icon in the dired buffer."
+ :group 'all-the-icons
+ :type 'number)
+
+(defvar all-the-icons-dired-mode)
+
+(defun all-the-icons-dired--add-overlay (pos string)
+ "Add overlay to display STRING at POS."
+ (let ((ov (make-overlay (1- pos) pos)))
+ (overlay-put ov 'all-the-icons-dired-overlay t)
+ (overlay-put ov 'after-string string)))
+
+(defun all-the-icons-dired--overlays-in (beg end)
+ "Get all all-the-icons-dired overlays between BEG to END."
+ (cl-remove-if-not
+ (lambda (ov)
+ (overlay-get ov 'all-the-icons-dired-overlay))
+ (overlays-in beg end)))
+
+(defun all-the-icons-dired--overlays-at (pos)
+ "Get all-the-icons-dired overlays at POS."
+ (apply #'all-the-icons-dired--overlays-in `(,pos ,pos)))
+
+(defun all-the-icons-dired--remove-all-overlays ()
+ "Remove all `all-the-icons-dired' overlays."
+ (save-restriction
+ (widen)
+ (mapc #'delete-overlay
+ (all-the-icons-dired--overlays-in (point-min) (point-max)))))
+
+(defun all-the-icons-dired--refresh ()
+ "Display the icons of files in a dired buffer."
+ (all-the-icons-dired--remove-all-overlays)
+ (save-excursion
+ (goto-char (point-min))
+ (while (not (eobp))
+ (when (dired-move-to-filename nil)
+ (let ((file (dired-get-filename 'relative 'noerror)))
+ (when file
+ (let ((icon (if (file-directory-p file)
+ (all-the-icons-icon-for-dir file
+ :face 'all-the-icons-dired-dir-face
+ :v-adjust all-the-icons-dired-v-adjust)
+ (all-the-icons-icon-for-file file :v-adjust all-the-icons-dired-v-adjust))))
+ (if (member file '("." ".."))
+ (all-the-icons-dired--add-overlay (point) " \t")
+ (all-the-icons-dired--add-overlay (point) (concat icon "\t")))))))
+ (forward-line 1))))
+
+(defun all-the-icons-dired--refresh-advice (fn &rest args)
+ "Advice function for FN with ARGS."
+ (apply fn args)
+ (when all-the-icons-dired-mode
+ (all-the-icons-dired--refresh)))
+
+(defun all-the-icons-dired--setup ()
+ "Setup `all-the-icons-dired'."
+ (when (derived-mode-p 'dired-mode)
+ (setq-local tab-width 1)
+ (advice-add 'dired-readin :around #'all-the-icons-dired--refresh-advice)
+ (advice-add 'dired-revert :around #'all-the-icons-dired--refresh-advice)
+ (advice-add 'dired-internal-do-deletions :around #'all-the-icons-dired--refresh-advice)
+ (advice-add 'dired-insert-subdir :around #'all-the-icons-dired--refresh-advice)
+ (advice-add 'dired-do-kill-lines :around #'all-the-icons-dired--refresh-advice)
+ (with-eval-after-load 'dired-narrow
+ (advice-add 'dired-narrow--internal :around #'all-the-icons-dired--refresh-advice))
+ (all-the-icons-dired--refresh)))
+
+(defun all-the-icons-dired--teardown ()
+ "Functions used as advice when redisplaying buffer."
+ (advice-remove 'dired-readin #'all-the-icons-dired--refresh-advice)
+ (advice-remove 'dired-revert #'all-the-icons-dired--refresh-advice)
+ (advice-remove 'dired-internal-do-deletions #'all-the-icons-dired--refresh-advice)
+ (advice-remove 'dired-narrow--internal #'all-the-icons-dired--refresh-advice)
+ (advice-remove 'dired-insert-subdir #'all-the-icons-dired--refresh-advice)
+ (advice-remove 'dired-do-kill-lines #'all-the-icons-dired--refresh-advice)
+ (all-the-icons-dired--remove-all-overlays))
+
+;;;###autoload
+(define-minor-mode all-the-icons-dired-mode
+ "Display all-the-icons icon for each files in a dired buffer."
+ :lighter " all-the-icons-dired-mode"
+ (when (and (derived-mode-p 'dired-mode) (display-graphic-p))
+ (if all-the-icons-dired-mode
+ (all-the-icons-dired--setup)
+ (all-the-icons-dired--teardown))))
+#+end_src
+
+Hook with ~dired-mode~
+#+begin_src emacs-lisp
+(add-hook 'dired-mode-hook 'all-the-icons-dired-mode)
+#+end_src
+* Terminals
+** Vterm
+#+begin_src emacs-lisp
+ (use-package vterm
+ :ensure nil)
+
+ (use-package multi-vterm
+ :ensure nil
+ :config
+ (setq multi-vterm-dedicated-window-height 25))
+#+end_src
+*** Keys
+#+begin_src emacs-lisp
+ (defvar thanos/vterm-map (make-sparse-keymap))
+ (define-prefix-command 'thanos/vterm-map)
+ (define-key global-map (kbd "C-c v") 'thanos/vterm-map)
+ (define-key thanos/vterm-map (kbd "n") 'multi-vterm-next)
+ (define-key thanos/vterm-map (kbd "p") 'multi-vterm-prev)
+ (define-key thanos/vterm-map (kbd "d") 'multi-vterm-dedicated-open)
+#+end_src
+** Eshell
+#+begin_src emacs-lisp
+ (use-package eshell
+ :ensure nil
+ :bind (("C-c e" . 'eshell))
+ :config
+ (defvar eshell-path-env (getenv "~/.local/bin")))
+
+ (defun with-face (str &rest face-plist)
+ (propertize str 'face face-plist))
+
+ (defun apollo-eshell-prompt ()
+ (let ((winter-blue "#3F3B6C")
+ (white-summer "#E5E5CB")
+ (green-night "#03C988")
+ (orange-summer "#FFB100")
+ (green-summer "#A3BB98")
+ (summer-sea "#2192FF")
+ (black "#000000"))
+ (concat
+ (with-face (concat "[" user-login-name) :foreground orange-summer :background black)
+ (with-face "@" :foreground orange-summer :background black)
+ (with-face (concat system-name "]\n") :foreground orange-summer :background black)
+ (with-face (concat "|" (eshell/pwd) ) :foreground "#F0E9D2" :background winter-blue)
+ (with-face (format-time-string " | %H:%M" (current-time)) :background winter-blue :foreground "#888")
+ (with-face "\n -> "))))
+
+ ;; (setq eshell-prompt-function 'apollo-eshell-prompt)
+ ;; (setq eshell-highlight-prompt t)
+#+end_src
+* Custom
+** ChatGPT
+#+begin_src emacs-lisp
+ (require 'seq)
+ (eval-when-compile
+ (require 'cl-lib)
+ (require 'subr-x)
+ (require 'env)
+ (require 'json))
+ (defgroup chatgpt nil
+ "ChatGPT frontend."
+ :group 'convenience
+ :prefix "chatgpt-")
+ (defcustom chatgpt-max-tokens 300
+ "Upper limit on the number of tokens the API will return."
+ :type 'integer)
+ (defvar chatgpt-buffer "*ChatGPT*"
+ "Title of the buffer used to store the results of an OpenAI API query.")
+ (define-error 'chatgpt-error "An error related to the ChatGPT emacs package")
+ (define-error 'chatgpt-parsing-error
+ "An error caused by a failure to parse an OpenAI API Response")
+ (defmacro chatgpt-show-results-buffer-if-active ()
+ "Show the results in other window if necessary."
+ `(if (and (not ;; visible
+ (get-buffer-window chatgpt-buffer))
+ (called-interactively-p 'interactive))
+ (lambda (&optional buf) (ignore buf)
+ (with-current-buffer buf
+ (view-mode t))
+ (switch-to-buffer-other-window chatgpt-buffer))
+ #'identity))
+ ;;;###autoload
+ (defun chatgpt-prompt (prompt callback)
+ "Query OpenAI with PROMPT calling the CALLBACK function on the resulting buffer.
+ Returns buffer containing the text from this query"
+ (interactive (list (read-string "Prompt ChatGPT with: ")
+ (lambda (buf) (with-current-buffer buf
+ (view-mode t))
+ (switch-to-buffer-other-window chatgpt-buffer))))
+ (chatgpt--query-open-api prompt
+ (lambda (results)
+ (with-current-buffer (get-buffer-create chatgpt-buffer)
+ ;; Erase contents of buffer after receiving response
+ (read-only-mode -1)
+ (erase-buffer)
+ (insert results)
+ ;; Return the chatgpt output buffer for non interactive usage
+ (funcall callback (current-buffer))))))
+ ;;;###autoload
+ (defun chatgpt-fix-region (BEG END)
+ "Takes a region BEG to END asks ChatGPT to explain whats wrong with it.
+ It then displays the answer in the `chatgpt-buffer'."
+ (interactive "r")
+ (let ((current-code (buffer-substring BEG END)))
+ (chatgpt-prompt (chatgpt--append-to-prompt
+ current-code
+ "Why doesn't this code work?")
+ (chatgpt-show-results-buffer-if-active))))
+ ;;;###autoload
+ (defun chatgpt-explain-region (BEG END)
+ "Takes a region BEG to END asks ChatGPT what it does.
+ The answer in the displays in `chatgpt-buffer'."
+ (interactive "r")
+ (let ((current-code (buffer-substring BEG END)))
+ (chatgpt-prompt (chatgpt--append-to-prompt
+ current-code
+ "What does this code do?")
+ (chatgpt-show-results-buffer-if-active))))
+ ;;;###autoload
+ (defun chatgpt-gen-tests-for-region (BEG END)
+ "Takes a region BEG to END asks ChatGPT to write a test for it.
+ It then displays the answer in the `chatgpt-buffer'."
+ (interactive "r")
+ (let ((current-code (buffer-substring BEG END)))
+ (chatgpt-prompt (chatgpt--append-to-prompt
+ current-code
+ "Write me a tests for this code")
+ (chatgpt-show-results-buffer-if-active))))
+ ;; TODO currently just says what changed but doesn't wanna show the code it's self
+ ;; (defun chatgpt-optimize-region (BEG END)
+ ;; "Takes a region BEG to END asks ChatGPT to optimize it for speed.
+ ;; It then displays the answer in the `chatgpt-buffer'."
+ ;; (interactive "r")
+ ;; (let ((current-code (buffer-substring BEG END)))
+ ;; (chatgpt-prompt (chatgpt--append-to-prompt
+ ;; current-code
+ ;; "Refactor this code for speed and tell me what you changed and why it's faster")
+ ;; (chatgpt-show-results-buffer-if-active))))
+ ;;;###autoload
+ (defun chatgpt-refactor-region (BEG END)
+ "Takes a region BEG to END asks ChatGPT refactor it.
+ It then displays the answer in the `chatgpt-buffer'."
+ (interactive "r")
+ (let ((current-code (buffer-substring BEG END)))
+ (chatgpt-prompt (chatgpt--append-to-prompt
+ current-code
+ "Refactor this code and tell me what you changed")
+ (chatgpt-show-results-buffer-if-active))))
+ ;;;###autoload
+ (defun chatgpt-prompt-region (BEG END)
+ "Prompt ChatGPT with the region BEG END.
+ It then displays the results in a separate buffer `chatgpt-buffer'."
+ (interactive "r")
+ (chatgpt-prompt (buffer-substring BEG END)
+ ;; Show the results if not already being viewed
+ (chatgpt-show-results-buffer-if-active)))
+ ;;;###autoload
+ (defun chatgpt-prompt-region-and-replace (BEG END)
+ "Replace region from BEG to END with the response from the ChatGPT API.
+ The region is BEG and until END"
+ (interactive "r")
+ (let ((og-buf (current-buffer)))
+ (chatgpt-prompt (buffer-substring BEG END)
+ (lambda (buf)
+ (save-excursion
+ (with-current-buffer og-buf
+ (delete-region BEG END)
+ (goto-char BEG)
+ (insert (with-current-buffer buf (buffer-string)))))))))
+ (defun chatgpt--append-to-prompt (prompt comment-str)
+ "Append the string COMMENT-STR extra information to a PROMPT as a comment."
+ (concat prompt
+ "\n"
+ comment-start
+ " "
+ comment-str))
+ (defun chatgpt--extract-text-from-query (query-result)
+ "Extract the resulting text from a given OpenAI response QUERY-RESULT."
+ (condition-case err
+ (thread-last query-result
+ (assoc-default 'choices)
+ seq-first
+ (assoc-default 'text)
+ string-trim)
+ (error
+ (signal 'chatgpt-parsing-error err))))
+ (defun chatgpt--parse-response (status callback)
+ "Ignoring STATUS and parse the response executing the CALLBACK function on the resulting string."
+ (ignore status)
+ ;; All this is ran inside the buffer containing the response
+ (goto-char 0)
+ (re-search-forward "^$")
+ (funcall callback (chatgpt--extract-text-from-query (json-read))))
+ (defun chatgpt--query-open-api (prompt callback)
+ "Send a string PROMPT to OpenAI API and pass the resulting buffer to CALLBACK.
+ The environment variable OPENAI_API_KEY is used as your API key
+ You can register an account here
+ https://beta.openai.com/docs/introduction/key-concepts"
+ (let* ((api-key sercret-api)
+ (url-request-method (encode-coding-string "POST" 'us-ascii))
+ (url-request-extra-headers `(("Content-Type" . "application/json")
+ ("Authorization" . ,(format "Bearer %s" api-key))))
+ (url-request-data (json-encode
+ `(("model" . "text-davinci-003")
+ ("prompt" . ,prompt)
+ ("max_tokens" . ,chatgpt-max-tokens)
+ ("temperature" . 0)))))
+ (cl-assert (not (string= "" api-key))
+ t
+ "Current contents of the environmental variable OPENAI_API_KEY
+ are '%s' which is not an appropriate OpenAI token please ensure
+ you have the correctly set the OPENAI_API_KEY variable"
+ api-key)
+ (url-retrieve
+ "https://api.openai.com/v1/completions"
+ 'chatgpt--parse-response
+ (list callback))))
+#+end_src
+** Random functions
+#+begin_src emacs-lisp
+ (defun apollo/html-boostrap-boilerplate ()
+ "Insert html boilerplate with boostrap link."
+ (interactive)
+ (insert
+ "<!DOCTYPE html>
+ <html lang=\"en\">
+ <head>
+ <meta charset=\"UTF-8\">
+ <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">
+ <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">
+ <title>My Title</title>
+ <link rel=\"stylesheet\" href=\"./style.css\">
+ <link href=\"https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi\" crossorigin=\"anonymous\">
+ </head>
+ <body>
+ <main>
+ <h1>Starting point</h1>
+ </main>
+ <script src=\"index.js\"></script>
+ </body>
+ </html>" ))
+
+
+ (defun apollo/center-buffer ()
+ "Centers/Uncenters selected buffer"
+ (interactive)
+ (if visual-fill-column-center-text
+ (setq visual-fill-column-center-text nil)
+ (setq visual-fill-column-center-text t))
+ (visual-fill-column-mode 1)
+ (message "General's task completed!"))
+
+
+ (defun apollo/rofi-switch-window ()
+ "Navigate X11 buffers using rofi."
+ (interactive)
+ (start-process-shell-command
+ "rofi" nil "rofi -show window"))
+
+ (defun apollo/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 rofi ()
+ "Run Rofi."
+ (interactive)
+ (apollo/run-in-background "rofi -show drun"))
+
+ (defun apollo/volume-increase ()
+ "Increase Volume."
+ (interactive)
+ (start-process-shell-command
+ "amixer" nil "amixer sset Master 5%+"))
+
+ (defun apollo/volume-decrease ()
+ "Decrease Volume."
+ (interactive)
+ (start-process-shell-command
+ "amixer" nil "amixer sset Master 5%-"))
+
+ (defun apollo/restore-wallpaper ()
+ "Set NAME as wallpaper."
+ (interactive)
+ (start-process-shell-command
+ "feh" nil "feh --bg-scale ~/dotfiles/wallpaper.png"))
+
+ (defun apollo/emacs-keys ()
+ "Swap caps with ctrl."
+ (interactive)
+ (start-process-shell-command
+ "setxkbmap" nil "setxkbmap us -option ctrl:swapcaps"))
+
+ (defun apollo/greek-keyboard ()
+ "Swap caps with ctrl."
+ (interactive)
+ (start-process-shell-command
+ "setxkbmap" nil "setxkbmap gr"))
+
+ (defun apollo/exwm-update-class ()
+ (exwm-workspace-rename-buffer exwm-class-name))
+
+ (defun eshell-new()
+ "Open a new instance of eshell."
+ (interactive)
+ (eshell 'N))
+
+ (defun make-mini-geiser ()
+ (interactive)
+ (split-window-below 60)
+ (geiser nil))
+
+ (defun start-polybar ()
+ "Check which system is running, start polybar accordingly."
+ (interactive)
+ (if (string= (system-name) "fsociety")
+ (start-process-shell-command
+ "polybar" nil "polybar main & polybar second")
+ (start-process-shell-command
+ "polybar" nil "polybar main")))
+
+ (defun create-scratch-writter-buffer nil
+ "create a scratch buffer"
+ (interactive)
+ (switch-to-buffer (get-buffer-create "*scratch-writter*")))
+#+end_src
+** Key-bindings
+#+begin_src emacs-lisp
+ (global-set-key (kbd "<escape>") 'keyboard-escape-quit)
+ (global-set-key (kbd "s-=") 'text-scale-increase)
+ (global-set-key (kbd "s--") 'text-scale-decrease)
+ ;; Pass
+ (global-set-key (kbd "C-c p i") 'password-store-insert)
+ (global-set-key (kbd "C-c p e") 'password-store-edit)
+#+end_src
+*** General
+#+begin_src emacs-lisp
+
+ ;; my general's leader key!
+ (defconst general-key "C-c g")
+
+ (general-create-definer general-does
+ :prefix general-key)
+
+ ;; Basic functions
+ (general-define-key
+ "C-d" 'kill-region
+ "C-k" 'copy-region-as-kill
+ "C-x 9" 'make-mini-buffer
+ "C-c l e" 'apollo/emacs-keys
+ ;;Change keyboard layouts/language
+ "C-c l g" 'apollo/greek-keyboard
+ "C-κ" 'apollo/emacs-keys
+ "C-x C-b" 'ibuffer)
+
+
+
+ ;; My Generals does:
+ (general-does
+ "t" 'counsel-load-theme
+ "l" 'display-line-numbers-mode
+ "v" 'multi-vterm
+ "e" 'eshell
+ "i" 'circe
+ "c" 'apollo/center-buffer
+ "m" 'mu4e
+ "f" 'elfeed
+ "C-t" 'telega
+ "g" 'guix)
+
+ ;;pdf-tools
+ (general-define-key
+ :keymaps 'pdf-view-mode-map
+ "C-c d" 'pdf-view-midnight-minor-mode
+ "C-s" 'isearch-forward
+ "C-o" 'pdf-isearch-occur)
+
+ ;;vterm
+ (general-does
+ :keymaps 'vterm-mode-map
+ "n" 'multi-vterm-next
+ "o" 'multi-vterm
+ "p" 'multi-vterm-prev)
+
+ (general-does
+ :keymaps 'eshell-mode-map
+ "n" 'eshell-new)
+
+ (general-does
+ :keymaps 'org-mode-map
+ "3" 'org-insert-image-size-300)
+#+end_src
+* Org-mode Configuration
+** org-make-toc
+#+begin_src emacs-lisp
+ (add-hook 'org-mode-hook 'org-make-toc-mode)
+#+end_src
+** Themes
+*** Dracula
+#+begin_src emacs-lisp
+(defun apollo/org-theme-dracula ()
+ "Enable Dracula theme for Org headers."
+ (interactive)
+ (dolist
+ (face
+ '((org-level-1 1.7 "#8be9fd" extra-bold)
+ (org-level-2 1.6 "#bd93f9" extra-bold)
+ (org-level-3 1.5 "#50fa7b" bold)
+ (org-level-4 1.4 "#ff79c6" semi-bold)
+ (org-level-5 1.3 "#9aedfe" normal)
+ (org-level-6 1.2 "#caa9fa" normal)
+ (org-level-7 1.1 "#5af78e" normal)
+ (org-level-8 1.0 "#ff92d0" normal)))
+ (set-face-attribute (nth 0 face) nil
+ :font "JetBrains Mono"
+ :weight (nth 3 face)
+ :height (nth 1 face)
+ :foreground (nth 2 face)))
+ (set-face-attribute 'org-table nil
+ :font "JetBrains Mono"
+ :weight 'normal
+ :height 1.0
+ :foreground "#bfafdf"))
+#+end_src
+*** Darkone
+#+begin_src emacs-lisp
+(defun apollo/org-theme-darkone ()
+ "Enable Darkone theme for Org headers."
+ (interactive)
+ (dolist
+ (face
+ '((org-level-1 1.70 "#51afef" bold)
+ (org-level-2 1.55 "#7FBCD2" bold)
+ (org-level-3 1.40 "#da8548" bold)
+ (org-level-4 1.20 "#da8548" semi-bold)
+ (org-level-5 1.20 "#5699af" normal)
+ (org-level-6 1.20 "#a9a1e1" normal)
+ (org-level-7 1.10 "#46d9ff" normal)
+ (org-level-8 1.00 "#ff6c6b" normal)))
+ (set-face-attribute (nth 0 face) nil
+ :font "Jetbrains Mono"
+ :weight (nth 3 face)
+ :height (nth 1 face)
+ :foreground (nth 2 face)))
+ (set-face-attribute 'org-table nil
+ :font "Jetbrains Mono"
+ :weight 'normal
+ :height 1.0
+ :foreground "#A66CFF"))
+#+end_src
+*** Gruvbox
+#+begin_src emacs-lisp
+ (defun apollo/org-theme-gruvbox ()
+ "Enable Darkone theme for Org headers."
+ (interactive)
+ (dolist
+ (face
+ '((org-level-1 1.70 "#fb4934" bold)
+ (org-level-2 1.55 "#98971a" bold)
+ (org-level-3 1.40 "#458588" bold)
+ (org-level-4 1.20 "#b16286" semi-bold)
+ (org-level-5 1.20 "#689d6a" normal)
+ (org-level-6 1.20 "#d3869b" normal)
+ (org-level-7 1.10 "#8ec07c" normal)
+ (org-level-8 1.00 "#ebdbb2" normal)))
+ (set-face-attribute (nth 0 face) nil
+ :font "Jetbrains Mono"
+ :weight (nth 3 face)
+ :height (nth 1 face)
+ :foreground (nth 2 face)))
+ (set-face-attribute 'org-table nil
+ :font "Jetbrains Mono"
+ :weight 'normal
+ :height 1.0
+ :foreground "#A66CFF"))
+#+end_src
+*** Org Modern
+#+begin_src emacs-lisp
+ (modify-all-frames-parameters
+ '((right-divider-width . 5)
+ (internal-border-width . 5)))
+ (dolist (face '(window-divider
+ window-divider-first-pixel
+ window-divider-last-pixel))
+ (face-spec-reset-face face)
+ (set-face-foreground face (face-attribute 'default :background)))
+ (set-face-background 'fringe (face-attribute 'default :background))
+
+ (setq
+ ;; Edit settings
+ org-auto-align-tags nil
+ org-tags-column 0
+ org-catch-invisible-edits 'show-and-error
+ org-special-ctrl-a/e t
+ org-insert-heading-respect-content t
+
+ ;; Org styling, hide markup etc.
+ org-hide-emphasis-markers t
+ org-pretty-entities t
+
+ ;; Agenda styling
+ org-agenda-tags-column 0
+ org-agenda-block-separator ?─
+ org-agenda-time-grid
+ '((daily today require-timed)
+ (800 1000 1200 1400 1600 1800 2000)
+ " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")
+ org-agenda-current-time-string
+ "⭠ now ─────────────────────────────────────────────────")
+
+ (global-org-modern-mode)
+#+end_src
+** Settings
+#+begin_src emacs-lisp
+ (require 'ox-md nil t)
+
+ (setq org-directory "~/org/"
+ org-agenda-files '("~/org/agenda.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-agenda-start-log-mode t
+ org-log-done 'time
+ org-log-into-drawer t
+ org-indent-mode t
+ org-todo-keywords ;; This overwrites the default Doom org-todo-keywords
+ '((sequence
+ "TODO(t)" ;; A task that is ready to be tackled
+ "BLOG(b)" ;; Blog writing assignments
+ "GYM(g)" ;; Things to accomplish at the gym
+ "WAIT(w)" ;; Something is holding up this task
+ "|" ;; The pipe necessary to separate "active" states and "inactive" states
+ "DONE(d)" ;; Task has been completed
+ "CANCELLED(c)" ))
+ org-superstar-headline-bullets-list '("◉" "●" "○" "●" "○" "●" "◆")
+ org-superstar-itembullet-alist '((?+ . ?➤) (?- . ?✦))) ;; changes +/- symbols in item lists)
+
+ ;; Hooks
+ (add-hook 'org-mode-hook 'apollo/org-theme-gruvbox)
+ (add-hook 'org-mode-hook 'flyspell-mode)
+ (add-hook 'org-mode-hook 'toc-org-mode)
+#+end_src
+** Babel
+
+#+begin_src emacs-lisp
+ (defadvice org-edit-src-code (around set-buffer-file-name activate compile)
+ (let ((file-name (buffer-file-name))) ;; (1)
+ ad-do-it ;; (2)
+ (setq buffer-file-name file-name))) ;; (3)
+
+ (org-babel-do-load-languages
+ 'org-babel-load-languages
+ '((emacs-lisp . t)
+ (python . t)))
+
+ (add-to-list 'org-structure-template-alist '("ex" . "SRC EXAMPLE"))
+ (add-to-list 'org-structure-template-alist '("b" . "src bash"))
+ (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 '("li" . "src lisp"))
+
+ ;;Auto tangle
+ (add-hook 'org-mode-hook 'org-auto-tangle-mode)
+#+end_src
+
+* Markdown
+** Theme
+#+begin_src emacs-lisp
+(defun apollo/markdown-theme ()
+ (interactive)
+ (dolist
+ (face
+ '(markdown-header-face-1 :height 2.0))))
+#+end_src
+** Settings
+#+begin_src emacs-lisp
+(setq markdown-header-scaling t)
+
+
+(use-package markdown-mode
+ :ensure t
+ :mode (".md" . gfm-mode)
+ :init (setq markdown-command "multimarkdown"))
+#+end_src
+* Programming
+** Essentials
+#+begin_src emacs-lisp
+(electric-pair-mode 1)
+(global-flycheck-mode)
+
+(use-package company
+ :after lsp-mode
+ :hook (lsp-mode . company-mode)
+ :bind (:map company-active-map
+ ("<tab>" . company-complete-selection))
+ (:map lsp-mode-map
+ ("<tab>" . company-indent-or-complete-common))
+ :custom
+ (company-minimum-prefix-length 1)
+ (company-idle-delay 0.0))
+
+(use-package dap-mode
+ :custom
+ (lsp-enable-dap-auto-configure nil)
+ :config
+ (dap-ui-mode 1))
+
+(use-package company-box
+ :hook (company-mode . company-box-mode))
+#+end_src
+*** Magit
+#+begin_src emacs-lisp
+(use-package magit
+ :custom
+ (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1))
+#+end_src
+** Emacs lisp
+#+begin_src emacs-lisp
+(setq tab-always-indent 'complete)
+(add-to-list 'completion-styles 'initials t)
+
+(add-hook 'emacs-lisp-mode-hook #'rainbow-delimiters-mode)
+(add-hook 'scheme-mode-hook #'rainbow-delimiters-mode)
+#+end_src
+** LSP-Mode
+#+begin_src emacs-lisp
+(defun apollo/lsp-mode-setup ()
+ (setq lsp-headerline-breadcrumb-segments '(path-up-to-project file symbols))
+ (lsp-headerline-breadcrumb-mode))
+
+(use-package lsp-mode
+ :commands (lsp lsp-deferred)
+ :hook (lsp-mode . apollo/lsp-mode-setup)
+ :init
+ (setq lsp-keymap-prefix "C-c l") ;; Or 'C-l', 's-l'
+ :config
+ (lsp-enable-which-key-integration t)
+ (setq lsp-pyls-server-command "~/.local/bin/pylsp"))
+
+(use-package lsp-ui
+ :hook (lsp-mode . lsp-ui-mode)
+ :custom
+ (lsp-ui-doc-position 'bottom))
+#+end_src
+** Python
+#+begin_src emacs-lisp
+(use-package python-mode
+ :ensure t
+ :mode ".py"
+ :hook (python-mode . lsp-deferred)
+ :custom
+ (dap-python-debugger 'debugpy)
+ :config
+ (require 'dap-python))
+
+(use-package pyvenv
+ :config
+ (pyvenv-mode 1))
+#+end_src
+** JSON
+#+begin_src emacs-lisp
+(use-package json-mode
+ :mode ".json"
+ :hook (json-mode . lsp-deferred))
+#+end_src
+** Javascript
+#+begin_src emacs-lisp
+(use-package rjsx-mode
+ :mode ".js"
+ :hook (rjsx-mode . lsp-deferred)
+ :config
+ (defadvice js-jsx-indent-line (after js-jsx-indent-line-after-hack activate)
+ "Workaround sgml-mode and follow airbnb component style."
+ (save-excursion
+ (beginning-of-line)
+ (if (looking-at-p "^ +\/?> *$")
+ (delete-char sgml-basic-offset)))))
+#+end_src
+* Elfeed
+** Feeds
+#+begin_src emacs-lisp
+ (require 'elfeed)
+ (require 'elfeed-goodies)
+ (setq elfeed-feeds (quote
+ (
+ ("https://hackaday.com/blog/feed/"
+ hackaday linux)
+ ("https://thanosapollo.com/public/feed.xml"
+ me)
+ ("https://protesilaos.com/news.xml"
+ protesilaos)
+ ("https://protesilaos.com/codelog.xml"
+ proetesilaos)
+ ("https://guix.gnu.org/feeds/blog.atom"
+ gnu guix)
+ ("https://thanosapollo.com/posts/index.xml"
+ thanos me)
+ ("https://rss.nytimes.com/services/xml/rss/nyt/Science.xml"
+ NYT science news)
+ ("https://rss.nytimes.com/services/xml/rss/nyt/Health.xml"
+ NYT med news)
+ ("https://rss.nytimes.com/services/xml/rss/nyt/World.xml"
+ NYT world news)
+ ("https://rss.nytimes.com/services/xml/rss/nyt/US.xml"
+ NYT us news)
+ ("https://www.addtoany.com/add_to/feed?linkurl=http%3A%2F%2Fwww.thelancet.com%2Frssfeed%2Flancet_current.xml&type=feed&linkname=The%20Lancet%20Current%20Issue&linknote="
+ lancet med)
+ ("http://nullprogram.com/feed/"
+ emacs linux)
+ ("https://drewdevault.com/blog/index.xml"
+ sourcehut drewdevault)
+ ("https://spacepub.space/feeds/videos.xml?videoChannelId=2"
+ drewdevault youtube)
+ ("https://www.youtube.com/feeds/videos.xml?channel_id=UCVls1GmFKf6WlTraIb_IaJg"
+ video dt)
+ ("https://www.youtube.com/feeds/videos.xml?channel_id=UC7YOGHUfC1Tb6E4pudI9STA"
+ video mental)
+ ("https://www.youtube.com/feeds/videos.xml?channel_id=UCAiiOTio8Yu69c3XnR7nQBQ"
+ video daviwil)
+ ("https://videos.lukesmith.xyz/feeds/videos.atom?sort=-publishedAt&isLocal=true"
+ video luke)
+ ("https://www.youtube.com/feeds/videos.xml?channel_id=UCrc2iv2-G1FZ3VscM3zu2jg"
+ video zoogirl)
+ ("https://www.youtube.com/feeds/videos.xml?channel_id=UC0uTPqBCFIpZxlz_Lv1tk_g"
+ video prot)
+ ("https://www.youtube.com/feeds/videos.xml?channel_id=UCq6VFHwMzcMXbuKyG7SQYIg"
+ video moist)
+ ("https://www.youtube.com/feeds/videos.xml?channel_id=UC05XpvbHZUQOfA6xk4dlmcw"
+ video djware))))
+
+#+end_src
+** Settings & Keys
+#+begin_src emacs-lisp
+ (defun elfeed-v-mpv (url)
+ "Watch a video from URL in MPV"
+ (async-shell-command (format "mpv %s" url)))
+
+ (defun elfeed-view-mpv (&optional use-generic-p)
+ "Youtube-feed link"
+ (interactive "P")
+ (let ((entries (elfeed-search-selected)))
+ (cl-loop for entry in entries
+ do (elfeed-untag entry 'unread)
+ when (elfeed-entry-link entry)
+ do (elfeed-v-mpv it))
+ (mapc #'elfeed-search-update-entry entries)
+ (unless (use-region-p) (forward-line))))
+
+ (define-key elfeed-search-mode-map (kbd "v") 'elfeed-view-mpv)
+ (define-key elfeed-search-mode-map (kbd "U") 'elfeed-update)
+
+
+ (setq elfeed-goodies/entry-pane-size 0.65)
+ (elfeed-goodies/setup)
+#+end_src
+
+* PDF
+#+begin_src emacs-lisp
+
+;;Add pdf-isearch-minor-mode hook, otherwise isearch will be buggy
+;;Darkmode hook, cause I don't want color or light in my life, I'm a vampire.
+(add-hook 'pdf-view-mode-hook 'pdf-isearch-minor-mode)
+(add-hook 'pdf-view-mode-hook 'pdf-view-midnight-minor-mode)
+(add-to-list 'auto-mode-alist '("\\.pdf\\'" . pdf-view-mode))
+#+end_src
+* mu4e | Email Configuration
+
+#+begin_src emacs-lisp
+ ;; Check if we have mu4e available
+ ;; if t load mu4e settings
+ (when (require 'mu4e nil 'noerror)
+ (setq mu4e-update-interval (* 10 60))
+ (setq mu4e-get-mail-command "mbsync -a")
+ (setq mu4e-maildir-list "~/Mail/Inbox")
+
+ (defun set-mu4e-context (context-name full-name mail-address signature server)
+ "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"))
+ (smtpmail-smtp-service . ,465)
+ (smtpmail-smtp-server . ,server)
+ (mu4e-compose-signature . ,signature)))))
+ ;;Fixing duplicate UID errors when using mbsync and mu4e
+ (setq mu4e-change-filenames-when-moving t)
+
+ (setq mu4e-maildir-shortcuts
+ '(("/Fastmail/Inbox" . ?i)
+ ("/Fastmail/Sent" . ?s)
+ ))
+
+ (setq mu4e-contexts
+ `(, (set-mu4e-context
+ "Fastmail" "Thanos Apollo"
+ "[email protected]" "Thanos\nhttps://thanosapollo.com"
+ "smtp.fastmail.com")))
+
+ ;; (setq smtpmail-smtp-service 465
+ ;; smtpmail-stream-type 'ssl
+ ;; smtpmail-smtp-server "smtp.fastmail.com")
+
+
+
+ (setq message-send-mail-function 'smtpmail-send-it
+ smtpmail-stream-type 'ssl))
+
+
+#+end_src
+
+* EXWM
+EXWM configuration is tangled with ~.exwm~
++ In GuixSD ~emacs-exwm~ package will look for ~~/.exwm~
+
+#+begin_src emacs-lisp :tangle ../.exwm.el
+
+ (defun apollo/exwm-init-hook ()
+ "Do this upon start."
+ (if (string= (system-name) "fsociety") ;; Check if it's my desktop, otherwise display battery
+ (display-battery-mode 0)
+ (display-battery-mode 1))
+
+ (setq display-time-day-and-date t)
+ (display-time-mode 1)
+
+ (exwm-firefox-holyK-mode 1)
+
+ ;;Launch apps that will run in the background
+ ;; (apollo/run-in-background "blueman-applet")
+ (apollo/run-in-background "picom")
+ ;; (apollo/run-in-background "nm-applet")
+ (apollo/emacs-keys)
+ (apollo/restore-wallpaper)
+ )
+
+ (defun apollo/exwm-update-class ()
+ (exwm-workspace-rename-buffer exwm-class-name))
+
+
+ (setq exwm-workspace-number 6)
+ ;; When window "class" updates, use it to set the buffer name
+ (add-hook 'exwm-update-class-hook #'apollo/exwm-update-class)
+
+ ;;When EXWM starts up, run this hook
+ (add-hook 'exwm-init-hook #'apollo/exwm-init-hook)
+ (start-process-shell-command
+ "xrandr" nil "xrandr --output DisplayPort-0 --primary --mode 2560x1440 --pos 1930x0 --rotate normal --output DisplayPort-1 --off --output DisplayPort-2 --off --output HDMI-A-0 --mode 1920x1080 --pos 0x0 --rotate normal")
+
+ ;; Set the screen resolution
+
+ (require 'exwm-randr)
+ (setq exwm-randr-workspace-monitor-plist '(0 "DP-1" 2 "HDMI-A-0"))
+ (add-hook 'exwm-randr-screen-change-hook
+ (lambda ()
+ (start-process-shell-command
+ "xrandr" nil "xrandr --output DisplayPort-2 --primary --mode 2560x1440 --pos 1920x0 --rotate normal --output HDMI-A-0 --mode 1920x1080 --pos 0x0 --rotate normal" )))
+ (exwm-randr-enable)
+
+
+ ;; Load the system tray before exwm-init
+ (require 'exwm-systemtray)
+ (exwm-systemtray-enable)
+
+ ;; These keys should always pass through to Emacs
+ (setq exwm-input-prefix-keys
+ '(?\C-x
+ ?\C-u
+ ?\C-h
+ ?\C-w
+ ?\M-x
+ ?\M-`
+ ?\M-&
+ ?\M-:
+ ?\s-d
+ ?\C-\M-j ;; Buffer list
+ ?\C-\
+ ?\C-k
+ ?\C-y
+ ?\C-n
+ ?\C-p
+ ?\C-f
+ ?\C-b
+ ?\C-s
+ ?\M-f
+ ?\M-b
+ ?\M-<
+ ?\M->))
+
+ ;; Ctrl+Q will enable the next key to be sent directly
+ (define-key exwm-mode-map [?\C-q] 'exwm-input-send-next-key)
+
+ ;; Set up global key bindings. These always work, no matter the input state!
+ ;; Keep in mind that changing this list after EXWM initializes has no effect.
+ (setq exwm-input-global-keys
+ `(
+
+ ([?\s-r] . exwm-reset)
+
+
+
+ ;; ;; Launch applications via shell command
+ ;; ([?\s-&] . (lambda (command)
+ ;; (interactive (list (read-shell-command "$ ")))
+ ;; (start-process-shell-command command nil command)))
+
+ ;; Switch workspace
+ ([?\s-e] . exwm-workspace-switch)
+ ([?\s-`] . (lambda () (interactive) (exwm-workspace-switch-create 0)))
+ ([?\s-2] . (lambda () (interactive) (exwm-workspace-switch-create 1)))
+ ([?\s-3] . (lambda () (interactive) (exwm-workspace-switch-create 2)))
+ ([?\s-4] . (lambda () (interactive) (exwm-workspace-switch-create 3)))
+ ([?\s-5] . (lambda () (interactive) (exwm-workspace-switch-create 4)))
+
+ ,@(mapcar (lambda (i)
+ `(,(kbd (format "s-%d" i)) .
+ (lambda ()
+ (interactive)
+ (exwm-workspace-switch-create ,i))))
+ (number-sequence 0 9))))
+
+ (defun exwm-enlarge-horizontally-50 ()
+ (interactive)
+ (exwm-layout-enlarge-window-horizontally 50))
+
+ (defun exwm-shrink-horizontally-50 ()
+ "Shrink window horizontally by 10"
+ (interactive)
+ (exwm-layout-shrink-window-horizontally 50))
+
+ (defun exwm-shrink-vertically-50 ()
+ "Shrink window by 50."
+ (interactive)
+ (exwm-layout-shrink-window 50))
+
+ (defun exwm-enlarge-vertically-50 ()
+ "Enlarge window by 50."
+ (interactive)
+ (exwm-layout-enlarge-window 50))
+
+ (exwm-input-set-key (kbd "C-c d") 'dmenu)
+ (exwm-input-set-key (kbd "s-<tab>") 'rofi)
+ (exwm-input-set-key (kbd "s-Q") 'kill-emacs)
+ (exwm-input-set-key (kbd "<XF86AudioRaiseVolume>") 'apollo/volume-increase)
+ (exwm-input-set-key (kbd "<XF86AudioLowerVolume>") 'apollo/volume-decrease)
+ (exwm-input-set-key (kbd "s-0") 'apollo/emacs-keys)
+ (exwm-input-set-key (kbd "s-9") 'apollo/greek-keyboard)
+ (exwm-input-set-key (kbd "C-c C-<left>") 'exwm-shrink-horizontally-50)
+ (exwm-input-set-key (kbd "C-c C-<right>") 'exwm-enlarge-horizontally-50)
+ (exwm-input-set-key (kbd "C-c C-<up>") 'exwm-shrink-vertically-50)
+ (exwm-input-set-key (kbd "C-c C-<down>") 'exwm-enlarge-vertically-50)
+ (exwm-input-set-key (kbd "C-c C-e") 'exwm-layout-toggle-fullscreen)
+
+
+ (exwm-enable)
+#+end_src
+
diff --git a/org/shells.org b/org/shells.org
new file mode 100755
index 0000000..4bf1a20
--- /dev/null
+++ b/org/shells.org
@@ -0,0 +1,148 @@
+#+TITLE: Shells configuration
+#+PROPERTY:
+#+auto_tangle: t
+#+STARTUP: overview
+* Aliases
+#+begin_src bash :tangle ../.shells/alias.sh
+ alias ll='ls -l'
+ alias grep='grep --color=auto'
+ alias anki='QTWEBENGINE_CHROMIUM_FLAGS="--disable-seccomp-filter-sandbox" anki'
+
+ alias vim='nvim'
+ alias vi='nvim'
+
+ #git
+ alias config='/usr/bin/git --git-dir=$HOME/Developer/config/ --work-tree=$HOME'
+ alias ga='git add'
+ alias gaa='git add .'
+ alias gc='git commit -m'
+ alias gp='git push -u origin'
+ alias gpm='git push -u origin master'
+ alias gpd='git push -u origin developer'
+ alias gs='git status'
+ alias cpm='config push -u origin master'
+ alias ca='config add'
+ alias cs='config status'
+ alias cc='config commit -m'
+
+ #pacman | yay
+ alias yeet='paru -Rsc'
+
+ # weather
+ alias weather="curl wttr.in"
+
+ alias ls='ls -la --color'
+ alias sb='sudo systemctl start bluetooth'
+ alias mykeys='setxkbmap -option caps:escape'
+ alias logout='pkill -U $USER'
+ #alias neofetch='neofetch | lolcat'
+ alias b='bluetoothctl'
+ alias ba='bluetooth-autoconnect'
+ alias music='mocp'
+ alias ytd="yt-dlp"
+ alias c="pavucontrol"
+ alias r="ranger"
+ alias klight="brightnessctl --device='tpacpi::kbd_backlight' set 1"
+
+
+ alias clear="printf '\e[2J\e[H'"
+ ##yarn
+ alias sweb='BROWSER="firefox" yarn start'
+
+ ##flatpaks
+ alias fanki='flatpak run net.ankiweb.Anki'
+#+end_src
+
+* Exports
+#+begin_src shell :tangle ../.shells/exports.sh
+ # Export 'SHELL' to child processes. Programs such as 'screen'
+ # honor it and otherwise use /bin/sh.
+ path+=('~/node_modules/.bin')
+ export SHELL
+ export PATH
+
+
+ if [[ $- != *i* ]]
+ then
+ # We are being invoked from a non-interactive shell. If this
+ # is an SSH session (as in "ssh host command"), source
+ # /etc/profile so we get PATH and other essential variables.
+ [[ -n "$SSH_CLIENT" ]] && source /etc/profile
+
+ # Don't do anything else.
+ return
+ fi
+#+end_src
+
+* bashrc
+#+begin_src shell :tangle ../.bashrc
+ source ~/.shells/alias.sh
+ source ~/.shells/exports.sh
+
+
+ PS1='\n\[\e[0m\][\[\e[0;1;38;5;208m\]\w\[\e[0;2;38;5;248m\]|\[\e[0;2;38;5;220m\]$(git branch 2>/dev/null | grep '"'"'^*'"'"' | colrm 1 2) \[\e[0;2;38;5;242m\]\t\[\e[0m\]]\n\[\e[0m\]-\[\e[0m\]> \[\e[0m\]'
+
+ # Uncomment next line to enable starship prompt
+ # eval "$(starship init bash)"
+#+end_src
+
+* zshrc
+#+begin_src bash :tangle ../.zshrc
+ source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
+ source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
+
+ source ~/.shells/alias.sh
+ source ~/.shells/exports.sh
+ export PATH=/home/apollo/.local/bin:$PATH
+
+ eval "$(starship init zsh)"
+
+ autoload Uz compinit
+ compinit
+
+ typeset -g -A key
+
+ key[Home]="${terminfo[khome]}"
+ key[End]="${terminfo[kend]}"
+ key[Insert]="${terminfo[kich1]}"
+ key[Backspace]="${terminfo[kbs]}"
+ key[Delete]="${terminfo[kdch1]}"
+ key[Up]="${terminfo[kcuu1]}"
+ key[Down]="${terminfo[kcud1]}"
+ key[Left]="${terminfo[kcub1]}"
+ key[Right]="${terminfo[kcuf1]}"
+ key[PageUp]="${terminfo[kpp]}"
+ key[PageDown]="${terminfo[knp]}"
+ key[ShiftTab]="${terminfo[kcbt]}"
+
+ # setup key accordingly
+ [[ -n "${key[Home]}" ]] && bindkey -- "${key[Home]}" beginning-of-line
+ [[ -n "${key[End]}" ]] && bindkey -- "${key[End]}" end-of-line
+ [[ -n "${key[Insert]}" ]] && bindkey -- "${key[Insert]}" overwrite-mode
+ [[ -n "${key[Backspace]}" ]] && bindkey -- "${key[Backspace]}" backward-delete-char
+ [[ -n "${key[Delete]}" ]] && bindkey -- "${key[Delete]}" delete-char
+ [[ -n "${key[Up]}" ]] && bindkey -- "${key[Up]}" up-line-or-history
+ [[ -n "${key[Down]}" ]] && bindkey -- "${key[Down]}" down-line-or-history
+ [[ -n "${key[Left]}" ]] && bindkey -- "${key[Left]}" backward-char
+ [[ -n "${key[Right]}" ]] && bindkey -- "${key[Right]}" forward-char
+ [[ -n "${key[PageUp]}" ]] && bindkey -- "${key[PageUp]}" beginning-of-buffer-or-history
+ [[ -n "${key[PageDown]}" ]] && bindkey -- "${key[PageDown]}" end-of-buffer-or-history
+ [[ -n "${key[Shift-Tab]}" ]] && bindkey -- "${key[Shift-Tab]}" reverse-menu-complete
+
+ # Finally, make sure the terminal is in application mode, when zle is
+ # active. Only then are the values from $terminfo valid.
+ if (( ${+terminfo[smkx]} && ${+terminfo[rmkx]} )); then
+ autoload -Uz add-zle-hook-widget
+ function zle_application_mode_start { echoti smkx }
+ function zle_application_mode_stop { echoti rmkx }
+ add-zle-hook-widget -Uz zle-line-init zle_application_mode_start
+ add-zle-hook-widget -Uz zle-line-finish zle_application_mode_stop
+ fi
+
+ # History search
+ autoload -Uz up-line-or-beginning-search down-line-or-beginning-search
+ zle -N up-line-or-beginning-search
+ zle -N down-line-or-beginning-search
+
+ [[ -n "${key[Up]}" ]] && bindkey -- "${key[Up]}" up-line-or-beginning-search
+#+end_src