Compare commits

...
32 Commits
Author SHA1 Message Date
Riyyi f0835c1a06 Neovim: WIP on navigation workflow 2025-01-18 13:54:36 +01:00
Riyyi 98cf182406 Neovim: Improve file browsing 2024-12-12 22:53:27 +01:00
Riyyi 16321c0c4f Neovim: Update packages 2024-12-10 22:19:29 +01:00
Riyyi 9d7b1f5850 Emacs: Improve buffer group separation for projects 2024-11-25 03:14:05 +01:00
Riyyi 3c5fbbf581 Emacs: Add go-mode, fix :load-after typo in restclient 2024-11-14 22:54:27 +01:00
Riyyi a38b5d1e15 Emacs+Packages: Add Swift-mode, add hunspell packages 2024-11-13 11:44:12 +01:00
Riyyi f223178f39 Config: Fix pinentry 2024-07-16 21:51:03 +02:00
Riyyi 33f22e6471 Firefox: Fix URL bar 2024-07-15 22:15:46 +02:00
Riyyi b21b6d2462 Emacs: Add worklog org-capture templates 2024-07-13 11:25:39 +02:00
Riyyi 795f2aad5b Emacs: Append instead of prepend to startup hook 2024-05-13 21:51:13 +02:00
Riyyi cf156ca80b Emacs: Make solution for removal of (elpaca nil) semantics 2024-05-12 22:56:52 +02:00
Riyyi a282e01692 Neovim: Add rainbow-mode, improve diffview colors 2024-02-25 15:44:57 +01:00
Riyyi 88f9e2e408 Neovim: Disable tabs at the top 2024-02-24 20:41:27 +01:00
Riyyi a208f458c1 Config: Add Neovim as git diff/merge tool 2024-02-24 20:36:17 +01:00
Riyyi d488a323da Neovim: Apply custom Telescope setting to its matching layout 2024-02-24 20:30:44 +01:00
Riyyi 9cc18db3ba Neovim: Add config, switch to it from Vim 2024-02-11 18:11:01 +01:00
Riyyi 88dc203b9f Emacs: Fix YASnippet expansion in insert mode 2023-12-08 23:33:28 +01:00
Riyyi 50d8e3f455 Emacs: Fix YASnippet expansion in insert mode 2023-12-08 23:30:45 +01:00
Riyyi 5e7058563f Emacs: Update Elpaca bootstrap to 0.6 2023-11-27 11:42:17 +01:00
Riyyi 5bc947db3d Scripts: Play video from clipboard 2023-11-27 11:32:03 +01:00
Riyyi 94f59f5b31 Emacs: Update function name 2023-11-02 20:44:47 +01:00
Riyyi 484fa668de Emacs: Fill last modified with timestamp when saving org files 2023-11-02 20:36:45 +01:00
Riyyi 1fb041fffc Emacs: Don't fuzzy search in consult-line 2023-08-12 11:53:51 +02:00
Riyyi 9f5ce80255 Emacs: Add hunspell multi-dictionary spell checking 2023-08-10 22:42:38 +02:00
Riyyi 1068ef9502 Emacs: Fix Elpaca call 2023-07-31 23:03:59 +02:00
Riyyi 3b01c0b759 Emacs: Update config to use version 29 features 2023-07-31 23:00:27 +02:00
Riyyi 11d351f629 Emacs: Read cache directory from ~ if no XDG is set 2023-05-01 10:06:49 +02:00
Riyyi dbf929c687 Emacs: Update Elpaca bootstrap to version 0.3 2023-03-31 21:53:49 +02:00
Riyyi 9461c904cd Emacs: Fix org-roam by adding SQLite dependency 2023-03-12 13:35:11 +01:00
Riyyi f9459cfe66 Emacs: Update to use vertico-prescient, update Elpaca bootstrap 2023-03-10 23:36:30 +01:00
Riyyi 17cbd91236 Emacs: Fix dashboard startup 2023-01-23 13:29:52 +01:00
Riyyi 89607db905 Emacs: Complete restructure of the config
Changed
- Org-mode babel config to separate .el modules
- Built-in package manager package.el to Elpaca
- Configuration macro use-package to setup.el
- Completion framework selectrum to vertico
2023-01-01 22:46:55 +01:00
55 changed files with 5326 additions and 2720 deletions
File diff suppressed because it is too large Load Diff
-471
View File
@@ -1,471 +0,0 @@
#+TITLE: Development
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#company][Company]]
- [[#git][Git]]
- [[#project][Project]]
- [[#languages][Languages]]
- [[#language-server-support][Language Server Support]]
- [[#debug-adapter-support][Debug Adapter Support]]
- [[#cc][C/C++]]
- [[#cmake][CMake]]
- [[#glsl][GLSL]]
- [[#html][HTML]]
- [[#kotlin][Kotlin]]
- [[#lua][Lua]]
- [[#php][PHP]]
- [[#python][Python]]
- [[#yaml][YAML]]
- [[#quality-of-life][Quality of Life]]
- [[#flycheck][Flycheck]]
- [[#flyspell][Flyspell]]
- [[#rainbow-delimiters][Rainbow Delimiters]]
- [[#rainbow-mode][Rainbow Mode]]
- [[#yasnippet][YASnippet]]
** Company
#+BEGIN_SRC emacs-lisp
(use-package company
:hook
((c-mode-common
emacs-lisp-mode
latex-mode
org-mode
php-mode
shell-mode
shell-script-mode)
. company-mode)
:config
(setq company-idle-delay 0.2)
(setq company-minimum-prefix-length 2)
(setq company-show-numbers t)
(setq company-tooltip-align-annotations 't))
#+END_SRC
Sort Company completions.
#+BEGIN_SRC emacs-lisp
(use-package company-prescient
:after (company prescient)
:config (company-prescient-mode))
#+END_SRC
Auto-completion for C/C++ headers.
#+BEGIN_SRC emacs-lisp
(use-package company-c-headers
:after company
:config (add-to-list 'company-backends 'company-c-headers))
#+END_SRC
GLSL integration with company requires the package: ~glslang~.
#+BEGIN_SRC emacs-lisp
(when (executable-find "glslangValidator")
(use-package company-glsl
:after company
:config (add-to-list 'company-backends 'company-glsl)))
#+END_SRC
** Git
#+BEGIN_SRC emacs-lisp
(use-package diff-hl
:demand
:hook (prog-mode . turn-on-diff-hl-mode)
:hook (prog-mode . dot/diff-hl-enable-flydiff-and-fringe)
:config
(defun dot/diff-hl-enable-flydiff-and-fringe ()
"Enable on the fly diff checking if file is under version control."
(let ((buffer buffer-file-name))
(when (and buffer (vc-registered buffer))
(diff-hl-flydiff-mode)
(dot/toggle-fringe 1)))))
(use-package transient
:defer t
:config
(setq transient-history-file (concat dot-cache-dir "/transient/history.el"))
(setq transient-values-file (concat dot-cache-dir "/transient/values.el")))
(use-package magit
:after (diff-hl transient)
:hook (git-commit-setup . git-commit-turn-on-auto-fill)
:hook (git-commit-setup . git-commit-turn-on-flyspell)
:hook (magit-pre-refresh . diff-hl-magit-pre-refresh)
:hook (magit-post-refresh . diff-hl-magit-post-refresh)
:config
(setq git-commit-fill-column 72)
(setq git-commit-summary-max-length 72)
(setq magit-completing-read-function #'selectrum-completing-read)
(setq magit-diff-paint-whitespace-lines 'both)
(setq magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
(setq magit-repository-directories '(("~/dotfiles" . 0)
("~/code" . 3)))
(put 'magit-log-select-pick :advertised-binding [?\M-c])
(put 'magit-log-select-quit :advertised-binding [?\M-k])
(defun dot/magit-select-repo ()
"Select project repo."
(interactive)
(let ((current-prefix-arg '(t)))
(call-interactively #'magit-status))))
#+END_SRC
** Project
Project manager.
[[https://michael.stapelberg.ch/posts/2021-04-02-emacs-project-override/][Adding to project.el project directory detection]].
#+BEGIN_SRC emacs-lisp
(use-package project
:defer t
:init (setq project-list-file (concat dot-cache-dir "/projects"))
:config
(defun dot/project-find (dir)
(let ((root (locate-dominating-file dir ".project")))
(and root (cons 'vc root))))
(add-hook 'project-find-functions #'dot/project-find)
(defun dot/find-project-root ()
"Return root of the project, determined by `.git/' and `.project',
`default-directory' otherwise."
(let ((project (project-current)))
(if project
(project-root project)
default-directory)))
(defun dot/find-file-in-project-root ()
"Find file in project root."
(interactive)
(let ((default-directory (dot/find-project-root)))
(call-interactively 'find-file)))
(defun dot/project-remember-projects-under (dir maxdepth)
"Index all projects below directory DIR recursively, until MAXDEPTH."
(let ((files (mapcar 'file-name-directory
(dot/directory-files-recursively-depth
dir "\\.git$\\|\\.project$" t maxdepth))))
(dolist (path files)
(project-remember-projects-under path))))
(unless (file-exists-p project-list-file)
(project-remember-projects-under "~/dotfiles")
(dot/project-remember-projects-under "~/code" 4))
(defun dot/project-project-name ()
"Return project name."
(let ((project (project-current)))
(if project
(file-name-nondirectory (directory-file-name (project-root project)))
"-")))
(defun dot/project-save-project-buffers ()
"Save all project buffers."
(interactive)
(let ((buffers (cl-remove-if (lambda (buffer) (not (buffer-file-name buffer)))
(project-buffers (project-current)))))
(save-some-buffers t (lambda () (member (current-buffer) buffers))))))
#+END_SRC
** Languages
*** Language Server Support
Language Server Protocol.
#+BEGIN_SRC emacs-lisp
(use-package lsp-mode
:commands lsp
:after which-key
:hook
((c-mode ; clangd
c++-mode ; clangd
lua-mode ; lua-language-server
php-mode ; nodejs-intelephense
latex-mode ; texlab
kotlin-mode ; kotlin-language-server
web-mode)
. lsp-deferred)
:config
(setq lsp-auto-guess-root t)
(setq lsp-clients-clangd-args '("-j=2"
"--background-index"
"--clang-tidy"
"--compile-commands-dir=build"
"--log=error"
"--pch-storage=memory"
"--enable-config"))
(setq lsp-clients-lua-language-server-bin "/usr/bin/lua-language-server")
(setq lsp-clients-lua-language-server-install-dir "/usr/lib/lua-language-server/")
(setq lsp-clients-lua-language-server-main-location "/usr/lib/lua-language-server/main.lua")
(setq lsp-enable-xref t)
(setq lsp-headerline-breadcrumb-enable nil)
(setq lsp-intelephense-storage-path (concat dot-cache-dir "/lsp-cache"))
(setq lsp-keep-workspace-alive nil)
(setq lsp-prefer-flymake nil)
(setq lsp-session-file (concat dot-cache-dir "/lsp-session-v1"))
;; Mark clangd args variable as safe to modify via .dir-locals.el
(put 'lsp-clients-clangd-args 'safe-local-variable #'listp)
;; Enable which-key descriptions
(dolist (leader-key (list dot/leader-key dot/leader-alt-key))
(let ((lsp-keymap-prefix (concat leader-key " l")))
(lsp-enable-which-key-integration)))
(defun dot/lsp-format-buffer-or-region ()
"Format the selection (or buffer) with LSP."
(interactive)
(unless (bound-and-true-p lsp-mode)
(message "Not in an LSP buffer"))
(call-interactively
(if (use-region-p)
#'lsp-format-region
#'lsp-format-buffer)))
;; This is cached to prevent unneeded I/O
(setq lsp-in-cpp-project-cache nil)
(defun dot/lsp-format-cpp-buffer ()
"Format buffer in C++ projects."
(unless lsp-in-cpp-project-cache
(set (make-local-variable 'lsp-in-cpp-project-cache)
(list
(if (and (eq major-mode 'c++-mode)
(bound-and-true-p lsp-mode)
(or
(locate-dominating-file "." ".clang-format")
(locate-dominating-file "." "_clang-format")))
t
nil))))
(when (car lsp-in-cpp-project-cache)
(lsp-format-buffer)))
(add-hook 'before-save-hook #'dot/lsp-format-cpp-buffer))
;; TODO: add lsp-signature keybinds
(use-package lsp-ui
:commands lsp-ui-mode
:after (flycheck lsp-mode)
:config
(setq lsp-ui-doc-border (face-foreground 'default))
(setq lsp-ui-doc-delay 0.5)
(setq lsp-ui-doc-enable t)
(setq lsp-ui-doc-header t)
(setq lsp-ui-doc-include-signature t)
(setq lsp-ui-doc-position 'top)
(setq lsp-ui-doc-use-childframe t)
(setq lsp-ui-flycheck-list-position 'right)
(setq lsp-ui-imenu-enable nil)
(setq lsp-ui-peek-enable nil)
(setq lsp-ui-sideline-enable nil))
#+END_SRC
*** Debug Adapter Support
Debug Adapter Protocol.
#+BEGIN_SRC emacs-lisp
(use-package treemacs
:after all-the-icons
:hook (treemacs-mode . dot/hook-disable-line-numbers)
:config (setq treemacs-persist-file (concat dot-cache-dir "/treemacs/persist")))
(use-package dap-mode
:after (treemacs lsp-mode)
:hook (lsp-after-initialize . dot/dap-install-debug-adapters)
:config
(setq dap-auto-configure-features '(sessions locals expressions controls tooltip))
(setq dap-breakpoints-file (concat dot-cache-dir "/dap/breakpoints"))
(setq dap-utils-extension-path (concat dot-cache-dir "/dap"))
;; Create dap extension directory
(unless (file-directory-p dap-utils-extension-path)
(make-directory dap-utils-extension-path t))
(defun dot/dap-install-debug-adapters ()
"Install and Load debug adapters."
(interactive)
(unless (bound-and-true-p lsp-mode)
(user-error "Not in an LSP buffer"))
(when (string-equal major-mode "c++-mode")
(require 'dap-cpptools)
(dap-cpptools-setup))))
#+END_SRC
*** C/C++
#+BEGIN_SRC emacs-lisp
(use-package c-mode
:ensure nil
:defer t
;; C++ // line comment style in c-mode
:hook (c-mode . (lambda ()
(c-toggle-comment-style -1))))
#+END_SRC
*** CMake
#+BEGIN_SRC emacs-lisp
(use-package cmake-mode
:config (setq cmake-tab-width 4)
:defer t)
#+END_SRC
*** GLSL
#+BEGIN_SRC emacs-lisp
(use-package glsl-mode
:defer t)
#+END_SRC
*** HTML
#+BEGIN_SRC emacs-lisp
(use-package web-mode
:defer t)
#+END_SRC
*** Kotlin
#+BEGIN_SRC emacs-lisp
(use-package kotlin-mode
:defer t)
#+END_SRC
*** Lua
#+BEGIN_SRC emacs-lisp
(use-package lua-mode
:defer t
:config (setq lua-indent-level 4))
#+END_SRC
*** PHP
#+BEGIN_SRC emacs-lisp
(use-package php-mode
:defer t
:hook
(php-mode . (lambda ()
(setq indent-tabs-mode t))))
(use-package restclient
:defer t)
#+END_SRC
*** Python
#+BEGIN_SRC emacs-lisp
(use-package python-mode
:ensure nil
:defer t
:hook (python-mode . (lambda ()
(setq indent-tabs-mode t)
(setq python-indent-offset 4)
(setq tab-width 4))))
#+END_SRC
*** YAML
#+BEGIN_SRC emacs-lisp
(use-package yaml-mode
:defer t)
#+END_SRC
** Quality of Life
**** Flycheck
On the fly syntax checking.
#+BEGIN_SRC emacs-lisp
(use-package flycheck
:hook
((c-mode-common
emacs-lisp-mode
latex-mode
org-mode
php-mode
sh-mode
shell-mode
shell-script-mode)
. flycheck-mode)
:config
(setq flycheck-clang-language-standard "c++20")
(setq flycheck-gcc-language-standard "c++20"))
;; For .el files which are intended to be packages
(use-package flycheck-package
:after flycheck
:config
(add-to-list 'flycheck-checkers 'flycheck-emacs-lisp-package)
(flycheck-package-setup))
(use-package flycheck-clang-tidy
:after flycheck
:hook (flycheck-mode . flycheck-clang-tidy-setup)
:config (setq flycheck-clang-tidy-extra-options "--format-style=file"))
#+END_SRC
**** Flyspell
Give Flyspell a selection menu.
#+BEGIN_SRC emacs-lisp
(use-package flyspell-correct
:after flyspell
:demand
:hook (org-mode . flyspell-mode)
:config
(setq flyspell-issue-message-flag nil)
(setq flyspell-issue-welcome-flag nil)
(defun dot/flyspell-toggle ()
"Toggle Flyspell, prompt for language."
(interactive)
(if (symbol-value flyspell-mode)
(flyspell-mode -1)
(call-interactively 'ispell-change-dictionary)
(if (derived-mode-p 'prog-mode)
(flyspell-prog-mode)
(flyspell-mode))
(flyspell-buffer))))
#+END_SRC
**** Rainbow Delimiters
#+BEGIN_SRC emacs-lisp
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))
#+END_SRC
**** Rainbow Mode
#+BEGIN_SRC emacs-lisp
(use-package rainbow-mode
:hook (css-mode . rainbow-mode))
#+END_SRC
**** YASnippet
#+BEGIN_SRC emacs-lisp
(use-package yasnippet
:defer t
:init
(setq yas-snippet-dirs (list (concat dot-emacs-dir "/snippets")))
(setq yas-prompt-functions '(yas-completing-prompt))
:config
(yas-global-mode))
(use-package yasnippet-snippets
:after yasnippet)
#+END_SRC
https://stackoverflow.com/questions/22735895/configuring-a-yasnippet-for-two-scenarios-1-region-is-active-2-region-is
-108
View File
@@ -1,108 +0,0 @@
#+TITLE: Evil
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#evil][Evil]]
** Evil
Evil mode and related packages.
#+BEGIN_SRC emacs-lisp
(use-package undo-tree
:config
(setq undo-tree-auto-save-history t)
(setq undo-tree-history-directory-alist `(("." . ,(concat dot-cache-dir "/undo-tree"))))
(global-undo-tree-mode))
(use-package goto-chg)
(use-package evil
:after (undo-tree goto-chg)
:init
(setq evil-ex-complete-emacs-commands nil)
(setq evil-kill-on-visual-paste nil)
(setq evil-operator-state-cursor 'box) ; Do not set half cursor
(setq evil-search-module 'evil-search)
(setq evil-split-window-below t)
(setq evil-undo-system 'undo-tree)
(setq evil-vsplit-window-right t)
(setq evil-want-C-u-scroll t)
(setq evil-want-Y-yank-to-eol t)
(setq evil-want-keybinding nil) ; Needed by evil-collection
:config
(defun dot/evil-normal-sort-paragraph ()
"Sort paragraph cursor is under.
Vim equivalence: vip:sort<CR>"
(interactive)
(let ((p (point)))
(evil-visual-char)
(call-interactively 'evil-inner-paragraph)
(evil-ex-sort (region-beginning) (region-end))
(goto-char p)))
(defun dot/evil-insert-shift-left ()
"Shift line left, retains cursor position.
Vim equivalence: <C-D>"
(interactive)
(evil-shift-left-line 1))
(defun dot/evil-insert-shift-right ()
"Shift line right, retains cursor position.
Vim equivalence: <Tab>"
(interactive)
(insert "\t"))
(defun dot/evil-visual-shift-left ()
"Shift visual selection left, retains the selection.
Vim equivalence: <gv"
(interactive)
(call-interactively #'evil-shift-left)
(setq deactivate-mark nil))
(defun dot/evil-visual-shift-right ()
"Shift visual selection left, retains the selection.
Vim equivalence: >gv"
(interactive)
(call-interactively #'evil-shift-right)
(setq deactivate-mark nil))
(evil-mode))
#+END_SRC
Evil command aliases.
#+BEGIN_SRC emacs-lisp
(use-package evil-ex
:ensure nil ; evil-ex.el is part of evil
:after evil
:config
(evil-ex-define-cmd "W" "w")
(evil-ex-define-cmd "Q" "q")
(evil-ex-define-cmd "WQ" "wq")
(evil-ex-define-cmd "Wq" "wq"))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package evil-collection
:after evil
:init
(setq evil-collection-company-use-tng nil)
(setq evil-collection-key-blacklist (list dot/leader-key dot/localleader-key
dot/leader-alt-key dot/localleader-alt-key
"M-h" "M-j" "M-k" "M-l"))
(setq evil-collection-setup-minibuffer t)
:config
(evil-collection-init))
(use-package evil-nerd-commenter
:defer t
:after evil)
#+END_SRC
-157
View File
@@ -1,157 +0,0 @@
#+TITLE: Mail Configuration
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#mail-functions][Mail Functions]]
- [[#mail-in-emacs-with-mu4e][Mail in Emacs with mu4e]]
- [[#sources][Sources]]
** Mail Functions
#+BEGIN_SRC emacs-lisp
(with-eval-after-load 'auth-source
(defun dot/mail-auth-get-field (host prop)
"Find PROP in `auth-sources' for HOST entry."
(when-let ((source (auth-source-search :max 1 :host host)))
(if (eq prop :secret)
(funcall (plist-get (car source) prop))
(plist-get (flatten-list source) prop)))))
#+END_SRC
** Mail in Emacs with mu4e
Useful mu4e manual pages:
- [[https://www.djcbsoftware.nl/code/mu/mu4e/MSGV-Keybindings.html#MSGV-Keybindings][Key bindings]]
#+BEGIN_SRC emacs-lisp
(use-package mu4e
:ensure nil
:load-path "/usr/share/emacs/site-lisp/mu4e"
:defer 20
:commands mu4e
:config
(setq auth-sources `(,(concat dot-etc-dir "/authinfo.gpg")))
(setq user-full-name (dot/mail-auth-get-field "fullname" :user))
(setq user-mail-address (dot/mail-auth-get-field "info" :user))
(setq mail-user-agent 'mu4e-user-agent)
;; Headers
(setq mu4e-headers-date-format "%d-%m-%Y")
(setq mu4e-headers-time-format "%I:%M %p")
(setq mu4e-headers-long-date-format "%d-%m-%Y %I:%M:%S %p")
;; Syncing
(setq mu4e-get-mail-command (concat "mbsync -a -c " (getenv "XDG_CONFIG_HOME") "/isync/mbsyncrc"))
(setq mu4e-update-interval (* 15 60)) ; 15 minutes
(setq mu4e-maildir "~/mail")
(setq mu4e-attachment-dir "~/downloads")
;; Avoid mail syncing issues when using mbsync
(setq mu4e-change-filenames-when-moving t)
;; Misc
(setq mu4e-completing-read-function 'completing-read)
(setq mu4e-confirm-quit nil)
(setq mu4e-display-update-status-in-modeline t)
(setq mu4e-hide-index-messages t)
(setq mu4e-sent-messages-behavior 'sent)
(setq mu4e-view-show-addresses t)
(setq mu4e-view-show-images nil)
;; Compose
(setq mu4e-compose-context-policy 'ask)
(setq mu4e-compose-dont-reply-to-self t)
(setq mu4e-compose-signature (concat (dot/mail-auth-get-field "fullname" :user) "\nriyyi.com\n"))
(setq mu4e-compose-signature-auto-include t)
;; Contexts
(setq mu4e-context-policy 'pick-first)
(setq mu4e-contexts
`(,(make-mu4e-context
:name "info"
:match-func (lambda (msg)
(when msg
(string= (mu4e-message-field msg :maildir) "/info")))
:vars `((user-mail-address . ,(dot/mail-auth-get-field "info" :user))
(mu4e-drafts-folder . "/info/Drafts")
(mu4e-refile-folder . "/info/Archive")
(mu4e-sent-folder . "/info/Sent")
(mu4e-trash-folder . "/info/Trash")))
,(make-mu4e-context
:name "private"
:match-func (lambda (msg)
(when msg
(string= (mu4e-message-field msg :maildir) "/private")))
:vars `((user-mail-address . ,(dot/mail-auth-get-field "private" :user))
(mu4e-drafts-folder . "/private/Drafts")
(mu4e-refile-folder . "/private/Archive")
(mu4e-sent-folder . "/private/Sent")
(mu4e-trash-folder . "/private/Trash")))
))
;; Do not mark messages as IMAP-deleted, just move them to the Trash directory!
;; https://github.com/djcb/mu/issues/1136#issuecomment-486177435
(setf (alist-get 'trash mu4e-marks)
(list :char '("d" . "")
:prompt "dtrash"
:dyn-target (lambda (target msg)
(mu4e-get-trash-folder msg))
:action (lambda (docid msg target)
(mu4e~proc-move docid (mu4e~mark-check-target target) "-N"))))
;; Start mu4e in the background for mail syncing
(mu4e t))
#+END_SRC
Use [[https://github.com/iqbalansari/mu4e-alert][mu4e-alert]] to show new e-mail notifications.
#+BEGIN_SRC emacs-lisp
(use-package mu4e-alert
:after mu4e
:config
(setq mu4e-alert-interesting-mail-query "(maildir:/info/Inbox OR maildir:/private/Inbox) AND flag:unread AND NOT flag:trashed")
(setq mu4e-alert-notify-repeated-mails nil)
(mu4e-alert-set-default-style 'libnotify)
(mu4e-alert-enable-notifications))
#+END_SRC
Sending mail.
#+BEGIN_SRC emacs-lisp
(use-package smtpmail
:ensure nil ; built-in
:after mu4e
:init (setq smtpmail-default-smtp-server "mail.riyyi.com")
:config
(setq smtpmail-smtp-server "mail.riyyi.com")
(setq smtpmail-local-domain "riyyi.com")
(setq smtpmail-smtp-service 587)
(setq smtpmail-stream-type 'starttls)
(setq smtpmail-queue-mail nil))
(use-package sendmail
:ensure nil ; built-in
:after mu4e
:config (setq send-mail-function 'smtpmail-send-it))
(use-package message
:ensure nil ; built-in
:after mu4e
:config
(setq message-kill-buffer-on-exit t)
(setq message-send-mail-function 'smtpmail-send-it))
#+END_SRC
** Sources
- https://rakhim.org/fastmail-setup-with-emacs-mu4e-and-mbsync-on-macos/
- https://wiki.archlinux.org/title/Isync
- https://man.archlinux.org/man/community/isync/mbsync.1.en
- https://gitlab.com/protesilaos/dotfiles/-/blob/master/mbsync/.mbsyncrc
- https://gitlab.com/protesilaos/dotfiles/-/blob/master/emacs/.emacs.d/prot-lisp/prot-mail.el
- https://gitlab.com/protesilaos/dotfiles/-/blob/master/emacs/.emacs.d/prot-lisp/prot-mu4e-deprecated-conf.el
- https://github.com/daviwil/dotfiles/blob/master/Mail.org
-331
View File
@@ -1,331 +0,0 @@
#+TITLE: Org Mode
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#latex-configuration][LaTeX Configuration]]
- [[#org-configuration][Org Configuration]]
- [[#org-functions][Org Functions]]
- [[#org-bullets][Org Bullets]]
- [[#org-export-packages][Org Export Packages]]
- [[#org-roam][Org Roam]]
- [[#org-table-of-contents][Org "Table of Contents"]]
** LaTeX Configuration
#+BEGIN_SRC emacs-lisp
(use-package tex-mode
:ensure nil ; built-in
:defer t
:hook (latex-mode . (lambda ()
(setq indent-tabs-mode t)
(setq tab-width 4)
(setq tex-indent-basic 4)))
:config
(with-eval-after-load 'project
(defun compile-latex ()
"Compile LaTeX project."
(interactive)
(let ((default-directory (dot/find-project-root)))
(dot/project-save-project-buffers)
(shell-command "make")))))
#+END_SRC
** Org Configuration
Base Org.
#+BEGIN_SRC emacs-lisp
(use-package org
:config
(setq org-adapt-indentation nil)
(setq org-default-notes-file (expand-file-name "notes.org" org-directory))
(setq org-directory (concat (getenv "HOME") "/documents/org"))
(setq org-ellipsis "")
(setq org-image-actual-width nil)
;; Enable structured template completion
(add-to-list 'org-modules 'org-tempo t)
(add-to-list 'org-structure-template-alist
'("el" . "src emacs-lisp")))
#+END_SRC
Org agenda.
#+BEGIN_SRC emacs-lisp
(use-package org-agenda
:ensure nil ; built-in
:defer t
:config
(setq org-agenda-files `(,org-directory ,user-emacs-directory))
(setq org-agenda-span 14)
(setq org-agenda-window-setup 'current-window)
(evil-set-initial-state 'org-agenda-mode 'motion))
#+END_SRC
Org capture.
#+BEGIN_SRC emacs-lisp
(use-package org-capture
:ensure nil ; built-in
;; Org-capture in new tab, rather than split window
:hook (org-capture-mode . delete-other-windows))
#+END_SRC
Org keys.
#+BEGIN_SRC emacs-lisp
(use-package org-keys
:ensure nil ; built-in
:config
(setq org-return-follows-link t))
#+END_SRC
Org links.
#+BEGIN_SRC emacs-lisp
(use-package ol
:ensure nil ; built-in
:config
;; Do not open links to .org files in a split window
(add-to-list 'org-link-frame-setup '(file . find-file)))
#+END_SRC
Org source code blocks.
#+BEGIN_SRC emacs-lisp
(use-package org-src
:ensure nil ; built-in
:config
(setq org-edit-src-content-indentation 0)
(setq org-src-fontify-natively t)
(setq org-src-preserve-indentation t)
(setq org-src-tab-acts-natively t)
(setq org-src-window-setup 'current-window))
#+END_SRC
Org exporter.
#+BEGIN_SRC emacs-lisp
(use-package ox
:ensure nil ; built-in
:defer t
:config
(setq org-export-coding-system 'utf-8-unix))
#+END_SRC
Org latex exporter.
#+BEGIN_SRC emacs-lisp
(use-package ox-latex
:ensure nil ; built-in
:defer t
:config
;; Define how minted (highlighted src code) is added to src code blocks
(setq org-latex-listings 'minted)
(setq org-latex-minted-options '(("frame" "lines") ("linenos=true")))
;; Set 'Table of Contents' layout
(setq org-latex-toc-command "\\newpage \\tableofcontents \\newpage")
;; Add minted package to every LaTeX header
(add-to-list 'org-latex-packages-alist '("" "minted"))
;; Add -shell-escape so pdflatex exports minted correctly
(setcar org-latex-pdf-process (replace-regexp-in-string
"-%latex -interaction"
"-%latex -shell-escape -interaction"
(car org-latex-pdf-process))))
#+END_SRC
** Org Functions
#+BEGIN_SRC emacs-lisp
(with-eval-after-load 'evil-commands
(defun dot/org-ret-at-point ()
"Org return key at point.
If point is on:
checkbox -- toggle it
link -- follow it
table -- go to next row
otherwise -- run the default (evil-ret) expression"
(interactive)
(let ((type (org-element-type (org-element-context))))
(pcase type
('link (if org-return-follows-link (org-open-at-point) (evil-ret)))
((guard (org-at-item-checkbox-p)) (org-toggle-checkbox))
('table-cell (org-table-next-row))
(_ (evil-ret))
))))
#+END_SRC
** Org Bullets
#+BEGIN_SRC emacs-lisp
(use-package org-bullets
:hook (org-mode . org-bullets-mode))
#+END_SRC
** Org Export Packages
HTML exporter.
#+BEGIN_SRC emacs-lisp
(use-package htmlize
:defer t
:config (setq org-export-html-postamble nil))
;;org-export-html-postamble-format ; TODO
#+END_SRC
GitHub flavored Markdown exporter.
#+BEGIN_SRC emacs-lisp
(use-package ox-gfm
:defer t)
#+END_SRC
** Org Roam
Setup =org-roam=.
#+BEGIN_SRC emacs-lisp
(use-package org-roam
:defer 1
:init
(setq org-roam-v2-ack t)
:config
(setq org-roam-db-location (expand-file-name "org-roam.db" dot-cache-dir))
(setq org-roam-directory org-directory)
;; Exclude Syncthing backup directory
(setq org-roam-file-exclude-regexp "\\.stversions")
(setq org-roam-verbose nil)
(setq org-roam-capture-templates
'(("d" "default" plain
"%?"
:target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n#+FILETAGS: %^{File tags}\n")
:unnarrowed t)))
(defun dot/org-roam-node-insert-immediate (arg &rest args)
(interactive "P")
(let ((args (push arg args))
(org-roam-capture-templates (list (append (car org-roam-capture-templates)
'(:immediate-finish t)))))
(apply #'org-roam-node-insert args)))
(cl-defmethod org-roam-node-slug ((node org-roam-node))
"Return the slug of NODE, strip out common words."
(let* ((title (org-roam-node-title node))
(words (split-string title " "))
(common-words '("a" "an" "and" "as" "at" "by" "is" "it" "of" "the" "to"))
(title (string-join (seq-remove (lambda (element) (member element common-words)) words) "_"))
(pairs '(("c\\+\\+" . "cpp") ;; convert c++ -> cpp
("c#" . "cs") ;; convert c# -> cs
("[^[:alnum:][:digit:]]" . "_") ;; convert anything not alphanumeric
("__*" . "_") ;; remove sequential underscores
("^_" . "") ;; remove starting underscore
("_$" . "")))) ;; remove ending underscore
(cl-flet ((cl-replace (title pair)
(replace-regexp-in-string (car pair) (cdr pair) title)))
(downcase (-reduce-from #'cl-replace title pairs)))))
;; Right-align org-roam-node-tags in the completion menu without a length limit
;; Source: https://github.com/org-roam/org-roam/issues/1775#issue-971157225
(setq org-roam-node-display-template "${title} ${tags:0}")
(setq org-roam-node-annotation-function #'dot/org-roam-annotate-tag)
(defun dot/org-roam-annotate-tag (node)
(let ((tags (mapconcat 'identity (org-roam-node-tags node) " #")))
(unless (string-empty-p tags)
(concat
(propertize " " 'display `(space :align-to (- right ,(+ 2 (length tags)))))
(propertize (concat "#" tags) 'face 'bold)))))
(org-roam-setup))
#+END_SRC
Enable [[https://www.orgroam.com/manual.html#Roam-Protocol][Roam Protocol]], needed to process =org-protocol://= links
#+BEGIN_SRC emacs-lisp
(use-package org-roam-protocol
:ensure nil ; org-roam-protocol.el is part of org-roam
:after org-roam
:config
;; Templates used when creating a new file from a bookmark
(setq org-roam-capture-ref-templates
'(("r" "ref" plain
"%?"
:target (file+head "${slug}.org" "#+TITLE: ${title}\n \n${body}")
:unnarrowed t))))
#+END_SRC
The roam-ref protocol bookmarks to add:
#+BEGIN_SRC javascript
javascript:location.href =
'org-protocol://roam-ref?template=r'
+ '&ref=' + encodeURIComponent(location.href)
+ '&title=' + encodeURIComponent(document.title)
+ '&body=' + encodeURIComponent(window.getSelection())
#+END_SRC
Setup =org-roam-ui=, runs at http://127.0.0.1:35901.
#+BEGIN_SRC emacs-lisp
(use-package org-roam-ui
:after org-roam
:config
(setq org-roam-ui-follow t)
(setq org-roam-ui-open-on-start t)
(setq org-roam-ui-sync-theme nil) ;; FIXME: Make this work (org-roam-ui-get-theme)
(setq org-roam-ui-update-on-save t))
#+END_SRC
Easily searchable .org files via Deft.
#+BEGIN_SRC emacs-lisp
(use-package deft
:after org
:hook (deft-mode . dot/hook-disable-line-numbers)
:config
(setq deft-auto-save-interval 0)
(setq deft-default-extension "org")
(setq deft-directory org-directory)
(setq deft-file-naming-rules '((noslash . "-")
(nospace . "-")
(case-fn . downcase)))
(setq deft-new-file-format "%Y%m%d%H%M%S-deft")
(setq deft-recursive t)
;; Exclude Syncthing backup directory
(setq deft-recursive-ignore-dir-regexp (concat "\\.stversions\\|" deft-recursive-ignore-dir-regexp))
;; Remove file variable -*- .. -*- and Org Mode :PROPERTIES: lines
(setq deft-strip-summary-regexp (concat "\\(^.*-\\*-.+-\\*-$\\|^:[[:alpha:]_]+:.*$\\)\\|" deft-strip-summary-regexp))
(setq deft-use-filename-as-title nil)
(setq deft-use-filter-string-for-filename t)
(add-to-list 'deft-extensions "tex")
;; Start filtering immediately
(evil-set-initial-state 'deft-mode 'insert)
(defun deft-parse-title (file contents)
"Parse the given FILE and CONTENTS and determine the title."
(org-element-property
:value
(car
(org-element-map
(with-temp-buffer
(insert contents)
(org-element-parse-buffer 'greater-element))
'keyword
(lambda (e) (when (string-match "TITLE" (org-element-property :key e)) e)))))))
#+END_SRC
** Org "Table of Contents"
Generate table of contents without exporting.
#+BEGIN_SRC emacs-lisp
(use-package toc-org
:hook (org-mode . toc-org-mode))
#+END_SRC
-52
View File
@@ -1,52 +0,0 @@
#+TITLE: Selection
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#selection][Selection]]
** Selection
#+BEGIN_SRC emacs-lisp
(use-package selectrum
:hook (emacs-startup . selectrum-mode)
:config
(defun dot/selectrum-backspace ()
"In Selectrum file completion, backward kill sexp, delete char otherwise."
(interactive)
(if (and selectrum-is-active
minibuffer-completing-file-name)
(evil-with-state 'insert
(move-end-of-line 1) (backward-kill-sexp 1))
(evil-delete-backward-char-and-join 1))))
(use-package prescient
:after selectrum
:config
(setq prescient-filter-method '(literal regexp fuzzy))
(setq prescient-save-file (concat dot-cache-dir "/prescient-save.el"))
(prescient-persist-mode))
(use-package selectrum-prescient
:after (selectrum prescient)
:config
(selectrum-prescient-mode))
(use-package marginalia
:after selectrum
:config
(setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light))
(marginalia-mode))
(use-package consult
:after selectrum
:config (setq consult-narrow-key (kbd "?")))
(use-package consult-flycheck
:after (consult flycheck))
(use-package consult-project-extra
:after (consult project)
:config (setq project-switch-commands 'consult-project-extra-find))
#+END_SRC
-253
View File
@@ -1,253 +0,0 @@
#+TITLE: UI
#+OPTIONS: toc:nil
#+PROPERTY: header-args:emacs-lisp :shebang ";;; -*- lexical-binding: t; -*-\n"
** Table of Contents :toc_4:
- [[#all-the-icons][All the icons]]
- [[#centaur-tabs][Centaur Tabs]]
- [[#dashboard][Dashboard]]
- [[#helpful][Helpful]]
- [[#neotree][NeoTree]]
- [[#telephone-line][Telephone Line]]
- [[#theme][Theme]]
- [[#which-key][Which-key]]
** All the icons
#+BEGIN_SRC emacs-lisp
(use-package all-the-icons
:defer t
:config
;; Install all-the-icons if font files are not found
(unless (find-font (font-spec :name "all-the-icons"))
(all-the-icons-install-fonts t)))
(use-package all-the-icons-dired
:after all-the-icons
:hook (dired-mode . all-the-icons-dired-mode)
:config (setq all-the-icons-dired-monochrome nil))
#+END_SRC
** Centaur Tabs
Places buffers as tabs in a bar at the top of the frame.
#+BEGIN_SRC emacs-lisp
(use-package centaur-tabs
:after all-the-icons
:demand
:hook
((eshell-mode
help-mode
helpful-mode
mu4e-view-mode
neotree-mode
shell-mode)
. centaur-tabs-local-mode)
:config
(setq centaur-tabs-enable-ido-completion nil)
(setq centaur-tabs-height (if dot/hidpi 38 18))
(setq centaur-tabs-modified-marker "")
(setq centaur-tabs-set-icons t)
(setq centaur-tabs-set-modified-marker t)
(setq centaur-tabs-style "slant")
(setq centaur-tabs-project-buffer-group-calc nil)
(defun centaur-tabs-buffer-groups ()
"Organize tabs into groups by buffer."
(unless centaur-tabs-project-buffer-group-calc
(set (make-local-variable 'centaur-tabs-project-buffer-group-calc)
(list
(cond
((string-equal "*" (substring (buffer-name) 0 1)) "Emacs")
((or (memq major-mode '(magit-process-mode
magit-status-mode
magit-diff-mode
magit-log-mode
magit-file-mode
magit-blob-mode
magit-blame-mode))
(string= (buffer-name) "COMMIT_EDITMSG")) "Magit")
((project-current) (dot/project-project-name))
((memq major-mode '(org-mode
emacs-lisp-mode)) "Org Mode")
((derived-mode-p 'dired-mode) "Dired")
((derived-mode-p 'prog-mode
'text-mode) "Editing")
(t "Other")))))
(symbol-value 'centaur-tabs-project-buffer-group-calc))
(defun centaur-tabs-hide-tab (buffer)
"Hide from the tab bar by BUFFER name."
(let ((name (format "%s" buffer)))
(or
;; Current window is dedicated window
(window-dedicated-p (selected-window))
;; Buffer name matches below blacklist
(string-match-p "^ ?\\*.*\\*" name))))
(defun dot/centaur-tabs-is-buffer-unimportant (buffer)
"Return t if BUFFER is unimportant and can be killed without caution."
(let ((name (format "%s" buffer)))
(cond
((centaur-tabs-hide-tab name) t)
((string-match-p "^magit\\(-[a-z]+\\)*: .*" name) t)
(t nil))))
(defun dot/centaur-tabs-buffer-cleanup ()
"Clean up all the hidden buffers."
(interactive)
(dolist (buffer (buffer-list))
(when (dot/centaur-tabs-is-buffer-unimportant buffer)
(kill-buffer buffer)))
(princ "Cleaned buffers"))
(defun dot/centaur-tabs-kill-buffer-or-window ()
"Delete window of the current buffer, also kill if the buffer is hidden."
(interactive)
(if (dot/centaur-tabs-is-buffer-unimportant (buffer-name))
(kill-buffer-and-window)
(delete-window)))
(centaur-tabs-headline-match)
(centaur-tabs-mode))
#+END_SRC
** Dashboard
#+BEGIN_SRC emacs-lisp
(use-package page-break-lines)
(use-package dashboard
:demand
:hook (dashboard-mode . dot/hook-disable-line-numbers)
:config
(setq initial-buffer-choice (lambda () (get-buffer "*dashboard*")))
(setq dashboard-banner-logo-title "GNU Emacs master race!")
(setq dashboard-center-content t)
(setq dashboard-page-separator "\n\f\n")
(setq dashboard-projects-backend 'project-el)
(setq dashboard-set-file-icons t)
(setq dashboard-set-footer nil)
(setq dashboard-set-heading-icons t)
(setq dashboard-show-shortcuts t)
(setq dashboard-startup-banner 'logo)
(setq dashboard-items '((projects . 10)
(bookmarks . 5)
(recents . 5)))
(defun dot/dashboard-goto ()
"Go to the *dashboard* buffer, create if non-existing."
(interactive)
(let ((buffer "*dashboard*"))
(unless (get-buffer buffer)
(generate-new-buffer buffer)
(dashboard-refresh-buffer))
(switch-to-buffer buffer)))
;; Fix keybinds..
(defun dot/dashboard-goto-bookmarks ()
"Move point to bookmarks."
(interactive)
(funcall (local-key-binding "m")))
(defun dot/dashboard-goto-projects ()
"Move point to projects."
(interactive)
(funcall (local-key-binding "p")))
(defun dot/dashboard-goto-recent-files ()
"Move point to recent files."
(interactive)
(funcall (local-key-binding "r")))
(dashboard-setup-startup-hook))
#+END_SRC
** Helpful
A better *help* buffer.
#+BEGIN_SRC emacs-lisp
(use-package helpful
:hook (helpful-mode . dot/hook-disable-line-numbers))
#+END_SRC
** NeoTree
Provides Emacs with a file tree.
#+BEGIN_SRC emacs-lisp
(use-package neotree
:after all-the-icons
:hook (neotree-mode . dot/hook-disable-line-numbers)
:hook (neotree-mode . hl-line-mode)
:init
;; This needs to be in init to actually start loading the package
(with-eval-after-load 'project
(defun neotree-toggle-in-project-root ()
"Toggle Neotree in project root."
(interactive)
(let ((default-directory (dot/find-project-root)))
(call-interactively #'neotree-toggle))))
:config
(setq neo-theme (if (display-graphic-p) 'icons 'arrow))
(setq neo-autorefresh nil)
(setq neo-mode-line-type 'none)
(setq neo-show-hidden-files t)
(setq neo-vc-integration '(face)))
#+END_SRC
** Telephone Line
Emacs mode line replacement.
#+BEGIN_SRC emacs-lisp
(use-package telephone-line
:config
(setq telephone-line-height (if dot/hidpi 30 15))
(setq telephone-line-lhs
'((evil . (telephone-line-evil-tag-segment))
(accent . (telephone-line-erc-modified-channels-segment
telephone-line-process-segment
telephone-line-buffer-segment))
(nil . (telephone-line-project-segment))))
(telephone-line-mode))
#+END_SRC
** Theme
#+BEGIN_SRC emacs-lisp
(use-package hybrid-reverse-theme
:ensure nil
:load-path "~/code/elisp/emacs-hybrid-reverse"
:config (load-theme 'hybrid-reverse t))
#+END_SRC
** Which-key
Popup that displays available key bindings.
#+BEGIN_SRC emacs-lisp
(use-package which-key
:hook (emacs-startup . which-key-mode)
:config
(setq which-key-add-column-padding 1)
(setq which-key-max-display-columns nil)
(setq which-key-min-display-lines 6)
(setq which-key-sort-order #'dot/which-key-prefix-then-key-order-alpha)
(setq which-key-sort-uppercase-first nil)
(defun dot/which-key-prefix-then-key-order-alpha (acons bcons)
"Order by prefix, then lexicographical."
(let ((apref? (which-key--group-p (cdr acons)))
(bpref? (which-key--group-p (cdr bcons))))
(if (not (eq apref? bpref?))
(and (not apref?) bpref?)
(which-key-key-order-alpha acons bcons)))))
#+END_SRC
+2 -13
View File
@@ -23,19 +23,8 @@
;; Prefer to `load' the newest elisp file ;; Prefer to `load' the newest elisp file
(setq load-prefer-newer t) (setq load-prefer-newer t)
;; Set package install location ;; Disable package.el
(setq package-user-dir (concat user-emacs-directory "elpa")) (setq package-enable-at-startup nil)
;; Set package quickstart location
(setq package-quickstart-file (concat
(getenv "XDG_CACHE_HOME")
"/emacs/package-quickstart.el"))
;; Precompute activation actions to speed up startup
(setq package-quickstart t)
;; Native compilation
(setq package-native-compile t)
;; ------------------------------------- ;; -------------------------------------
+14 -22
View File
@@ -2,31 +2,23 @@
;;; Commentary: ;;; Commentary:
;; Setup package archives and build configuration file. ;; Load modules.
;;; Code: ;;; Code:
(require 'package) ;; -----------------------------------------
;; Add the MELPA repository to the package manager (add-to-list 'load-path (locate-user-emacs-file "site-lisp"))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
;; Install the `use-package' dependency (require 'dot-elpaca)
(unless (package-installed-p 'use-package) (require 'dot-setup-el)
(package-refresh-contents)
(package-install 'use-package))
(use-package benchmark-init (require 'dot-core)
:ensure t (require 'dot-ui)
:config (require 'dot-evil)
;; To disable collection of benchmark data after init is complete (require 'dot-development)
(add-hook 'after-init-hook 'benchmark-init/deactivate)) (require 'dot-selection)
(require 'dot-org-mode)
;; ------------------------------------- (require 'dot-mail)
(require 'dot-rss)
;; Tangle and load configuration file (require 'dot-keybinds)
(require 'org)
(when (file-readable-p (concat user-emacs-directory "config.org"))
(org-babel-load-file (concat user-emacs-directory "config.org")))
;;; init.el ends here
@@ -0,0 +1,25 @@
;;; dot-core-advice.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Advice and Aliases.
;;; Code:
;; -----------------------------------------
;; Advice
;; Define default terminal option.
(defun dot/ansi-term (program &optional new-buffer-name)
(interactive (list dot/shell)))
(advice-add 'ansi-term :before #'dot/ansi-term)
;; Aliases
;; Make confirm easier, by just pressing y/n.
(defalias 'yes-or-no-p 'y-or-n-p)
(provide 'dot-core-advice)
;;; dot-core-advice.el ends here
@@ -0,0 +1,249 @@
;;; dot-core-config.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; ??
;;; Code:
;; -----------------------------------------
;; General
;; Columns start at 1
(setq column-number-indicator-zero-based nil)
;; TODO: Make variable below compatible with telephone-line
;; (setq mode-line-position-column-format " C%C")
;; Dont confirm on quitting Emacs
(setq confirm-kill-processes nil)
;; Custom thems, do not ask if safe
(setq custom-safe-themes t)
;; Dired move to trash
(setq delete-by-moving-to-trash t)
;; Column indicator character
(setq display-fill-column-indicator-character ?\N{U+2503})
;; Scrolling
(setq scroll-conservatively 1)
(setq mouse-wheel-scroll-amount '(5))
(setq mouse-wheel-progressive-speed nil)
(setq pixel-scroll-precision-mode t)
;; Parenthesis, set behavior
(setq show-paren-delay 0)
(setq show-paren-style 'mixed)
(setq show-paren-context-when-offscreen t)
;; Tramp default protocol
(setq tramp-default-method "ssh")
;; Set undo limit, measured in bytes
(setq-default undo-limit 400000)
(setq-default undo-strong-limit 3000000)
(setq-default undo-outer-limit 12000000)
;; Enable line numbers
(global-display-line-numbers-mode)
;; C++ syntax highlighting for .h files
(add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))
;; Set the frame title
(setq frame-title-format
`("%b"
(:eval
(if (buffer-file-name)
(concat
(if (buffer-modified-p) "" nil)
" ("
(abbreviate-file-name
(directory-file-name
(file-name-directory (buffer-file-name))))
")")
nil))
,(format " - GNU Emacs %s" emacs-version)
))
(setq icon-title-format frame-title-format)
;; -----------------------------------------
;; Buffers
(setq confirm-nonexistent-file-or-buffer nil)
(setq ibuffer-expert t)
;; -----------------------------------------
;; Dired
(setq wdired-allow-to-change-permissions t)
;; -----------------------------------------
;; Electric
;; Make return key also do indent of previous line
(electric-indent-mode 1)
(setq electric-pair-pairs '(
(?\( . ?\))
(?\[ . ?\])
))
(electric-pair-mode 1)
;; -----------------------------------------
;; File Paths
;; Set file paths for built-in features like: auto-saves, backups, etc.
;; Set Directory locations
(setq auto-save-list-file-prefix (expand-file-name "auto-save/" dot-cache-dir))
(setq auto-save-file-name-transforms `((".*" ,auto-save-list-file-prefix t)))
(setq backup-directory-alist `((".*" . ,(expand-file-name "backup/" dot-cache-dir))))
(setq custom-theme-directory (expand-file-name "themes/" dot-emacs-dir))
(setq eshell-directory-name (expand-file-name "eshell/" dot-cache-dir))
(setq tramp-auto-save-directory (expand-file-name "tramp-auto-save/" dot-cache-dir))
(setq tramp-backup-directory-alist backup-directory-alist)
(setq treesit-extra-load-path `(,(expand-file-name "tree-sitter" dot-cache-dir)))
(setq url-configuration-directory (expand-file-name "url/" dot-cache-dir))
(startup-redirect-eln-cache (expand-file-name "eln-cache" dot-cache-dir))
;; Set file locations
(setq bookmark-default-file (expand-file-name "bookmarks" dot-etc-dir))
(setq nsm-settings-file (expand-file-name "network-security.data" dot-cache-dir))
(setq org-id-locations-file (expand-file-name "org-id-locations" dot-cache-dir))
(setq tramp-persistency-file-name (expand-file-name "tramp" dot-cache-dir ))
;; -----------------------------------------
;; File Backups Versioning
;; Setup file backups versioning.
(setq backup-by-copying t) ; Don't cobbler symlinks
(setq create-lockfiles nil) ; Disable lockfiles (.#)
(setq delete-old-versions t) ; Cleanup backups
(setq kept-new-versions 5) ; Newest backups to keep
(setq kept-old-versions 2) ; Oldest backups to keep
(setq version-control t) ; Use version numbers on backups
;; -----------------------------------------
;; Formatting
;; Columnn after line-wrapping happens
(setq-default fill-column 80)
;; Automatically add newline on save at the end of the file
(setq require-final-newline t)
;; End sentences with a single space
(setq sentence-end-double-space nil)
;; `tabify' and `untabify' should only affect indentation
(setq tabify-regexp "^\t* [ \t]+")
;; Do not wrap lines
(setq-default truncate-lines t)
;; Wrap lines in the middle of words, gives a \ indicator
(setq-default word-wrap nil)
;; -----------------------------------------
;; Hide Elements
(menu-bar-mode 0)
(scroll-bar-mode 0)
(tool-bar-mode 0)
(tooltip-mode 0)
(fringe-mode 0)
(blink-cursor-mode 0)
(setq inhibit-startup-message t)
(setq initial-scratch-message nil)
(setq ring-bell-function 'ignore)
;; -----------------------------------------
;; Native Compilation
(setq native-comp-async-report-warnings-errors nil)
;; -----------------------------------------
;; Recentf
(elpaca-nil (setup recentf ; built-in
(:require recentf)
(:when-loaded
(setq recentf-auto-cleanup 'never)
(setq recentf-exclude '("~$" "/ssh:" "/sudo:"))
(setq recentf-filename-handlers '(abbreviate-file-name))
(setq recentf-max-menu-items 0)
(setq recentf-max-saved-items 200)
(setq recentf-save-file (expand-file-name "recentf" dot-cache-dir))
(recentf-mode))))
;; -----------------------------------------
;; Tabs
;; Tabs
(setq-default tab-width 4
indent-tabs-mode t
c-basic-offset 4
sgml-basic-offset 4
sh-basic-offset 4)
;; C/C++-like languages formatting style
;; https://www.emacswiki.org/emacs/IndentingC
;; https://www.gnu.org/software/emacs/manual/html_mono/ccmode.html#Getting-Started
;; https://www.gnu.org/software/emacs/manual/html_mono/ccmode.html#Adding-Styles
;; https://www.gnu.org/software/emacs/manual/html_mono/ccmode.html#Sample-Init-File
(c-add-style "user" `("linux"
(c-basic-offset . ,(default-value 'tab-width))
(c-offsets-alist
(innamespace . -)
)))
(setq-default c-default-style "user")
;; -----------------------------------------
;; UTF-8
;; Set UTF-8 encoding as default.
(prefer-coding-system 'utf-8-unix)
(setq locale-coding-system 'utf-8-unix)
;; Default also sets file-name, keyboard and terminal coding system
(set-default-coding-systems 'utf-8-unix)
(set-buffer-file-coding-system 'utf-8-unix)
(set-selection-coding-system 'utf-8-unix)
;; -----------------------------------------
;; Window
;; Set `switch-to-buffer' to respect the window rules
(setq switch-to-buffer-obey-display-actions t)
;; Window rules
(setq display-buffer-alist
'(
;; ^\*(e?shell|(ansi-|v)?term).*
("^\\*\\(e?shell\\|\\(ansi-\\|v\\)?term\\).*"
(display-buffer-in-side-window)
(window-height . 0.25)
(side . bottom)
(slot . -1))
("\\*Faces\\*"
(display-buffer-in-side-window)
(window-height . 0.25)
(side . bottom)
(slot . 1))
("\\*Help.*"
(display-buffer-in-side-window)
(window-height . 0.25)
(side . bottom)
(slot . 0))
))
;; Allow 'undo' and 'redo' changes in Window Configuration.
(winner-mode)
(provide 'dot-core-config)
;;; dot-core-config.el ends here
@@ -0,0 +1,19 @@
;;; dot-core-customize.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; ??
;;; Code:
;; -----------------------------------------
;; Customizations
;; Store customize file separately, don't freak out when it's not found.
(setq custom-file (expand-file-name "custom.el" dot-etc-dir))
(load custom-file 'noerror)
(provide 'dot-core-customize)
;;; dot-core-customize.el ends here
@@ -0,0 +1,17 @@
;;; dot-core-fonts.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; ??
;;; Code:
;; -----------------------------------------
;; Set fonts
(set-face-attribute 'default nil :height 90 :family "DejaVu Sans Mono")
(set-face-attribute 'fixed-pitch-serif nil :height 100)
(provide 'dot-core-fonts)
;;; dot-core-fonts.el ends here
@@ -0,0 +1,195 @@
;;; dot-core-functions.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Custom elisp functions and macros.
;;; Code:
;; -----------------------------------------
;; General Functions
;; Functions that only use built-in Emacs functionality.
(defun display-startup-echo-area-message ()
"Hide default startup message."
(message nil))
(defun dot/config-visit ()
"Edit config file."
(interactive)
(find-file (expand-file-name "init.el" dot-emacs-dir)))
(defun dot/config-reload ()
"Reload config file."
(interactive)
(load (expand-file-name "init.el" dot-emacs-dir)))
(defun dot/copy-cpp-function-implementation ()
"Copy C++ function implementation to clipboard."
(interactive)
(save-excursion
(let ((func (save-excursion
(re-search-backward "\\b")
(re-search-forward "\\([^;]+\\);")
(match-string 1)))
(type (progn
(re-search-backward "\\b")
(push-mark)
(back-to-indentation)
(buffer-substring (mark) (point))))
(class (progn
(backward-up-list)
(backward-sexp)
(back-to-indentation)
(forward-to-word 1)
(current-word))))
(kill-new (concat type class "::" func "\n{\n}"))))
(message "Copied function implementation"))
;; Reference: http://turingmachine.org/bl/2013-05-29-recursively-listing-directories-in-elisp.html
(defun dot/directory-files-recursively-depth (dir regexp include-directories maxdepth)
"Depth limited variant of the built-in `directory-files-recursively'."
(let ((result '())
(current-directory-list (directory-files dir t)))
(dolist (path current-directory-list)
(cond
((and (file-regular-p path)
(file-readable-p path)
(string-match regexp path))
(setq result (cons path result)))
((and (file-directory-p path)
(file-readable-p path)
(not (string-equal "/.." (substring path -3)))
(not (string-equal "/." (substring path -2))))
(when (and include-directories
(string-match regexp path))
(setq result (cons path result)))
(when (> maxdepth 1)
(setq result (append (nreverse (dot/directory-files-recursively-depth
path regexp include-directories (- maxdepth 1)))
result))))
(t)))
(reverse result)))
(defun dot/dired-find-file ()
"In Dired, visit the file or directory named on this line."
(interactive)
(if (file-directory-p (dired-file-name-at-point))
(dired-find-alternate-file)
(dired-find-file)))
(defun dot/dired-up-directory ()
"Run Dired on parent directory of current directory."
(interactive)
(find-alternate-file ".."))
(defun dot/find-file-emacsd ()
"Find file under `dot-emacs-dir', recursively."
(interactive)
(let ((files (mapcar 'abbreviate-file-name
(directory-files-recursively dot-emacs-dir ""))))
(find-file (completing-read "Find file (emacs): " files nil t))))
(defun dot/indent-buffer ()
"Indent each nonblank line in the buffer."
(interactive)
(save-excursion
(indent-region (point-min) (point-max) nil)))
(defun dot/insert-spaces-until-column (until-column)
"Insert spaces from point to UNTIL-COLUMN."
(interactive "nInsert spaces until column: ")
(let ((current-column (current-column)))
;; Increment column if the index is 1 based
(when (not column-number-indicator-zero-based)
(setq current-column (+ current-column 1)))
;; Insert spaces
(let ((diff (- until-column current-column)))
(if (> diff 0)
(save-excursion (insert (make-string diff ?\ )))
(user-error "Column should be higher than point")))))
(defun dot/reload-theme ()
"Reload custom theme."
(interactive)
(mapc 'load (file-expand-wildcards
(concat (car custom-theme-load-path) "*.el")))
(load-theme (car custom-enabled-themes) t))
(defun dot/sudo-find-file (filename)
"Edit file FILENAME as root."
(interactive "FOpen file (as root): ")
(find-file (concat "/sudo:root@localhost:" filename)))
(defun dot/sudo-this-file ()
"Edit the current file as root."
(interactive)
(if buffer-file-name
(find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))
(princ "Current buffer isn't a file")))
(defun dot/toggle-fringe (&optional arg)
"Toggle left-only fringe, or set state with ARG."
(interactive)
(if (or (and (eq fringe-mode 0) (eq arg nil))
(eq arg 1))
(set-fringe-mode '(nil . 0))
(set-fringe-mode 0)))
(defun dot/M-x (command)
"Prompt and execute COMMAND."
(interactive "CCommand: ")
(command-execute command))
(defun split-follow-horizontally ()
"Split and follow window."
(interactive)
(split-window-below)
(other-window 1))
(defun split-follow-vertically ()
"Split and follow window."
(interactive)
(split-window-right)
(other-window 1))
;; https://emacsredux.com/blog/2013/05/04/rename-file-and-buffer/
(defun rename-file-and-buffer ()
"Rename the current buffer and file it is visiting."
(interactive)
(let ((filename (buffer-file-name)))
(if (not (and filename (file-exists-p filename)))
(message "Buffer is not visiting a file!")
(let ((new-name (read-file-name "New name: " filename)))
(cond
((vc-backend filename) (vc-rename-file filename new-name))
(t
(rename-file filename new-name t)
(set-visited-file-name new-name t t)))))))
;; -----------------------------------------
;; Hook call functions
(defun dot/hook-disable-line-numbers ()
"Disable the line numbers."
(display-line-numbers-mode 0))
(defun dot/hook-disable-mode-line ()
"Disable the mode line."
(setq-local mode-line-format nil))
(provide 'dot-core-functions)
;; -----------------------------------------
;; Macros
;; Reference: https://github.com/arcticicestudio/nord-emacs/issues/59#issuecomment-414882071
(defmacro dot/run-after-new-frame (func)
"Run FUNC once or after every frame creation.
This is needed for UI initialization when running with the daemon."
`(if (daemonp)
(add-hook 'after-make-frame-functions
(lambda (frame) (with-selected-frame frame ,func)))
,func))
;;; dot-core-functions.el ends here
@@ -0,0 +1,32 @@
;;; dot-hooks.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Add hooks.
;;; Code:
;; -----------------------------------------
;; Delete trailing whitespace
(add-hook 'before-save-hook #'delete-trailing-whitespace)
;; Display fill column indicator
(add-hook 'prog-mode-hook #'display-fill-column-indicator-mode)
(add-hook 'text-mode-hook #'display-fill-column-indicator-mode)
;; Highlight parenthesis
(add-hook 'prog-mode-hook #'show-paren-mode)
;; Disable line numbers
(add-hook 'Custom-mode-hook #'dot/hook-disable-line-numbers)
(add-hook 'dired-mode-hook #'dot/hook-disable-line-numbers)
(add-hook 'Info-mode-hook #'dot/hook-disable-line-numbers)
(add-hook 'term-mode-hook #'dot/hook-disable-line-numbers)
;; Wrap lines in the middle of words, gives a \ indicator
(add-hook 'visual-line-mode-hook (lambda () (setq word-wrap nil)))
(provide 'dot-core-hooks)
;;; dot-hooks.el ends here
@@ -0,0 +1,90 @@
;;; dot-core-packages.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Install core packages.
;;; Code:
;;; Compile
;; Automatically compile all packages.
;; https://github.com/emacscollective/auto-compile
(elpaca-setup auto-compile
(:require auto-compile)
(:when-loaded
(auto-compile-on-load-mode)
(auto-compile-on-save-mode)))
;;; General packages
(elpaca-setup general
(:load-after evil)
(:when-loaded
;; Fix for issue: general #493 and evil #130, #301
;; https://github.com/noctuid/evil-guide#why-dont-keys-defined-with-evil-define-key-work-immediately
(defun dot/general-fix-leader-key ()
"Fix leader key in *Messages* buffer."
(when-let ((messages-buffer (get-buffer "*Messages*")))
(with-current-buffer messages-buffer
(evil-normalize-keymaps))))
(add-hook 'emacs-startup-hook #'dot/general-fix-leader-key)))
(elpaca-setup avy)
(elpaca-setup hungry-delete
(:require hungry-delete)
(:when-loaded (global-hungry-delete-mode)))
(elpaca-setup smart-tabs-mode
;; TODO: how does this get auto-loaded?
(:when-loaded
(smart-tabs-add-language-support latex latex-mode-hook
((latex-indent-line . 4)
(latex-indent-region . 4)))
;; FIXME: breaks for Python files
(smart-tabs-insinuate 'c 'c++ 'java 'python 'latex)))
(elpaca-setup super-save
(:require super-save)
(:when-loaded
(setq super-save-auto-save-when-idle t)
;; Fix for issues: super-save #38 and lsp-mode #1322
(defun dot/super-save-disable-advice (orig-fun &rest args)
"Dont auto-save under these conditions."
(unless (equal (car args) " *LV*")
(apply orig-fun args)))
(advice-add 'super-save-command-advice :around #'dot/super-save-disable-advice)
(super-save-mode)))
(elpaca-nil (setup desktop ; built-in
(:require desktop)
(:when-loaded
(setq desktop-base-file-name "state")
(setq desktop-base-lock-name "state.lock")
(setq desktop-dirname (expand-file-name "desktop/" dot-cache-dir))
(setq desktop-path (list desktop-dirname))
(setq desktop-globals-to-save '()) ;; Only need frames and buffers
;; Create directory to store desktop file in
(unless (file-directory-p desktop-dirname)
(make-directory desktop-dirname t))
(defun dot/desktop-save ()
"Save frame state and buffers."
(interactive)
(dot/centaur-tabs-buffer-cleanup)
(desktop-save desktop-dirname t))
(defun dot/desktop-save-on-exit ()
"Save state of buffers before closing Emacs."
(dot/desktop-save)
(desktop-release-lock desktop-dirname))
(add-hook 'kill-emacs-hook #'dot/desktop-save-on-exit))))
(provide 'dot-core-packages)
;;; dot-core-packages.el ends here
@@ -0,0 +1,48 @@
;;; dot-core-variables.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Global variables.
;;; Code:
;; -----------------------------------------
;; Global Variables
;; Variables for directories, leader keys, etc.
(defvar dot-emacs-dir (directory-file-name (file-truename user-emacs-directory))
"Directory base.") ; ~/.config/emacs
(defvar dot-etc-dir (expand-file-name "etc" dot-emacs-dir)
"Directory for non-volatile storage.") ; ~/.config/emacs/etc
(defvar dot-cache-dir
(expand-file-name "emacs" (if (getenv "XDG_CACHE_HOME") (getenv "XDG_CACHE_HOME") "~/.cache"))
"Directory for cache data.") ; ~/.cache/emacs
(defvar dot/leader-key "SPC"
"Leader prefix key.")
(defvar dot/leader-alt-key "M-SPC"
"Alternative leader prefix key, used for Insert and Emacs states.")
(defvar dot/localleader-key "SPC m"
"Local leader prefix key, for 'major-mode' specific commands.")
(defvar dot/localleader-alt-key "M-SPC m"
"Alternative local leader prefix key, used for Insert and Emacs states.")
(defvar dot/shell "/bin/zsh"
"Command interpreter binary path.")
(defvar dot/hidpi (getenv "HIDPI")
"Whether the primary screen is HiDPI.")
;; Create cache directory
(unless (file-directory-p dot-cache-dir)
(make-directory dot-cache-dir t))
(provide 'dot-core-variables)
;;; dot-core-variables.el ends here
+24
View File
@@ -0,0 +1,24 @@
;;; dot-core.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Load configuration core.
;;; Code:
;; -----------------------------------------
(add-to-list 'load-path (locate-user-emacs-file "site-lisp/core"))
(require 'dot-core-variables)
(require 'dot-core-customize)
(require 'dot-core-fonts)
(require 'dot-core-packages)
(require 'dot-core-config)
(require 'dot-core-functions)
(require 'dot-core-advice)
(require 'dot-core-hooks)
(provide 'dot-core)
;;; dot-core.el ends here
+501
View File
@@ -0,0 +1,501 @@
;;; dot-development.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Development.
;;; Code:
;; -----------------------------------------
;; Company
(elpaca-setup company
(:require company)
(:with-mode
(c-mode-common
emacs-lisp-mode
latex-mode
org-mode
php-mode
shell-mode
shell-script-mode)
(:hook company-mode))
(:when-loaded
(setq company-idle-delay 0.2)
(setq company-minimum-prefix-length 2)
(setq company-show-numbers t)
(setq company-tooltip-align-annotations 't)))
;; Sort Company completions.
(elpaca-setup company-prescient
(:load-after company prescient)
(:when-loaded (company-prescient-mode)))
;; Auto-completion for C/C++ headers.
(elpaca-setup company-c-headers
(:when-loaded (add-to-list 'company-backends 'company-c-headers)))
;; GLSL integration with company requires the package: ~glslang~.
(when (executable-find "glslangValidator")
(elpaca-setup company-glsl
(:when-loaded (add-to-list 'company-backends 'company-glsl))))
;; -----------------------------------------
;; Git
(elpaca-setup diff-hl
(:require diff-hl)
(:with-mode prog-mode
(:hook turn-on-diff-hl-mode)
(:hook dot/diff-hl-enable-flydiff-and-fringe))
(:when-loaded
(defun dot/diff-hl-enable-flydiff-and-fringe ()
"Enable on the fly diff checking if file is under version control."
(let ((buffer buffer-file-name))
(when (and buffer (vc-registered buffer))
(diff-hl-flydiff-mode)
(dot/toggle-fringe 1))))))
(elpaca-setup transient
(:when-loaded
(setq transient-history-file (expand-file-name "transient/history.el" dot-cache-dir))
(setq transient-values-file (expand-file-name "transient/values.el" dot-cache-dir))))
(elpaca-setup magit
(:autoload magit-status magit-status-here)
(:with-mode git-commit-setup
(:hook git-commit-turn-on-auto-fill)
(:hook git-commit-turn-on-flyspell))
(:with-mode magit-pre-refresh (:hook diff-hl-magit-pre-refresh))
(:with-mode magit-post-refresh (:hook diff-hl-magit-post-refresh))
(:load-after diff-hl transient)
(:when-loaded
(setq git-commit-fill-column 72)
(setq git-commit-summary-max-length 72)
(setq magit-completing-read-function #'completing-read)
(setq magit-diff-paint-whitespace-lines 'both)
(setq magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
(setq magit-process-extreme-logging nil)
(setq magit-repository-directories '(("~/dotfiles" . 0)
("~/code" . 3)))
(put 'magit-log-select-pick :advertised-binding [?\M-c])
(put 'magit-log-select-quit :advertised-binding [?\M-k])
(defun dot/magit-select-repo ()
"Select project repo."
(interactive)
(let ((current-prefix-arg '(t)))
(call-interactively #'magit-status)))))
(elpaca-setup magit-todos
(:load-after magit)
(:when-loaded
(magit-todos-mode)))
;; -----------------------------------------
;; Project
;; Project manager.
;; Adding to project.el project directory detection
;; https://michael.stapelberg.ch/posts/2021-04-02-emacs-project-override/
(elpaca-nil (setup project ; built-in
(setq project-list-file (expand-file-name "projects" dot-cache-dir))
(:when-loaded
(defun dot/project-find (dir)
(let ((root (locate-dominating-file dir ".project")))
(and root (list 'vc 'Filewise root))))
(add-hook 'project-find-functions #'dot/project-find)
(defun dot/find-project-root ()
"Return root of the project, determined by `.git/' and `.project',
`default-directory' otherwise."
(let ((project (project-current)))
(if project
(project-root project)
default-directory)))
(defun dot/find-file-in-project-root ()
"Find file in project root."
(interactive)
(let ((default-directory (dot/find-project-root)))
(call-interactively 'find-file)))
(defun dot/project-remember-projects-under (dir maxdepth)
"Index all projects below directory DIR recursively, until MAXDEPTH."
(let ((files (mapcar 'file-name-directory
(dot/directory-files-recursively-depth
dir "\\.git$\\|\\.project$" t maxdepth))))
(dolist (path files)
(project-remember-projects-under path))))
(unless (file-exists-p project-list-file)
(project-remember-projects-under "~/dotfiles")
(dot/project-remember-projects-under "~/code" 4))
(defun dot/project-project-name ()
"Return project name."
(let ((project (project-current)))
(if project
(let* ((project (file-truename (directory-file-name (project-root (project-current)))))
(parent-dir-full (file-name-directory (directory-file-name project)))
(parent-dir (file-name-nondirectory (substring parent-dir-full 0 -1)))
(filename (file-name-nondirectory project)))
(concat filename "/" parent-dir))
"-")))
(defun dot/project-save-project-buffers ()
"Save all project buffers."
(interactive)
(let ((buffers (cl-remove-if (lambda (buffer) (not (buffer-file-name buffer)))
(project-buffers (project-current)))))
(save-some-buffers t (lambda () (member (current-buffer) buffers))))))))
;; -----------------------------------------
;; Compile
;; Enable color escape codes.
(elpaca-nil (setup ansi-color ; built-in
(:with-mode compilation-filter (:hook ansi-color-compilation-filter))
;; :hook (compilation-filter . ansi-color-compilation-filter)
(:when-loaded (setq ansi-color-bold-is-bright t))))
(elpaca-nil (setup compile ; built-in
(defun dot/compile-disable-underline () ""
(face-remap-add-relative 'underline :underline nil))
(:with-mode comint-mode (:hook dot/compile-disable-underline))
(:when-loaded
(setq compilation-scroll-output 'first-error)
(defun dot/compile ()
"Compile project."
(interactive)
(let ((default-directory (dot/find-project-root)))
(dot/project-save-project-buffers)
(let ((current-prefix-arg '(t)))
(call-interactively 'compile)))))))
;; -----------------------------------------
;; Languages
;;; Language Server Protocol
(elpaca-setup lsp-mode
(:autoload lsp-deferred)
;; (:require lsp-modeline lsp-mode)
(:with-mode
(c-mode ; clangd
c++-mode ; clangd
php-mode ; nodejs-intelephense
csharp-mode ; omnisharp-roslyn-bin
go-mode ; gopls
kotlin-mode ; kotlin-language-server
lua-mode ; lua-language-server
latex-mode ; texlab
swift-mode ; swift-bin
web-mode)
(:hook lsp-deferred))
(:when-loaded
(setq lsp-auto-guess-root t)
(setq lsp-clients-clangd-args '("-j=2"
"--background-index"
"--clang-tidy"
"--compile-commands-dir=build"
"--log=error"
"--header-insertion-decorators=0"
"--pch-storage=memory"
"--enable-config"))
(setq lsp-csharp-omnisharp-roslyn-binary-path "/usr/bin/omnisharp")
(setq lsp-csharp-server-install-dir "/usr/lib/omnisharp/")
(setq lsp-clients-lua-language-server-bin "/usr/bin/lua-language-server")
(setq lsp-clients-lua-language-server-install-dir "/usr/lib/lua-language-server/")
(setq lsp-clients-lua-language-server-main-location "/usr/lib/lua-language-server/main.lua")
(setq lsp-enable-xref t)
(setq lsp-headerline-breadcrumb-enable nil)
(setq lsp-intelephense-storage-path (expand-file-name "lsp-cache" dot-cache-dir))
(setq lsp-keep-workspace-alive nil)
;; (setq lsp-modeline-code-actions-enable nil)
;; (setq lsp-modeline-diagnostics-enable nil)
;; (setq lsp-modeline-workspace-status-enable nil)
(setq lsp-prefer-flymake nil)
(setq lsp-session-file (expand-file-name "lsp-session-v1" dot-cache-dir))
;; Mark clangd args variable as safe to modify via .dir-locals.el
(put 'lsp-clients-clangd-args 'safe-local-variable #'listp)
;; Enable which-key descriptions
(dolist (leader-key (list dot/leader-key dot/leader-alt-key))
(let ((lsp-keymap-prefix (concat leader-key " l")))
(lsp-enable-which-key-integration)))
(defun dot/lsp-format-buffer-or-region ()
"Format the selection (or buffer) with LSP."
(interactive)
(unless (bound-and-true-p lsp-mode)
(message "Not in an LSP buffer"))
(call-interactively
(if (use-region-p)
#'lsp-format-region
#'lsp-format-buffer)))
;; This is cached to prevent unneeded I/O
(setq lsp-in-cpp-project-cache nil)
(defun dot/lsp-format-cpp-buffer ()
"Format buffer in C++ projects."
(unless lsp-in-cpp-project-cache
(set (make-local-variable 'lsp-in-cpp-project-cache)
(list
(if (and (eq major-mode 'c++-mode)
(bound-and-true-p lsp-mode)
(or
(locate-dominating-file "." ".clang-format")
(locate-dominating-file "." "_clang-format")))
t
nil))))
(when (car lsp-in-cpp-project-cache)
(lsp-format-buffer)))
(add-hook 'before-save-hook #'dot/lsp-format-cpp-buffer)))
(elpaca-setup lsp-ui
(:autoload lsp-ui-mode)
(:load-after flycheck lsp-mode)
(:when-loaded
(setq lsp-ui-doc-border (face-foreground 'default))
(setq lsp-ui-doc-delay 0.5)
(setq lsp-ui-doc-enable t)
(setq lsp-ui-doc-header t)
(setq lsp-ui-doc-include-signature t)
(setq lsp-ui-doc-position 'top)
(setq lsp-ui-doc-use-childframe t)
(setq lsp-ui-flycheck-list-position 'right)
(setq lsp-ui-imenu-enable nil)
(setq lsp-ui-peek-enable nil)
(setq lsp-ui-sideline-enable nil)))
;;; Debug Adapter Protocol
(elpaca-setup treemacs
(:hook dot/hook-disable-line-numbers)
(:when-loaded (setq treemacs-persist-file (expand-file-name "treemacs/persist" dot-cache-dir))))
(elpaca-setup lsp-treemacs
(:load-after treemacs)
(:when-loaded (setq lsp-treemacs-error-list-current-project-only t)))
(elpaca-setup dap-mode
(:with-mode lsp-after-initialize (:hook dot/dap-install-debug-adapters))
(:load-after lsp-treemacs lsp-mode)
(:when-loaded
(setq dap-auto-configure-features '(sessions locals expressions controls tooltip))
(setq dap-breakpoints-file (expand-file-name "dap/breakpoints" dot-cache-dir))
(setq dap-utils-extension-path (expand-file-name "dap" dot-cache-dir))
;; Create dap extension directory
(unless (file-directory-p dap-utils-extension-path)
(make-directory dap-utils-extension-path t))
(defun dot/dap-install-debug-adapters ()
"Install and Load debug adapters."
(interactive)
(unless (bound-and-true-p lsp-mode)
(user-error "Not in an LSP buffer"))
(when (string-equal major-mode "c++-mode")
(require 'dap-cpptools)
(dap-cpptools-setup)))))
;;; C/C++
(elpaca-nil (setup c-mode ; built-in
;; C++ // line comment style in c-mode
(defun dot/c-mode-comment-style () ""
(c-toggle-comment-style -1))
(:hook dot/c-mode-comment-style)))
;;; C#
;; Packages:
;; - dotnet-host
;; - dotnet-runtime-6.0
;; - dotnet-sdk-6.0
;; - dotnet-targeting-pack-6.0
;; - omnisharp-roslyn-bin
;; - netcoredbg (edit PKGBUILD to detect dotnet -6.0 dependencies)
(elpaca-nil (setup csharp-mode)) ; built-in
;;; CMake
(elpaca-setup cmake-mode
(:defer 2)
(:when-loaded (setq cmake-tab-width (default-value 'tab-width))))
;;; Emacs Lisp
(elpaca-nil (setup emacs-lisp ; built-in
(defun dot/elisp-init () ""
(setq-local indent-tabs-mode nil))
(:hook dot/elisp-init)))
;;; GLSL
(elpaca-setup glsl-mode)
;;; Golang
(elpaca-setup go-mode)
;;; HTML
(elpaca-setup web-mode
(:file-match "\\.ts")
(:file-match "\\.vue"))
;;; Kotlin
(elpaca-setup kotlin-mode)
;;; Lua
(elpaca-setup lua-mode
(:when-loaded (setq lua-indent-level (default-value 'tab-width))))
;;; PHP
(elpaca-setup php-mode
(defun dot/php-mode-init () ""
(setq-local indent-tabs-mode t))
(:hook dot/php-mode-init))
(elpaca-setup restclient)
(elpaca-setup restclient-jq
(:load-after restclient))
;;; Python
(elpaca-nil (setup python-mode ; built-in
(defun dot/python-mode-init () ""
(setq-local indent-tabs-mode t)
(setq-local tab-width (default-value 'tab-width))
(setq python-indent-offset (default-value 'tab-width)))
(:hook dot/python-mode-init)))
;;; Swift
(elpaca-setup swift-mode)
(elpaca-setup lsp-sourcekit
(:load-after lsp-mode)
(:when-loaded
(setq lsp-sourcekit-executable "/usr/bin/sourcekit-lsp")))
;;; YAML
(elpaca-setup yaml-mode)
;; :defer t)
;; -----------------------------------------
;; Syntax Highlighting
;; (elpaca-setup tree-sitter-langs))
;; (elpaca-setup tree-sitter)
;; (:also-load tree-sitter-langs)
;; (:when-loaded
;; (global-tree-sitter-mode)
;; (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode)))
;; -----------------------------------------
;; Quality of Life
;;; Flycheck, on the fly syntax checking
(elpaca-setup flycheck
(:autoload flycheck-mode)
(:with-mode
(c-mode-common
emacs-lisp-mode
latex-mode
org-mode
php-mode
sh-mode
shell-mode
shell-script-mode)
(:hook flycheck-mode))
(:when-loaded
(setq flycheck-clang-language-standard "c++20")
(setq flycheck-gcc-language-standard "c++20")))
;; For .el files which are intended to be packages
(elpaca-setup flycheck-package
(:load-after flycheck)
(:when-loaded
(add-to-list 'flycheck-checkers 'flycheck-emacs-lisp-package)
(flycheck-package-setup)))
(elpaca-setup flycheck-clang-tidy
(:load-after flycheck)
(:with-mode flycheck-mode (:hook flycheck-clang-tidy-setup))
(:when-loaded (setq flycheck-clang-tidy-extra-options "--format-style=file")))
;;; Flyspell
(elpaca-nil (setup ispell ; built-in
(:when-loaded
(setq ispell-program-name "/usr/bin/hunspell")
(ispell-set-spellchecker-params)
(ispell-hunspell-add-multi-dic "en_US,nl_NL")
(setq ispell-dictionary "en_US,nl_NL"))))
;; Give Flyspell a selection menu.
(elpaca-setup flyspell-correct
(:load-after flyspell)
(:with-mode org-mode (:hook flyspell-mode))
(:when-loaded
(setq flyspell-issue-message-flag nil)
(setq flyspell-issue-welcome-flag nil))
(defun dot/flyspell-toggle ()
"Toggle Flyspell, prompt for language."
(interactive)
(if (symbol-value flyspell-mode)
(flyspell-mode -1)
(call-interactively 'ispell-change-dictionary)
(if (derived-mode-p 'prog-mode)
(flyspell-prog-mode)
(flyspell-mode))
(flyspell-buffer))))
;;; Rainbow Delimiters
(elpaca-setup rainbow-delimiters
(:hook-into prog-mode))
;;; Rainbow Mode
(elpaca-setup rainbow-mode
(:hook-into css-mode))
;;; YASnippet
(elpaca-setup yasnippet
(:autoload yas-expand yas-insert-snippet)
(setq yas-snippet-dirs (list (expand-file-name "snippets" dot-emacs-dir)))
(setq yas-prompt-functions '(yas-completing-prompt))
(:when-loaded
(yas-global-mode)))
(elpaca-setup yasnippet-snippets
(:load-after yasnippet))
;; https://stackoverflow.com/questions/22735895/configuring-a-yasnippet-for-two-scenarios-1-region-is-active-2-region-is
(provide 'dot-development)
;;; dot-org-mode.el ends here
+62
View File
@@ -0,0 +1,62 @@
;;; dot-elpaca.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Elpaca bootstrap
;;; Code:
;; -----------------------------------------
;; Elpaca bootstrap
(defvar elpaca-installer-version 0.8)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
:ref nil :depth 1
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
(build (expand-file-name "elpaca/" elpaca-builds-directory))
(order (cdr elpaca-order))
(default-directory repo))
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
(when (< emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
(if-let* ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
((zerop (apply #'call-process `("git" nil ,buffer t "clone"
,@(when-let* ((depth (plist-get order :depth)))
(list (format "--depth=%d" depth) "--no-single-branch"))
,(plist-get order :repo) ,repo))))
((zerop (call-process "git" nil buffer t "checkout"
(or (plist-get order :ref) "--"))))
(emacs (concat invocation-directory invocation-name))
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
((require 'elpaca))
((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
(load "./elpaca-autoloads")))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
;;;###autoload
(defmacro elpaca-nil (body)
"Defer execution until all Elpaca queues have been processed."
(declare (indent 1))
`(add-hook 'elpaca-after-init-hook (lambda () (,@body)) 1))
;; Stop coping with startup time, its done loading when its done loading
(elpaca-nil (setq after-init-time (current-time)))
(provide 'dot-elpaca)
;;; dot-elpaca.el ends here
+106
View File
@@ -0,0 +1,106 @@
;;; dot-evil.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Setup Evil and related packages.
;;; Code:
;; -----------------------------------------
(elpaca-setup undo-tree
(:when-loaded
(setq undo-tree-auto-save-history t)
(setq undo-tree-history-directory-alist `(("." . ,(expand-file-name "undo-tree" dot-cache-dir))))
(global-undo-tree-mode)))
(elpaca-setup goto-chg)
(elpaca-setup evil
(:also-load undo-tree goto-chg)
(setq evil-ex-complete-emacs-commands nil)
(setq evil-kill-on-visual-paste nil)
(setq evil-operator-state-cursor 'box) ; Do not set half cursor
(setq evil-search-module 'evil-search)
(setq evil-split-window-below t)
(setq evil-undo-system 'undo-tree)
(setq evil-vsplit-window-right t)
(setq evil-want-C-u-scroll t)
(setq evil-want-Y-yank-to-eol t)
(setq evil-want-integration t)
(setq evil-want-keybinding nil) ; Needed by evil-collection
(:require evil)
(:when-loaded
;; Put search results in the center of the window
(defun dot/evil-scroll-center (&rest _)
"Scroll cursor to center of the window."
(evil-scroll-line-to-center nil))
(advice-add 'evil-ex-search :after #'dot/evil-scroll-center)
(advice-add 'evil-match :after #'dot/evil-scroll-center)
(defun dot/evil-normal-sort-paragraph ()
"Sort paragraph cursor is under.
Vim equivalence: vip:sort<CR>"
(interactive)
(let ((p (point)))
(evil-visual-char)
(call-interactively 'evil-inner-paragraph)
(evil-ex-sort (region-beginning) (region-end))
(goto-char p)))
(defun dot/evil-insert-shift-left ()
"Shift line left, retains cursor position.
Vim equivalence: <C-D>"
(interactive)
(evil-shift-left-line 1))
(defun dot/evil-insert-shift-right ()
"Shift line right, retains cursor position.
Vim equivalence: <Tab>"
(interactive)
(unless (yas-expand)
(insert "\t")))
(defun dot/evil-visual-shift-left ()
"Shift visual selection left, retains the selection.
Vim equivalence: <gv"
(interactive)
(call-interactively #'evil-shift-left)
(setq deactivate-mark nil))
(defun dot/evil-visual-shift-right ()
"Shift visual selection left, retains the selection.
Vim equivalence: >gv"
(interactive)
(call-interactively #'evil-shift-right)
(setq deactivate-mark nil))
(evil-mode)))
;; Evil command aliases.
(elpaca-nil (setup evil-ex ; evil-ex.el is part of evil
(:when-loaded
(evil-ex-define-cmd "W" "w")
(evil-ex-define-cmd "Q" "q")
(evil-ex-define-cmd "WQ" "wq")
(evil-ex-define-cmd "Wq" "wq"))))
(elpaca-setup evil-collection
(setq evil-collection-company-use-tng nil)
(setq evil-collection-key-blacklist (list dot/leader-key dot/localleader-key
dot/leader-alt-key dot/localleader-alt-key
"M-h" "M-j" "M-k" "M-l"))
(setq evil-collection-setup-minibuffer t)
(:load-after evil)
(:when-loaded
(evil-collection-init)))
(elpaca-setup evil-nerd-commenter
(:load-after evil))
(provide 'dot-evil)
;;; dot-evil.el ends here
+673
View File
@@ -0,0 +1,673 @@
;;; dot-keybinds.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; All keybinds.
;;; Code:
;; -----------------------------------------
;; Useful links
;; Mastering Emacs key bindings
;; https://www.masteringemacs.org/article/mastering-key-bindings-emacs
;; use-package bind key
;; https://github.com/jwiegley/use-package/blob/master/bind-key.el
;; GNU remapping commands
;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Remapping-Commands.html
;; GNU binding combinations of modifiers
;; https://www.gnu.org/software/emacs/manual/html_node/efaq/Binding-combinations-of-modifiers-and-function-keys.html
;; Doom Emacs bindings
;; https://github.com/hlissner/doom-emacs/blob/develop/modules/config/default/+evil-bindings.el
;; Keybindings and States
;; https://github.com/noctuid/evil-guide#keybindings-and-states
;; General.el
;; https://github.com/noctuid/general.el
;; -----------------------------------------
;; Disable Native
;; Disable keybinds of native modes that clash with other custom keybinds.
(elpaca-nil (setup emacs
(:global
"M-h" nil
"M-j" nil
"M-k" nil
"M-l" nil
"<pinch>" nil ; Do not scale text when pinching touchpad
)))
(elpaca-nil (setup org
(:bind "M-h" nil
"C-M-h" nil
)))
(elpaca-nil (setup cc-mode
(:bind-into c-mode-base-map
"M-j" nil
"C-M-h" nil
)))
(elpaca-nil (setup nxml-mode
(:bind "M-h" nil
)))
;; -----------------------------------------
;; Disable Package
;; Disable keybinds of installed packages that clash with other custom keybinds.
(elpaca-nil (setup evil-states
(:bind-into evil-motion-state-map dot/leader-key nil
)))
(elpaca-nil (setup magit
(:evil-bind normal
;; Do not close magit when pressing escape
"<escape>" nil)))
(elpaca-nil (setup php-mode
(:bind "M-j" nil
"C-M-h" nil
)))
;; -----------------------------------------
;; Set Native
;; Set keybinds to native functionality.
;;; Set Native Global Keybinds
(elpaca-nil (setup emacs
(:global
;; Buffers
"C-x C-b" ibuffer
"M-w" kill-buffer-and-window
;; Config edit/reload
"C-c r" dot/config-reload
"C-c v" dot/config-visit
;; Find file
"C-x C-f" dot/find-file-in-project-root
;; Split and follow window
"C-x 2" split-follow-horizontally
"C-x 3" split-follow-vertically
;; Terminal
"<s-backspace>" ansi-term
;; Universal prefix argument
"C-M-u" universal-argument
)))
;;; Set Native Mode Keybinds
;; Dired
(elpaca-nil (setup dired
(:bind
[remap dired-find-file] dot/dired-find-file
[remap dired-up-directory] dot/dired-up-directory
)))
;; Org
(elpaca-nil (setup org
(:bind "M-c" org-edit-special
)))
(elpaca-nil (setup org-src
(:bind "M-c" org-edit-src-exit
"M-k" org-edit-src-abort
)))
(elpaca-nil (setup org-capture
(:bind "M-c" org-capture-finalize
"M-w" org-capture-refile
"M-k" org-capture-kill
)))
;; -----------------------------------------
;; Set Package
;; Set keybinds to functionality of installed packages.
(elpaca-nil (setup emacs
(:global
;; Buffers
"M-h" centaur-tabs-backward-tab
"M-j" centaur-tabs-forward-group
"M-k" centaur-tabs-backward-group
"M-l" centaur-tabs-forward-tab
"M-H" centaur-tabs-move-current-tab-to-left
"M-L" centaur-tabs-move-current-tab-to-right
"M-\`" evil-switch-to-windows-last-buffer
;; Other
"M-s" avy-goto-char-timer
"M-x" dot/M-x
)))
(elpaca-nil (setup company
(:bind-into company-active-map
;; Company completion selection
"M-n" nil
"M-p" nil
"M-h" company-abort
"M-j" company-select-next
"M-k" company-select-previous
"M-l" company-complete-selection
"<escape>" company-abort
)))
(elpaca-nil (setup evil-ex
(:bind-into evil-ex-completion-map
;; Evil command history selection
"M-h" abort-recursive-edit
"M-j" next-complete-history-element
"M-k" previous-complete-history-element
"M-l" exit-minibuffer
)))
(elpaca-nil (setup emacs
(:global
;; flyspell-correct
[remap ispell-word] flyspell-correct-at-point ; z=
;; Helpful overwrite default help functions
[remap describe-command] helpful-command
[remap describe-function] helpful-callable
[remap describe-key] helpful-key
[remap describe-symbol] helpful-at-point
[remap describe-variable] helpful-variable
)
(setup which-key
(:when-loaded
(which-key-add-key-based-replacements "C-h o" "describe-symbol-at-point")))))
;; LSP
(elpaca-nil (setup lsp-mode
(:bind-into lsp-signature-mode-map
"M-j" lsp-signature-next
"M-k" lsp-signature-previous
)))
;; Magit
(elpaca-nil (setup magit
(:bind-into magit-log-select-mode-map
"M-c" magit-log-select-pick
"M-k" magit-log-select-quit
)))
;; Org-roam
(elpaca-nil (setup org-roam
(:bind [down-mouse-1] org-roam-visit-thing
)))
;; Minibuffer completion selection
(elpaca-nil (setup minibuffer
(:bind-into minibuffer-local-map
"M-J" next-history-element
"M-K" previous-history-element
"M-h" abort-recursive-edit
"M-i" vertico-quick-insert
"M-j" vertico-next
"M-k" vertico-previous
"M-l" vertico-exit
"M-m" vertico-quick-exit
"<backspace>" dot/vertico-backspace
"<S-backspace>" evil-delete-backward-char-and-join
)))
;; with-editor
(elpaca-nil (setup with-editor
(:bind
"M-c" with-editor-finish
"M-k" with-editor-cancel
)))
;;; Global evil keymap
(elpaca-nil (setup evil
(:bind-into evil-normal-state-map
"C-n" neotree-toggle-in-project-root
"C-S-p" evil-paste-pop-next
"S-<up>" scroll-down-line
"S-<down>" scroll-up-line
)
(:bind-into evil-insert-state-map
"<backtab>" dot/evil-insert-shift-left ; <S-Tab>
"TAB" dot/evil-insert-shift-right ; <Tab>
)
(:bind-into evil-visual-state-map
"<" dot/evil-visual-shift-left ; <gv
">" dot/evil-visual-shift-right ; >gv
)
(:bind-into evil-ex-map
"e" dot/find-file-in-project-root
)))
;;; Other evil state-related keybinds
;; Custom (M-x customize)
(elpaca-nil (setup cus-edit
(:evil-bind-into normal custom-mode-map
[down-mouse-1] widget-button-click
)))
;; Dashboard
(elpaca-nil (setup dashboard
(:evil-bind normal
[down-mouse-1] widget-button-click
"g" dashboard-refresh-buffer
"m" dot/dashboard-goto-bookmarks
"p" dot/dashboard-goto-projects
"r" dot/dashboard-goto-recent-files
)))
;; Dap
(elpaca-nil (setup dap-ui
(:evil-bind-into normal dap-ui-session-mode-map
"D" dap-ui-delete-session
)))
;; Deft
(elpaca-nil (setup deft
(:evil-bind normal
[down-mouse-1] widget-button-click
"+" deft-new-file-named
"-" deft-new-file
"a" deft-archive-file
"c" deft-filter-clear
"d" deft-delete-file
"f" deft-find-file
"g" deft-refresh
"q" kill-this-buffer
"R" deft-rename-file
"s" deft-filter
"ts" '("Toggle search" . deft-toggle-incremental-search) ; which-key
"tt" '("Toggle sort" . deft-toggle-sort-method) ; custom string
)))
;; Elfeed
(elpaca-nil (setup elfeed
(:evil-bind-into normal elfeed-search-mode-map
"b" elfeed-search-browse-url
"c" elfeed-search-clear-filter
"gr" '("Refresh buffer" . elfeed-search-update--force)
"gR" '("Update feeds" . elfeed-search-fetch)
"q" elfeed-search-quit-window
"u" elfeed-search-tag-all-unread
"U" nil
"r" elfeed-search-untag-all-unread
)
(:evil-bind-into normal elfeed-show-mode-map
"b" elfeed-show-visit
"g" elfeed-show-refresh
"q" elfeed-kill-buffer
"u" elfeed-show-tag--unread
"y" elfeed-show-yank
)))
;; Magit
(elpaca-nil (setup magit
(:evil-bind (normal visual)
"{" magit-section-backward-sibling
"}" magit-section-forward-sibling
)))
;; Minibuffer
(elpaca-nil (setup minibuffer
(:evil-bind-into normal minibuffer-local-map
"TAB" vertico-insert
"j" vertico-next
"k" vertico-previous
"<up>" vertico-previous
"<down>" vertico-next
)
(:evil-bind-into insert minibuffer-local-map
"TAB" vertico-insert
)))
;; Mu4e
(elpaca-nil (setup mu4e
(:evil-bind-into normal mu4e-compose-mode-map
"q" mu4e-message-kill-buffer
"M-c" message-send-and-exit
"M-k" mu4e-message-kill-buffer
)))
;; Neotree
(elpaca-nil (setup neotree
(:evil-bind normal
"RET" neotree-enter
"<backtab>" neotree-collapse-all ; <S-tab>
"c" neotree-create-node
"r" neotree-rename-node
"d" neotree-delete-node
"h" neotree-select-previous-sibling-node
"g" neotree-refresh
"j" neotree-next-line
"k" neotree-previous-line
"l" neotree-enter
"C" neotree-change-root
"H" neotree-hidden-file-toggle
"q" neotree-hide
)))
;; Org
(elpaca-nil (setup org
(:evil-bind normal
"RET" dot/org-ret-at-point
)
(:evil-bind insert
"RET" evil-ret
)
(:evil-bind-into motion org-agenda-mode-map
"RET" org-agenda-switch-to
)))
;; Wdired
(elpaca-nil (setup wdired
(:evil-bind (normal insert)
"M-c" wdired-finish-edit
"M-k" wdired-abort-changes
)))
;; -----------------------------------------
;; Set leader key
;; General.el ~leader key binds.
;;; Global Leader
(elpaca-nil (setup general
(:when-loaded
(general-create-definer space-leader
:prefix dot/leader-key
:non-normal-prefix dot/leader-alt-key
:global-prefix dot/leader-alt-key
:states '(normal visual insert motion emacs)
:keymaps 'override) ; prevent leader keybindings from ever being overridden
(space-leader
"SPC" '(dot/M-x :which-key "Execute command")
"RET" '(consult-bookmark :which-key "Go to bookmark")
;; Apps
"a" '(:ignore t :which-key "apps")
"a d" '(deft :which-key "Deft")
"a e" '(elfeed :which-key "Elfeed")
;; Buffer / bookmark
"b" '(:ignore t :which-key "buffer/bookmark")
"b a" '(auto-revert-mode :which-key "Auto revert buffer")
"b b" '(consult-buffer :which-key "Switch buffer")
"b d" '(dashboard-refresh-buffer :which-key "Dashboard")
"b k" '(kill-current-buffer :which-key "Kill buffer")
"b m" '(bookmark-set :which-key "Make bookmark")
"b n" '(evil-buffer-new :which-key "New empty buffer")
"b r" '(revert-buffer :which-key "Revert buffer")
"b s" '(basic-save-buffer :which-key "Save buffer")
"b B" '(ibuffer :which-key "List buffers")
"b C" '(dot/centaur-tabs-buffer-cleanup :which-key "Cleanup buffers")
"b M" '(bookmark-delete :which-key "Delete bookmark")
"b S" '(evil-write-all :which-key "Save all buffers")
"b <left>" '(previous-buffer :which-key "Previous buffer")
"b <right>" '(next-buffer :which-key "Next buffer")
;; Comments
"c" '(:ignore t :which-key "comment/config")
"c c" '(evilnc-comment-or-uncomment-lines :which-key "Toggle comment")
"c p" '(evilnc-comment-or-uncomment-paragraphs :which-key "Toggle comment paragraph")
"c y" '(evilnc-comment-and-kill-ring-save :which-key "Comment and copy")
;; Elisp
"e" '(:ignore t :which-key "elisp")
"e ;" '(eval-expression :which-key "Evaluate expression")
"e b" '(eval-buffer :which-key "Evaluate buffer")
"e e" '(eval-last-sexp :which-key "Evaluate last sexp")
"e r" '(eval-region :which-key "Evaluate region")
"e t" '(dot/reload-theme :which-key "Reload theme")
;; File
"f" '(:ignore t :which-key "file")
"f d" '(dired :which-key "Find directory")
"f f" '(dot/find-file-in-project-root :which-key "Find file")
"f o" '(ff-find-other-file :which-key "Find header/source file")
"f r" '(consult-recent-file :which-key "Find recent file")
"f R" '(rename-file-and-buffer :which-key "Rename file")
"f s" '(basic-save-buffer :which-key "Save file")
"f S" '(write-file :which-key "Save file as...")
"f u" '(dot/sudo-find-file :which-key "Sudo find file")
"f U" '(dot/sudo-this-file :which-key "Sudo this file")
"f e" '(:ignore t :which-key "emacs")
"f e c" '(dot/config-visit :which-key "Config visit")
"f e f" '(dot/find-file-emacsd :which-key "Find emacs file")
"f e r" '(dot/config-reload :which-key "Config reload")
;; Go to
"g" '(:ignore t :which-key "goto")
"g b" '(consult-bookmark :which-key "Go to bookmark")
"g f" '(consult-flycheck :which-key "Go to flycheck error")
"g m" '(consult-mark :which-key "Go to marker")
;; Help
"h" '(:keymap help-map :which-key "help")
"h o" '(:ignore t :which-key "describe-symbol-at-point")
;; Insert
"i" '(:ignore t :which-key "insert")
"i b" '(dot/indent-buffer :which-key "Indent buffer")
"i f" '(fill-region :which-key "Reflow region")
"i F" '(fill-paragraph :which-key "Reflow paragraph")
"i r" '(indent-region :which-key "Indent region")
"i s" '(dot/evil-normal-sort-paragraph :which-key "Sort paragraph")
"i S" '(dot/insert-spaces-until-column :which-key "Insert spaces")
"i y" '(yas-insert-snippet :which-key "Insert yasnippet")
;; Notes
"n" '(:ignore t :which-key "notes")
"n a" '(org-agenda :which-key "Org agenda")
"n r" '(:ignore t :which-key "org-roam")
"n r c" '(org-roam-capture :which-key "Capture")
"n r C" '(org-roam-db-sync :which-key "Build cache")
"n r f" '(org-roam-node-find :which-key "Find node")
"n r g" '(org-roam-graph :which-key "Show graph")
"n r i" '(org-roam-node-insert :which-key "Insert")
"n r I" '(dot/org-roam-node-insert-immediate :which-key "Insert (without capture)")
"n r r" '(org-roam-buffer-toggle :which-key "Toggle buffer")
"n r s" '(org-roam-ui-mode :which-key "Toggle server")
;; Org
"o" '(:ignore t :which-key "org")
"o i" '(dot/org-clock-in :which-key "Clock in")
"o o" '(dot/org-clock-out :which-key "Clock out")
"o s" '(dot/org-switch-task :which-key "Switch task")
;; Project
"p" '(:keymap project-prefix-map :which-key "project")
"p b" '(consult-project-buffer :which-key "project-switch-buffer")
"p f" '(consult-project-extra-find :which-key "project-find-file")
"p g" '(consult-grep :which-key "project-find-regexp")
;; Quit
"q" '(:ignore t :which-key "quit")
"q q" '(save-buffers-kill-terminal :which-key "Quit Emacs")
"q Q" '(save-buffers-kill-emacs :which-key "Quit Emacs (and daemon)")
"q f" '(delete-frame :which-key "Close frame")
"q o" '(delete-other-frames :which-key "Close other frames")
;; Search
"s" '(:ignore t :which-key "search")
"s a" '(avy-goto-char-timer :which-key "Avy goto char")
"s f" '(consult-find :which-key "Search file")
"s l" '(avy-goto-line :which-key "Avy goto line")
"s p" '(consult-grep :which-key "Search project")
"s q" '(evil-ex-nohighlight :which-key "Stop search")
"s s" '(dot/consult-line-no-fuzzy :which-key "Search buffer")
"s S" '(consult-line-multi :which-key "Search all buffers")
;; Tabs / toggle
"t" '(:ignore t :which-key "tabs/toggle")
"t f" '(dot/toggle-fringe :which-key "Toggle fringe")
"t g" '(centaur-tabs-switch-group :which-key "Switch tab group")
"t h" '(centaur-tabs-backward-group :which-key "Tab backward group")
"t j" '(centaur-tabs-select-end-tab :which-key "Tab select first")
"t k" '(centaur-tabs-select-beg-tab :which-key "Tab select last")
"t l" '(centaur-tabs-forward-group :which-key "Tab forward group")
"t n" '(neotree-toggle-in-project-root :which-key "Toggle Neotree")
"t s" '(dot/flyspell-toggle :which-key "Toggle spell checker")
"t w" '(visual-line-mode :which-key "Toggle line wrapping")
;; Update packages
"U" '(elpaca-merge-all :which-key "Update packages")
;; Version control
"v" '(:ignore t :which-key "git")
"v b" '(magit-branch-checkout :which-key "Magit switch branch")
"v B" '(magit-blame-addition :which-key "Magit blame")
"v C" '(magit-clone :which-key "Magit clone")
"v F" '(magit-fetch :which-key "Magit fetch")
"v L" '(magit-log :which-key "Magit log")
"v s" '(magit-show-commit :which-key "Magit show commit")
"v S" '(magit-stage-file :which-key "Stage file")
"v U" '(magit-unstage-file :which-key "Unstage file")
"v v" '(magit-status :which-key "Magit status")
"v V" '(magit-status-here :which-key "Magit status here")
"v c" '(:ignore t :which-key "create")
"v c c" '(magit-commit-create :which-key "Commit")
"v c b" '(magit-branch-and-checkout :which-key "Branch")
"v c r" '(magit-init :which-key "Initialize repo")
"v f" '(:ignore t :which-key "file")
"v f c" '(magit-find-git-config-file :which-key "Find gitconfig file")
"v f D" '(magit-file-delete :which-key "Delete file")
"v f f" '(magit-find-file :which-key "Find file")
"v f R" '(magit-file-rename :which-key "Rename file")
"v l" '(:ignore t :which-key "list")
"v l r" '(magit-list-repositories :which-key "List repositories")
"v l s" '(magit-list-submodules :which-key "List submodules")
"v r" '(dot/magit-select-repo :which-key "Select repo")
;; Window
"w" '(:ignore t :which-key "window")
"w +" '(evil-window-increase-height :which-key "Increase window height")
"w -" '(evil-window-decrease-height :which-key "Decrease window height")
"w <" '(evil-window-decrease-width :which-key "Decrease window width")
"w =" '(balance-windows :which-key "Balance windows")
"w >" '(evil-window-increase-width :which-key "Increase window width")
"w _" '(evil-window-set-height :which-key "Maximize window height")
"w h" '(windmove-left :which-key "Focus window left")
"w j" '(windmove-down :which-key "Focus window down")
"w k" '(windmove-up :which-key "Focus window up")
"w l" '(windmove-right :which-key "Focus window right")
"w o" '(delete-other-windows :which-key "Close other windows")
"w s" '(split-follow-horizontally :which-key "Split horizontal")
"w v" '(split-follow-vertically :which-key "Split vertical")
"w w" '(other-window :which-key "Focus other window")
"w q" '(dot/centaur-tabs-kill-buffer-or-window :which-key "Close window")
"w r" '(winner-redo :which-key "Redo window configuration")
"w u" '(winner-undo :which-key "Undo window configuration")
"w <left>" '(windmove-left :which-key "Focus window left")
"w <right>" '(windmove-right :which-key "Focus window right")
"w <up>" '(windmove-up :which-key "Focus window up")
"w <down>" '(windmove-down :which-key "Focus window down")
)
;; Evaluated keybinds.
(with-eval-after-load 'lsp-mode
(space-leader lsp-mode-map
"l" lsp-command-map
"l = f" '(dot/lsp-format-buffer-or-region :which-key "format buffer or region")
))
(with-eval-after-load 'dap-mode
(space-leader lsp-mode-map
"l d" '(dap-hydra :which-key "DAP hydra")
)))))
;; Source:
;; https://github.com/redguardtoo/emacs.d/blob/master/lisp/init-evil.el#L712
;; https://github.com/suyashbire1/emacs.d/blob/master/init.el
;;; Local Leader
(elpaca-nil (setup general
(:when-loaded
(general-create-definer local-leader
:prefix dot/localleader-key
:non-normal-prefix dot/localleader-alt-key
:global-prefix dot/localleader-alt-key
:states '(normal visual insert motion emacs)
:keymaps 'override ; prevent leader keybindings from ever being overridden
"" '(:ignore t :which-key "<localleader>")
)
(local-leader c++-mode-map
"i" '(:ignore t :which-key "insert")
"i i" '(dot/copy-cpp-function-implementation :which-key "Copy function implementation")
)
(local-leader org-mode-map
"'" '(org-edit-special :which-key "Org edit")
"e" '(org-export-dispatch :which-key "Org export")
"o" '(org-open-at-point :which-key "Org open at point")
"q" '(org-set-tags-command :which-key "Org tags")
"g" '(:ignore t :which-key "goto")
"g o" '(consult-outline :which-key "Org go to heading")
"i" '(:ignore t :which-key "insert")
"i c" '(org-table-insert-column :which-key "Insert table column")
"i h" '(org-table-insert-hline :which-key "Insert table hline")
"i H" '(org-table-hline-and-move :which-key "Insert table hline and move")
"i r" '(org-table-insert-row :which-key "Insert table row")
"i t" '(org-insert-structure-template :which-key "Insert template")
"l" '(:ignore t :which-key "links")
"l i" '(org-id-store-link :which-key "Store ID link")
"l l" '(org-insert-link :which-key "Insert link")
"l s" '(org-store-link :which-key "Store link")
"l S" '(org-insert-last-stored-link :which-key "Insert stored link")
"s" '(:ignore t :which-key "tree/subtree")
"s h" '(org-promote-subtree :which-key "Org promote subtree")
"s j" '(org-metadown :which-key "Org move subtree down")
"s k" '(org-metaup :which-key "Org move subtree up")
"s l" '(org-demote-subtree :which-key "Org demote subtree")
"s <left>" '(org-promote-subtree :which-key "Org promote subtree")
"s <right>" '(org-demote-subtree :which-key "Org demote subtree")
"s <up>" '(org-move-subree-up :which-key "Org move subtree up")
"s <down>" '(org-move-subtree-down :which-key "Org move subtree down")
"t" '(:ignore t :which-key "toggle")
"t t" '(org-todo :which-key "Org todo state")
"t l" '(org-toggle-link-display :which-key "Org link display")
)
(local-leader org-src-mode-map
"k" '(org-edit-src-abort :which-key "Org Edit abort"))
(local-leader elfeed-search-mode-map
"g" '(elfeed-search-update--force :which-key "Elfeed refresh buffer")
"G" '(elfeed-search-fetch :which-key "Elfeed update feeds")
)
(local-leader elfeed-show-mode-map
"g" '(elfeed-show-refresh :which-key "Elfeed refresh buffer")
))))
;; c-fill-paragraph Reflow comment
;; https://youtu.be/hbmV1bnQ-i0?t=1910
(provide 'dot-keybinds)
;;; dot-keybinds.el ends here
+148
View File
@@ -0,0 +1,148 @@
;;; dot-mail.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Mail configuration.
;;; Code:
;; -----------------------------------------
;; Mail Functions
(with-eval-after-load 'auth-source
(defun dot/mail-auth-get-field (host prop)
"Find PROP in `auth-sources' for HOST entry."
(when-let ((source (auth-source-search :max 1 :host host)))
(if (eq prop :secret)
(funcall (plist-get (car source) prop))
(plist-get (flatten-list source) prop)))))
;; Mail in Emacs with mu4e
;; Useful mu4e manual pages:
;; Key bindings
;; [https://www.djcbsoftware.nl/code/mu/mu4e/MSGV-Keybindings.html#MSGV-Keybindings]
(elpaca-nil (setup mu4e ; loaded from AUR package
(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
(:autoload mu4e mu4e-update-index)
(:when-loaded
(add-to-list 'auth-sources (expand-file-name "authinfo.gpg" dot-etc-dir))
(setq user-full-name (dot/mail-auth-get-field "fullname" :user))
(setq user-mail-address (dot/mail-auth-get-field "info" :user))
(setq mail-user-agent 'mu4e-user-agent)
;; Headers
(setq mu4e-headers-date-format "%d-%m-%Y")
(setq mu4e-headers-time-format "%I:%M %p")
(setq mu4e-headers-long-date-format "%d-%m-%Y %I:%M:%S %p")
;; Syncing
(setq mu4e-get-mail-command (concat "mbsync -a -c " (expand-file-name "isync/mbsyncrc" (getenv "XDG_CONFIG_HOME"))))
(setq mu4e-update-interval (* 15 60)) ; 15 minutes
(setq mu4e-maildir "~/mail")
(setq mu4e-attachment-dir "~/downloads")
;; Avoid mail syncing issues when using mbsync
(setq mu4e-change-filenames-when-moving t)
;; Misc
(setq mu4e-completing-read-function 'completing-read)
(setq mu4e-confirm-quit nil)
(setq mu4e-display-update-status-in-modeline t)
(setq mu4e-hide-index-messages t)
(setq mu4e-sent-messages-behavior 'sent)
(setq mu4e-view-show-addresses t)
(setq mu4e-view-show-images nil)
;; Compose
(setq mu4e-compose-context-policy 'ask)
(setq mu4e-compose-dont-reply-to-self t)
(setq mu4e-compose-signature (concat (dot/mail-auth-get-field "fullname" :user) "\nriyyi.com\n"))
(setq mu4e-compose-signature-auto-include t)
;; Contexts
(setq mu4e-context-policy 'pick-first)
(setq mu4e-contexts
`(,(make-mu4e-context
:name "info"
:match-func (lambda (msg)
(when msg
(string= (mu4e-message-field msg :maildir) "/info")))
:vars `((user-mail-address . ,(dot/mail-auth-get-field "info" :user))
(mu4e-drafts-folder . "/info/Drafts")
(mu4e-refile-folder . "/info/Archive")
(mu4e-sent-folder . "/info/Sent")
(mu4e-trash-folder . "/info/Trash")))
,(make-mu4e-context
:name "private"
:match-func (lambda (msg)
(when msg
(string= (mu4e-message-field msg :maildir) "/private")))
:vars `((user-mail-address . ,(dot/mail-auth-get-field "private" :user))
(mu4e-drafts-folder . "/private/Drafts")
(mu4e-refile-folder . "/private/Archive")
(mu4e-sent-folder . "/private/Sent")
(mu4e-trash-folder . "/private/Trash")))
))
;; Do not mark messages as IMAP-deleted, just move them to the Trash directory!
;; https://github.com/djcb/mu/issues/1136#issuecomment-486177435
(setf (alist-get 'trash mu4e-marks)
(list :char '("d" . "")
:prompt "dtrash"
:dyn-target (lambda (target msg)
(mu4e-get-trash-folder msg))
:action (lambda (docid msg target)
(mu4e~proc-move docid (mu4e~mark-check-target target) "-N"))))
;; Start mu4e in the background for mail syncing
(mu4e t))))
;; Use mu4e-alert to show new e-mail notifications.
;; https://github.com/iqbalansari/mu4e-alert
(elpaca-setup mu4e-alert
(:defer 20)
(:when-loaded
(setq mu4e-alert-interesting-mail-query "(maildir:/info/Inbox OR maildir:/private/Inbox) AND flag:unread AND NOT flag:trashed")
(setq mu4e-alert-notify-repeated-mails nil)
(mu4e-alert-set-default-style 'libnotify)
(mu4e-alert-enable-notifications)))
;; Sending mail.
(elpaca-nil (setup smtpmail ; built-in
(setq smtpmail-default-smtp-server "mail.riyyi.com")
(:load-after mu4e)
(:when-loaded
(setq smtpmail-smtp-server "mail.riyyi.com")
(setq smtpmail-local-domain "riyyi.com")
(setq smtpmail-smtp-service 587)
(setq smtpmail-stream-type 'starttls)
(setq smtpmail-queue-mail nil))))
(elpaca-nil (setup sendmail ; built-in
(:load-after mu4e)
(:when-loaded (setq send-mail-function 'smtpmail-send-it))))
(elpaca-nil (setup message ; built-in
(:load-after mu4e)
(:when-loaded
(setq message-kill-buffer-on-exit t)
(setq message-send-mail-function 'smtpmail-send-it))))
;; Sources:
;; - https://rakhim.org/fastmail-setup-with-emacs-mu4e-and-mbsync-on-macos/
;; - https://wiki.archlinux.org/title/Isync
;; - https://man.archlinux.org/man/community/isync/mbsync.1.en
;; - https://gitlab.com/protesilaos/dotfiles/-/blob/master/mbsync/.mbsyncrc
;; - https://gitlab.com/protesilaos/dotfiles/-/blob/master/emacs/.emacs.d/prot-lisp/prot-mail.el
;; - https://gitlab.com/protesilaos/dotfiles/-/blob/master/emacs/.emacs.d/prot-lisp/prot-mu4e-deprecated-conf.el
;; - https://github.com/daviwil/dotfiles/blob/master/Mail.org
(provide 'dot-mail)
;;; dot-mail.el ends here
+351
View File
@@ -0,0 +1,351 @@
;;; dot-org-mode.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Load org-mode modules.
;;; Code:
;; -----------------------------------------
;; LaTeX Configuration
(elpaca-nil (setup tex-mode ; built-in
(:when-loaded
(defun dot/tex-mode-init () ""
(setq indent-tabs-mode t)
(setq tab-width 4)
(setq tex-indent-basic 4))
(:hook dot/tex-mode-init)
(with-eval-after-load 'project
(defun compile-latex ()
"Compile LaTeX project."
(interactive)
(let ((default-directory (dot/find-project-root)))
(dot/project-save-project-buffers)
(shell-command "make")))))))
;; -----------------------------------------
;; Org Configuration
;; Base Org.
(elpaca-nil (setup org ; built-in
(setq org-directory (expand-file-name "documents/org" (getenv "HOME")))
(setq org-default-notes-file (expand-file-name "notes.org" org-directory))
(:with-mode before-save
(:hook dot/org-set-last-modified))
(:when-loaded
(setq org-adapt-indentation nil)
(setq org-ellipsis "")
(setq org-image-actual-width nil)
(setq org-startup-folded nil)
;; Enable structured template completion
(add-to-list 'org-modules 'org-tempo t)
(add-to-list 'org-structure-template-alist
'("el" . "src emacs-lisp"))
(defun dot/org-find-or-create-heading (heading level)
"Find or create heading"
(if (re-search-forward (format org-complex-heading-regexp-format
(regexp-quote heading))
nil t)
(beginning-of-line)
(goto-char (point-max))
(unless (bolp) (insert "\n"))
(insert (concat (make-string level ?*) " ") heading "\n")
(beginning-of-line 0)))
(defun dot/org-find-month-week-day ()
"Find or create the journal tree for the current week under current month"
(unless (derived-mode-p 'org-mode)
(error "Target buffer \"%s\" for dot/find-org-week should be in Org mode"
(current-buffer)))
(org-capture-put-target-region-and-position)
(widen)
(goto-char (point-min))
(dot/org-find-or-create-heading "Worklog" 1)
(org-narrow-to-subtree)
(dot/org-find-or-create-heading (format-time-string "%B") 2) ;; month
(org-narrow-to-subtree)
(dot/org-find-or-create-heading (format-time-string "Week %W") 3)
(org-narrow-to-subtree)
(dot/org-find-or-create-heading (format-time-string "%A") 4) ;; day
(org-end-of-subtree))
;; Capture templates
(setq org-capture-templates
`(("i" "Clock in" plain (file+function ,(expand-file-name "worklog.org" org-directory) dot/org-find-month-week-day)
"| %<%Y-%m-%d> | IN | %<%H:%M> | %^{Location|Office|Home|Office|Visit} |\n===================================%?"
:immediate-finish t)
("o" "Clock out" plain (file+function ,(expand-file-name "worklog.org" org-directory) dot/org-find-month-week-day)
"===================================\n| %<%Y-%m-%d> | OUT | %<%H:%M> |%?"
:immediate-finish t)
("s" "Switch task" plain (file+function ,(expand-file-name "worklog.org" org-directory) dot/org-find-month-week-day)
"| %<%Y-%m-%d> | %<%H:%M> | %^{Item ID} | X | %^{Description|-} |%?"
:immediate-finish t)))
;; Keybind functions
(defun dot/org-clock-in () (interactive) (org-capture nil "i"))
(defun dot/org-clock-out () (interactive) (org-capture nil "o"))
(defun dot/org-switch-task () (interactive) (org-capture nil "s"))
(with-eval-after-load 'evil-commands
(defun dot/org-ret-at-point ()
"Org return key at point.
If point is on:
checkbox -- toggle it
link -- follow it
table -- go to next row
otherwise -- run the default (evil-ret) expression"
(interactive)
(let ((type (org-element-type (org-element-context))))
(pcase type
('link (if org-return-follows-link (org-open-at-point) (evil-ret)))
((guard (org-at-item-checkbox-p)) (org-toggle-checkbox))
('table-cell (org-table-next-row))
(_ (evil-ret))
))))
(defun dot/org-find-file-property (property &optional anywhere)
"Return the position of the file PROPERTY if it exists.
When ANYWHERE is non-nil, search beyond the preamble."
(save-excursion
(goto-char (point-min))
(let ((first-heading
(save-excursion
(re-search-forward org-outline-regexp-bol nil t))))
(when (re-search-forward (format "^#\\+%s:" property)
(if anywhere nil first-heading)
t)
(point)))))
(defun dot/org-set-file-property (property value)
"Set the file PROPERTY in the preamble."
(when-let ((pos (dot/org-find-file-property property)))
(save-excursion
(goto-char pos)
(if (looking-at-p " ")
(forward-char)
(insert " "))
(delete-region (point) (line-end-position))
(insert value))))
(defun dot/org-set-last-modified ()
"Update the LAST_MODIFIED file property in the preamble."
(when (derived-mode-p 'org-mode)
(dot/org-set-file-property "LAST_MODIFIED"
(format-time-string "[%Y-%m-%d %a %H:%M]")))))))
;; Org agenda.
(elpaca-nil (setup org-agenda ; built-in
(:load-after evil org)
(:when-loaded
(setq org-agenda-files `(,org-directory ,user-emacs-directory))
(setq org-agenda-span 14)
(setq org-agenda-window-setup 'current-window)
(evil-set-initial-state 'org-agenda-mode 'motion))))
;; Org capture.
(elpaca-nil (setup org-capture ; built-in
;; Org-capture in new tab, rather than split window
(:hook delete-other-windows)))
;; Org keys.
(elpaca-nil (setup org-keys ; built-in
(:when-loaded
(setq org-return-follows-link t))))
;; Org links.
(elpaca-nil (setup ol ; built-in
(:when-loaded
;; Do not open links to .org files in a split window
(add-to-list 'org-link-frame-setup '(file . find-file)))))
;; Org source code blocks.
(elpaca-nil (setup org-src ; built-in
(:when-loaded
(setq org-edit-src-content-indentation 0)
(setq org-src-fontify-natively t)
(setq org-src-preserve-indentation t)
(setq org-src-tab-acts-natively t)
(setq org-src-window-setup 'current-window))))
;; Org exporter.
(elpaca-nil (setup ox ; built-in
(:when-loaded
(setq org-export-coding-system 'utf-8-unix))))
;; Org latex exporter.
(elpaca-nil (setup ox-latex ; built-in
(:when-loaded
;; Define how minted (highlighted src code) is added to src code blocks
;; Requires packages: texlive-bin, texlive-latexextra and python-pygments
(setq org-latex-listings 'minted)
(setq org-latex-minted-options '(("frame" "lines") ("linenos=true")))
;; Set 'Table of Contents' layout
(setq org-latex-toc-command "\\newpage \\tableofcontents \\newpage")
;; Add minted package to every LaTeX header
(add-to-list 'org-latex-packages-alist '("" "minted"))
;; Add -shell-escape so pdflatex exports minted correctly
(setcar org-latex-pdf-process (replace-regexp-in-string
"-%latex -interaction"
"-%latex -shell-escape -interaction"
(car org-latex-pdf-process))))))
;;; Org Bullets
(elpaca-setup org-bullets
(:hook-into org-mode))
;;; Org Export Packages
;; HTML exporter.
(elpaca-setup htmlize
(:when-loaded (setq org-export-html-postamble nil)))
;;org-export-html-postamble-format ; TODO
;; GitHub flavored Markdown exporter.
(elpaca-setup ox-gfm)
;;; Org Roam
(elpaca-setup emacsql-sqlite-builtin)
(elpaca-setup org-roam
(:autoload org-roam-node-find) ;; TODO, is this enough?
(setq org-roam-v2-ack t)
(setq org-roam-database-connector 'sqlite-builtin)
(:when-loaded
(setq org-roam-db-location (expand-file-name "org-roam.db" dot-cache-dir))
(setq org-roam-directory org-directory)
;; Exclude Syncthing backup directory
(setq org-roam-file-exclude-regexp "\\.stversions")
(setq org-roam-verbose nil)
(setq org-roam-capture-templates
'(("d" "default" plain
"%?"
:target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n#+LAST_MODIFIED:\n#+FILETAGS: %^{File tags||:structure:}\n")
:unnarrowed t)))
(defun dot/org-roam-node-insert-immediate (arg &rest args)
(interactive "P")
(let ((args (push arg args))
(org-roam-capture-templates (list (append (car org-roam-capture-templates)
'(:immediate-finish t)))))
(apply #'org-roam-node-insert args)))
(cl-defmethod org-roam-node-slug ((node org-roam-node))
"Return the slug of NODE, strip out common words."
(let* ((title (org-roam-node-title node))
(words (split-string title " "))
(common-words '("a" "an" "and" "as" "at" "by" "is" "it" "of" "the" "to"))
(title (string-join (seq-remove (lambda (element) (member element common-words)) words) "_"))
(pairs '(("c\\+\\+" . "cpp") ;; convert c++ -> cpp
("c#" . "cs") ;; convert c# -> cs
("[^[:alnum:][:digit:]]" . "_") ;; convert anything not alphanumeric
("__*" . "_") ;; remove sequential underscores
("^_" . "") ;; remove starting underscore
("_$" . "")))) ;; remove ending underscore
(cl-flet ((cl-replace (title pair)
(replace-regexp-in-string (car pair) (cdr pair) title)))
(downcase (-reduce-from #'cl-replace title pairs)))))
;; Right-align org-roam-node-tags in the completion menu without a length limit
;; Source: https://github.com/org-roam/org-roam/issues/1775#issue-971157225
(setq org-roam-node-display-template "${title} ${tags:0}")
(setq org-roam-node-annotation-function #'dot/org-roam-annotate-tag)
(defun dot/org-roam-annotate-tag (node)
(let ((tags (mapconcat 'identity (org-roam-node-tags node) " #")))
(unless (string-empty-p tags)
(concat
(propertize " " 'display `(space :align-to (- right ,(+ 2 (length tags)))))
(propertize (concat "#" tags) 'face 'bold)))))
(org-roam-setup)))
;; Enable https://www.orgroam.com/manual.html#org_002droam_002dprotocol, needed to process org-protocol:// links
(elpaca-nil (setup org-roam-protocol ; org-roam-protocol.el is part of org-roam
(:load-after org-roam)
(:when-loaded
;; Templates used when creating a new file from a bookmark
(setq org-roam-capture-ref-templates
'(("r" "ref" plain
"%?"
:target (file+head "${slug}.org" "#+TITLE: ${title}\n \n${body}")
:unnarrowed t))))))
;; The roam-ref protocol bookmarks to add:
;; javascript:location.href =
;; 'org-protocol://roam-ref?template=r'
;; + '&ref=' + encodeURIComponent(location.href)
;; + '&title=' + encodeURIComponent(document.title)
;; + '&body=' + encodeURIComponent(window.getSelection())
;; Setup org-roam-ui, runs at http://127.0.0.1:35901.
(elpaca-setup org-roam-ui
(:load-after org-roam)
(:when-loaded
(setq org-roam-ui-follow t)
(setq org-roam-ui-open-on-start t)
(setq org-roam-ui-sync-theme nil) ;; FIXME: Make this work (org-roam-ui-get-theme)
(setq org-roam-ui-update-on-save t)))
;; Easily searchable .org files via Deft.
(elpaca-setup deft
(:hook dot/hook-disable-line-numbers)
(:when-loaded
(setq deft-auto-save-interval 0)
(setq deft-default-extension "org")
(setq deft-directory org-directory)
(setq deft-file-naming-rules '((noslash . "-")
(nospace . "-")
(case-fn . downcase)))
(setq deft-new-file-format "%Y%m%d%H%M%S-deft")
(setq deft-recursive t)
;; Exclude Syncthing backup directory
(setq deft-recursive-ignore-dir-regexp (concat "\\.stversions\\|" deft-recursive-ignore-dir-regexp))
;; Remove file variable -*- .. -*- and Org Mode :PROPERTIES: lines
(setq deft-strip-summary-regexp (concat "\\(^.*-\\*-.+-\\*-$\\|^:[[:alpha:]_]+:.*$\\)\\|" deft-strip-summary-regexp))
(setq deft-use-filename-as-title nil)
(setq deft-use-filter-string-for-filename t)
(add-to-list 'deft-extensions "tex")
;; Start filtering immediately
(with-eval-after-load 'evil
(evil-set-initial-state 'deft-mode 'insert))
(defun deft-parse-title (file contents)
"Parse the given FILE and CONTENTS and determine the title."
(if (string-match "#\\+\\(TITLE\\|title\\):\s*\\(.*\\)$" contents)
(match-string 2 contents)
(deft-base-filename file)))))
;;; Org "Table of Contents"
;; Generate table of contents without exporting.
(elpaca-setup toc-org
(:hook-into org-mode))
(provide 'dot-org-mode)
;;; dot-org-mode.el ends here
+29
View File
@@ -0,0 +1,29 @@
;;; dot-rss.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; RSS.
;;; Code:
;; -----------------------------------------
(elpaca-setup elfeed
(:autoload elfeed)
(:with-mode dot/hook-disable-line-numbers
(:hook-into elfeed-search-mode)
(:hook-into elfeed-show-mode))
(:when-loaded
(setq elfeed-db-directory (expand-file-name "elfeed" dot-cache-dir))
(setq elfeed-enclosure-default-dir "~/downloads/")
(setq elfeed-search-filter "@6-months-ago +unread")
(setq elfeed-search-clipboard-type 'CLIPBOARD)
(setq elfeed-search-title-max-width 100)
(setq elfeed-search-title-min-width 30)
(setq elfeed-search-trailing-width 55)
(setq elfeed-show-unique-buffers t)
(load (expand-file-name "elfeed-feeds" dot-etc-dir))))
(provide 'dot-rss)
;;; dot-rss.el ends here
+83
View File
@@ -0,0 +1,83 @@
;;; dot-selection.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Incremental narrowing in Emacs.
;;; Code:
(elpaca-setup prescient
(:require prescient)
(:when-loaded
(setq completion-styles '(prescient basic))
(setq prescient-filter-method '(literal regexp fuzzy))
(setq prescient-save-file (expand-file-name "prescient-save.el" dot-cache-dir))
(prescient-persist-mode)))
(elpaca-setup (vertico :files (:defaults "extensions/*"))
(:load-after prescient)
(:when-loaded
(setq vertico-previous-directory nil)
(defun dot/vertico-backspace ()
"In Vertico file completion, backward kill sexp, delete char otherwise."
(interactive)
(if (not (and (active-minibuffer-window)
minibuffer-completing-file-name))
(backward-delete-char 1)
(setq vertico-previous-directory
(concat (file-name-nondirectory (directory-file-name (minibuffer-contents)))
"/"))
(vertico-directory-delete-word 1)))
(vertico-mode))
(defun dot/vertico-dired-goto-last-visited (&rest _)
"Go to directory candidate that was last visited."
(when minibuffer-completing-file-name
(setq vertico--index (or (seq-position vertico--candidates vertico-previous-directory)
(when (string= vertico-previous-directory "~/")
(seq-position vertico--candidates (concat user-login-name "/")))
(if (= vertico--total 0) -1 0)))
(setq vertico-previous-directory nil)))
(advice-add 'vertico--update-candidates :after #'dot/vertico-dired-goto-last-visited))
(elpaca-nil (setup vertico-mouse ; vertico-mouse.el is part of vertico
(:load-after vertico)
(:when-loaded (vertico-mouse-mode))))
(elpaca-setup vertico-prescient
(:load-after vertico prescient)
(:when-loaded
(vertico-prescient-mode)))
(elpaca-setup marginalia
(:load-after vertico)
(:when-loaded
(setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light))
(marginalia-mode)))
(elpaca-setup consult
(:load-after vertico)
(:when-loaded
(setq consult-narrow-key (kbd "?"))
(defun dot/consult-line-no-fuzzy ()
"Call consult-line without fuzzy matching."
(interactive)
(let ((prescient-filter-method (delete 'fuzzy (copy-tree prescient-filter-method))))
(consult-line)))
(consult-customize
dot/consult-line-no-fuzzy :prompt "Search: "
consult-line-multi :prompt "Search: " :initial nil)))
(elpaca-setup consult-flycheck
(:load-after consult flycheck))
(elpaca-setup consult-project-extra
(:load-after consult project)
(:when-loaded (setq project-switch-commands 'consult-project-extra-find)))
(provide 'dot-selection)
;;; dot-selection.el ends here
+107
View File
@@ -0,0 +1,107 @@
;;; dot-setup.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Configure SetupEl and keywords.
;;; Code:
;; -----------------------------------------
;; SetupEl
;; Install and load SetupEl immediately
(elpaca setup (require 'setup)
;;; Configure custom macros
(setup-define :load-after
(lambda (&rest features)
(let ((body `(require ',(setup-get 'feature))))
(dolist (feature (nreverse features))
(setq body `(with-eval-after-load ',feature ,body)))
body))
:documentation "Load the current feature after FEATURES.")
(setup-define :autoload
(lambda (func)
(let ((fn (if (memq (car-safe func) '(quote function))
(cadr func)
func)))
`(unless (fboundp (quote ,fn))
(autoload (function ,fn) ,(symbol-name (setup-get 'feature)) nil t))))
:documentation "Autoload COMMAND if not already bound."
:repeatable t
:signature '(FUNC ...))
(setup-define :defer
(lambda (secs)
`(if (numberp ,secs)
(run-with-idle-timer ,secs nil (lambda () (require ',(setup-get 'feature))))
,(setup-quit)))
:documentation "Defer loading of feature for SECS idle seconds.")
;;; Configure custom macros for evil bindings
(setup-define :with-evil-state
(lambda (states &rest body)
(setup-bind body (states states)))
:documentation "Change the STATE that BODY will bind to."
:indent 1)
(setup-define :evil-bind-impl
(lambda (key command)
`(evil-define-key* ',(setup-get 'states) ,(setup-get 'map) ,key ,command))
:documentation "Bind KEY to COMMAND in the current map."
:after-loaded t
:ensure '(kbd func)
:repeatable t)
(setup-define :evil-bind
(lambda (states &rest keybinds)
`(with-eval-after-load 'evil
(:with-evil-state ,states (:evil-bind-impl ,@keybinds))))
:documentation "Bind KEYBINDS in STATES in the current map.")
(setup-define :evil-bind-into
(lambda (states feature-or-map &rest keybinds)
(if (string-match-p "-map\\'" (symbol-name feature-or-map))
`(:with-map ,feature-or-map (:evil-bind ,states ,@keybinds))
`(:with-feature ,feature-or-map (:evil-bind ,states ,@keybinds))))
:documentation "Bind KEYBINDS in STATE into the map of FEATURE-OR-MAP.
The arguments REST are handled as by `:evil-bind'."
:indent 1)
)
;;; Add setup.el macro
;;;###autoload
(defmacro elpaca-setup (order &rest body)
"Execute BODY in `setup' declaration after ORDER is finished.
If the :disabled keyword is present in body, the package is completely ignored.
This happens regardless of the value associated with :disabled.
The expansion is a string indicating the package has been disabled."
(declare (indent 1))
(if (memq :disabled body)
(format "%S :disabled by elpaca-setup" order)
(let ((o order))
(when-let ((ensure (cl-position :ensure body)))
(setq o (if (null (nth (1+ ensure) body)) nil order)
body (append (cl-subseq body 0 ensure)
(cl-subseq body (+ ensure 2)))))
`(elpaca ,o (setup
,(if-let (((memq (car-safe order) '(quote \`)))
(feature (flatten-tree order)))
(cadr feature)
(elpaca--first order))
,@body)))))
;; Startup benchmark
(elpaca-setup benchmark-init
(:require benchmark-init)
(:when-loaded
(benchmark-init/activate)
(add-hook 'elpaca-after-init-hook #'benchmark-init/deactivate)))
(provide 'dot-setup-el)
;;; dot-setup.el ends here
+238
View File
@@ -0,0 +1,238 @@
;;; dot-ui.el --- -*- lexical-binding: t; -*-
;;; Commentary:
;; Setup UI packages.
;;; Code:
;; -----------------------------------------
;; All the icons
(elpaca-setup all-the-icons
(:require all-the-icons)
(:when-loaded
;; Install all-the-icons if font files are not found
(dot/run-after-new-frame
(unless (find-font (font-spec :name "all-the-icons"))
(all-the-icons-install-fonts t)))))
(elpaca-setup all-the-icons-dired
(:hook-into dired-mode)
(:load-after all-the-icons)
(:when-loaded (setq all-the-icons-dired-monochrome nil)))
;; -----------------------------------------
;; Centaur tabs
;; Places buffers as tabs in a bar at the top of the frame.
(elpaca-setup centaur-tabs
(:load-after all-the-icons)
(:with-mode
(eshell-mode
help-mode
helpful-mode
mu4e-view-mode
neotree-mode
shell-mode)
(:hook centaur-tabs-local-mode))
(:when-loaded
(setq centaur-tabs-enable-ido-completion nil)
(setq centaur-tabs-height (if dot/hidpi 38 18))
(setq centaur-tabs-modified-marker "")
(setq centaur-tabs-set-icons t)
(setq centaur-tabs-set-modified-marker t)
(setq centaur-tabs-style "slant")
(setq centaur-tabs-project-buffer-group-calc nil)
(defun centaur-tabs-buffer-groups ()
"Organize tabs into groups by buffer."
(unless centaur-tabs-project-buffer-group-calc
(set (make-local-variable 'centaur-tabs-project-buffer-group-calc)
(list
(cond
((string-equal "*" (substring (buffer-name) 0 1)) "Emacs")
((or (memq major-mode '(magit-process-mode
magit-status-mode
magit-diff-mode
magit-log-mode
magit-file-mode
magit-blob-mode
magit-blame-mode))
(string= (buffer-name) "COMMIT_EDITMSG")) "Magit")
((project-current) (dot/project-project-name))
((memq major-mode '(org-mode
emacs-lisp-mode)) "Org Mode")
((derived-mode-p 'dired-mode) "Dired")
((derived-mode-p 'prog-mode
'text-mode) "Editing")
(t "Other")))))
(symbol-value 'centaur-tabs-project-buffer-group-calc))
(defun centaur-tabs-hide-tab (buffer)
"Hide from the tab bar by BUFFER name."
(let ((name (format "%s" buffer)))
(or
;; Current window is dedicated window
(window-dedicated-p (selected-window))
;; Buffer name matches below blacklist
(string-match-p "^ ?\\*.*\\*" name))))
(defun dot/centaur-tabs-is-buffer-unimportant (buffer)
"Return t if BUFFER is unimportant and can be killed without caution."
(let ((name (format "%s" buffer)))
(cond
((centaur-tabs-hide-tab name) t)
((string-match-p "^magit\\(-[a-z]+\\)*: .*" name) t)
(t nil))))
(defun dot/centaur-tabs-buffer-cleanup ()
"Clean up all the hidden buffers."
(interactive)
(dolist (buffer (buffer-list))
(when (dot/centaur-tabs-is-buffer-unimportant buffer)
(kill-buffer buffer)))
(princ "Cleaned buffers"))
(defun dot/centaur-tabs-kill-buffer-or-window ()
"Delete window of the current buffer, also kill if the buffer is hidden."
(interactive)
(if (dot/centaur-tabs-is-buffer-unimportant (buffer-name))
(kill-buffer-and-window)
(delete-window)))
(centaur-tabs-headline-match)
(centaur-tabs-mode)))
;; -----------------------------------------
;; Dashboard
(elpaca-setup page-break-lines
(:require page-break-lines))
(elpaca-setup dashboard
(:require dashboard)
(:hook dot/hook-disable-line-numbers)
(:when-loaded
(setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*") (dashboard-refresh-buffer)))
(setq dashboard-banner-logo-title "GNU Emacs master race!")
(setq dashboard-center-content t)
(setq dashboard-page-separator "\n\f\n")
(setq dashboard-projects-backend 'project-el)
(setq dashboard-set-file-icons t)
(setq dashboard-set-footer nil)
(setq dashboard-set-heading-icons t)
(setq dashboard-show-shortcuts t)
(setq dashboard-startup-banner 'logo)
(setq dashboard-items '((projects . 10)
(bookmarks . 5)
(recents . 5)))
;; Fix keybinds..
(defun dot/dashboard-goto-bookmarks ()
"Move point to bookmarks."
(interactive)
(funcall (local-key-binding "m")))
(defun dot/dashboard-goto-projects ()
"Move point to projects."
(interactive)
(funcall (local-key-binding "p")))
(defun dot/dashboard-goto-recent-files ()
"Move point to recent files."
(interactive)
(funcall (local-key-binding "r")))
(dashboard-setup-startup-hook)
))
;; -----------------------------------------
;; Helpful
;; A better *help* buffer.
(elpaca-setup helpful
(:require helpful)
(:hook dot/hook-disable-line-numbers))
;; -----------------------------------------
;; Neotree
;; Provides Emacs with a file tree.
(elpaca-setup neotree
(:autoload neotree-toggle)
(:hook dot/hook-disable-line-numbers)
(:hook hl-line-mode)
;; This needs to be in init to actually start loading the package
(with-eval-after-load 'project
(defun neotree-toggle-in-project-root ()
"Toggle Neotree in project root."
(interactive)
(let ((default-directory (dot/find-project-root)))
(call-interactively #'neotree-toggle))))
(:when-loaded
(setq neo-theme (if (display-graphic-p) 'icons 'arrow))
(setq neo-autorefresh nil)
(setq neo-mode-line-type 'none)
(setq neo-show-hidden-files t)
(setq neo-vc-integration '(face))))
;; -----------------------------------------
;; Telephone Line
;; Emacs mode line replacement.
(elpaca-setup telephone-line
(:require telephone-line)
(:when-loaded
(setq telephone-line-height (if dot/hidpi 30 15))
(setq telephone-line-lhs
'((evil . (telephone-line-evil-tag-segment))
(accent . (telephone-line-erc-modified-channels-segment
telephone-line-process-segment
telephone-line-buffer-segment))
(nil . (telephone-line-project-segment))))
(telephone-line-mode)))
;; -----------------------------------------
;; Theme
(elpaca-setup hybrid-reverse-theme
(:require hybrid-reverse-theme)
(:when-loaded
(dot/run-after-new-frame
(load-theme 'hybrid-reverse t))))
;; -----------------------------------------
;; Which-key
;; Popup that displays available key bindings.
(elpaca-setup which-key
(:hook-into elpaca-after-init)
(:when-loaded
(setq which-key-add-column-padding 1)
(setq which-key-max-display-columns nil)
(setq which-key-min-display-lines 6)
(setq which-key-sort-order #'dot/which-key-prefix-then-key-order-alpha)
(setq which-key-sort-uppercase-first nil)
(defun dot/which-key-prefix-then-key-order-alpha (acons bcons)
"Order by prefix, then lexicographical."
(let ((apref? (which-key--group-p (cdr acons)))
(bpref? (which-key--group-p (cdr bcons))))
(if (not (eq apref? bpref?))
(and (not apref?) bpref?)
(which-key-key-order-alpha acons bcons))))))
(provide 'dot-ui)
;;; dot-ui.el ends here
+8
View File
@@ -7,3 +7,11 @@
[user] [user]
name = Riyyi name = Riyyi
email = riyyi3@gmail.com email = riyyi3@gmail.com
[diff]
tool = nvimdiff
[merge]
tool = nvimdiff
conflictstyle = diff3
[mergetool]
prompt = false
keepBackup = false
+1 -1
View File
@@ -1,4 +1,4 @@
pinentry-program /usr/bin/pinentry pinentry-program /usr/bin/pinentry-gtk
default-cache-ttl 900 default-cache-ttl 900
max-cache-ttl 7200 max-cache-ttl 7200
+3 -1
View File
@@ -1,10 +1,12 @@
[dmenu] [dmenu]
dmenu_command = /usr/bin/rofi -dmenu -i dmenu_command = /usr/bin/rofi -dmenu -i
pinentry = /usr/bin/pinentry pinentry = /usr/bin/pinentry-gtk
[database] [database]
database_1 = ~/documents/password.kdbx database_1 = ~/documents/password.kdbx
keyfile_1 =
pw_cache_period_min = 60 pw_cache_period_min = 60
autotype_default = {USERNAME}{TAB}{PASSWORD}{ENTER}
gui_editor = emacsclient gui_editor = emacsclient
editor = vim editor = vim
+2
View File
@@ -0,0 +1,2 @@
-- when opening a .lua file, this file gets executed
vim.opt.expandtab = false
+9
View File
@@ -0,0 +1,9 @@
require("core")
require("packages").setup({
require("ui"),
require("selection"),
require("editor"),
require("development"),
require("git"),
})
require("keybinds").setup()
+42
View File
@@ -0,0 +1,42 @@
{
"Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" },
"LuaSnip": { "branch": "master", "commit": "33b06d72d220aa56a7ce80a0dd6f06c70cd82b9d" },
"auto-save.nvim": { "branch": "main", "commit": "b58948445c43e6903987a9bb97c82e66fdcc0786" },
"cmp-buffer": { "branch": "main", "commit": "3022dbc9166796b644a841a02de8dd1cc1d311fa" },
"cmp-nvim-lsp": { "branch": "main", "commit": "99290b3ec1322070bcfb9e846450a46f6efa50f0" },
"cmp-nvim-lua": { "branch": "main", "commit": "f12408bdb54c39c23e67cab726264c10db33ada8" },
"cmp-path": { "branch": "main", "commit": "91ff86cd9c29299a64f968ebb45846c485725f23" },
"cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" },
"dashboard-nvim": { "branch": "master", "commit": "ae309606940d26d8c9df8b048a6e136b6bbec478" },
"diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" },
"friendly-snippets": { "branch": "main", "commit": "efff286dd74c22f731cdec26a70b46e5b203c619" },
"gitsigns.nvim": { "branch": "main", "commit": "5f808b5e4fef30bd8aca1b803b4e555da07fc412" },
"lazy.nvim": { "branch": "main", "commit": "7c493713bc2cb392706866eeba53aaef6c8e9fc6" },
"lspkind.nvim": { "branch": "master", "commit": "d79a1c3299ad0ef94e255d045bed9fa26025dab6" },
"lspsaga.nvim": { "branch": "main", "commit": "2710a0ad97b5aaff404cd4756c296df454b3f726" },
"lualine.nvim": { "branch": "master", "commit": "2a5bae925481f999263d6f5ed8361baef8df4f83" },
"neodev.nvim": { "branch": "main", "commit": "46aa467dca16cf3dfe27098042402066d2ae242d" },
"neogit": { "branch": "master", "commit": "40038473707c54a846bd11ecaf5933dd45858972" },
"nvim-base16": { "branch": "master", "commit": "6ac181b5733518040a33017dde654059cd771b7c" },
"nvim-cmp": { "branch": "main", "commit": "3403e2e9391ed0a28c3afddd8612701b647c8e26" },
"nvim-colorizer.lua": { "branch": "master", "commit": "a065833f35a3a7cc3ef137ac88b5381da2ba302e" },
"nvim-lspconfig": { "branch": "master", "commit": "5a812abc65d529ea7673059a348814c21d7f87ff" },
"nvim-treesitter": { "branch": "master", "commit": "337b503688eccb3046547661e4c738e674548fcf" },
"nvim-treesitter-textobjects": { "branch": "master", "commit": "ad8f0a472148c3e0ae9851e26a722ee4e29b1595" },
"nvim-web-devicons": { "branch": "master", "commit": "e73d2774d12d0ecf9e05578d692ba1ea50508cf2" },
"omnisharp-extended-lsp.nvim": { "branch": "main", "commit": "4916fa12e5b28d21a1f031f0bdd10aa15a75d85d" },
"plenary.nvim": { "branch": "master", "commit": "2d9b06177a975543726ce5c73fca176cedbffe9d" },
"project.nvim": { "branch": "main", "commit": "8c6bad7d22eef1b71144b401c9f74ed01526a4fb" },
"rainbow-delimiters.nvim": { "branch": "master", "commit": "c7e489756b5455f922ce79ac374a4ede594f4a20" },
"sqlite.lua": { "branch": "master", "commit": "d0ffd703b56d090d213b497ed4eb840495f14a11" },
"telescope-all-recent.nvim": { "branch": "main", "commit": "267e9e5fd13a6e9a4cc6ffe00452d446d040401d" },
"telescope-file-browser.nvim": { "branch": "master", "commit": "626998e5c1b71c130d8bc6cf7abb6709b98287bb" },
"telescope-fzf-native.nvim": { "branch": "main", "commit": "cf48d4dfce44e0b9a2e19a008d6ec6ea6f01a83b" },
"telescope-recent-files": { "branch": "main", "commit": "3a7a1b9c6b52b6ff7938c59f64c87a05e013dff8" },
"telescope.nvim": { "branch": "0.1.x", "commit": "a0bbec21143c7bc5f8bb02e0005fa0b982edc026" },
"todo-comments.nvim": { "branch": "main", "commit": "ae0a2afb47cf7395dc400e5dc4e05274bf4fb9e0" },
"trouble.nvim": { "branch": "main", "commit": "46cf952fc115f4c2b98d4e208ed1e2dce08c9bf6" },
"ultimate-autopair.nvim": { "branch": "development", "commit": "9e3209190c22953566ae4e6436ad2b4ff4dabb95" },
"vim-sleuth": { "branch": "master", "commit": "be69bff86754b1aa5adcbb527d7fcd1635a84080" },
"which-key.nvim": { "branch": "main", "commit": "9b365a6428a9633e3eeb34dbef1b791511c54f70" }
}
+5
View File
@@ -0,0 +1,5 @@
require("core.leader-key")
require("core.config")
require("core.buffers")
require("core.autocommands")
require("core.globals")
+53
View File
@@ -0,0 +1,53 @@
local F = require("core.functions")
--------------------------------------------
--- Commands ---
-- Prevent typo
vim.cmd [[
cnoreabbrev <expr> W (getcmdtype() is# ":" && getcmdline() is# "W") ? ("w") : ("W")
cnoreabbrev <expr> Q (getcmdtype() is# ":" && getcmdline() is# "Q") ? ("q") : ("Q")
cnoreabbrev <expr> WQ (getcmdtype() is# ":" && getcmdline() is# "WQ") ? ("wq") : ("WQ")
cnoreabbrev <expr> Wq (getcmdtype() is# ":" && getcmdline() is# "Wq") ? ("wq") : ("Wq")
]]
--------------------------------------------
--- Autocommands ---
-- Cut off trailing whitespace and trailing blank lines
vim.api.nvim_create_autocmd({ "BufWritePre" }, {
pattern = "*",
callback = F.trim_buffer,
})
-- Highlight on yank
-- See `:help vim.highlight.on_yank()`
local highlight_group = vim.api.nvim_create_augroup("YankHighlight", { clear = true })
vim.api.nvim_create_autocmd("TextYankPost", {
pattern = "*",
group = highlight_group,
callback = function() vim.highlight.on_yank() end,
})
-- Show message when autosaving
local autosave_group = vim.api.nvim_create_augroup("autosave", {})
vim.api.nvim_create_autocmd("User", {
pattern = "AutoSaveWritePost",
group = autosave_group,
callback = function(opts)
if opts.data.saved_buffer ~= nil then
local filename = vim.api.nvim_buf_get_name(opts.data.saved_buffer)
vim.notify("Wrote " .. filename, vim.log.levels.INFO)
end
end,
})
-- Create an autocommand for full window buffers
vim.api.nvim_create_autocmd("BufWinEnter", {
-- callback = require("core.buffers").add_buffer
callback = function()
require("core.buffers").add_buffer()
LOG(require("core.buffers").buffers)
end,
desc = "Track all full window buffers visited",
})
+213
View File
@@ -0,0 +1,213 @@
local F = require("core.functions")
-- Module for managing buffers, these are used for navigation
local M = {}
-- Buffer table structure:
-- {
-- "Group" = { "buffer1", "buffer2", active_index = 1 }
-- }
M.buffers = {}
M.buffer_default_group = "Other"
M.buffer_matcher = {
-- match = truthy, function() -> thruthy, or string matching buffer filename
-- group = string, function() -> string
{ match = F.find_project_root, group = F.find_project_root },
{ match = true, group = "Other" }, -- default
}
--------------------------------------------
local get_buffer_name = function()
local buf = vim.api.nvim_get_current_buf()
local buffer_name = vim.api.nvim_buf_get_name(buf)
if not buffer_name or buffer_name == "" then return nil end
return buffer_name
end
M.add_buffer = function()
local buffer_name = get_buffer_name()
if not buffer_name then return end
-- Evaluate group
local eval_group = function(config_group)
if not config_group then return M.buffer_default_group end
if type(config_group) == "function" then return config_group() end
return config_group
end
-- Add if buffer does not exist yet
local add = function(config_group)
local group = eval_group(config_group)
if not M.buffers[group] then M.buffers[group] = {} end
for i, buffer in ipairs(M.buffers[group]) do
if buffer == buffer_name then
M.buffers[group]["active_index"] = i
return group, i
end
end
table.insert(M.buffers[group], buffer_name)
local count = #M.buffers[group]
M.buffers[group]["active_index"] = count
return group, count
end
-- Walk matcher configuration
local matcher = M.buffer_matcher or {}
if matcher and type(matcher) == "function" then
matcher = matcher()
end
if #matcher == 0 then add(M.buffer_default_group) end
for _, config in ipairs(M.buffer_matcher) do
if type(config.match) == "function" and config.match() then
return add(config.group)
end
-- Match path's filename
if type(config.match) == "string" and config.match == buffer_name:match("([^/]+)$") then
return add(config.group)
end
if type(config.match) == "boolean" and config.match then
return add(config.group)
end
end
return add(M.buffer_default_group)
end
local get_group_from_buffer = function(buffer_name)
for group, buffers in pairs(M.buffers) do
for i, buffer in ipairs(buffers) do
if buffer == buffer_name then return group, i end
end
end
return nil
end
local buffer_action_in_active_group = function(action, direction)
local buffer_name = get_buffer_name()
if not buffer_name then return end
local group, index = get_group_from_buffer(buffer_name)
if not group then group, index = M.add_buffer() end
local buffers = M.buffers[group]
if #buffers < 2 then return end
-- Determine the other index
local other_index = index + direction
if index == 1 and direction == -1 then
other_index = #buffers
elseif index == #buffers and direction == 1 then
other_index = 1
end
if action == "move" then
for _, buffer in ipairs(vim.api.nvim_list_bufs()) do
-- Remove inactive buffers
if not vim.api.nvim_buf_is_loaded(buffer) then
for i, group_buffer in ipairs(buffers) do
if buffer == group_buffer then
table.remove(buffers, i)
if i > 1 and i <= other_index then
other_index = other_index - 1
end
end
end
goto continue
end
-- Make buffer active
if vim.api.nvim_buf_get_name(buffer) == buffers[other_index] then
vim.api.nvim_set_current_buf(buffer)
buffers.active_index = other_index
break
end
::continue::
end
elseif action == "swap" then
local tmp = buffers[other_index]
buffers[other_index] = buffers[index]
buffers[index] = tmp
end
M.buffers[group] = buffers
end
M.buffer_move_left = function()
buffer_action_in_active_group("move", -1)
end
M.buffer_move_right = function()
buffer_action_in_active_group("move", 1)
end
M.buffer_swap_left = function()
buffer_action_in_active_group("swap", -1)
end
M.buffer_swap_right = function()
buffer_action_in_active_group("swap", 1)
end
--------------------------------------------
-- Group move
local buffer_group_move = function(direction)
local buffer_name = get_buffer_name()
if not buffer_name then return end
-- TODO: How to get groups deterministically?
-- Get active group from the current buffer
-- Check groups bounds
-- Change active group
end
M.buffer_group_move_up = function()
buffer_group_move(-1)
end
M.buffer_group_move_down = function()
buffer_group_move(1)
end
-- TODO: functions that can
-- v Navigate buffer left
-- v Navigate buffer right
-- - Navigate group up (use active_index when swapping)
-- - Navigate group down
-- v Move buffer left
-- v Move buffer right
-- - Remove buffer from currently active group (decrease active_index)
return M
-- (cond
-- ((string-equal "*" (substring (buffer-name) 0 1)) "Emacs")
-- ((or (memq major-mode '(magit-process-mode
-- magit-status-mode
-- magit-diff-mode
-- magit-log-mode
-- magit-file-mode
-- magit-blob-mode
-- magit-blame-mode))
-- (string= (buffer-name) "COMMIT_EDITMSG")) "Magit")
-- ((project-current) (dot/project-project-name))
-- ((memq major-mode '(org-mode
-- emacs-lisp-mode)) "Org Mode")
-- ((derived-mode-p 'dired-mode) "Dired")
-- ((derived-mode-p 'prog-mode
-- 'text-mode) "Editing")
-- (t "Other")))))
+50
View File
@@ -0,0 +1,50 @@
--- Behavior ---
-- vim.opt.autochdir = true
vim.opt.clipboard = "unnamedplus"
vim.opt.encoding = "utf-8"
vim.opt.fileencoding = "utf-8"
vim.opt.mouse = "a"
vim.opt.scrolloff = 8
vim.opt.signcolumn = "yes" -- always show gutter/fringe
vim.opt.ttimeoutlen = 0
-- Case-insensitive searching UNLESS \C or capital in search
vim.opt.ignorecase = true
vim.opt.smartcase = true
--- Editing ---
vim.opt.number = true
vim.opt.breakindent = true
vim.opt.backspace = "indent,eol,start"
vim.opt.expandtab = false
vim.opt.shiftround = true
vim.opt.shiftwidth = 4
vim.opt.softtabstop = 4
vim.opt.tabstop = 4
vim.opt.smartindent = true
vim.opt.wrap = false
--- Files
vim.opt.backup = true
vim.opt.backupdir = vim.fn.stdpath("cache") .. "/backup"
vim.opt.swapfile = false
vim.opt.undofile = true
vim.opt.undodir = vim.fn.stdpath("cache") .. "/undodir"
vim.opt.shadafile = vim.fn.stdpath("cache") .. "/netrwhist"
--- UI ---
vim.opt.colorcolumn = "81"
vim.opt.completeopt = "menuone,noselect"
vim.opt.cursorline = true
vim.opt.fillchars = vim.opt.fillchars + "diff:"
vim.opt.showtabline = 0
vim.opt.termguicolors = true
vim.opt.title = true
+75
View File
@@ -0,0 +1,75 @@
local M = {}
M.is_buffer_a_file = function()
local buffer_name = vim.fn.bufname()
return buffer_name ~= "" and vim.fn.filereadable(buffer_name) == 1
end
M.get_file_path = function()
if not M.is_buffer_a_file() then
return nil
end
local file_path = vim.fn.expand("%:p")
return vim.fn.fnamemodify(file_path, ":h") .. "/"
end
M.get_netrw_path = function() -- b:netrw_curdir
if vim.fn.expand("#" .. vim.fn.bufnr()) == "0" then
return nil
end
return vim.fn.fnamemodify(vim.fn.bufname(), ":p")
end
M.get_current_directory = function()
return M.get_file_path() or M.get_netrw_path() or vim.fn.getcwd()
end
M.find_project_root = function()
local current_directory = M.get_current_directory()
local directory = current_directory
while directory ~= "/" do
local git_path = vim.loop.fs_stat(directory .. "/.git")
if git_path then
return directory:gsub("/$", "") -- remove trailing slash
end
local project_file = vim.loop.fs_stat(directory .. "/.project")
if project_file and project_file.type == "file" then
return directory:gsub("/$", "") -- remove trailing slash
end
directory = vim.fn.fnamemodify(directory, ":h")
end
return nil, current_directory
end
-- This will merge tables with index-value pairs and keep the unique values
M.table_merge_unique = function(...)
local result = {}
local seen_values = {}
for _, value in ipairs(vim.tbl_flatten(...)) do
if not seen_values[value] then
seen_values[value] = true
table.insert(result, value)
end
end
return result
end
-- Cut off trailing whitespace and trailing blank lines
-- https://vi.stackexchange.com/questions/37421/how-to-remove-neovim-trailing-white-space
-- https://stackoverflow.com/questions/7495932/how-can-i-trim-blank-lines-at-the-end-of-file-in-vim
M.trim_buffer = function()
local save_cursor = vim.fn.getpos(".")
pcall(function() vim.cmd([[%s/\s\+$//e]]) end)
pcall(function() vim.cmd([[%s#\($\n\s*\)\+\%$##]]) end)
vim.fn.setpos(".", save_cursor)
end
return M
+19
View File
@@ -0,0 +1,19 @@
-- Usage:
-- :lua P("Hello World!")
P = function(v)
print(vim.inspect(v))
return v
end
RELOAD = function(...)
return require("plenary.reload").reload_module(...)
end
R = function(name)
RELOAD(name)
return require(name)
end
LOG = function(v)
vim.fn.writefile({ vim.inspect(v) }, "/tmp/nvim-log", "a")
end
+6
View File
@@ -0,0 +1,6 @@
-- Set <space> as the leader key
-- See `:help mapleader`
-- NOTE: Must happen before plugins are required (otherwise wrong leader will be used)
vim.keymap.set({ "n", "v" }, "<Space>", "<Nop>", { silent = true })
vim.g.mapleader = " "
vim.g.maplocalleader = " "
+207
View File
@@ -0,0 +1,207 @@
return {
-- Autocompletion
{
"hrsh7th/nvim-cmp",
lazy = true, -- defer
dependencies = {
-- Snippet Engine & its associated nvim-cmp source
"L3MON4D3/LuaSnip",
"saadparwaiz1/cmp_luasnip",
-- Adds LSP completion capabilities
"hrsh7th/cmp-nvim-lsp", -- source for neovim"s built-in LSP client
"hrsh7th/cmp-nvim-lua", -- source for neovim"s Lua API
"hrsh7th/cmp-buffer",
"hrsh7th/cmp-path",
-- Adds a number of user-friendly snippets
"rafamadriz/friendly-snippets",
-- Icons in the completion menu
"onsails/lspkind.nvim",
},
config = function()
local luasnip = require("luasnip")
require("luasnip.loaders.from_vscode").lazy_load()
luasnip.config.setup({})
require("cmp").setup({
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
completion = {
completeopt = "menu,menuone,noinsert",
},
sources = {
{ name = "nvim_lsp" },
{ name = "nvim_lua" },
{ name = "luasnip" },
{ name = "buffer" },
{ name = "path" },
},
formatting = {
fields = { "kind", "abbr", "menu" },
-- https://github.com/hrsh7th/nvim-cmp/wiki/Menu-Appearance#how-to-get-types-on-the-left-and-offset-the-menu
-- https://github.com/onsails/lspkind.nvim#option-2-nvim-cmp
format = function(entry, vim_item)
local kind = require("lspkind").cmp_format({ mode = "symbol_text", maxwidth = 50 })(entry,
vim_item)
local strings = vim.split(kind.kind, "%s", { trimempty = true })
kind.kind = strings[1] or ""
kind.menu = " (" .. (strings[2] or "") .. ")"
return kind
end,
expandable_indicator = true,
},
mapping = require("keybinds").nvim_cmp(),
})
end,
},
-- LSP Configuration & Plugins
{ -- https://github.com/neovim/nvim-lspconfig
"neovim/nvim-lspconfig",
dependencies = {
-- Improve the built-in LSP UI
"nvimdev/lspsaga.nvim",
-- Additional lua configuration, makes Nvim stuff amazing!
"folke/neodev.nvim",
-- C# "Goto Definition" with decompilation support
"Hoffs/omnisharp-extended-lsp.nvim",
},
config = function()
-- Setup neovim Lua configuration
require("lspsaga").setup() -- ?? does this do anything with doc hover
require("neodev").setup()
-- Vim process
local pid = vim.fn.getpid()
-- Setup language servers
-- https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
local servers = {
clangd = {}, -- C/C++
intelephense = {}, -- PHP
lua_ls = { -- Lua, via lua-language-server
settings = {
Lua = {
workspace = { checkThirdParty = false },
telemetry = { enable = false },
diagnostics = {
-- Ignore Lua_LS's noisy `missing-fields` warnings
disable = { "missing-fields" },
-- Ignore Lua_LS's noise `undefined global` warnings
globals = { "vim" },
},
},
},
},
omnisharp = { -- C#, via omnisharp-roslyn-bin
cmd = { "/usr/bin/omnisharp", "--languageserver", "--hostPID", tostring(pid) },
handlers = {
["textDocument/definition"] = require('omnisharp_extended').handler,
},
},
ts_ls = {
init_options = {
plugins = {
{
name = '@vue/typescript-plugin',
location = '/home/rick/.cache/.bun/install/global/node_modules/@vue/language-server',
languages = { 'vue' },
},
},
},
filetypes = { 'javascript', 'javascriptreact', 'javascript.jsx', 'typescript', 'typescriptreact', 'typescript.tsx', 'vue', },
-- filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
-- requires: bun install -g typescript-language-server
-- TODO: Update which-key config, maybe other packages
-- Sources:
-- https://github.com/vuejs/language-tools?tab=readme-ov-file#hybrid-mode-configuration-requires-vuelanguage-server-version-200
-- https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/configs/ts_ls.lua#L4
},
volar = {
-- init_options = {
-- vue = {
-- hybridMode = false,
-- },
-- },
},
-- volar = {
-- -- init_options = {
-- -- typescript = {
-- -- serverPath = '/home/rick/.cache/.bun/install/global/node_modules/typescript/lib//tsserverlibrary.js'
-- -- }
-- -- },
-- -- filetypes = {'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue', 'json'}
-- },
}
-- nvim-cmp supports additional completion capabilities, so broadcast that to servers
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities = require("cmp_nvim_lsp").default_capabilities(capabilities)
for server, _ in pairs(servers) do
local opts = vim.tbl_extend("keep", servers[server], {
capabilities = capabilities,
on_attach = require("keybinds").lspconfig_on_attach,
})
-- P(server)
-- P(opts)
require("lspconfig")[server].setup(opts)
end
end,
},
-- Project
{
"ahmedkhalf/project.nvim",
opts = {
detection_methods = { "lsp", "pattern" },
patterns = { ".git", ".project" },
datapath = vim.fn.stdpath("cache"),
},
config = function(_, opts)
-- Add syncing between project.nvim and dashboard-nvim project entries.
-- NOTE: Must come before the project.nvim setup(),
-- so the glue's VimLeavePre autocmd is defined before it.
local F = require("core.functions")
vim.api.nvim_create_autocmd("VimLeavePre", {
pattern = "*",
callback = function()
-- Fetch project.nvim projects
local project = require("project_nvim.project")
local history = require("project_nvim.utils.history")
local recent = history.recent_projects or {}
local session = history.session_projects or {}
local recent_plus_session = F.table_merge_unique(recent, session)
-- Fetch dashboard-nvim projects
local utils = require("dashboard.utils")
local path = utils.path_join(vim.fn.stdpath("cache"), "dashboard/cache")
local projects = utils.read_project_cache(path) or {}
-- Add any projects that project.nvim uniquely knows about to dashboard-nvim
local all_projects = F.table_merge_unique(recent_plus_session, projects)
vim.fn.writefile({ "return " .. vim.inspect(all_projects) }, path)
-- Add any projects that dashboard-nvim uniquely knows about to project.nvim
for _, value in ipairs(projects) do
if not vim.tbl_contains(recent_plus_session, value) then
pcall(project.set_pwd, value, "manual") -- skip non-existent directories, dont error
end
end
end,
})
require("project_nvim").setup(opts)
require("telescope").load_extension("projects")
end
}
}
+84
View File
@@ -0,0 +1,84 @@
return {
-- Detect tabstop and shiftwidth automatically
"tpope/vim-sleuth",
-- "gc" to comment visual regions/lines
"numToStr/Comment.nvim",
-- Highlight, edit, and navigate code
{
"nvim-treesitter/nvim-treesitter",
dependencies = {
"nvim-treesitter/nvim-treesitter-textobjects",
},
build = ":TSUpdate",
opts = {
ensure_installed = {
"bash", "c", "cmake", "cpp", "c_sharp", "css", "go",
"haskell", "html", "java", "javascript", "jsdoc", "json",
"latex", "lua", "make", "markdown", "php", "python",
"query", "regex", "rust", "toml", "tsx", "typescript",
"vim", "vimdoc", "yaml",
},
sync_install = false,
auto_install = true,
-- Default install directory is <plugin_path>/parser
-- parser_install_dir
highlight = {
enable = true,
additional_vim_regex_highlighting = false,
},
indent = {
enable = true,
},
}
},
-- Auto-save
{
"okuuva/auto-save.nvim",
cmd = "ASToggle", -- defer, until run command
event = { "InsertLeave", "TextChanged" }, -- defer, until event trigger
opts = {
debounce_delay = 5000, -- delay for `defer_save`, in ms
condition = function(buf)
-- Dont save special-buffers
return vim.fn.getbufvar(buf, "&buftype") == ""
end,
},
config = function(_, opts)
require("auto-save").setup(opts)
-- Cut off trailing whitespace and trailing blank lines
local group = vim.api.nvim_create_augroup("AutoSave", { clear = false })
local core = require("core.functions")
vim.api.nvim_create_autocmd("User", {
pattern = "AutoSaveWritePre",
group = group,
callback = function(event)
if event.data.saved_buffer ~= nil then
core.trim_buffer()
end
end,
})
end,
},
-- Autopair / electric pair
{ -- https://github.com/altermo/ultimate-autopair.nvim
"altermo/ultimate-autopair.nvim",
event = { "InsertEnter", "CmdlineEnter" }, -- defer
branch = "development",
opts = {
bs = { -- See: `:h ultimate-autopair-map-backspace-config`
-- Call the backspace logic from the config, instead of automap
-- https://github.com/altermo/ultimate-autopair.nvim/issues/60
map = "<Plug>ultimate-autopair-BS",
},
},
},
}
+34
View File
@@ -0,0 +1,34 @@
return {
-- Adds git related signs to the gutter/fringe
{
"lewis6991/gitsigns.nvim",
opts = {
-- See `:help gitsigns.txt`
signs = {
add = { text = "" },
change = { text = "" },
delete = { text = "" },
topdelete = { text = "" },
changedelete = { text = "" },
untracked = { text = "" },
},
},
},
-- Magit clone
{
"NeogitOrg/neogit",
cmd = "Neogit", -- defer
lazy = true,
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-telescope/telescope.nvim",
"sindrets/diffview.nvim", -- diff integration
-- { "sindrets/diffview.nvim", opts = { enhanced_diff_hl = true } }, -- diff integration
},
opts = {},
},
}
+309
View File
@@ -0,0 +1,309 @@
local builtin
local telescope
local F = require("core.functions")
local M = {}
M.setup = function()
-- Prevent dependency loop
builtin = require("telescope.builtin")
telescope = require("telescope")
end
-- Set which-key key section description
M.wk = function(keybind, description, bufnr)
require("which-key").add({
{ keybind, group = description, mode = { "n", "v" }, buffer = bufnr },
})
end
M.buffer_close = function()
-- Check if there are more than 2 buffers and alternate file is set
local command = vim.fn.expand("#") ~= "" and #vim.fn.getbufinfo({ buflisted = 1 }) > 1
and "e #|bd #|bwipeout #" -- see `:h c_#`
or "bd"
vim.api.nvim_command(command)
end
M.buffer_dashboard = function()
vim.api.nvim_command("Dashboard")
end
M.file_config = function()
builtin.find_files({
prompt_title = "Nvim Config",
cwd = vim.fn.stdpath("config"),
hidden = true,
no_ignore = true,
-- path_display = { "shorten" },
})
end
M.file_find = function()
telescope.extensions.file_browser.file_browser({
cwd = F.get_current_directory(),
hidden = true,
no_ignore = true,
})
end
M.file_find_home = function()
telescope.extensions.file_browser.file_browser({
cwd = "~",
hidden = true,
no_ignore = true,
})
end
M.file_find_recent = function()
telescope.extensions.recent_files.pick()
end
M.file_save = function()
vim.api.nvim_command("w")
end
M.goto_trouble = function()
vim.api.nvim_command("Trouble")
end
M.goto_todos_telescope = function()
vim.api.nvim_command("TodoTelescope")
end
M.goto_todos_trouble = function()
vim.api.nvim_command("TodoTrouble")
end
-- Smart delete
M.hungry_delete = function()
return function()
local start_line = vim.fn.line(".")
local start_col = vim.fn.col(".")
local start_line_content = vim.fn.getline(start_line)
local line_length = start_line_content:len()
-- Check if there are multiple whitespace characters after the cursor
local is_1_whitespace = start_line_content:sub(start_col, start_col):match("%s")
local is_2_whitespace = start_line_content:sub(start_col + 1, start_col + 1):match("%s")
if (start_col <= line_length - 1 and is_1_whitespace and is_2_whitespace)
or (start_col == line_length and is_1_whitespace)
or start_col - 1 == line_length then -- in insert mode, the column is 1 higher
-- Hungry delete
-- Iterate forwards through each line and character
local last_line = vim.fn.line("$")
for line = start_line, last_line do
local line_content = (line == start_line) and start_line_content or vim.fn.getline(line)
local col = (line == start_line) and start_col or 1
for c = col, #line_content do
local char = line_content:sub(c, c)
-- Look until it hits a non-whitespace character
if not vim.fn.strcharpart(char, 0, 1):match("%s") then
-- Delete empty lines, from the starting line to the current line
vim.api.nvim_buf_set_lines(0, start_line - 1, line - 1, false, {})
-- Keep the content that was before the cursor at the start_line,
-- plus the content from the current column to the end of the current line
vim.fn.setline(start_line,
start_line_content:sub(1, start_col - 1) .. line_content:sub(c))
vim.fn.cursor({ start_line, start_col })
return
end
end
end
-- Delete empty lines, if the end of the buffer was only whitespace
vim.api.nvim_buf_set_lines(0, start_line - 1, last_line, false, {})
-- Keep the content that was before the cursor
vim.fn.setline(start_line, start_line_content:sub(1, start_col - 1))
vim.fn.cursor({ start_line, start_col })
else
-- Normal delete
vim.cmd("normal! x")
end
end
end
-- Smart backspace
M.hungry_delete_backspace = function()
-- Cache some values
local core = require("ultimate-autopair.core")
local keycode = vim.api.nvim_replace_termcodes("<Plug>ultimate-autopair-BS", true, false, true)
local fallback = vim.api.nvim_replace_termcodes("<C-h>", true, false, true) -- <BS> => <C-h>, \b
return function()
local start_line = vim.fn.line(".")
local start_col = vim.fn.col(".")
local start_line_content = vim.fn.getline(start_line)
-- Check if there are multiple whitespace characters before the cursor
local is_1_whitespace = start_line_content:sub(start_col - 1, start_col - 1):match("%s")
local is_2_whitespace = start_line_content:sub(start_col - 2, start_col - 2):match("%s")
if (start_col >= 3 and is_1_whitespace and is_2_whitespace)
or (start_col == 2 and is_1_whitespace)
or start_col == 1 then
-- Hungry delete
-- Iterate backwards through each line and character
for line = start_line, 1, -1 do
local line_content = (line == start_line) and start_line_content or vim.fn.getline(line)
local col = (line == start_line) and (start_col - 1) or #line_content
for c = col, 1, -1 do
local char = line_content:sub(c, c)
-- Look until it hits a non-whitespace character
if not vim.fn.strcharpart(char, 0, 1):match("%s") then
-- Delete empty lines, from the starting line to the current line
vim.api.nvim_buf_set_lines(0, line - 1, start_line - 1, false, {})
-- Keep the content from the start of the current line to the current column,
-- plus the content that was after the cursor at the start_line
vim.fn.setline(line, line_content:sub(1, c) .. (line == start_line
and line_content:sub(start_col) -- found non-whitespace on the same line it started
or start_line_content:sub(start_col))) -- jumped through empty lines
vim.fn.cursor({ line, c + 1 })
return
end
end
end
-- Delete empty lines, if the start of the buffer was only whitespace
vim.api.nvim_buf_set_lines(0, 0, start_line - 1, false, {})
-- Keep the content that was after the cursor
vim.fn.setline(1, "" .. start_line_content:sub(start_col))
else
-- Normal backspace, prevent run_run recursive mapping via fallback to \b
local actions = core.run_run(keycode)
vim.api.nvim_feedkeys(actions ~= keycode and actions or fallback, "n", false) -- equivalent to { expr = true }
end
end
end
M.lsp_format_buffer = function()
vim.lsp.buf.format({
formatting_options = {
tabSize = 4,
insertSpaces = false,
},
})
end
M.project_file = function()
local res, err = F.find_project_root()
if res then
builtin.git_files({ cwd = res })
else -- fall-back to find_files, if current buffer isnt in a project
builtin.find_files({ cwd = err })
end
end
M.project_grep = function()
local res, err = F.find_project_root()
builtin.live_grep({ cwd = res or err })
end
M.project_list = function()
telescope.extensions.projects.projects()
end
M.search_buffer = function()
builtin.current_buffer_fuzzy_find({
previewer = false,
sorting_strategy = "ascending",
})
end
-- TODO: Temporary copy/pasted until project_nvim exposes this function
-- https://github.com/ahmedkhalf/project.nvim/issues/145
-- TODO: Create a Telescope extension out of this, for telescope-all-recent
local function create_finder()
local results = require("project_nvim").get_recent_projects()
local entry_display = require("telescope.pickers.entry_display")
local finders = require("telescope.finders")
-- Reverse results
for i = 1, math.floor(#results / 2) do
results[i], results[#results - i + 1] = results[#results - i + 1], results[i]
end
local displayer = entry_display.create({
separator = " ",
items = {
{
width = 30,
},
{
remaining = true,
},
},
})
local function make_display(entry)
return displayer({ entry.name, { entry.value, "Comment" } })
end
return finders.new_table({
results = results,
entry_maker = function(entry)
local name = vim.fn.fnamemodify(entry, ":t")
return {
display = make_display,
name = name,
value = entry,
ordinal = name .. " " .. entry,
}
end,
})
end
M.vc_select_repo = function()
-- local projects = require("project_nvim").get_recent_projects()
local actions = require("telescope.actions")
local action_state = require("telescope.actions.state")
local conf = require("telescope.config").values
-- local finders = require("telescope.finders")
local pickers = require("telescope.pickers")
pickers.new({}, {
prompt_title = "Select Project",
finder = create_finder(),
-- finder = telescope.extensions.projects.create_finder(),
-- finder = finders.new_table {
-- results = projects,
-- },
previewer = false,
sorter = conf.generic_sorter({}),
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
-- require("neogit").open({ cwd = selection[1] })
require("neogit").open({ cwd = selection.value })
end)
return true
end,
}):find()
end
M.vc_status = function()
if F.find_project_root() then
-- Open the repository of the current file
require("neogit").open({ cwd = "%:p:h" })
else
-- Pick a project to open
M.vc_select_repo()
end
end
return M
+242
View File
@@ -0,0 +1,242 @@
local K = vim.keymap.set
local builtin
local wk = require("which-key")
local F = require("keybind-functions")
local M = {}
--------------------------------------------
--- Keybindings ---
M.setup = function()
F.setup()
-- Prevent dependency loop
builtin = require("telescope.builtin")
-- Change default behavior
K("n", "Y", "y$")
K("v", "p", "pgvy")
K("n", "J", "mzJ`z") -- dont move cursor to end of line
K("n", "<C-d>", "<C-d>zz") -- stay in the middle
K("n", "<C-u>", "<C-u>zz")
K("n", "n", "nzzzv")
K("n", "N", "Nzzzv")
K("x", "p", "\"_dP") -- dont overwrite clipboard when pasting visually
-- Remap for dealing with word wrap
K("n", "k", [[v:count == 0 ? "gk" : "k"]], { expr = true, silent = true })
K("n", "j", [[v:count == 0 ? "gj" : "j"]], { expr = true, silent = true })
-- Tab/Shift+Tab functionality
K("n", "<Tab>", ">>_")
K("n", "<S-Tab>", "<<_")
K("i", "<S-Tab>", "<C-D>")
K("v", "<Tab>", ">gv")
K("v", "<S-Tab>", "<gv")
-- Move highlighted blocks
K("v", "J", ":m '>+1<CR>gv=gv")
K("v", "K", ":m '<-2<CR>gv=gv")
-- Switch to previous buffer
K("n", "<M-`>", "<C-6>")
-- Center buffer with Ctrl+L
K("n", "<C-l>", "zz")
-- Close buffer with Alt-w
K("n", "<M-w>", F.buffer_close)
-- Hungry delete
K("i", "<BS>", F.hungry_delete_backspace())
K("i", "<Del>", F.hungry_delete())
----------------------------------------
--- Leader keys ---
K("n", "<leader><space>", builtin.commands, { desc = "Execute command" })
F.wk("<leader>b", "buffer/bookmark")
K("n", "<leader>bb", builtin.buffers, { desc = "Switch buffer" })
K("n", "<leader>bd", F.buffer_dashboard, { desc = "Dashboard" })
F.wk("<leader>c", "comment")
-- numToStr/Comment.nvim
K("n", "<leader>cc", "<Plug>(comment_toggle_linewise_current)", { desc = "Comment toggle linewise" })
K("n", "<leader>cp", "<Plug>(comment_toggle_blockwise_current)", { desc = "Comment toggle blockwise" })
K("x", "<leader>cc", "<Plug>(comment_toggle_linewise_visual)", { desc = "Comment toggle linewise (visual)" })
K("x", "<leader>cp", "<Plug>(comment_toggle_blockwise_visual)", { desc = "Comment toggle blockwise (visual)" })
F.wk("<leader>e", "eval")
K("n", "<leader>eb", ":w<CR>:source %<CR>", { desc = "Evaluate buffer" })
F.wk("<leader>f", "file")
K("n", "<leader>fc", F.file_config, { desc = "Config file" })
K("n", "<leader>ff", F.file_find, { desc = "Find file" })
K("n", "<leader>fh", F.file_find_home, { desc = "Find file in ~" })
K("n", "<leader>fr", F.file_find_recent, { desc = "Find recent file" })
K("n", "<leader>fs", F.file_save, { desc = "Save file" })
F.wk("<leader>h", "help")
K("n", "<leader>hh", builtin.help_tags, { desc = "Describe" })
K("n", "<leader>hk", builtin.keymaps, { desc = "Describe key" })
K("n", "<leader>hm", builtin.man_pages, { desc = "Describe manpage" })
F.wk("<leader>g", "goto")
K("n", "<leader>ge", F.goto_trouble, { desc = "Goto trouble" })
K("n", "<leader>gt", F.goto_todos_telescope, { desc = "Goto todos (Telescope)" })
K("n", "<leader>gT", F.goto_todos_trouble, { desc = "Goto todos (Trouble)" })
F.wk("<leader>p", "project")
K("n", "<leader>pf", F.project_file, { desc = "Find project file" })
K("n", "<leader>pg", F.project_grep, { desc = "Find in project" })
K("n", "<leader>pp", F.project_list, { desc = "List projects" })
F.wk("<leader>s", "search")
K("n", "<leader>ss", F.search_buffer, { desc = "Search buffer" })
K("n", "<leader>sq", ":nohlsearch<CR>", { desc = "Stop search", silent = true })
F.wk("<leader>v", "git") -- version control
K("n", "<leader>vr", F.vc_select_repo, { desc = "Select repo" })
K("n", "<leader>vv", F.vc_status, { desc = "Neogit status" })
K({ "n", "v" }, "<leader>w", "<C-W>", { remap = true }) -- keymap and which-key should *both* be triggered
wk.add({
{
mode = { "n", "v" },
{ "<leader>w", group = "window" },
{ "<leader>w+", desc = "Increase height" },
{ "<leader>w-", desc = "Decrease height" },
{ "<leader>w<", desc = "Decrease width" },
{ "<leader>w=", desc = "Equally high and wide" },
{ "<leader>w>", desc = "Increase width" },
{ "<leader>wT", desc = "Break out into a new tab" },
{ "<leader>w_", desc = "Max out the height" },
{ "<leader>wh", desc = "Go to the left window" },
{ "<leader>wj", desc = "Go to the down window" },
{ "<leader>wk", desc = "Go to the up window" },
{ "<leader>wl", desc = "Go to the right window" },
{ "<leader>wo", desc = "Close all other windows" },
{ "<leader>wq", desc = "Quit a window" },
{ "<leader>ws", desc = "Split window" },
{ "<leader>wv", desc = "Split window vertically" },
{ "<leader>ww", desc = "Switch windows" },
{ "<leader>wx", desc = "Swap current with next" },
{ "<leader>w|", desc = "Max out the width" },
},
})
-- https://github.com/folke/which-key.nvim/issues/270
-- https://github.com/folke/which-key.nvim/blob/main/lua/which-key/plugins/presets/misc.lua
end
--------------------------------------------
--- Plugin specific ---
-- This function gets run when an LSP connects to a particular buffer.
M.lspconfig_on_attach = function(_, bufnr)
local nnoremap = function(keys, func, desc)
vim.keymap.set("n", keys, func, { buffer = bufnr, desc = desc })
end
F.wk("<leader>l", "lsp", bufnr)
nnoremap("<leader>la", vim.lsp.buf.code_action, "Code action")
nnoremap("<leader>lf", F.lsp_format_buffer, "Format buffer")
nnoremap("<leader>lr", vim.lsp.buf.rename, "Rename")
nnoremap("<leader>ld", "<cmd>Lspsaga hover_doc<CR>", "Show documentation")
-- vim.keymap.set("n", "<leader>ld", "<cmd>Lspsaga hover_doc<CR>", { desc = "Show documentation" })
F.wk("<leader>lg", "goto", bufnr)
nnoremap("<leader>lga", builtin.lsp_dynamic_workspace_symbols, "Workspace symbols")
nnoremap("<leader>lgd", vim.lsp.buf.declaration, "Declaration")
nnoremap("<leader>lgg", vim.lsp.buf.definition, "Definition") -- builtin.lsp_definitions
nnoremap("<leader>lgi", builtin.lsp_implementations, "Implementation")
nnoremap("<leader>lgr", builtin.lsp_references, "References")
nnoremap("<leader>lgs", builtin.lsp_document_symbols, "Document symbols")
nnoremap("<leader>lgt", builtin.lsp_type_definitions, "Type definition")
-- See `:help K` for why this keymap
nnoremap("K", vim.lsp.buf.hover, "Hover Documentation")
nnoremap("<C-k>", vim.lsp.buf.signature_help, "Signature Documentation")
end
-- Keybindings for nvim-cmp popup
M.nvim_cmp = function()
local cmp = require("cmp")
local luasnip = require("luasnip")
return cmp.mapping.preset.insert({
["<M-h>"] = cmp.mapping.abort(),
["<M-j>"] = cmp.mapping.select_next_item(),
["<M-k>"] = cmp.mapping.select_prev_item(),
["<M-l>"] = cmp.mapping.confirm({
behavior = cmp.ConfirmBehavior.Replace,
select = true,
}),
["<Esc>"] = cmp.mapping.abort(),
["<CR>"] = cmp.mapping.confirm({
behavior = cmp.ConfirmBehavior.Replace,
select = true,
}),
["<C-Space>"] = cmp.mapping.complete(),
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_locally_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end, { "i", "s" }),
["<S-Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.locally_jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, { "i", "s" }),
})
end
-- Telescope picker generic mappings
M.telescope_default_mappings = function()
local actions = require("telescope.actions")
return {
n = {
["<M-h>"] = actions.close,
["<M-j>"] = actions.move_selection_next,
["<M-k>"] = actions.move_selection_previous,
["<M-l>"] = actions.select_default,
},
i = {
["<M-h>"] = actions.close,
["<M-j>"] = actions.move_selection_next,
["<M-k>"] = actions.move_selection_previous,
["<M-l>"] = actions.select_default,
["<Tab>"] = actions.select_default,
}
}
end
return M
+32
View File
@@ -0,0 +1,32 @@
local M = {}
local plugin_path = vim.fn.stdpath("cache") .. "/lazy"
-- Install lazy.nvim plugin manager
-- See `:help lazy.nvim.txt`
M.install = function()
local lazy_path = plugin_path .. "/lazy.nvim"
if not vim.loop.fs_stat(lazy_path) then
vim.fn.system {
"git",
"clone",
"--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable", -- latest stable release
lazy_path,
}
end
vim.opt.rtp:prepend(lazy_path)
end
M.setup = function(modules)
M.install()
local options = {
root = plugin_path, -- directory where plugins will be installed
}
require("lazy").setup(modules, options)
end
return M
+132
View File
@@ -0,0 +1,132 @@
return {
-- Fuzzy Finder (files, LSP, etc)
{
"nvim-telescope/telescope.nvim",
branch = "0.1.x",
dependencies = {
"nvim-lua/plenary.nvim",
-- Fuzzy Finder Algorithm which requires local dependencies to be built.
{
"nvim-telescope/telescope-fzf-native.nvim",
build = "make",
cond = function()
return vim.fn.executable "make" == 1
end,
},
-- Extensions
"nvim-telescope/telescope-file-browser.nvim",
"smartpde/telescope-recent-files",
},
extensions = {
"fzf",
},
config = function()
require("telescope").setup({
defaults = {
sorting_strategy = "ascending",
layout_strategy = "config",
layout_config = {
height = 10, -- amount of results
config = { -- apply settings to the "config" layout
search_condensed = true,
}
},
border = true,
history = {
path = vim.fn.stdpath("cache") .. "/telescope_history",
},
mappings = require("keybinds").telescope_default_mappings(),
},
extensions = {
file_browser = {
hide_parent_dir = true, -- hide "../"
prompt_path = true, -- set path as prompt prefix
},
},
})
require("telescope").load_extension("fzf")
require("telescope").load_extension "file_browser"
require("telescope").load_extension("recent_files")
--- ┌──────────────────────────────────────────────────┐
--- │ │
--- │ ┌───────────────────┐ │
--- │ │ │ │
--- │ │ │ │
--- │ │ Preview │ │
--- │ │ │ │
--- │ │ │ │
--- │ └───────────────────┘ │
--- │ │
--- ├──────────────────────────────────────────────────┤
--- │ Prompt │
--- ├──────────────────────────────────────────────────┤
--- │ Results │
--- │ │
--- └──────────────────────────────────────────────────┘
require("telescope.pickers.layout_strategies").config = function(picker, max_columns, max_lines,
layout_config)
local p_window = require "telescope.pickers.window"
local initial_options = p_window.get_initial_window_options(picker)
local results = initial_options.results
local prompt = initial_options.prompt
local preview = initial_options.preview
-- Layout config isnt filled by Telescope automatically
layout_config = require("telescope.config").values.layout_config or {}
results.title = ""
results.borderchars = { "", "", "", "", "", "", "", "" }
local bs = picker.window.border and 2 or 0
local search_condensed = bs ~= 0 and layout_config.config.search_condensed and 2 or 0
-- Height
prompt.height = 1
results.height = layout_config.height or 10
local search_height = (prompt.height + results.height + (bs * 3))
preview.height = math.floor((max_lines - search_height) * 0.8)
-- Width
prompt.width = max_columns - (bs ~= 0 and search_condensed == 0 and bs or 0)
results.width = max_columns - (bs ~= 0 and search_condensed == 0 and bs or 0)
preview.width = math.floor(max_columns * 0.75)
-- Line (position), coordinates start at top-left
prompt.line = max_lines - results.height + search_condensed - bs -- take overlapping border into account
results.line = max_lines - results.height + search_condensed - bs + (bs / 2) + prompt.height
preview.line = math.floor((max_lines - search_height - preview.height + bs) / 2) + 1
return {
preview = picker.previewer and preview.width > 0 and preview,
prompt = prompt,
results = results,
}
end
end,
},
-- Telescope pickers sorted by recency and frequency
{
"prochri/telescope-all-recent.nvim",
dependencies = {
"kkharji/sqlite.lua",
},
opts = {
database = {
folder = vim.fn.stdpath("cache"),
},
pickers = { -- extension_name#extension_method
["projects#projects"] = {
disable = false,
use_cwd = false,
sorting = "frecency",
},
},
}
},
}
+186
View File
@@ -0,0 +1,186 @@
return {
-- Theme
{
"RRethy/nvim-base16",
lazy = false, -- make sure to load this during startup if it is your main colorscheme
priority = 1000,
config = function()
require("base16-colorscheme").with_config({
-- TODO: maybe make Telescope borders visible?
-- telescope = false,
})
vim.cmd.colorscheme "base16-tomorrow-night"
local colors = require("base16-colorscheme").colors
-- local blue_m1 = "#9cc4e6"
local blue = colors.base0D -- #81a2be
-- local blue_p1 = "#5f819d"
local blue_p2 = "#445666"
local blue_p3 = "#2a3640"
local cyan = colors.base0C -- #8abeb7
local fg = colors.base05 -- #c5c8c6
local fg_dark = "#515151"
-- local green = colors.base0B -- #b5bd68
local green_p1 = "#8c9440"
-- local green_p2 = "#5f875f"
local green_bg = "#404324"
-- local orange = colors.base09 -- #de935f
-- local magenta = colors.base0E -- #b294bb
local red = colors.base08 -- #cc6666
local red_bg = "#4e2626"
local yellow = colors.base0A -- #f0c674
-- Cursor
vim.api.nvim_command("highlight CursorLineNr guifg=" .. yellow .. " gui=bold")
-- Diffview
vim.api.nvim_command("highlight DiffviewDiffAdd guibg=" .. green_bg)
vim.api.nvim_command("highlight DiffviewDiffChange guibg=" .. blue_p3) -- Unchanged part on a change line
vim.api.nvim_command("highlight DiffviewDiffDelete guibg=" .. red_bg .. " guifg=" .. fg_dark)
vim.api.nvim_command("highlight DiffviewDiffText guibg=" .. blue_p2) -- Changed part on a change line
-- Git gutter
vim.api.nvim_command("highlight GitSignsAdd guifg=" .. green_p1)
vim.api.nvim_command("highlight GitSignsChange guifg=" .. yellow)
-- Rainbow delimiters
vim.api.nvim_command("highlight RainbowDelimiterBlue guifg=" .. blue)
vim.api.nvim_command("highlight RainbowDelimiterCyan guifg=" .. cyan)
vim.api.nvim_command("highlight RainbowDelimiterGreen guifg=" .. green_p1)
vim.api.nvim_command("highlight RainbowDelimiterOrange guifg=" .. fg)
vim.api.nvim_command("highlight RainbowDelimiterRed guifg=" .. red)
vim.api.nvim_command("highlight RainbowDelimiterYellow guifg=" .. yellow)
end,
},
-- Set lualine as statusline
{
-- See `:help lualine.txt`
"nvim-lualine/lualine.nvim",
opts = {
options = {
icons_enabled = false,
theme = "base16",
component_separators = { left = "", right = "" },
section_separators = { left = "", right = "" },
globalstatus = true,
},
sections = {
lualine_a = { "mode" },
lualine_b = { "encoding", "filename" },
lualine_c = {
{
-- TODO: nvim alternate file stuff and closing files is busted
"project",
fmt = function()
local path = require("core.functions").find_project_root() or ""
return path:match("([^/]+)$")
end,
},
},
lualine_x = { "diagnostics", "fileformat" },
lualine_y = { "filetype" },
lualine_z = { "progress", "location" },
},
},
},
-- Add file type icons to plugins
{ "nvim-tree/nvim-web-devicons", lazy = true },
-- Dashboard
{
"nvimdev/dashboard-nvim",
event = "VimEnter",
opts = {
config = {
header = {
" . . ",
" ';;,. ::' ",
" ,:::;,, :ccc, ",
" ,::c::,,,,. :cccc, ",
" ,cccc:;;;;;. cllll, ",
" ,cccc;.;;;;;, cllll; ",
" :cccc; .;;;;;;. coooo; ",
" ;llll; ,:::::'loooo; ",
" ;llll: ':::::loooo: ",
" :oooo: .::::llodd: ",
" .;ooo: ;cclooo:. ",
" .;oc 'coo;. ",
" .' .,. ",
"",
" _______________________________________________________",
"",
"",
},
shortcut = {
{ desc = "Neovim master race!" },
},
footer = {},
},
}
},
-- Show project errors
{
"folke/trouble.nvim",
cmd = "Trouble", -- defer
opts = {
mode = "lsp_references",
use_diagnostic_signs = true,
},
config = function()
-- Gutter/fringe icons
-- https://github.com/folke/trouble.nvim/issues/52
local signs = {
Error = "»",
Warn = "»",
Hint = "»",
Info = "»",
Other = "»",
}
for type, icon in pairs(signs) do
local hl = "DiagnosticSign" .. type
vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl })
end
end,
},
-- Show project TODOs
{
"folke/todo-comments.nvim",
dependencies = { "nvim-lua/plenary.nvim" },
opts = {},
},
-- Useful plugin to show you pending keybinds.
"folke/which-key.nvim",
-- Rainbow delimiters
{
"HiPhish/rainbow-delimiters.nvim",
opts = {
highlight = {
"RainbowDelimiterOrange", -- white
"RainbowDelimiterCyan",
"RainbowDelimiterYellow",
"RainbowDelimiterGreen",
"RainbowDelimiterBlue",
"RainbowDelimiterOrange", -- white
"RainbowDelimiterCyan",
"RainbowDelimiterYellow",
"RainbowDelimiterGreen",
"RainbowDelimiterBlue",
"RainbowDelimiterRed",
},
},
config = function(_, opts)
require("rainbow-delimiters.setup").setup(opts)
end,
},
-- Rainbow-mode
{ -- https://github.com/norcalli/nvim-colorizer.lua
"norcalli/nvim-colorizer.lua",
opts = {},
}, -- :ColorizerToggle
}
+1 -1
View File
@@ -92,7 +92,7 @@ export SUDO_ASKPASS="$HOME/.local/bin/rofipass"
export TERMINAL="urxvt" export TERMINAL="urxvt"
# Vim # Vim
export VIMINIT="source $XDG_CONFIG_HOME/vim/vimrc" export VIMINIT="source $XDG_CONFIG_HOME/nvim/init.lua"
# Web browser # Web browser
export BROWSER="firefox" export BROWSER="firefox"
+5 -1
View File
@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# Depends: GNU getopt, mpv, socat, streamlink # Depends: GNU getopt, mpv, socat, streamlink, xclip
SOCK="/tmp/umpv-fifo" SOCK="/tmp/umpv-fifo"
@@ -255,8 +255,12 @@ elif [ $shuffleOption -eq 1 ]; then
shuffle "$*" shuffle "$*"
elif [ $queueOption -eq 1 ]; then elif [ $queueOption -eq 1 ]; then
queue "$*" queue "$*"
else
if [ "$*" = "" ]; then
play "$(xclip -o)"
else else
for url in "$@"; do for url in "$@"; do
play "$url" play "$url"
done done
fi fi
fi
@@ -42,8 +42,9 @@
} }
/* Url bar color */ /* Url bar color */
#urlbar { #urlbar-background {
background: #404552 !important; background: #404552 !important;
border-radius: 0;
} }
/* Hide ... button in URL bar */ /* Hide ... button in URL bar */
@@ -55,13 +56,6 @@
display: none; display: none;
} }
/* Unzoom URL bar */
#urlbar[breakout-extend] {
top: calc((var(--urlbar-toolbar-height) - var(--urlbar-height)) / 2) !important;
left: calc((var(--urlbar-toolbar-width) - var(--urlbar-width)) / 2) !important;
width: 100% !important;
}
#urlbar[breakout-extend] #urlbar-input-container { #urlbar[breakout-extend] #urlbar-input-container {
height: calc(var(--tab-min-height) - 3px) !important; height: calc(var(--tab-min-height) - 3px) !important;
padding: 0px !important; padding: 0px !important;
+586
View File
@@ -0,0 +1,586 @@
# ------------------------------------------------------------------------------
# /etc/tlp.conf - TLP user configuration (version 1.7.0)
# See full explanation: https://linrunner.de/tlp/settings
#
# Copyright (c) 2024 Thomas Koch <linrunner at gmx.net> and others.
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Settings are read in the following order:
#
# 1. Intrinsic defaults
# 2. /etc/tlp.d/*.conf - Drop-in customization snippets
# 3. /etc/tlp.conf - User configuration (this file)
#
# Notes:
# - In case of identical parameters, the last occurence has precedence
# - This also means, parameters enabled here will override anything else
# - However you may append values to a parameter already defined as intrinsic
# default or in a previously read file: use PARAMETER+="add values"
# - IMPORTANT: all parameters here are disabled; remove the leading '#' if you
# like to enable a feature without default or have a value different from the
# default
# - Default *: intrinsic default that is effective when the parameter is missing
# or disabled by a leading '#'; use PARAM="" to disable an intrinsic default
# - Default <none>: do nothing or use kernel/hardware defaults
# - IMPORTANT: parameters must always be specified pairwise i.e. for
# both AC and BAT. Omitting one of the two makes the set value effective for
# both power sources, since a change only occurs when different values are
# defined.
# ------------------------------------------------------------------------------
# tlp - Parameters for power saving
# Set to 0 to disable, 1 to enable TLP.
# Default: 1
#TLP_ENABLE=1
# Control how warnings about invalid settings are issued:
# 0=disabled,
# 1=background tasks (boot, resume, change of power source) report to syslog,
# 2=shell commands report to the terminal (stderr),
# 3=combination of 1 and 2
# Default: 3
#TLP_WARN_LEVEL=3
# Colorize error, warning, notice and success messages. Colors are specified
# with ANSI codes:
# 1=bold black, 90=grey, 91=red, 92=green, 93=yellow, 94=blue, 95=magenta,
# 96=cyan, 97=white.
# Other colors are possible, refer to:
# https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit
# Colors must be specified in the order "<error> <warning> <notice> <success>".
# By default, errors are shown in red, warnings in yellow, notices in bold
# and success in green.
# Default: "91 93 1 92"
#TLP_MSG_COLORS="91 93 1 92"
# Operation mode when no power supply can be detected: AC, BAT.
# Concerns some desktop and embedded hardware only.
# Default: <none>
#TLP_DEFAULT_MODE=AC
# Operation mode select: 0=depend on power source, 1=always use TLP_DEFAULT_MODE
# Note: use in conjunction with TLP_DEFAULT_MODE=BAT for BAT settings on AC.
# Default: 0
#TLP_PERSISTENT_DEFAULT=0
# Power supply classes to ignore when determining operation mode: AC, USB, BAT.
# Separate multiple classes with spaces.
# Note: try on laptops where operation mode AC/BAT is incorrectly detected.
# Default: <none>
#TLP_PS_IGNORE="BAT"
# Seconds laptop mode has to wait after the disk goes idle before doing a sync.
# Non-zero value enables, zero disables laptop mode.
# Default: 0 (AC), 2 (BAT)
#DISK_IDLE_SECS_ON_AC=0
#DISK_IDLE_SECS_ON_BAT=2
# Dirty page values (timeouts in secs).
# Default: 15 (AC), 60 (BAT)
#MAX_LOST_WORK_SECS_ON_AC=15
#MAX_LOST_WORK_SECS_ON_BAT=60
# Select a CPU scaling driver operation mode.
# Intel CPU with intel_pstate driver:
# active, passive.
# AMD Zen 2 or newer CPU with amd-pstate driver as of kernel 6.3/6.4(*):
# active, passive, guided(*).
# Default: <none>
#CPU_DRIVER_OPMODE_ON_AC=active
#CPU_DRIVER_OPMODE_ON_BAT=active
# Select a CPU frequency scaling governor.
# Intel CPU with intel_pstate driver or
# AMD CPU with amd-pstate driver in active mode ('amd-pstate-epp'):
# performance, powersave(*).
# Intel CPU with intel_pstate driver in passive mode ('intel_cpufreq') or
# AMD CPU with amd-pstate driver in passive or guided mode ('amd-pstate') or
# Intel, AMD and other CPU brands with acpi-cpufreq driver:
# conservative, ondemand(*), userspace, powersave, performance, schedutil(*).
# Use tlp-stat -p to show the active driver and available governors.
# Important:
# Governors marked (*) above are power efficient for *almost all* workloads
# and therefore kernel and most distributions have chosen them as defaults.
# You should have done your research about advantages/disadvantages *before*
# changing the governor.
# Default: <none>
#CPU_SCALING_GOVERNOR_ON_AC=powersave
#CPU_SCALING_GOVERNOR_ON_BAT=powersave
# Set the min/max frequency available for the scaling governor.
# Possible values depend on your CPU. For available frequencies see
# the output of tlp-stat -p.
# Notes:
# - Min/max frequencies must always be specified for both AC *and* BAT
# - Not recommended for use with the intel_pstate driver, use
# CPU_MIN/MAX_PERF_ON_AC/BAT below instead
# Default: <none>
#CPU_SCALING_MIN_FREQ_ON_AC=0
#CPU_SCALING_MAX_FREQ_ON_AC=0
#CPU_SCALING_MIN_FREQ_ON_BAT=0
#CPU_SCALING_MAX_FREQ_ON_BAT=0
# Set CPU energy/performance policies EPP and EPB:
# performance, balance_performance, default, balance_power, power.
# Values are given in order of increasing power saving.
# Requires:
# * Intel CPU
# EPP: Intel Core i 6th gen. or newer CPU with intel_pstate driver
# EPB: Intel Core i 2nd gen. or newer CPU with intel_pstate driver
# EPP and EPB are mutually exclusive: when EPP is available, Intel CPUs
# will not honor EPB. Only the matching feature will be applied by TLP.
# * AMD Zen 2 or newer CPU
# EPP: amd-pstate driver in active mode ('amd-pstate-epp') as of kernel 6.3
# Default: balance_performance (AC), balance_power (BAT)
#CPU_ENERGY_PERF_POLICY_ON_AC=balance_performance
#CPU_ENERGY_PERF_POLICY_ON_BAT=balance_power
# Set Intel CPU P-state performance: 0..100 (%).
# Limit the max/min P-state to control the power dissipation of the CPU.
# Values are stated as a percentage of the available performance.
# Requires Intel Core i 2nd gen. or newer CPU with intel_pstate driver.
# Default: <none>
#CPU_MIN_PERF_ON_AC=0
#CPU_MAX_PERF_ON_AC=100
#CPU_MIN_PERF_ON_BAT=0
#CPU_MAX_PERF_ON_BAT=30
# Set the CPU "turbo boost" (Intel) or "turbo core" (AMD) feature:
# 0=disable, 1=allow.
# Allows to raise the maximum frequency/P-state of some cores if the
# CPU chip is not fully utilized and below it's intended thermal budget.
# Note: a value of 1 does *not* activate boosting, it just allows it.
# Default: <none>
#CPU_BOOST_ON_AC=1
#CPU_BOOST_ON_BAT=0
# Set CPU dynamic boost feature:
# 0=disable, 1=enable.
# Improve performance by increasing minimum P-state limit dynamically
# whenever a task previously waiting on I/O is selected to run.
# Requires Intel Core i 6th gen. or newer CPU: intel_pstate driver in active mode.
# Note: AMD CPUs currently have no tunable for this.
# Default: <none>
#CPU_HWP_DYN_BOOST_ON_AC=1
#CPU_HWP_DYN_BOOST_ON_BAT=0
# Kernel NMI Watchdog:
# 0=disable (default, saves power), 1=enable (for kernel debugging only).
# Default: 0
#NMI_WATCHDOG=0
# Select platform profile:
# performance, balanced, low-power.
# Controls system operating characteristics around power/performance levels,
# thermal and fan speed. Values are given in order of increasing power saving.
# Note: check the output of tlp-stat -p to determine availability on your
# hardware and additional profiles such as: balanced-performance, quiet, cool.
# Default: <none>
#PLATFORM_PROFILE_ON_AC=performance
#PLATFORM_PROFILE_ON_BAT=low-power
# System suspend mode:
# s2idle: Idle standby - a pure software, light-weight, system sleep state,
# deep: Suspend to RAM - the whole system is put into a low-power state,
# except for memory, usually resulting in higher savings than s2idle.
# CAUTION: changing suspend mode may lead to system instability and even
# data loss. As for the availability of different modes on your system,
# check the output of tlp-stat -s. If unsure, stick with the system default
# by not enabling this.
# Default: <none>
#MEM_SLEEP_ON_AC=s2idle
#MEM_SLEEP_ON_BAT=deep
# Define disk devices on which the following DISK/AHCI_RUNTIME parameters act.
# Separate multiple devices with spaces.
# Devices can be specified by disk ID also (lookup with: tlp diskid).
# Default: "nvme0n1 sda"
#DISK_DEVICES="nvme0n1 sda"
# Disk advanced power management level: 1..254, 255 (max saving, min, off).
# Levels 1..127 may spin down the disk; 255 allowable on most drives.
# Separate values for multiple disks with spaces. Use the special value 'keep'
# to keep the hardware default for the particular disk.
# Default: 254 (AC), 128 (BAT)
#DISK_APM_LEVEL_ON_AC="254 254"
#DISK_APM_LEVEL_ON_BAT="128 128"
# Exclude disk classes from advanced power management (APM):
# sata, ata, usb, ieee1394.
# Separate multiple classes with spaces.
# CAUTION: USB and IEEE1394 disks may fail to mount or data may get corrupted
# with APM enabled. Be careful and make sure you have backups of all affected
# media before removing 'usb' or 'ieee1394' from the denylist!
# Default: "usb ieee1394"
#DISK_APM_CLASS_DENYLIST="usb ieee1394"
# Hard disk spin down timeout:
# 0: spin down disabled
# 1..240: timeouts from 5s to 20min (in units of 5s)
# 241..251: timeouts from 30min to 5.5 hours (in units of 30min)
# See 'man hdparm' for details.
# Separate values for multiple disks with spaces. Use the special value 'keep'
# to keep the hardware default for the particular disk.
# Default: <none>
#DISK_SPINDOWN_TIMEOUT_ON_AC="0 0"
#DISK_SPINDOWN_TIMEOUT_ON_BAT="0 0"
# Select I/O scheduler for the disk devices.
# Multi queue (blk-mq) schedulers:
# mq-deadline(*), none, kyber, bfq
# Single queue schedulers:
# deadline(*), cfq, bfq, noop
# (*) recommended.
# Separate values for multiple disks with spaces. Use the special value 'keep'
# to keep the kernel default scheduler for the particular disk.
# Notes:
# - Multi queue (blk-mq) may need kernel boot option 'scsi_mod.use_blk_mq=1'
# and 'modprobe mq-deadline-iosched|kyber|bfq' on kernels < 5.0
# - Single queue schedulers are legacy now and were removed together with
# the old block layer in kernel 5.0
# Default: keep
#DISK_IOSCHED="mq-deadline mq-deadline"
# AHCI link power management (ALPM) for SATA disks:
# min_power, med_power_with_dipm(*), medium_power, max_performance.
# (*) recommended.
# Multiple values separated with spaces are tried sequentially until success.
# Default: med_power_with_dipm (AC & BAT)
#SATA_LINKPWR_ON_AC="med_power_with_dipm"
#SATA_LINKPWR_ON_BAT="med_power_with_dipm"
# Exclude SATA links from AHCI link power management (ALPM).
# SATA links are specified by their host. Refer to the output of
# tlp-stat -d to determine the host; the format is "hostX".
# Separate multiple hosts with spaces.
# Default: <none>
#SATA_LINKPWR_DENYLIST="host1"
# Runtime Power Management for NVMe, SATA, ATA and USB disks
# as well as SATA ports:
# on=disable, auto=enable.
# Note: SATA controllers are PCIe bus devices and handled by RUNTIME_PM further
# down.
# Default: on (AC), auto (BAT)
#AHCI_RUNTIME_PM_ON_AC=on
#AHCI_RUNTIME_PM_ON_BAT=auto
# Seconds of inactivity before disk is suspended.
# Note: effective only when AHCI_RUNTIME_PM_ON_AC/BAT is activated.
# Default: 15
#AHCI_RUNTIME_PM_TIMEOUT=15
# Power off optical drive in UltraBay/MediaBay: 0=disable, 1=enable.
# Drive can be powered on again by releasing (and reinserting) the eject lever
# or by pressing the disc eject button on newer models.
# Note: an UltraBay/MediaBay hard disk is never powered off.
# Default: 0
#BAY_POWEROFF_ON_AC=0
#BAY_POWEROFF_ON_BAT=0
# Optical drive device to power off
# Default: sr0
#BAY_DEVICE="sr0"
# Set the min/max/turbo frequency for the Intel GPU.
# Possible values depend on your hardware. For available frequencies see
# the output of tlp-stat -g.
# Default: <none>
#INTEL_GPU_MIN_FREQ_ON_AC=0
#INTEL_GPU_MIN_FREQ_ON_BAT=0
#INTEL_GPU_MAX_FREQ_ON_AC=0
#INTEL_GPU_MAX_FREQ_ON_BAT=0
#INTEL_GPU_BOOST_FREQ_ON_AC=0
#INTEL_GPU_BOOST_FREQ_ON_BAT=0
# AMD GPU power management.
# Performance level (DPM): auto, low, high; auto is recommended.
# Note: requires amdgpu or radeon driver.
# Default: auto
#RADEON_DPM_PERF_LEVEL_ON_AC=auto
#RADEON_DPM_PERF_LEVEL_ON_BAT=auto
# Dynamic power management method (DPM): balanced, battery, performance.
# Note: radeon driver only.
# Default: <none>
#RADEON_DPM_STATE_ON_AC=performance
#RADEON_DPM_STATE_ON_BAT=battery
# Graphics clock speed (profile method): low, mid, high, auto, default;
# auto = mid on BAT, high on AC.
# Note: radeon driver on legacy ATI hardware only (where DPM is not available).
# Default: default
#RADEON_POWER_PROFILE_ON_AC=default
#RADEON_POWER_PROFILE_ON_BAT=default
# Display panel adaptive backlight modulation (ABM) level: 0(off), 1..4.
# Values 1..4 control the maximum brightness reduction allowed by the ABM
# algorithm, where 1 represents the least and 4 the most power saving.
# Notes:
# - Requires AMD Vega or newer GPU with amdgpu driver as of kernel 6.9
# - Savings are made at the expense of color balance
# Default: 0 (AC), 1 (BAT)
#AMDGPU_ABM_LEVEL_ON_AC=0
#AMDGPU_ABM_LEVEL_ON_BAT=3
# Wi-Fi power saving mode: on=enable, off=disable.
# Default: off (AC), on (BAT)
#WIFI_PWR_ON_AC=off
#WIFI_PWR_ON_BAT=on
# Disable Wake-on-LAN: Y/N.
# Default: Y
#WOL_DISABLE=Y
# Enable audio power saving for Intel HDA, AC97 devices (timeout in secs).
# A value of 0 disables, >= 1 enables power saving.
# Note: 1 is recommended for Linux desktop environments with PulseAudio,
# systems without PulseAudio may require 10.
# Default: 1
# >>> hostname=arch-desktop
SOUND_POWER_SAVE_ON_AC=1
SOUND_POWER_SAVE_ON_BAT=1
# <<<
# >>> hostname=arch-laptop
# SOUND_POWER_SAVE_ON_AC=0
# SOUND_POWER_SAVE_ON_BAT=0
# <<<
# Disable controller too (HDA only): Y/N.
# Note: effective only when SOUND_POWER_SAVE_ON_AC/BAT is activated.
# Default: Y
#SOUND_POWER_SAVE_CONTROLLER=Y
# PCIe Active State Power Management (ASPM):
# default(*), performance, powersave, powersupersave.
# (*) keeps BIOS ASPM defaults (recommended)
# Default: <none>
#PCIE_ASPM_ON_AC=default
#PCIE_ASPM_ON_BAT=default
# Runtime Power Management for PCIe bus devices: on=disable, auto=enable.
# Default: on (AC), auto (BAT)
#RUNTIME_PM_ON_AC=on
#RUNTIME_PM_ON_BAT=auto
# Exclude listed PCIe device adresses from Runtime PM.
# Note: this preserves the kernel driver default, to force a certain state
# use RUNTIME_PM_ENABLE/DISABLE instead.
# Separate multiple addresses with spaces.
# Use lspci to get the adresses (1st column).
# Default: <none>
#RUNTIME_PM_DENYLIST="11:22.3 44:55.6"
# Exclude PCIe devices assigned to the listed drivers from Runtime PM.
# Note: this preserves the kernel driver default, to force a certain state
# use RUNTIME_PM_ENABLE/DISABLE instead.
# Separate multiple drivers with spaces.
# Default: "mei_me nouveau radeon xhci_hcd", use "" to disable completely.
#RUNTIME_PM_DRIVER_DENYLIST="mei_me nouveau radeon xhci_hcd"
# Permanently enable/disable Runtime PM for listed PCIe device addresses
# (independent of the power source). This has priority over all preceding
# Runtime PM settings. Separate multiple addresses with spaces.
# Use lspci to get the adresses (1st column).
# Default: <none>
#RUNTIME_PM_ENABLE="11:22.3"
#RUNTIME_PM_DISABLE="44:55.6"
# Set to 0 to disable, 1 to enable USB autosuspend feature.
# Default: 1
#USB_AUTOSUSPEND=1
# Exclude listed devices from USB autosuspend (separate with spaces).
# Use lsusb to get the ids.
# Note: input devices (usbhid) and libsane-supported scanners are excluded
# automatically.
# Default: <none>
#USB_DENYLIST="1111:2222 3333:4444"
# Exclude audio devices from USB autosuspend:
# 0=do not exclude, 1=exclude.
# Default: 1
#USB_EXCLUDE_AUDIO=1
# Exclude bluetooth devices from USB autosuspend:
# 0=do not exclude, 1=exclude.
# Default: 0
#USB_EXCLUDE_BTUSB=0
# Exclude phone devices from USB autosuspend:
# 0=do not exclude, 1=exclude (enable charging).
# Default: 0
#USB_EXCLUDE_PHONE=0
# Exclude printers from USB autosuspend:
# 0=do not exclude, 1=exclude.
# Default: 1
#USB_EXCLUDE_PRINTER=1
# Exclude WWAN devices from USB autosuspend:
# 0=do not exclude, 1=exclude.
# Default: 0
#USB_EXCLUDE_WWAN=0
# Allow USB autosuspend for listed devices even if already denylisted or
# excluded above (separate with spaces). Use lsusb to get the ids.
# Default: 0
#USB_ALLOWLIST="1111:2222 3333:4444"
# Restore radio device state (Bluetooth, WiFi, WWAN) from previous shutdown
# on system startup: 0=disable, 1=enable.
# Note: the parameters DEVICES_TO_DISABLE/ENABLE_ON_STARTUP/SHUTDOWN below
# are ignored when this is enabled.
# Default: 0
#RESTORE_DEVICE_STATE_ON_STARTUP=0
# Radio devices to disable on startup: bluetooth, nfc, wifi, wwan.
# Separate multiple devices with spaces.
# Default: <none>
#DEVICES_TO_DISABLE_ON_STARTUP="bluetooth nfc wifi wwan"
# Radio devices to enable on startup: bluetooth, nfc, wifi, wwan.
# Separate multiple devices with spaces.
# Default: <none>
#DEVICES_TO_ENABLE_ON_STARTUP="wifi"
# Radio devices to enable on AC: bluetooth, nfc, wifi, wwan.
# Default: <none>
#DEVICES_TO_ENABLE_ON_AC="bluetooth nfc wifi wwan"
# Radio devices to disable on battery: bluetooth, nfc, wifi, wwan.
# Default: <none>
#DEVICES_TO_DISABLE_ON_BAT="bluetooth nfc wifi wwan"
# Radio devices to disable on battery when not in use (not connected):
# bluetooth, nfc, wifi, wwan.
# Default: <none>
#DEVICES_TO_DISABLE_ON_BAT_NOT_IN_USE="bluetooth nfc wifi wwan"
# Battery Care -- Charge thresholds
# Charging starts when the charger is connected and the charge level
# is below the start threshold. Charging stops when the charge level
# is above the stop threshold.
# Required hardware: Lenovo ThinkPads and select other laptop brands
# are driven via specific plugins
# - Active plugin and support status are shown by tlp-stat -b
# - Vendor specific threshold levels are shown by tlp-stat -b, some
# laptops support only 1 (on)/ 0 (off) instead of a percentage level
# - When your hardware supports a start *and* a stop threshold, you must
# specify both, otherwise TLP will refuse to apply the single threshold
# - When your hardware supports only a stop threshold, set the start
# value to 0
# - Older ThinkPads may require an external kernel module, refer to the
# output of tlp-stat -b
# For further explanation and vendor specific details refer to
# - https://linrunner.de/tlp/settings/battery.html
# - https://linrunner.de/tlp/settings/bc-vendors.html
# BAT0: Primary / Main / Internal battery
# Note: also use for batteries BATC, BATT and CMB0
# Default: <none>
# Battery charge level below which charging will begin.
#START_CHARGE_THRESH_BAT0=75
# Battery charge level above which charging will stop.
#STOP_CHARGE_THRESH_BAT0=80
# BAT1: Secondary / Ultrabay / Slice / Replaceable battery
# Note: primary on some laptops
# Default: <none>
# Battery charge level below which charging will begin.
#START_CHARGE_THRESH_BAT1=75
# Battery charge level above which charging will stop.
#STOP_CHARGE_THRESH_BAT1=80
# Restore charge thresholds when AC is unplugged: 0=disable, 1=enable.
# Default: 0
#RESTORE_THRESHOLDS_ON_BAT=1
# ------------------------------------------------------------------------------
# tlp-rdw - Parameters for the radio device wizard
# Possible devices: bluetooth, wifi, wwan.
# Separate multiple radio devices with spaces.
# Default: <none> (for all parameters below)
# Radio devices to disable on connect.
#DEVICES_TO_DISABLE_ON_LAN_CONNECT="wifi wwan"
#DEVICES_TO_DISABLE_ON_WIFI_CONNECT="wwan"
#DEVICES_TO_DISABLE_ON_WWAN_CONNECT="wifi"
# Radio devices to enable on disconnect.
#DEVICES_TO_ENABLE_ON_LAN_DISCONNECT="wifi wwan"
#DEVICES_TO_ENABLE_ON_WIFI_DISCONNECT=""
#DEVICES_TO_ENABLE_ON_WWAN_DISCONNECT=""
# Radio devices to enable/disable when docked.
#DEVICES_TO_ENABLE_ON_DOCK=""
#DEVICES_TO_DISABLE_ON_DOCK=""
# Radio devices to enable/disable when undocked.
#DEVICES_TO_ENABLE_ON_UNDOCK="wifi"
#DEVICES_TO_DISABLE_ON_UNDOCK=""
+3
View File
@@ -54,6 +54,9 @@ gvfs-gphoto2
gvfs-mtp gvfs-mtp
gvim gvim
htop htop
hunspell
hunspell-en_us
hunspell-nl
i3lock-color-git i3lock-color-git
imagemagick imagemagick
inetutils inetutils