nixos/config/emacs/emacs.org
2023-12-09 21:16:25 +04:00

1279 lines
40 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#+title: Sakomacs configuration
#+PROPERTY: header-args:emacs-lisp :tangle ./init.el
* Usage
M-x org-bable-tangle
* Lexical Binding
Should make startup faster, taken from doom-emacs
#+begin_src emacs-lisp
;; -*- lexical-binding: t; -*-
#+end_src
* Default Enconding
#+begin_src emacs-lisp
(setq utf-translate-cjk-mode nil) ; disable CJK coding/encoding (Chinese/Japanese/Korean characters)
(set-language-environment 'utf-8)
(set-keyboard-coding-system 'utf-8) ; For old Carbon emacs on OS X only
(setq locale-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-selection-coding-system
(if (eq system-type 'windows-nt)
'utf-16-le ;; https://rufflewind.com/2014-07-20/pasting-unicode-in-emacs-on-windows
'utf-8))
(prefer-coding-system 'utf-8)
#+end_src
* Put Backup Files Somewhere else
#+begin_src emacs-lisp
(setq backup-directory-alist '(("." . "~/.emacs.d/backup"))
backup-by-copying t
version-control t
delete-old-versions t
kept-new-versions 20
kept-old-versions 5)
#+end_src
* EmacsClient UI
#+begin_src emacs-lisp
(setq frame-resize-pixelwise t)
;; ui settings apparently go below
(setq default-frame-alist '((font . "JetBrains Mono")
'(vertical-scroll-bars . nil)
'(horizontal-scroll-bars . nil)))
#+end_src
* UI
#+begin_src emacs-lisp
;; UI/UX
(setq inhibit-splash-screen t)
;; remove useless GUI elements
(scroll-bar-mode -1)
(tool-bar-mode -1)
(tooltip-mode -1)
(set-fringe-mode 10)
(menu-bar-mode -1)
;; Line Numbers
(column-number-mode)
;; Bell
(setq visible-bell t)
;; prefer y/n
(fset 'yes-or-no-p 'y-or-n-p)
;; Stop Emacs from trying to use dialog boxes.
(setq use-dialog-box nil)
;; idc emacs just work already
(setq warning-minimum-level :emergency)
#+end_src
* Line Numbers
#+begin_src emacs-lisp
(add-hook 'prog-mode 'display-line-numbers-mode)
(add-hook 'yaml-mode 'display-line-numbers-mode)
(add-hook 'conf-mode 'display-line-numbers-mode)
(setq display-line-numbers-width-start t)
#+end_src
* Keymaps
#+begin_src emacs-lisp
;; switch buffers
(global-set-key (kbd "C-M-j") 'counsel-switch-buffer)
;; instead of control-g
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
;; repeat keybinds
(repeat-mode)
#+end_src
* Fonts
#+begin_src emacs-lisp
(set-face-attribute `default nil :font "JetBrains Mono" :height 130)
#+end_src
* Use-Package setup
#+begin_src emacs-lisp
(message "setting up use-package")
(require `package)
(setq package-archives `(("mepla" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")
("elpa" . "https://elpa.gnu.org/packages/")))
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
;; Init package for non-linux
(unless (package-installed-p `use-package)
(package-install `use-package))
(require 'use-package)
(setq use-package-always-ensure t)
#+end_src
* Straight.el setup
#+begin_src emacs-lisp
(message "setting up straight.el")
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 6))
(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))
#+end_src
* SPEED SPEED SPEED SPEED
** Avoid Garbage Collection at startup
#+begin_src emacs-lisp
(use-package gcmh
:init
(setq gcmh-idle-delay 5)
(setq gcmh-high-cons-threshold (* 16 1024 1024))
:config
(gcmh-mode))
#+end_src
** Move Garbage collection further back
#+begin_src emacs-lisp
(setq gc-cons-threshold most-positive-fixnum)
#+end_src
** Unset file-name-handler-alist temporarily
#+begin_src emacs-lisp
(defvar sakomacs--file-name-handler-alist file-name-handler-alist)
(setq file-name-handler-alist nil)
;; Alternatively, restore it even later:
(add-hook 'emacs-startup-hook
(lambda ()
(setq file-name-handler-alist sakomacs--file-name-handler-alist)))
#+end_src
** Go back to normal GC after init
#+begin_src emacs-lisp
(add-hook 'emacs-startup-hook
(lambda ()
;;(setq gc-cons-threshold 16777216 ; 16mb
;; this could be really bad idk
(setq gc-cons-threshold 100000000
gc-cons-percentage 0.1)))
#+end_src
** Don't use GC when minibuffer is used
#+begin_src emacs-lisp
(defun doom-defer-garbage-collection-h ()
"Disable garbage collection."
(setq gc-cons-threshold most-positive-fixnum))
(defun doom-restore-garbage-collection-h ()
"Restore garbage collection."
(run-at-time
1 nil (lambda () (setq gc-cons-threshold 16777216))))
(add-hook 'minibuffer-setup-hook #'doom-defer-garbage-collection-h)
(add-hook 'minibuffer-exit-hook #'doom-restore-garbage-collection-h)
#+end_src
** Make Emacs read more
#+begin_src emacs-lisp
(setq read-process-output-max (* 1024 1024)) ;; 1mb
#+end_src
* Native Compilation
#+begin_src emacs-lisp
(setq package-native-compile t)
(setq comp-deferred-compilation t)
(setq native-comp-deferred-compilation-deny-list nil)
(setq warning-suppress-log-types '((comp)))
#+end_src
* Packages
** Log state
#+begin_src emacs-lisp
(message "setting up packages")
#+end_src
** Command Log Mode
#+begin_src emacs-lisp
(use-package command-log-mode
:straight t
)
#+end_src
** Command Autocompletion Packages
#+begin_src emacs-lisp
;; better search
(use-package swiper
:straight t
)
;; better commands
(use-package counsel
:straight t
)
;; autocompletion on commands (?)
(use-package ivy
:diminish
:straight t
: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))
:demand
:config
(ivy-mode 1))
;; better ivy autocompletion
(use-package ivy-rich
:straight t
:init
(ivy-rich-mode 1))
;; ivy in the middle
(use-package ivy-posframe
:straight t
:init
(setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-center)))
:config
(ivy-posframe-mode 1))
;; counsel M+X
(use-package counsel
:straight t
:bind (("M-x" . counsel-M-x)
("C-x b" . counsel-ibuffer)
("C-x C-f" . counsel-find-file)
:map minibuffer-local-map
("C-r" . 'counsel-minibuffer-history))
:config
(setq ivy-inital-inputs-alist nil))
#+end_src
** Custom Themes
#+begin_src emacs-lisp
(use-package doom-themes
:straight t
:ensure t
:config
;; Global settings (defaults)
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
doom-themes-enable-italic t) ; if nil, italics is universally disabled
;; load the theme
(load-theme 'doom-homeage-black t)
(doom-themes-org-config)
(doom-themes-treemacs-config)
;; Enable flashing mode-line on errors
(doom-themes-visual-bell-config))
#+end_src
** All the Icons (to make doom-themes happy)
#+begin_src emacs-lisp
(use-package all-the-icons)
#+end_src
** Nerd-Fonts (All of the Icons doesnt work for me)
#+begin_src emacs-lisp
(use-package nerd-icons
:straight t
:custom
;; "Symbols Nerd Font Mono" is the default and is recommended
;; but you can use any other Nerd Font if you want
(nerd-icons-font-family "JetBrainsMono NF")
)
#+end_src
** Rainbow Delimiters
#+begin_src emacs-lisp
(use-package rainbow-delimiters
:straight t
:hook (prog-mode . rainbow-delimiters-mode))
#+end_src
** Keybinding autocompletion
#+begin_src emacs-lisp
(use-package which-key
:straight t
:init (which-key-mode)
:diminish which-key-mode
:config
(setq which-key-idle-delay 1))
#+end_src
** Custom Modeline
#+begin_src emacs-lisp
(use-package doom-modeline
:ensure t
:straight t
:hook (after-init . doom-modeline-mode)
:custom ((doom-modeline-height 40)))
#+end_src
** Hide Modeline
#+begin_src emacs-lisp
(use-package hide-mode-line
:straight t
:hook (((treemacs-mode
eshell-mode shell-mode
term-mode vterm-mode
embark-collect-mode
lsp-ui-imenu-mode
pdf-annot-list-mode
dashboard-mode) . turn-on-hide-mode-line-mode)
(dired-mode . turn-off-hide-mode-line-mode)))
#+end_src
** Minor mode menu for modline
#+begin_src emacs-lisp
(use-package minions
:straight t
:hook (doom-modeline-mode . minions-mode))
#+end_src
** Better help menu
#+begin_src emacs-lisp
(use-package helpful
:ensure t
:straight t
: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
** Modern selection behavior
#+begin_src emacs-lisp
(use-package delsel
:straight t
:ensure nil
:config (delete-selection-mode +1))
#+end_src
** General Leader Key
#+begin_src emacs-lisp
(use-package general
:straight t
:config
(general-create-definer sakomacs/leader-keys
:keymaps `(normal insert visual emacs)
:prefix "SPC"
:global-prefix "C-SPC")
(sakomacs/leader-keys
;; code
"c" `(:ignore c :which-key "code")
"cc" `(compile :which-key "compile")
"cC" `(recompile :which-key "compile")
"cX" `(lsp-treeemacs-errors-list :which-ley "list errors")
;; toggles
"t" `(:ignore t :which-key "toggles")
"tt" `(counsel-load-theme :which-key "choose theme")
;; search
"s" `(:ignore s :which-key "search")
"sb" `(swiper :which-key "search buffer")
;; insert
"i" `(:ignore i :which-key "insert")
"ie" `(emoji-search :which-key "Emoji")
;; project
"p" `(:ignore p :which-key "projects")
"pp" `(projectile-switch-project :which-key "open project")
"pk" `(projectile-kill-buffers :which-key "close project")
"pa" `(projectile-add-known-project :which-key "add project")
"pR" `(projectile-run-project :which-key "run project")
"pt" `(magit-todos-list :which-key "list project todos")
"ps" `(projectile-save-project-buffers :which-key "save project")
"po" `(projectile-find-other-file :which-key "find other file")
"pg" `(projectile-configure-project :which-key "configure project")
"pc" `(projectile-compile-project :which-key "compile project")
;; open
"o" `(:ignore o :which-key "open")
"op" `(treemacs :which-key "treemacs")
"oP" `(treemacs-find-file :which-key "treemacs find file")
"oe" `(eshell :which-key "eshell")
;; notes
"n" `(:ignore o :which-key "notes")
"na" `(org-agenda :which-key "agenda")
;; quit
"q" `(:ignore q :which-key "quit")
"qq" `(delete-frame :which-key "close emacs")
"qK" `(kill-emacs :which-key "quit emacs")
;; git
"g" `(:ignore g :which-key "git")
"gs" `(magit-status :which-key "status")
"gc" `(:ignore gc :which-key "create")
"gcr" `(magit-init :which-key "init repo")
"gcR" `(magit-clone :which-key "clone repo")
"gcc" `(magit-commit-create :which-key "commit")
"gci" `(forge-create-issue :which-key "issue")
"gcp" `(forge-create-pullreq :which-key "pull request")))
#+end_src
** Dashboard
#+begin_src emacs-lisp
(use-package dashboard
:straight t
:init
(setq dashboard-display-icons-p t) ;; display icons on both GUI and terminal
(setq dashboard-icon-type 'nerd-icons) ;; use `nerd-icons' package
(setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*")))
(setq dashboard-center-content t)
(setq dashboard-projects-backend 'projectile)
(setq dashboard-footer-messages '("i think i have emacs pinky"
"why are we still using lisp again?"
"why is this running on 1/16 threads?!?!?"
"still waiting for multithreaded :)"
"any day now"
"make sure to pray today"
"im literally kanye west"
"please dont break please dont break"
"GNU/Linux/Emacs/???"
"what is a GNU/Linux ?????????????"
"done!"
"remove / for faster emacs on linux"
""))
(setq dashboard-items '((recents . 3)
(projects . 3)
(agenda . 5)))
(setq dashboard-image-banner-max-height 250)
(setq dashboard-image-banner-max-width 500)
(setq dashboard-page-separator "\n\n")
(dashboard-setup-startup-hook))
#+end_src
** Evil Mode (vim)
#+begin_src emacs-lisp
(use-package evil
:straight t
:init
(setq evil-want-integration t)
(setq evil-want-keybinding nil)
(setq evil-want-C-u-scroll t)
(setq evil-want-C-i-jump nil)
:hook (evil-mode . sakomacs/evil-hook)
:ensure t
:demand
:config
(evil-mode 1)
(define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
(define-key evil-insert-state-map (kbd "C-h") `evil-delete-backward-char-and-join)
;; visual line motion
(evil-global-set-key 'motion "j" 'evil-next-visual-line)
(evil-global-set-key 'motion "k" 'evil-previous-visual-line)
(evil-set-initial-state 'messages-buffer-mode 'normal)
(evil-set-initial-state 'dashboard-mode 'normal))
;; extra things for Evil
(use-package evil-collection
:straight t
:after evil
:config
(evil-collection-init))
;; commenting
(use-package evil-commentary
:straight t
:after evil
:diminish
:config (evil-commentary-mode +1))
#+end_src
** Hydra for scaling text
#+begin_src emacs-lisp
(use-package hydra
:straight t
)
(defhydra hydra-text-scale (:timeout 4)
"scale text"
("j" text-scale-increase "in")
("k" text-scale-decrease "out")
("f" nil "finished" :exit t))
(sakomacs/leader-keys
"ts" '(hydra-text-scale/body :which-key "scale text"))
#+end_src
** Helpful for projects
#+begin_src emacs-lisp
(use-package projectile
:straight t
:diminish projectile-mode
:demand
:config (projectile-mode)
:custom ((projectile-completion-system 'ivy))
:bind-keymap
("C-c p" . projectile-command-map)
:init
(when (file-directory-p "~/dev")
(setq projectile-project-search-path '("~/dev")))
(setq projectile-switch-project-action #'projectile-dired))
(use-package counsel-projectile
:straight t
:config (counsel-projectile-mode))
#+end_src
** Org-Mode
#+begin_src emacs-lisp
(use-package org
:straight t
:hook (org-mode . org-indent-mode)
:config
(setq org-ellipsis "")
(setq org-agenda-start-with-log-mode t)
(setq org-log-done 'time)
(setq org-log-into-drawer t)
;; org habits thing
(require 'org-habit)
(add-to-list 'org-modules 'org-habit)
(setq org-habit-graph-column 60)
;; archive thingy i forgot
(setq org-refile-targets
'(("archive.org" :maxlevel . 1)))
;; save org buffer before refile
(advice-add 'org-refile :after 'org-save-all-org-buffers)
;; org agenda files
(setq org-agenda-files
'("~/org/tasks.org"
"~/org/school.org"
"~/org/daily.org"
"~/org/irl.org"
"~/org/work.org"))
;; Following
(setq org-return-follows-link t)
;; org mode src thing
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("sh" . "src shell"))
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(setq org-todo-keywords
'((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)")
(sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANCELED(k@)")))
(setq org-refile-targets
'(("archive.org" :maxlevel . 1)
("tasks.org" :maxlevel . 1)))
;; Save Org buffers after refiling!
(advice-add 'org-refile :after 'org-save-all-org-buffers)
(setq org-tag-alist
'((:startgroup)
; Put mutually exclusive tags here
(:endgroup)
("@errand" . ?E)
("@home" . ?H)
("@work" . ?W)
("agenda" . ?a)
("planning" . ?p)
("publish" . ?P)
("batch" . ?b)
("note" . ?n)
("idea" . ?i)))
;; Configure custom agenda views
(setq org-agenda-custom-commands
'(("d" "Dashboard"
((agenda "" ((org-deadline-warning-days 7)))
(todo "NEXT"
((org-agenda-overriding-header "Next Tasks")))
(tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects")))))
("n" "Next Tasks"
((todo "NEXT"
((org-agenda-overriding-header "Next Tasks")))))
("W" "Work Tasks" tags-todo "+work-email")
;; Low-effort next actions
("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0"
((org-agenda-overriding-header "Low Effort Tasks")
(org-agenda-max-todos 20)
(org-agenda-files org-agenda-files)))
("w" "Workflow Status"
((todo "WAIT"
((org-agenda-overriding-header "Waiting on External")
(org-agenda-files org-agenda-files)))
(todo "REVIEW"
((org-agenda-overriding-header "In Review")
(org-agenda-files org-agenda-files)))
(todo "PLAN"
((org-agenda-overriding-header "In Planning")
(org-agenda-todo-list-sublevels nil)
(org-agenda-files org-agenda-files)))
(todo "BACKLOG"
((org-agenda-overriding-header "Project Backlog")
(org-agenda-todo-list-sublevels nil)
(org-agenda-files org-agenda-files)))
(todo "READY"
((org-agenda-overriding-header "Ready for Work")
(org-agenda-files org-agenda-files)))
(todo "ACTIVE"
((org-agenda-overriding-header "Active Projects")
(org-agenda-files org-agenda-files)))
(todo "COMPLETED"
((org-agenda-overriding-header "Completed Projects")
(org-agenda-files org-agenda-files)))
(todo "CANC"
((org-agenda-overriding-header "Cancelled Projects")
(org-agenda-files org-agenda-files)))))))
(setq org-capture-templates
`(("t" "Tasks / Projects")
("tt" "Task" entry (file+olp "~/Projects/Code/emacs-from-scratch/OrgFiles/Tasks.org" "Inbox")
"* TODO %?\n %U\n %a\n %i" :empty-lines 1)
("j" "Journal Entries")
("jj" "Journal" entry
(file+olp+datetree "~/Projects/Code/emacs-from-scratch/OrgFiles/Journal.org")
"\n* %<%I:%M %p> - Journal :journal:\n\n%?\n\n"
;; ,(dw/read-file-as-string "~/Notes/Templates/Daily.org")
:clock-in :clock-resume
:empty-lines 1))))
#+end_src
** Org Mode Beautifers
We have to compete with notion somehow right?
*** Org-Superstar
#+begin_src emacs-lisp
(use-package org-superstar
:after org
:hook (org-mode . org-superstar-mode)
:config
(setq org-superstar-headline-bullets-list '("" "" "" "" ""))
(setq org-superstar-remove-leading-stars t)
(setq org-superstar-item-bullet-alist
'((?+ . ?•)
(?* . ?➤)
(?- . ?)))
)
#+end_src
*** Olivetti
#+begin_src emacs-lisp
(use-package olivetti
:hook (org-mode . (lambda () (interactive) (olivetti-mode) (olivetti-set-width 100))))
#+end_src
** Org-Roam
#+begin_src emacs-lisp
(use-package org-roam
:straight t
:ensure t
:custom
(org-roam-directory "~/org"
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n i" . org-roam-node-insert))
:config
(org-roam-setup)))
#+end_src
** Treemacs
#+begin_src emacs-lisp
(use-package treemacs
:ensure t
:defer t
:straight t
:init
(with-eval-after-load 'winum
(define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
:config
(progn
(setq treemacs-collapse-dirs (if treemacs-python-executable 3 0)
treemacs-deferred-git-apply-delay 0.5
treemacs-directory-name-transformer #'identity
treemacs-display-in-side-window t
treemacs-eldoc-display 'simple
treemacs-file-event-delay 2000
treemacs-file-extension-regex treemacs-last-period-regex-value
treemacs-file-follow-delay 0.2
treemacs-file-name-transformer #'identity
treemacs-follow-after-init t
treemacs-expand-after-init t
treemacs-find-workspace-method 'find-for-file-or-pick-first
treemacs-git-command-pipe ""
treemacs-goto-tag-strategy 'refetch-index
treemacs-header-scroll-indicators '(nil . "^^^^^^")
treemacs-hide-dot-git-directory t
treemacs-indentation 2
treemacs-indentation-string " "
treemacs-is-never-other-window nil
treemacs-max-git-entries 5000
treemacs-missing-project-action 'ask
treemacs-move-forward-on-expand nil
treemacs-no-png-images nil
treemacs-no-delete-other-windows t
treemacs-project-follow-cleanup nil
treemacs-persist-file (expand-file-name ".cache/treemacs-persist" user-emacs-directory)
treemacs-position 'left
treemacs-read-string-input 'from-child-frame
treemacs-recenter-distance 0.1
treemacs-recenter-after-file-follow nil
treemacs-recenter-after-tag-follow nil
treemacs-recenter-after-project-jump 'always
treemacs-recenter-after-project-expand 'on-distance
treemacs-litter-directories '("/node_modules" "/.venv" "/.cask")
treemacs-project-follow-into-home nil
treemacs-show-cursor nil
treemacs-show-hidden-files t
treemacs-silent-filewatch nil
treemacs-silent-refresh nil
treemacs-sorting 'alphabetic-asc
treemacs-select-when-already-in-treemacs 'move-back
treemacs-space-between-root-nodes t
treemacs-tag-follow-cleanup t
treemacs-tag-follow-delay 1.5
treemacs-text-scale nil
treemacs-user-mode-line-format nil
treemacs-user-header-line-format nil
treemacs-wide-toggle-width 70
treemacs-width 35
treemacs-width-increment 1
treemacs-width-is-initially-locked t
treemacs-workspace-switch-cleanup nil)
;; The default width and height of the icons is 22 pixels. If you are
;; using a Hi-DPI display, uncomment this to double the icon size.
;;(treemacs-resize-icons 44)
(treemacs-follow-mode t)
(treemacs-tag-follow-mode t)
(treemacs-project-follow-mode t)
(treemacs-filewatch-mode t)
(treemacs-fringe-indicator-mode 'always)
(when treemacs-python-executable
(treemacs-git-commit-diff-mode t))
(pcase (cons (not (null (executable-find "git")))
(not (null treemacs-python-executable)))
(`(t . t)
(treemacs-git-mode 'deferred))
(`(t . _)
(treemacs-git-mode 'simple)))
(treemacs-hide-gitignored-files-mode nil))
:bind
(:map global-map
("M-0" . treemacs-select-window)
("C-x t 1" . treemacs-delete-other-windows)
("C-x t d" . treemacs-select-directory)
("C-x t B" . treemacs-bookmark)
("C-x t C-t" . treemacs-find-file)
("C-x t M-t" . treemacs-find-tag)))
(use-package treemacs-evil
:after (treemacs evil)
:straight t
:ensure t)
(use-package treemacs-projectile
:after (treemacs projectile)
:straight t
:ensure t)
(use-package treemacs-magit
:after (treemacs magit)
:straight t
:ensure t)
#+end_src
** Dev Packages
*** Magit (git in emacs)
#+begin_src emacs-lisp
(use-package magit
:straight t
:custom
(magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
)
(use-package magit-todos
:straight t
:after magit
:config (magit-todos-mode 1))
#+end_src
*** Forge for Magit (Adds github, gitlab, etc PRs and Issues to magit)
make sure to setup authinfo
#+begin_src emacs-lisp
(use-package forge
:straight t
:after magit)
(setq auth-sources '("~/.authinfo"))
#+end_src
*** Direnv
#+begin_src emacs-lisp
(use-package direnv
:straight t
:config
(direnv-mode))
#+end_src
*** Lsp-mode
**** Language Servers
#+begin_src emacs-lisp
(defun sakomacs/lsp-mode-setup ()
(setq lsp-headerline-breadcrumb-segments '(path-up-to-project file symbols))
(lsp-headerline-breadcrumb-mode))
(use-package lsp-mode
:straight t
:commands (lsp lsp-deferred)
:hook (lsp-mode . sakomacs/lsp-mode-setup)
:init
(setq lsp-keymap-prefix "C-c l")
:config
(lsp-enable-which-key-integration t)
(setq lsp-keep-workspace-alive nil))
#+end_src
**** Lsp-ui
#+begin_src emacs-lisp
(use-package lsp-ui
:hook (lsp-mode . lsp-ui-mode)
:straight t
:custom
(lsp-ui-doc-position 'bottom))
#+end_src
**** Treemacs Lsp
#+begin_src emacs-lisp
(use-package lsp-treemacs
:straight t
:after lsp)
#+end_src
**** lsp-ivy
#+begin_src emacs-lisp
(use-package lsp-ivy
:straight t
)
#+end_src
**** Languages
***** HTML/CSS
#+begin_src emacs-lisp
(use-package web-mode
:straight t
:hook (web-mode . lsp)
:mode ("\\.html\\'"
"\\.css\\'"))
#+end_src
***** Javascript
#+begin_src emacs-lisp
(use-package js2-mode
:straight t
:mode ("\\.js\\'"
"\\.jsx\\'")
:hook (js2-mode . lsp)
:config
(setq web-mode-markup-indent-offset 2) ; HTML
(setq web-mode-css-indent-offset 2) ; CSS
(setq web-mode-code-indent-offset 2) ; JS/JSX/TS/TSX
(setq web-mode-content-types-alist '(("jsx" . "\\.js[x]?\\'"))))
#+end_src
***** Typescript
#+begin_src emacs-lisp
(use-package typescript-mode
:straight t
:mode ("\\.ts\\'"
"\\.tsx\\'")
:hook (typescript-mode . lsp))
#+end_src
***** Astro
#+begin_src emacs-lisp
(use-package astro-ts-mode
:straight t
:mode "\\.astro\\'"
:hook (astro-ts-mode . lsp)
:config
(setq treesit-language-source-alist
'((astro "https://github.com/virchau13/tree-sitter-astro")
(css "https://github.com/tree-sitter/tree-sitter-css")
(tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src"))))
#+end_src>
***** C/C++
#+begin_src emacs-lisp
(add-hook 'c-mode-hook 'lsp)
(add-hook 'c++-mode-hook 'lsp)
#+end_src
***** CMake
#+begin_src emacs-lisp
(use-package cmake-mode
:mode "CMakeLists.txt"
:straight t
:hook (cmake-mode . lsp))
#+end_src
***** Lua
#+begin_src emacs-lisp
(use-package lua-mode
:mode "\\.lua\\'"
:straight t
:hook (lua-mode . lsp))
#+end_src
***** Python
#+begin_src emacs-lisp
(use-package python-mode
:mode "\\.py\\'"
:straight t
:hook (python-mode . lsp))
(use-package elpy
:after python-mode
:straight t
:custom
(elpy-rpc-python-command "python3")
:config
(elpy-enable))
(use-package lsp-pyright
:ensure t
:straight t
:hook (python-mode . (lambda ()
(require 'lsp-pyright)
(lsp)))) ; or lsp-deferred
#+end_src
***** Haskell
#+begin_src emacs-lisp
(use-package haskell-mode
:mode "\\.hs\\'"
:straight t
:hook (python-mode . lsp))
#+end_src
***** Yaml editing
#+begin_src emacs-lisp
(use-package yaml-mode
:straight t
:mode ("\\.yaml\\'"
"\\.yml\\'"))
#+end_src
***** Nix
#+begin_src emacs-lisp
(use-package nix-mode
:straight t
:hook ((nix-mode . lsp)
(nix-mode . format-all-mode)
(nix-mode . (lambda () (setq-local format-all-formatters '(("Nix" alejandra))))))
:mode "\\.nix\\'")
#+end_src
***** Dart
#+begin_src emacs-lisp
(use-package dart-mode
:straight t
:hook (dart-mode . lsp)
:mode "\\.dart\\'" )
#+end_src
***** Markdown
#+begin_src emacs-lisp
(use-package markdown-mode
:straight t
:hook (markdown-mode . visual-line-mode))
#+end_src
*** Commenter
#+begin_src emacs-lisp
(use-package evil-nerd-commenter
:straight t
:bind ("M-/" . evilnc-comment-or-uncomment-lines))
#+end_src
*** Company Mode (Better Autocompletion)
#+begin_src emacs-lisp
(use-package company
:straight t
: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)
(company-selection-wrap-around t)
(company-tooltip-align-annotations t))
(use-package company-box
:straight t
:hook (company-mode . company-box-mode))
#+end_src
*** Syntax Checking (Flycheck)
#+begin_src emacs-lisp
(use-package flycheck :straight t :config (global-flycheck-mode +1))
#+end_src
*** Formatting
#+begin_src emacs-lisp
(use-package format-all
:straight t
)
#+end_src
*** Better Compile Messages
#+begin_src emacs-lisp
(use-package fancy-compilation
:straight t
:commands (fancy-compilation-mode))
(with-eval-after-load 'compile
(fancy-compilation-mode))
#+end_src
*** Snippets
#+begin_src emacs-lisp
(use-package yasnippet
:straight t
:diminish yas-minor-mode
:hook (after-init . yas-global-mode))
(use-package yasnippet-snippets
:straight t)
(use-package yasnippet-capf
:straight t
:init (add-to-list 'completion-at-point-functions #'yasnippet-capf))
#+end_src
** Dired (quick file management in emacs)
Dired is a built-in file manager for Emacs that does some pretty amazing things! Here are some key bindings you should try out:
*** Key Bindings
**** Navigation
*Emacs* / *Evil*
- =n= / =j= - next line
- =p= / =k= - previous line
- =j= / =J= - jump to file in buffer
- =RET= - select file or directory
- =^= - go to parent directory
- =S-RET= / =g O= - Open file in "other" window
- =M-RET= - Show file in other window without focusing (previewing files)
- =g o= (=dired-view-file=) - Open file but in a "preview" mode, close with =q=
- =g= / =g r= Refresh the buffer with =revert-buffer= after changing configuration (and after filesystem changes!)
**** Marking files
- =m= - Marks a file
- =u= - Unmarks a file
- =U= - Unmarks all files in buffer
- =* t= / =t= - Inverts marked files in buffer
- =% m= - Mark files in buffer using regular expression
- =*= - Lots of other auto-marking functions
- =k= / =K= - "Kill" marked items (refresh buffer with =g= / =g r= to get them back)
- Many operations can be done on a single file if there are no active marks!
**** Copying and Renaming files
- =C= - Copy marked files (or if no files are marked, the current file)
- Copying single and multiple files
- =U= - Unmark all files in buffer
- =R= - Rename marked files, renaming multiple is a move!
- =% R= - Rename based on regular expression: =^test= , =old-\&=
*Power command*: =C-x C-q= (=dired-toggle-read-only=) - Makes all file names in the buffer editable directly to rename them! Press =Z Z= to confirm renaming or =Z Q= to abort.
**** Deleting files
- =D= - Delete marked file
- =d= - Mark file for deletion
- =x= - Execute deletion for marks
- =delete-by-moving-to-trash= - Move to trash instead of deleting permanently
**** Creating and extracting archives
- =Z= - Compress or uncompress a file or folder to (=.tar.gz=)
- =c= - Compress selection to a specific file
- =dired-compress-files-alist= - Bind compression commands to file extension
**** Other common operations
- =T= - Touch (change timestamp)
- =M= - Change file mode
- =O= - Change file owner
- =G= - Change file group
- =S= - Create a symbolic link to this file
- =L= - Load an Emacs Lisp file into Emacs
*** Configuration
#+begin_src emacs-lisp
(use-package dired
:ensure nil
:commands (dired dired-jump)
:bind (("C-x C-j" . dired-jump))
:custom ((dired-listing-switches "-agho --group-directories-first"))
:config
(evil-collection-define-key 'normal 'dired-mode-map
"h" 'dired-single-up-directory
"l" 'dired-single-buffer))
(use-package dired-single)
;; (use-package dired-open
;; :config
;; (setq dired-open-extensions '(("png" . "feh")
;; ("mkv" . "mpv"))))
;; (use-package dired-hide-dotfiles
;; :hook (dired-mode . dired-hide-dotfiles-mode)
;; :config
;; (evil-collection-define-key 'normal 'dired-mode-map
;; "H" 'dired-hide-dotfiles-mode))
#+end_src
** Folder Cleaning
#+begin_src emacs-lisp
;; NOTE: If you want to move everything out of the ~/.emacs.d folder
;; reliably, set `user-emacs-directory` before loading no-littering!
;(setq user-emacs-directory "~/.cache/emacs")
(use-package no-littering
:straight t
)
;; no-littering doesn't set this by default so we must place
;; auto save files in the same path as it uses for sessions
(setq auto-save-file-name-transforms
`((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))
#+end_src
** RSS Reader
#+begin_src emacs-lisp
(use-package elfeed
:straight t
)
(use-package elfeed-protocol
:straight t
:after elfeed
:ensure t
:config
;; curl recommend
(setq elfeed-use-curl t)
(elfeed-set-timeout 36000)
(setq elfeed-curl-extra-arguments '("--insecure")) ;necessary for https without a trust certificate
;; workaround for smth
(setq elfeed-protocol-fever-update-unread-only t)
;; setup feeds
(setq elfeed-protocol-feeds '(("fever+https://sako@rss.sako.box"
:api-url "https://rss.sako.box/api/fever.php"
:use-authinfo t)))
;; enable elfeed-protocol
(setq elfeed-protocol-enabled-protocols '(fever newsblur owncloud ttrss))
(elfeed-protocol-enable)
)
(let* ((proto-id "fever+https://sako@rss.sako.box")
(last-id (elfeed-protocol-fever-get-update-mark proto-id 'update)))
(elfeed-protocol-fever-set-update-mark proto-id 'update (- last-id 1000)))
(run-at-time 300 300
(lambda () (when (= elfeed-curl-queue-active 0)
(elfeed-update))))
(add-hook 'emacs-startup-hook (elfeed-update))
#+end_src
** Telegram
only god knows why im doing this
#+begin_src emacs-lisp
(use-package telega
:straight t
)
#+end_src
** System Packages
#+begin_src emacs-lisp
(use-package system-packages
:init
(cond
((eq system-type 'windows-nt)
(progn
(add-to-list 'system-packages-support-package-managers
'(winget .
((default-sudio . nil)
(install . "winget install")
(uninstall . "winget uninstall")
(update . "winget update --all")
(log . nil)
(search . "winget search")
(change-log . nil)
(clean-cache. nil)
(get-info . nil)
(get-info-remote . nil)
(list-files-provided-by . nil)
(owning-file . nil)
(verify-all-dependencies . nil)
(remove-orphaned . nil)
(list-installed-packages . "winget list -q")
(list-installed-packages-all . "winget list")
(list-installed-packages-all . "winget list")
(noconfirm . "--accept-source-agreements --accept-package-agreements"))))
(setq system-packages-package-manager 'winget)
(setq system-packages-noconfirm t))
((eq system-type 'darwin)
(progn
;;(message "Mac OS X")))
(setq system-packages-package-manager 'brew)
((eq system-type 'gnu/linux)
(progn
(setq system-packages-package-manager 'nix)
)))))))
#+end_src
* Org Mode Configuration Setup
** Babel Languages
#+begin_src emacs-lisp
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(python . t)))
#+end_src
** Auto-tangle Configuration
#+begin_src emacs-lisp
(defun sakomacs/org-babel-tangle-config ()
(when (string-equal (buffer-file-name)
(expand-file-name "~/nixos/config/emacs/emacs.org"))
(let ((org-confirm-babel-evaluate nil))
(org-babel-tangle)))
(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'sakomacs/org-babel-tangle-config))))
#+end_src
* Terminals
** EShell
god dammit why are they making my shells in emacs lisp
#+begin_src emacs-lisp
(defun sakomacs/configure-eshell ()
;; Save command history when commands are entered
(add-hook 'eshell-pre-command-hook 'eshell-save-some-history)
;; Truncate buffer for performance
(add-to-list 'eshell-output-filter-functions 'eshell-truncate-buffer)
;; Bind some useful keys for evil-mode
(evil-define-key '(normal insert visual) eshell-mode-map (kbd "C-r") 'counsel-esh-history)
(evil-define-key '(normal insert visual) eshell-mode-map (kbd "<home>") 'eshell-bol)
(evil-normalize-keymaps)
(setq eshell-history-size 10000
eshell-buffer-maximum-lines 10000
eshell-hist-ignoredups t
eshell-scroll-to-bottom-on-input t))
(use-package eshell-git-prompt)
(use-package eshell
:straight t
:hook (eshell-first-time-mode . sakomacs/configure-eshell)
:config
(with-eval-after-load 'esh-opt
(setq eshell-destroy-buffer-when-process-dies t)
(setq eshell-visual-commands '("htop" "zsh" "vim")))
(eshell-git-prompt-use-theme 'powerline))
#+end_src
** VTerm
#+begin_src emacs-lisp
(use-package vterm
:straight t
:commands vterm
:config
(setq vterm-max-scrollback 10000))
#+end_src
* End
** notify that it has loaded
#+begin_src emacs-lisp
(require 'notifications)
(if (eq system-type 'windows-nt)
(w32-notification-notify
:title "Emacs Daemon"
:body "The Emacs Daemon has started"))
(if (eq system-type 'gnu/linux)
(notifications-notify
:title "Emacs Daemon"
:body "The Emacs Daemon has started"))
(message "Emacs is ready")
#+end_src