1874 lines
71 KiB
Org Mode
1874 lines
71 KiB
Org Mode
#+TITLE: KyleKrein's GNU Emacs Config
|
||
#+STARTUP: showeverything
|
||
#+OPTIONS: toc:2
|
||
#+PROPERTY: header-args:emacs-lisp :lexical t
|
||
|
||
* Table of contents :toc:
|
||
- [[#some-random-stuff-to-load-first][Some random stuff to load first]]
|
||
- [[#recent-files][Recent Files]]
|
||
- [[#golden-ratio][Golden ratio]]
|
||
- [[#duplicate-line][Duplicate line]]
|
||
- [[#keybindings][Keybindings]]
|
||
- [[#focus-new-windows][Focus new windows]]
|
||
- [[#support-functions][Support functions]]
|
||
- [[#git-package][Git package]]
|
||
- [[#emacs-function-launcher][Emacs function launcher]]
|
||
- [[#copy-to-clipboard][Copy to clipboard]]
|
||
- [[#detect-wsl][Detect WSL]]
|
||
- [[#is-android][Is Android]]
|
||
- [[#notifications][Notifications]]
|
||
- [[#app-launcher][App Launcher]]
|
||
- [[#standalone-run][Standalone run]]
|
||
- [[#backup-files-tilda-files][Backup files (tilda files)]]
|
||
- [[#dashboard][Dashboard]]
|
||
- [[#diminish][Diminish]]
|
||
- [[#dired-file-manager][DIRED (File manager)]]
|
||
- [[#emoji][Emoji]]
|
||
- [[#copy-to-clipboard-1][Copy to clipboard]]
|
||
- [[#standalone-emoji-picker][Standalone emoji picker]]
|
||
- [[#ediff][EDIFF]]
|
||
- [[#emacs-everywhere][Emacs Everywhere]]
|
||
- [[#fonts][Fonts]]
|
||
- [[#sane-defaults][Sane defaults]]
|
||
- [[#battery-info][Battery info]]
|
||
- [[#epub-support-reader-in-emacs][Epub support (Reader in Emacs)]]
|
||
- [[#magit][MAGIT]]
|
||
- [[#modeline][Modeline]]
|
||
- [[#drawing-tools][Drawing tools]]
|
||
- [[#rainbow-delimiters][RAINBOW DELIMITERS]]
|
||
- [[#calendar][Calendar]]
|
||
- [[#org-babel][Org Babel]]
|
||
- [[#org-mode][ORG MODE]]
|
||
- [[#org-copy-link][Org Copy Link]]
|
||
- [[#enabling-table-of-contents][Enabling Table of Contents]]
|
||
- [[#modern-org-mode][Modern Org Mode]]
|
||
- [[#org-level-headers][Org Level Headers]]
|
||
- [[#source-code-block-tag-expansion][Source Code Block Tag Expansion]]
|
||
- [[#insert-pictures][Insert pictures]]
|
||
- [[#update-org-tables][Update org tables]]
|
||
- [[#org-transclusion][Org transclusion]]
|
||
- [[#org-roam][ORG ROAM]]
|
||
- [[#org-roam-itself][Org Roam itself]]
|
||
- [[#ripgrep-files][Ripgrep files]]
|
||
- [[#org-roam-ui][Org Roam UI]]
|
||
- [[#inbox][Inbox]]
|
||
- [[#org-agenda][Org Agenda]]
|
||
- [[#refresh][Refresh]]
|
||
- [[#auto-update-agenda][Auto update agenda]]
|
||
- [[#todos-only-from-projects][TODOs only from Projects]]
|
||
- [[#small-settings][Small settings]]
|
||
- [[#todos-in-today][Todos in Today]]
|
||
- [[#notifications-1][Notifications]]
|
||
- [[#rainbow-mode][RAINBOW MODE]]
|
||
- [[#ai][AI]]
|
||
- [[#gptel][GPT.el]]
|
||
- [[#minuet][Minuet]]
|
||
- [[#shells-and-terminals][SHELLS AND TERMINALS]]
|
||
- [[#eshell][Eshell]]
|
||
- [[#vterm][Vterm]]
|
||
- [[#vterm-toggle][Vterm-Toggle]]
|
||
- [[#sudo-edit][SUDO EDIT]]
|
||
- [[#password-store][Password store]]
|
||
- [[#cmake-projects][CMake Projects]]
|
||
- [[#direnv][Direnv]]
|
||
- [[#language-support][Language support]]
|
||
- [[#nix][Nix]]
|
||
- [[#glsl][GLSL]]
|
||
- [[#qml][QML]]
|
||
- [[#rmlui][RmlUi]]
|
||
- [[#cmake][CMake]]
|
||
- [[#global-treesitter][Global treesitter]]
|
||
- [[#eglot][Eglot]]
|
||
- [[#nerd-icons][Nerd Icons]]
|
||
- [[#nerd-icons-completion][Nerd Icons Completion]]
|
||
- [[#persist-state][Persist state]]
|
||
- [[#multiple-cursors][Multiple cursors]]
|
||
- [[#buffer-move][Buffer Move]]
|
||
- [[#completions][Completions]]
|
||
- [[#corfu][Corfu]]
|
||
- [[#cape][Cape]]
|
||
- [[#vertico][Vertico]]
|
||
- [[#orderless][Orderless]]
|
||
- [[#consult][Consult]]
|
||
- [[#descriptions][Descriptions]]
|
||
- [[#communication][Communication]]
|
||
- [[#theme][Theme]]
|
||
- [[#theme-loading][Theme loading]]
|
||
- [[#transparency][Transparency]]
|
||
- [[#which-key][WHICH-KEY]]
|
||
- [[#emacs-on-android][Emacs on Android]]
|
||
- [[#fonts-1][Fonts]]
|
||
- [[#settings][Settings]]
|
||
- [[#emacs-on-wsl][Emacs on WSL]]
|
||
- [[#clipboard-fix][Clipboard fix]]
|
||
|
||
* Some random stuff to load first
|
||
** Recent Files
|
||
#+begin_src emacs-lisp
|
||
(recentf-mode t)
|
||
#+end_src
|
||
** Golden ratio
|
||
[[https://github.com/roman/golden-ratio.el][golden-ratio.el]] resizes windows content that you're working on
|
||
#+begin_src emacs-lisp
|
||
(use-package golden-ratio
|
||
:ensure t
|
||
:init
|
||
(setq golden-ratio-auto-scale t)
|
||
(golden-ratio-mode 1))
|
||
#+end_src
|
||
** Duplicate line
|
||
#+begin_src emacs-lisp
|
||
(defun kylekrein/duplicate-line()
|
||
"Duplicate current line and move cursor to it"
|
||
(interactive)
|
||
(let ((column (- (point) (point-at-bol)))
|
||
(line (let ((s (thing-at-point 'line t)))
|
||
(if s (string-remove-suffix "\n" s) ""))))
|
||
(move-end-of-line 1)
|
||
(newline)
|
||
(insert line)
|
||
(move-beginning-of-line 1)
|
||
(forward-char column)))
|
||
#+end_src
|
||
** Keybindings
|
||
#+begin_src emacs-lisp
|
||
(global-set-key [remap list-buffers] 'ibuffer)
|
||
(global-set-key (kbd "M-o") 'other-window)
|
||
(global-set-key (kbd "C-c o t") 'vterm-toggle)
|
||
(global-set-key (kbd "C-c o a") 'org-agenda)
|
||
(global-set-key (kbd "C-c o d") 'dashboard-open)
|
||
(global-set-key (kbd "C-c o p") 'pass)
|
||
(global-set-key (kbd "C-c o m") 'magit)
|
||
|
||
(global-set-key (kbd "C-.") 'kylekrein/duplicate-line)
|
||
;;(windmove-default-keybindings) ;; move between windows with S-<left>, S-<right>, S-<up>, S-<down>
|
||
#+end_src
|
||
** Focus new windows
|
||
Found this [[https://emacs.stackexchange.com/questions/21770/automatically-switch-focus-to-new-window][here]] and [[https://github.com/snackon/Witchmacs#creating-a-new-window-switches-your-cursor-to-it][here]]
|
||
#+begin_src emacs-lisp
|
||
(defun split-and-follow-horizontally ()
|
||
(interactive)
|
||
(split-window-below)
|
||
(balance-windows))
|
||
|
||
(defun split-and-follow-vertically ()
|
||
(interactive)
|
||
(split-window-right)
|
||
(balance-windows))
|
||
|
||
(use-package emacs
|
||
:bind (:map ctl-x-map
|
||
("2" . split-and-follow-horizontally)
|
||
("3" . split-and-follow-vertically))
|
||
:custom
|
||
(info-lookup-other-window-flag t)
|
||
(help-window-select t "Switch to help buffers automatically"))
|
||
;; Auto-select new Info buffer window when it’s created.
|
||
(advice-add 'info-lookup :after
|
||
(lambda (&rest _)
|
||
(when-let (window (get-buffer-window "*info*"))
|
||
(select-window window))))
|
||
|
||
;; Auto-select new window after splitting. Splitting commands almost
|
||
;;,all use `split-window’, so advice the function for auto selection.
|
||
(advice-add 'split-window :after
|
||
(lambda (&rest _) (select-window (get-lru-window))))
|
||
#+end_src
|
||
* Support functions
|
||
** Git package
|
||
#+begin_src emacs-lisp
|
||
(defun git-package (url)
|
||
(let* ((pkg-name (file-name-base (directory-file-name url)))
|
||
(pkg-sym (intern pkg-name)))
|
||
(eval
|
||
`(use-package ,pkg-sym
|
||
:vc (:url ,url :rev :newest)
|
||
:ensure nil))))
|
||
#+end_src
|
||
** Emacs function launcher
|
||
Launches emacs function as a window
|
||
#+begin_src emacs-lisp
|
||
(defun create-launcher-frame ()
|
||
(make-frame '((name . "emacs-run-launcher")
|
||
(minibuffer . only)
|
||
(fullscreen . 0)
|
||
(undecorated . t)
|
||
(internal-border-width . 10)
|
||
(width . 80)
|
||
(height . 11))))
|
||
|
||
(defun emacs-run-launcher (func)
|
||
"Create and select a frame called emacs-run-launcher which consists only of a minibuffer and has specific dimensions. Runs func on that frame, which is an emacs command that prompts you to select something and open it dmenu like behaviour. Delete the frame after that command has exited"
|
||
(interactive)
|
||
(with-selected-frame
|
||
(make-frame '((name . "emacs-run-launcher")
|
||
(minibuffer . only)
|
||
(fullscreen . 0) ; no fullscreen
|
||
(undecorated . t) ; remove title bar
|
||
;;(auto-raise . t) ; focus on this frame
|
||
;;(tool-bar-lines . 0)
|
||
;;(menu-bar-lines . 0)
|
||
(internal-border-width . 10)
|
||
(width . 80)
|
||
(height . 11)))
|
||
(unwind-protect
|
||
(funcall func)
|
||
(delete-frame))))
|
||
#+end_src
|
||
** Copy to clipboard
|
||
Copies to both kill ring and system clipboard
|
||
#+begin_src emacs-lisp
|
||
;;(setq select-enable-primary t)
|
||
(defun kylekrein/copy-to-clipboard (text)
|
||
(with-temp-buffer
|
||
(insert text)
|
||
(copy-region-as-kill (point-min) (point-max))
|
||
(clipboard-kill-region (point-min) (point-max))))
|
||
#+end_src
|
||
** Detect WSL
|
||
#+begin_src emacs-lisp
|
||
(defun kylekrein/detect-wsl ()
|
||
(and (eq system-type 'gnu/linux)
|
||
(file-exists-p "/proc/sys/fs/binfmt_misc/WSLInterop")))
|
||
#+end_src
|
||
** Is Android
|
||
#+begin_src emacs-lisp
|
||
(defun kylekrein/is-android ()
|
||
(string-equal system-type "android"))
|
||
#+end_src
|
||
** Notifications
|
||
*** Alert package
|
||
#+begin_src emacs-lisp
|
||
(use-package alert
|
||
:ensure t
|
||
)
|
||
#+end_src
|
||
*** Android notifications
|
||
Found the code [[https://www.reddit.com/r/emacs/comments/18xvtns/emacs_notifications_on_linux_and_android/][here]]
|
||
#+begin_src emacs-lisp
|
||
(require 'alert)
|
||
|
||
(defun alert-android-notifications-notify (info)
|
||
(unless (kylekrein/is-android)
|
||
(error "Android notifications are only supported on Android systems"))
|
||
|
||
"Send INFO using android-notifications-notify."
|
||
(let ((title (or (plist-get info :title) "Org Alert Reminder"))
|
||
(body (or (plist-get info :message) ""))
|
||
(urgency (let ((severity (plist-get info :severity)))
|
||
(cond ((eq severity 'urgent) 'critical)
|
||
((eq severity 'high) 'critical)
|
||
((eq severity 'moderate) 'normal)
|
||
((eq severity 'low) 'low)
|
||
((eq severity 'trivial) 'low)
|
||
(t 'normal))))
|
||
(icon (or (plist-get info :icon) alert-default-icon)))
|
||
(android-notifications-notify
|
||
:title title
|
||
:body body
|
||
:urgency urgency
|
||
:icon icon
|
||
)))
|
||
|
||
(alert-define-style 'android-notifications :title "Android Notifications"
|
||
:notifier #'alert-android-notifications-notify
|
||
)
|
||
|
||
#+end_src
|
||
*** Windows Notifications
|
||
Using [[https://github.com/gkowzan/alert-toast][Alert toast]]
|
||
#+begin_src emacs-lisp
|
||
(use-package alert-toast :ensure t :after alert)
|
||
#+end_src
|
||
*** Setting notification backend
|
||
#+begin_src emacs-lisp
|
||
(setq alert-default-style
|
||
(cond
|
||
((kylekrein/is-android) 'android-notifications)
|
||
((kylekrein/detect-wsl) 'toast)
|
||
(t 'libnotify)))
|
||
#+end_src
|
||
* App Launcher
|
||
This code creates a menu to launch linux apps, that have Desktop entry.
|
||
Code was taken from [[https://github.com/SebastienWae/app-launcher/blob/main/app-launcher.el][this awesome repo]]
|
||
#+begin_src emacs-lisp
|
||
(git-package "https://github.com/SebastienWae/app-launcher")
|
||
(use-package app-launcher)
|
||
#+end_src
|
||
** Standalone run
|
||
This code snippet runs app launcher without emacs frame
|
||
To use it, create a global keyboard shortcut with the following code
|
||
~emacsclient -cF "((visibility . nil))" -e "(emacs-run-app-launcher)"~
|
||
#+begin_src emacs-lisp
|
||
(defun emacs-run-app-launcher()
|
||
(emacs-run-launcher 'app-launcher-run-app))
|
||
#+end_src
|
||
* Backup files (tilda files)
|
||
By default, Emacs creates automatic backups of files in their original directories, such “file.el” and the backup “file.el~”. This leads to a lot of clutter, so let’s tell Emacs to put all backups that it creates in the ~.emacs.d~ directory.
|
||
#+begin_src emacs-lisp
|
||
(setq backup-directory-alist '((".*" . "~/.emacs.d/tildafiles")))
|
||
#+end_src
|
||
* Dashboard
|
||
Emacs Dashboard is an extensible startup screen showing you recent files, bookmarks, agenda items and an Emacs banner.
|
||
#+begin_src emacs-lisp
|
||
(use-package dashboard
|
||
:ensure t
|
||
:after (:all nerd-icons org org-agenda org-roam)
|
||
:init
|
||
(setq initial-buffer-choice (lambda () (get-buffer-create dashboard-buffer-name)))
|
||
(setq dashboard-week-agenda t)
|
||
;;(setq dashboard-filter-agenda-entry 'dashboard-no-filter-agenda)
|
||
(setq dashboard-display-icons-p t) ; display icons on both GUI and terminal
|
||
(setq dashboard-icon-type 'nerd-icons) ; use `nerd-icons' package
|
||
(setq dashboard-set-heading-icons t)
|
||
(setq dashboard-projects-backend 'project-el)
|
||
(setq dashboard-set-file-icons t)
|
||
(setq dashboard-banner-logo-title "Emacs Is More Than A Text Editor!\nPowered by Nix")
|
||
;;(setq dashboard-startup-banner 'logo) ;; use standard emacs logo as banner
|
||
(setq dashboard-center-content nil) ;; set to 't' for centered content
|
||
(setq dashboard-items '((recents . 5)
|
||
(agenda . 5 )
|
||
(bookmarks . 3)
|
||
(projects . 3)
|
||
(registers . 3)))
|
||
(setq dashboard-startupify-list '(dashboard-insert-banner
|
||
dashboard-insert-newline
|
||
dashboard-insert-banner-title
|
||
dashboard-insert-newline
|
||
dashboard-insert-navigator
|
||
dashboard-insert-newline
|
||
dashboard-insert-init-info
|
||
;dashboard-insert-items
|
||
dashboard-insert-newline
|
||
dashboard-insert-footer))
|
||
(setq dashboard-navigator-buttons
|
||
`(;; Line 1
|
||
((,(nerd-icons-mdicon "nf-md-inbox" :height 1.1 :v-adjust 0.0)
|
||
"To Inbox"
|
||
"Capture to inbox"
|
||
(lambda (&rest _) (kylekrein/org-roam-capture-inbox)))
|
||
|
||
(,(nerd-icons-mdicon "nf-md-calendar" :height 1.1 :v-adjust 0.0)
|
||
"Agenda"
|
||
"View agenda"
|
||
(lambda (&rest _) (org-agenda)))
|
||
|
||
(,(nerd-icons-mdicon "nf-md-note" :height 1.1 :v-adjust 0.0)
|
||
"Note"
|
||
"Find a note"
|
||
(lambda (&rest _) (org-roam-node-find))))
|
||
|
||
;; Line 2
|
||
((,(nerd-icons-mdicon "nf-md-sync" :height 1.1 :v-adjust 0.0)
|
||
"Sync"
|
||
"Sync org-roam and agenda"
|
||
(lambda (&rest _)
|
||
(org-roam-db-sync)
|
||
(kylekrein/org-roam-refresh-agenda-list)
|
||
(org-agenda-redo)
|
||
(message "Org-Roam and Agenda synced!")))
|
||
|
||
(,(nerd-icons-mdicon "nf-md-calendar_today" :height 1.1 :v-adjust 0.0)
|
||
"Today"
|
||
"View today's tasks"
|
||
(lambda (&rest _) (org-agenda nil "a"))))))
|
||
|
||
:custom
|
||
(dashboard-modify-heading-icons '((recents . "nf-oct-file_text")
|
||
(bookmarks . "nf-oct-book")))
|
||
:config
|
||
(dashboard-setup-startup-hook)
|
||
(let ((banner-file "~/.emacs.d/nixmacs.xpm"))
|
||
(when (file-exists-p (expand-file-name banner-file))
|
||
(setq dashboard-startup-banner ,banner-file))))
|
||
#+end_src
|
||
* Diminish
|
||
This package implements hiding or abbreviation of the modeline displays (lighters) of minor-modes. With this package installed, you can add ‘:diminish’ to any use-package block to hide that particular mode in the modeline.
|
||
#+begin_src emacs-lisp
|
||
(use-package diminish :ensure t)
|
||
#+end_src
|
||
* DIRED (File manager)
|
||
#+begin_src emacs-lisp
|
||
(use-package dired-open
|
||
:ensure t
|
||
:config
|
||
(setq dired-open-extensions '(("gif" . "gwenview")
|
||
("jpg" . "gwenview")
|
||
("png" . "gwenview")
|
||
("mkv" . "vlc")
|
||
("mp4" . "vlc"))))
|
||
|
||
(use-package dired
|
||
:config
|
||
(setq dired-listing-switches
|
||
"--almost-all --human-readable --group-directories-first --no-group")
|
||
;; this command is useful when you want to close the window of `dirvish-side'
|
||
;; automatically when opening a file
|
||
(put 'dired-find-alternate-file 'disabled nil))
|
||
|
||
(use-package dirvish
|
||
:ensure t
|
||
:init
|
||
(dirvish-override-dired-mode)
|
||
:custom
|
||
(dirvish-quick-access-entries ; It's a custom option, `setq' won't work
|
||
'(("h" "~/" "Home")
|
||
("d" "~/Downloads/" "Downloads")))
|
||
:config
|
||
;;(dirvish-peek-mode) ; Preview files in minibuffer
|
||
(dirvish-side-follow-mode) ; similar to `treemacs-follow-mode'
|
||
(setq dirvish-mode-line-format
|
||
'(:left (sort symlink) :right (omit yank index)))
|
||
(setq dirvish-attributes ; The order *MATTERS* for some attributes
|
||
'(vc-state subtree-state nerd-icons collapse git-msg file-time file-size)
|
||
dirvish-side-attributes
|
||
'(vc-state nerd-icons collapse file-size))
|
||
;; open large directory (over 20000 files) asynchronously with `fd' command
|
||
(setq dirvish-large-directory-threshold 20000)
|
||
(setq dirvish-use-mode-line nil)
|
||
(setq dirvish-default-layout '(0 0.4 0.6))
|
||
:bind ; Bind `dirvish-fd|dirvish-side|dirvish-dwim' as you see fit
|
||
(("C-c f" . dirvish-dwim)
|
||
("C-c o f" . dirvish-side)
|
||
:map dirvish-mode-map ; Dirvish inherits `dired-mode-map'
|
||
(";" . dired-up-directory) ; So you can adjust `dired' bindings here
|
||
("?" . dirvish-dispatch) ; [?] a helpful cheatsheet
|
||
("a" . dirvish-setup-menu) ; [a]ttributes settings:`t' toggles mtime, `f' toggles fullframe, etc.
|
||
("f" . dirvish-file-info-menu) ; [f]ile info
|
||
("o" . dirvish-quick-access) ; [o]pen `dirvish-quick-access-entries'
|
||
("s" . dirvish-quicksort) ; [s]ort flie list
|
||
("r" . dirvish-history-jump) ; [r]ecent visited
|
||
("l" . dirvish-ls-switches-menu) ; [l]s command flags
|
||
("v" . dirvish-vc-menu) ; [v]ersion control commands
|
||
("*" . dirvish-mark-menu)
|
||
("y" . dirvish-yank-menu)
|
||
("N" . dirvish-narrow)
|
||
("^" . dirvish-history-last)
|
||
("TAB" . dirvish-subtree-toggle)
|
||
("M-f" . dirvish-history-go-forward)
|
||
("M-b" . dirvish-history-go-backward)
|
||
("M-e" . dirvish-emerge-menu)))
|
||
|
||
#+end_src
|
||
* Emoji
|
||
** Copy to clipboard
|
||
#+begin_src emacs-lisp
|
||
(use-package emojify :ensure t)
|
||
(defun kylekrein/copy-emoji-to-clipboard()
|
||
(interactive)
|
||
(require 'emojify)
|
||
;;(let ((emoji (emoji--read-emoji))) ;;works without external package, but not so pretty
|
||
(let ((emoji (emojify-completing-read "Copy Emoji: ")))
|
||
(when emoji
|
||
(kylekrein/copy-to-clipboard emoji)
|
||
(message "Copied: %s" (current-kill 0 t)))))
|
||
#+end_src
|
||
** Standalone emoji picker
|
||
To use it, create a global keyboard shortcut with the following code
|
||
~emacsclient -cF "((visibility . nil))" -e "(emacs-run-emoji-picker)"~
|
||
#+begin_src emacs-lisp
|
||
(defun emacs-run-emoji-picker ()
|
||
"Create and select a frame called emacs-run-launcher which consists only of a minibuffer and has specific dimensions. Runs func on that frame, which is an emacs command that prompts you to select something and open it dmenu like behaviour. Delete the frame after some time after that command has exited in order to keep copied text in system clipboard"
|
||
(interactive)
|
||
(let ((launcher-frame (create-launcher-frame)))
|
||
(with-selected-frame launcher-frame
|
||
(kylekrein/copy-emoji-to-clipboard)
|
||
(make-frame-invisible launcher-frame)
|
||
(run-at-time "60 sec" nil (lambda (frame) (delete-frame frame)) launcher-frame))))
|
||
#+end_src
|
||
* EDIFF
|
||
#+begin_src emacs-lisp
|
||
(setq ediff-split-window-function 'split-window-horizontally)
|
||
;;(setq ediff-window-setup-function 'ediff-setup-windows-plain)
|
||
#+end_src
|
||
* Emacs Everywhere
|
||
Doesn't work on Hyprland (22.05.2025)
|
||
#+begin_src emacs-lispp
|
||
(use-package emacs-everywhere :ensure t)
|
||
#+end_src
|
||
* Fonts
|
||
Defining the various fonts that Emacs will use.
|
||
#+begin_src emacs-lisp
|
||
(set-face-attribute 'variable-pitch nil
|
||
:family "DejaVu Sans";;"ET Bembo"
|
||
:height 220
|
||
:weight 'normal)
|
||
(set-face-attribute 'default nil
|
||
:family "Iosevka"
|
||
:height 210
|
||
:weight 'medium)
|
||
|
||
(set-face-attribute 'fixed-pitch nil
|
||
:family "Iosevka"
|
||
:height 210
|
||
:weight 'medium)
|
||
|
||
;; Makes commented text and keywords italics.
|
||
;; This is working in emacsclient but not emacs.
|
||
;; Your font must have an italic face available.
|
||
(set-face-attribute 'font-lock-comment-face nil
|
||
:slant 'italic)
|
||
(set-face-attribute 'font-lock-keyword-face nil
|
||
:slant 'italic)
|
||
|
||
;; This sets the default font on all graphical frames created after restarting Emacs.
|
||
;; Does the same thing as 'set-face-attribute default' above, but emacsclient fonts
|
||
;; are not right unless I also add this method of setting the default font.
|
||
;;(add-to-list 'default-frame-alist '(font . "Iosevka Mono-20"))
|
||
|
||
;; Uncomment the following line if line spacing needs adjusting.
|
||
(setq-default line-spacing 0.12)
|
||
|
||
|
||
(add-hook 'text-mode-hook #'variable-pitch-mode)
|
||
;; Enable variable-pitch-mode in Org
|
||
(add-hook 'org-mode-hook #'variable-pitch-mode)
|
||
|
||
;; Ensure code blocks, tables, and special elements remain fixed-pitch
|
||
(custom-set-faces
|
||
;; Keep code blocks, src, and tables fixed-pitch (Iosevka)
|
||
'(org-block ((t (:inherit fixed-pitch))))
|
||
'(org-block-begin-line ((t (:inherit fixed-pitch))))
|
||
'(org-block-end-line ((t (:inherit fixed-pitch))))
|
||
'(org-table ((t (:inherit fixed-pitch))))
|
||
'(org-code ((t (:inherit fixed-pitch))))
|
||
'(org-verbatim ((t (:inherit fixed-pitch))))
|
||
'(org-meta-line ((t (:inherit fixed-pitch))))
|
||
'(org-checkbox ((t (:inherit fixed-pitch))))
|
||
)
|
||
#+end_src
|
||
|
||
* Sane defaults
|
||
The following settings are simple modes that are enabled (or disabled) so that Emacs functions more like you would expect a proper editor/IDE to function.
|
||
#+begin_src emacs-lisp
|
||
(electric-indent-mode -1) ;; Turn off the weird indenting that Emacs does by default.
|
||
(electric-pair-mode 1) ;; Turns on automatic parens pairing
|
||
;; The following prevents <> from auto-pairing when electric-pair-mode is on.
|
||
;; Otherwise, org-tempo is broken when you try to <s TAB...
|
||
(add-hook 'org-mode-hook (lambda ()
|
||
(setq-local electric-pair-inhibit-predicate
|
||
`(lambda (c)
|
||
(if (char-equal c ?<) t (,electric-pair-inhibit-predicate c))))))
|
||
(global-auto-revert-mode t) ;; Automatically show changes if the file has changed
|
||
;;(global-display-line-numbers-mode 1) ;; Display line numbers
|
||
(add-hook 'prog-mode-hook #'display-line-numbers-mode)
|
||
(global-visual-line-mode t) ;; Enable truncated lines
|
||
(winner-mode t) ;; Undo (C-c <left>) and Redo (C-c <right>) for windows
|
||
(setq sentence-end-double-space t) ;; Single space doesn't end a sentence
|
||
|
||
(save-place-mode t) ;; Restore cursor place in file
|
||
#+end_src
|
||
** Battery info
|
||
#+begin_src emacs-lisp
|
||
(unless (or
|
||
(equal "Battery status not available" (battery))
|
||
(equal "Power N/A, battery Charging (N/A% load, remaining time N/A)" (battery))
|
||
(equal "Power N/A, battery Discharging (N/A% load, remaining time N/A)" (battery)))
|
||
(display-battery-mode 1))
|
||
#+end_src
|
||
* Epub support (Reader in Emacs)
|
||
[[https://depp.brause.cc/nov.el/][Nov.el]] is recommended by [[https://www.masteringemacs.org/book][Author of Mastering Emacs book]]
|
||
#+begin_src emacs-lisp
|
||
(use-package nov :ensure t)
|
||
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
|
||
#+end_src
|
||
* MAGIT
|
||
Magit is a full-featured git client for Emacs.
|
||
#+begin_src emacs-lisp
|
||
(use-package magit
|
||
:ensure t)
|
||
#+end_src
|
||
* Modeline
|
||
The modeline is the bottom status bar that appears in Emacs windows. While you can create your own custom modeline, why go to the trouble when Doom Emacs already has a nice modeline package available. For more information on what is available to configure in the Doom modeline, check out: [[https://github.com/seagle0128/doom-modeline][Doom Modeline]]
|
||
#+begin_src emacs-lisp
|
||
(use-package doom-modeline
|
||
:ensure t
|
||
:init (doom-modeline-mode 1)
|
||
:config
|
||
(setq doom-modeline-height 35 ;; sets modeline height
|
||
doom-modeline-bar-width 5 ;; sets right bar width
|
||
doom-modeline-persp-name nil ;; adds perspective name to modeline
|
||
doom-modeline-time t ;; shows time
|
||
doom-modeline-persp-icon nil)) ;; adds folder icon next to persp name
|
||
#+end_src
|
||
* Drawing tools
|
||
[[https://github.com/misohena/el-easydraw][el-easydraw]]
|
||
#+begin_src emacs-lisp
|
||
;;(use-package el-easydraw :ensure t :demand nil)
|
||
(with-eval-after-load 'org
|
||
(require 'edraw-org)
|
||
(edraw-org-setup-default))
|
||
;; When using the org-export-in-background option (when using the
|
||
;; asynchronous export function), the following settings are
|
||
;; required. This is because Emacs started in a separate process does
|
||
;; not load org.el but only ox.el.
|
||
(with-eval-after-load "ox"
|
||
(require 'edraw-org)
|
||
(edraw-org-setup-exporter))
|
||
#+end_src
|
||
* RAINBOW DELIMITERS
|
||
Adding rainbow coloring to parentheses.
|
||
#+begin_src emacs-lisp
|
||
(use-package rainbow-delimiters
|
||
:ensure t
|
||
:hook ((emacs-lisp-mode . rainbow-delimiters-mode)
|
||
(clojure-mode . rainbow-delimiters-mode)))
|
||
#+end_src
|
||
* Calendar
|
||
#+begin_src emacs-lisp
|
||
(setq calendar-date-style "european")
|
||
(setq calendar-week-start-day 1)
|
||
|
||
;;Line truncation
|
||
(defun kylekrein/truncate-calendar-hook ()
|
||
"Turn line truncation on."
|
||
(toggle-truncate-lines 1))
|
||
|
||
(add-hook 'calendar-mode-hook #'kylekrein/truncate-calendar-hook)
|
||
|
||
;;Current month is the first
|
||
(add-hook 'calendar-initial-window-hook #'calendar-scroll-left)
|
||
|
||
;;Calendar in org agenda
|
||
(setq org-agenda-include-diary t)
|
||
|
||
(defadvice revert-buffer (after refresh-org-agenda-on-revert activate)
|
||
(if (member (buffer-file-name (current-buffer)) org-agenda-files)
|
||
(org-agenda-redo-all t)))
|
||
#+end_src
|
||
* Org Babel
|
||
[[https://orgmode.org/worg//org-contrib/babel/languages/ob-doc-C.html][How to use C++ code blocks (tables included)]]
|
||
#+begin_src emacs-lisp
|
||
(git-package "https://github.com/ljos/ob-prolog")
|
||
(use-package ob-prolog)
|
||
(org-babel-do-load-languages
|
||
'org-babel-load-languages
|
||
'((shell . t)
|
||
(C . t)
|
||
(python . t)
|
||
(prolog . t)))
|
||
#+end_src
|
||
* ORG MODE
|
||
** Org Copy Link
|
||
[[https://sachachua.com/blog/2024/01/org-mode-custom-link-copy-to-clipboard/][Org-mode custom link to copy to clipboard]]
|
||
#+begin_src emacs-lisp
|
||
(use-package org
|
||
:config
|
||
(org-link-set-parameters
|
||
"copy"
|
||
:follow (lambda (link) (kill-new link))
|
||
:export (lambda (_ desc &rest _) desc)))
|
||
#+end_src
|
||
** Enabling Table of Contents
|
||
#+begin_src emacs-lisp
|
||
(setq org-directory "~/Documents/org")
|
||
(use-package toc-org
|
||
:ensure t
|
||
:commands toc-org-enable
|
||
:init (add-hook 'org-mode-hook 'toc-org-enable))
|
||
#+end_src
|
||
|
||
** Modern Org Mode
|
||
|
||
#+begin_src emacs-lisp
|
||
;;;; Better Looking Bullets
|
||
(add-hook 'org-mode-hook 'org-indent-mode)
|
||
(use-package org-bullets :ensure t)
|
||
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
|
||
#+end_src
|
||
** Org Level Headers
|
||
#+begin_src emacs-lisp
|
||
(custom-set-faces
|
||
'(org-level-1 ((t (:inherit outline-1 :height 1.45))))
|
||
'(org-level-2 ((t (:inherit outline-2 :height 1.35))))
|
||
'(org-level-3 ((t (:inherit outline-3 :height 1.30))))
|
||
'(org-level-4 ((t (:inherit outline-4 :height 1.25))))
|
||
'(org-level-5 ((t (:inherit outline-5 :height 1.20))))
|
||
'(org-level-6 ((t (:inherit outline-5 :height 1.15))))
|
||
'(org-level-7 ((t (:inherit outline-5 :height 1.10)))))
|
||
#+end_src
|
||
|
||
** Source Code Block Tag Expansion
|
||
Org-tempo is not a separate package but a module within org that can be enabled. Org-tempo allows for '<s' followed by TAB to expand to a begin_src tag. Other expansions available include:
|
||
|
||
| Typing the below + TAB | Expands to ... |
|
||
|------------------------+-----------------------------------------|
|
||
| <a | '#+BEGIN_EXPORT ascii' … '#+END_EXPORT |
|
||
| <c | '#+BEGIN_CENTER' … '#+END_CENTER' |
|
||
| <C | '#+BEGIN_COMMENT' … '#+END_COMMENT' |
|
||
| <e | '#+BEGIN_EXAMPLE' … '#+END_EXAMPLE' |
|
||
| <E | '#+BEGIN_EXPORT' … '#+END_EXPORT' |
|
||
| <h | '#+BEGIN_EXPORT html' … '#+END_EXPORT' |
|
||
| <l | '#+BEGIN_EXPORT latex' … '#+END_EXPORT' |
|
||
| <q | '#+BEGIN_QUOTE' … '#+END_QUOTE' |
|
||
| <s | '#+BEGIN_SRC' … '#+END_SRC' |
|
||
| <v | '#+BEGIN_VERSE' … '#+END_VERSE' |
|
||
#+begin_src emacs-lisp
|
||
(require 'org-tempo)
|
||
#+end_src
|
||
** Insert pictures
|
||
[[https://github.com/abo-abo/org-download][Org-download]]
|
||
#+begin_src emacs-lisp
|
||
(use-package org-download :ensure t)
|
||
(require 'org-download)
|
||
;; Drag-and-drop to `dired`
|
||
(add-hook 'dired-mode-hook 'org-download-enable)
|
||
|
||
(setq org-download-method 'attach) ;;attach or directory
|
||
;; (setq-default org-download-image-dir "~/Pictures/foo") ;;for directory
|
||
#+end_src
|
||
** Update org tables
|
||
#+begin_src emacs-lisp
|
||
(defun org-update-table-by-name (name)
|
||
"Update the named table."
|
||
(org-table-map-tables
|
||
(lambda ()
|
||
(let ((table_name (org-element-property :name (org-element-at-point))))
|
||
(if (and table_name (string-match-p name table_name))
|
||
(org-table-recalculate))))))
|
||
#+end_src
|
||
#+begin_src emacs-lisp
|
||
(defun org-update-and-realign-tables ()
|
||
(interactive)
|
||
(org-map-dblocks 'org-update-dblock)
|
||
(redisplay)
|
||
(org-table-map-tables 'org-table-recalculate)
|
||
(org-table-map-tables 'org-table-align))
|
||
|
||
(global-set-key (kbd "C-c n u") 'org-update-and-realign-tables)
|
||
#+end_src
|
||
** Org transclusion
|
||
#+begin_src emacs-lisp
|
||
(use-package org-transclusion :ensure t)
|
||
(custom-set-faces
|
||
'(org-transclusion-fringe
|
||
((t
|
||
(:background "green"))))
|
||
'(org-transclusion-source-fringe
|
||
((t
|
||
(:background "blue")))))
|
||
#+end_src
|
||
* ORG ROAM
|
||
** Org Roam itself
|
||
#+begin_src emacs-lisp
|
||
(use-package org-roam
|
||
:ensure t
|
||
:init
|
||
(setq org-roam-v2-ack t)
|
||
:custom
|
||
(org-roam-directory "~/Documents/org")
|
||
(org-roam-completion-everywhere t)
|
||
(org-roam-capture-templates
|
||
'(("d" "default" plain
|
||
"%?"
|
||
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+category: ${title}\n")
|
||
:unnarrowed t)
|
||
("p" "project" plain "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n"
|
||
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+category: ${title}\n#+filetags: Project")
|
||
:unnarrowed t))
|
||
)
|
||
(org-roam-dailies-capture-templates
|
||
'(("d" "default" entry "* %<%I:%M %p>: %?"
|
||
:if-new (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n"))))
|
||
:bind (("C-c n l" . org-roam-buffer-toggle)
|
||
("C-c n f" . org-roam-node-find)
|
||
("C-c n i" . org-roam-node-insert)
|
||
:map org-mode-map
|
||
("C-M-i" . completion-at-point))
|
||
:bind-keymap
|
||
("C-c n d" . org-roam-dailies-map)
|
||
:config
|
||
(require 'org-roam-dailies) ;; Ensure the keymap is available
|
||
(org-roam-db-autosync-mode)
|
||
(org-roam-setup))
|
||
#+end_src
|
||
** Ripgrep files
|
||
#+begin_src emacs-lisp
|
||
(defun kylekrein/org-roam-ripgrep ()
|
||
(interactive)
|
||
(require 'consult)
|
||
(require 'org-roam)
|
||
(let ((consult-ripgrep-command "rg --null --ignore-case --type org --line-buffered --color=always --max-columns=500 --no-heading --line-number . -e ARG OPTS"))
|
||
(consult-ripgrep org-roam-directory)))
|
||
(global-set-key (kbd "C-c n r") #'kylekrein/org-roam-ripgrep)
|
||
#+end_src
|
||
** Org Roam UI
|
||
#+begin_src emacs-lisp
|
||
(use-package org-roam-ui
|
||
:ensure t
|
||
:after org-roam)
|
||
#+end_src
|
||
** Inbox
|
||
#+begin_src emacs-lisp
|
||
(defun kylekrein/org-roam-capture-inbox ()
|
||
(interactive)
|
||
(org-roam-capture- :node (org-roam-node-create)
|
||
:templates '(("i" "inbox" plain "* %?"
|
||
:if-new (file+head "Inbox.org" "#+title: Inbox\n#+category: Inbox\n#+filetags: Project")))))
|
||
(global-set-key (kbd "C-c n b") #'kylekrein/org-roam-capture-inbox)
|
||
#+end_src
|
||
* Org Agenda
|
||
** Refresh
|
||
#+begin_src emacs-lisp
|
||
(defun org-agenda-refresh ()
|
||
"Refresh all `org-agenda' buffers."
|
||
(dolist (buffer (buffer-list))
|
||
(with-current-buffer buffer
|
||
(when (derived-mode-p 'org-agenda-mode)
|
||
(org-agenda-maybe-redo)))))
|
||
#+end_src
|
||
** Auto update agenda
|
||
*** On Schedule
|
||
#+begin_src emacs-lisp
|
||
(defadvice org-schedule (after refresh-agenda activate)
|
||
"Refresh org-agenda."
|
||
(org-agenda-refresh))
|
||
#+end_src
|
||
** TODOs only from Projects
|
||
Collect and show todos only defined in files with tag ~Project~
|
||
#+begin_src emacs-lisp
|
||
(require 'org-roam-node)
|
||
(defun kylekrein/org-roam-filter-by-tag (tag-name)
|
||
(lambda (node)
|
||
(member tag-name (org-roam-node-tags node))))
|
||
|
||
(defun kylekrein/org-roam-list-notes-by-tag (tag-name)
|
||
(mapcar #'org-roam-node-file
|
||
(seq-filter
|
||
(kylekrein/org-roam-filter-by-tag tag-name)
|
||
(org-roam-node-list))))
|
||
|
||
(defun kylekrein/org-roam-refresh-agenda-list ()
|
||
(interactive)
|
||
(setq org-agenda-files (kylekrein/org-roam-list-notes-by-tag "Project")))
|
||
|
||
|
||
(setq org-agenda-files nil
|
||
org-roam-node-display-template "${title} ${tags}"
|
||
org-agenda-start-on-weekday 1 ;; Week starts on Monday instead of Sunday
|
||
)
|
||
;; Build the agenda list the first time for the session
|
||
(kylekrein/org-roam-refresh-agenda-list)
|
||
#+end_src
|
||
** Small settings
|
||
#+begin_src emacs-lisp
|
||
;; Log time a task was set to DONE.
|
||
(setq org-log-done (quote time))
|
||
|
||
;; Don't log the time a task was rescheduled or redeadlined.
|
||
(setq org-log-redeadline nil)
|
||
(setq org-log-reschedule nil)
|
||
|
||
;; Prefer rescheduling to future dates and times
|
||
(setq org-read-date-prefer-future 'time)
|
||
#+end_src
|
||
** Todos in Today
|
||
Automatically copies all *DONE* TODOs to Today's daily
|
||
#+begin_src emacs-lisp
|
||
(defun kylekrein/org-roam-copy-todo-to-today ()
|
||
(interactive)
|
||
(let ((org-refile-keep t) ;; Set this to nil to delete the original!
|
||
(org-roam-dailies-capture-templates
|
||
'(("t" "tasks" entry "%?"
|
||
:if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n#+filetags: Daily\n" ("Completed Tasks:")))))
|
||
(org-after-refile-insert-hook #'save-buffer)
|
||
today-file
|
||
pos)
|
||
(save-window-excursion
|
||
(org-roam-dailies--capture (current-time) t)
|
||
(setq today-file (buffer-file-name))
|
||
(setq pos (point)))
|
||
|
||
;; Only refile if the target file is different than the current file
|
||
(unless (equal (file-truename today-file)
|
||
(file-truename (buffer-file-name)))
|
||
(org-refile nil nil (list "Tasks" today-file nil pos)))))
|
||
|
||
(add-to-list 'org-after-todo-state-change-hook
|
||
(lambda ()
|
||
(when (equal org-state "DONE")
|
||
(kylekrein/org-roam-copy-todo-to-today))))
|
||
#+end_src
|
||
** Notifications
|
||
*** Appt
|
||
Internal emacs tool and [[https://github.com/jwiegley/alert][alert]]. Settings for alert are at the beginning of this file.
|
||
This solution was found [[https://igormelo.org/you_dont_need_org_alert.html][here]].
|
||
#+begin_src emacs-lisp
|
||
(use-package emacs
|
||
:config
|
||
;; start warning 60 minutes before the appointment
|
||
(setq appt-message-warning-time 60)
|
||
|
||
;; warn me every 5 minutes
|
||
(setq appt-display-interval 15)
|
||
(setq appt-disp-window-function
|
||
(lambda (remaining new-time msg)
|
||
(alert (format "In %s minutes" remaining)
|
||
:title msg
|
||
:severity 'moderate
|
||
:category 'org-agenda
|
||
:id (intern msg))))
|
||
|
||
(advice-add 'appt-check
|
||
:before
|
||
(lambda (&rest args)
|
||
(org-agenda-to-appt t)))
|
||
|
||
(appt-activate t))
|
||
(setq alert-fade-time 50)
|
||
#+end_src
|
||
**** Appt on modeline
|
||
#+begin_src emacs-lisp
|
||
(use-package org-upcoming-modeline
|
||
:ensure t
|
||
:after org
|
||
:config
|
||
(setq appt-display-mode-line nil)
|
||
(org-upcoming-modeline-mode))
|
||
#+end_src
|
||
* RAINBOW MODE
|
||
Display the actual color as a background for any hex color value (ex. #ffffff). The code block below enables rainbow-mode in all programming modes (prog-mode) as well as org-mode, which is why rainbow works in this document.
|
||
|
||
#+begin_src emacs-lisp
|
||
(use-package rainbow-mode
|
||
:ensure t
|
||
:hook
|
||
((org-mode prog-mode) . rainbow-mode))
|
||
#+end_src
|
||
* AI
|
||
** GPT.el
|
||
#+begin_src emacs-lisp
|
||
(use-package gptel
|
||
:ensure t
|
||
:bind
|
||
("C-c a c" . gptel)
|
||
("C-c a r" . gptel-rewrite)
|
||
("C-c a s" . gptel-send)
|
||
("C-c a f" . gptel-add-file))
|
||
(setq
|
||
gptel-model 'llama3.1
|
||
gptel-backend (gptel-make-ollama "Ollama"
|
||
:host "localhost:11434"
|
||
:stream t
|
||
:models '(llama3.1 qwen2.5-coder:7b))
|
||
gptel-track-media t
|
||
gptel-default-mode 'org-mode)
|
||
(add-hook 'gptel-post-stream-hook 'gptel-auto-scroll)
|
||
(add-hook 'gptel-post-response-functions 'gptel-end-of-response)
|
||
#+end_src
|
||
** Minuet
|
||
#+begin_src emacs-lisp
|
||
(use-package minuet
|
||
:ensure t
|
||
:bind
|
||
(("M-y" . #'minuet-complete-with-minibuffer) ;; use minibuffer for completion
|
||
("M-i" . #'minuet-show-suggestion) ;; use overlay for completion
|
||
("C-c m" . #'minuet-configure-provider)
|
||
:map minuet-active-mode-map
|
||
;; These keymaps activate only when a minuet suggestion is displayed in the current buffer
|
||
("M-p" . #'minuet-previous-suggestion) ;; invoke completion or cycle to next completion
|
||
("M-n" . #'minuet-next-suggestion) ;; invoke completion or cycle to previous completion
|
||
("M-A" . #'minuet-accept-suggestion) ;; accept whole completion
|
||
;; Accept the first line of completion, or N lines with a numeric-prefix:
|
||
;; e.g. C-u 2 M-a will accepts 2 lines of completion.
|
||
("M-a" . #'minuet-accept-suggestion-line)
|
||
("M-e" . #'minuet-dismiss-suggestion))
|
||
|
||
:init
|
||
;; if you want to enable auto suggestion.
|
||
;; Note that you can manually invoke completions without enable minuet-auto-suggestion-mode
|
||
;;(add-hook 'prog-mode-hook #'minuet-auto-suggestion-mode)
|
||
|
||
:config
|
||
;; You can use M-x minuet-configure-provider to interactively configure provider and model
|
||
(setq minuet-provider 'openai-fim-compatible)
|
||
(setq minuet-n-completions 1) ; recommended for Local LLM for resource saving
|
||
;; I recommend beginning with a small context window size and incrementally
|
||
;; expanding it, depending on your local computing power. A context window
|
||
;; of 512, serves as an good starting point to estimate your computing
|
||
;; power. Once you have a reliable estimate of your local computing power,
|
||
;; you should adjust the context window to a larger value.
|
||
(setq minuet-context-window 512)
|
||
(plist-put minuet-openai-fim-compatible-options :end-point "http://localhost:11434/v1/completions")
|
||
;; an arbitrary non-null environment variable as placeholder.
|
||
;; For Windows users, TERM may not be present in environment variables.
|
||
;; Consider using APPDATA instead.
|
||
(plist-put minuet-openai-fim-compatible-options :name "Ollama")
|
||
(plist-put minuet-openai-fim-compatible-options :api-key "TERM")
|
||
(plist-put minuet-openai-fim-compatible-options :model "qwen2.5-coder:7b")
|
||
|
||
(minuet-set-optional-options minuet-openai-fim-compatible-options :max_tokens 80))
|
||
#+end_src
|
||
* SHELLS AND TERMINALS
|
||
** Eshell
|
||
Eshell is an Emacs 'shell' that is written in Elisp.
|
||
|
||
#+begin_src emacs-lisp
|
||
(use-package eshell-syntax-highlighting
|
||
:ensure t
|
||
:after esh-mode
|
||
:config
|
||
(eshell-syntax-highlighting-global-mode +1))
|
||
#+end_src
|
||
** Vterm
|
||
Vterm is a terminal emulator within Emacs. The 'shell-file-name' setting sets the shell to be used in M-x shell, M-x term, M-x ansi-term and M-x vterm. By default, the shell is set to 'fish' but could change it to 'bash' or 'zsh' if you prefer.
|
||
|
||
#+begin_src emacs-lisp
|
||
(unless (kylekrein/is-android) ;;Fails to compile
|
||
(use-package vterm
|
||
:ensure t
|
||
;;:config
|
||
))
|
||
#+end_src
|
||
|
||
** Vterm-Toggle
|
||
[[https://github.com/jixiuf/vterm-toggle][vterm-toggle]] toggles between the vterm buffer and whatever buffer you are editing.
|
||
|
||
#+begin_src emacs-lisp
|
||
(unless (kylekrein/is-android)
|
||
(use-package vterm-toggle
|
||
:ensure t
|
||
:after vterm
|
||
:config
|
||
(setq vterm-toggle-fullscreen-p nil)
|
||
(setq vterm-toggle-scope 'project)
|
||
(add-to-list 'display-buffer-alist
|
||
'((lambda (buffer-or-name _)
|
||
(let ((buffer (get-buffer buffer-or-name)))
|
||
(with-current-buffer buffer
|
||
(or (equal major-mode 'vterm-mode)
|
||
(string-prefix-p vterm-buffer-name (buffer-name buffer))))))
|
||
(display-buffer-reuse-window display-buffer-at-bottom)
|
||
;;(display-buffer-reuse-window display-buffer-in-direction)
|
||
;;display-buffer-in-direction/direction/dedicated is added in emacs27
|
||
;;(direction . bottom)
|
||
;;(dedicated . t) ;dedicated is supported in emacs27
|
||
(reusable-frames . visible)
|
||
(window-height . 0.3)))))
|
||
#+end_src
|
||
|
||
* SUDO EDIT
|
||
[[https://github.com/nflath/sudo-edit][sudo-edit]] gives us the ability to open files with sudo privileges or switch over to editing with sudo privileges if we initially opened the file without such privileges.
|
||
|
||
#+begin_src emacs-lisp
|
||
(use-package sudo-edit
|
||
:ensure t)
|
||
#+end_src
|
||
* Password store
|
||
[[https://github.com/NicolasPetton/pass][Pass]] is a package that interacts with [[https://www.passwordstore.org/][Standard UNIX password manager]]
|
||
#+begin_src emacs-lisp
|
||
(use-package pass
|
||
:ensure t)
|
||
(setq epg-pinentry-mode 'loopback)
|
||
#+end_src
|
||
|
||
This code snippet runs allows to get field for a password entry without emacs frame
|
||
To use it, create a global keyboard shortcut with the following code
|
||
~emacsclient -cF "((visibility . nil))" -e "(emacs-run-password-copy-field)"~
|
||
#+begin_src emacs-lisp
|
||
(defun emacs--run-password-copy-field ()
|
||
(interactive)
|
||
(let* ((entry (password-store--completing-read))
|
||
(field (password-store-read-field entry))
|
||
(value (if (string= field "secret")
|
||
(password-store-get entry)
|
||
(password-store-get-field entry field))))
|
||
(password-store--save-field-in-kill-ring entry value field)
|
||
(alert (format "%s:%s\nClipboard will be cleared in 45 seconds" entry field)
|
||
:title "Copied"
|
||
:severity 'trivial
|
||
:category 'pass
|
||
:id 'pass)))
|
||
|
||
(defun emacs-run-password-copy-field()
|
||
(let ((launcher-frame (create-launcher-frame)))
|
||
(with-selected-frame launcher-frame
|
||
(emacs--run-password-copy-field)
|
||
(make-frame-invisible launcher-frame)
|
||
(run-at-time "60 sec" nil (lambda (frame) (delete-frame frame)) launcher-frame))))
|
||
#+end_src
|
||
* CMake Projects
|
||
#+begin_src emacs-lisp
|
||
(git-package "https://github.com/darcamo/cmake-integration.git")
|
||
(use-package cmake-integration
|
||
:commands (cmake-integration-transient)
|
||
:custom
|
||
(cmake-integration-generator "Ninja")
|
||
(cmake-integration-use-separated-compilation-buffer-for-each-target t))
|
||
|
||
(defun is-cmake-project? ()
|
||
"Determine if the current directory is a CMake project."
|
||
(interactive)
|
||
(if-let* ((project (project-current))
|
||
(project-root (project-root project))
|
||
(cmakelist-path (expand-file-name "CMakeLists.txt" project-root)))
|
||
(file-exists-p cmakelist-path)))
|
||
|
||
|
||
(defun cmake-integration-keybindings-mode-turn-on-in-cmake-projects ()
|
||
"Turn on `cmake-integration-keybindings-mode' in CMake projects."
|
||
(when (is-cmake-project?)
|
||
(cmake-integration-keybindings-mode 1)))
|
||
|
||
|
||
(define-minor-mode cmake-integration-keybindings-mode
|
||
"A minor-mode for adding keybindings to compile C++ code using cmake-integration package."
|
||
nil
|
||
"cmake"
|
||
'(
|
||
([f5] . cmake-integration-transient) ;; Open main transient menu
|
||
([M-f9] . cmake-integration-save-and-compile) ;; Ask for the target name and compile it
|
||
([f9] . cmake-integration-save-and-compile-last-target) ;; Recompile the last target
|
||
([C-f9] . cmake-integration-run-ctest) ;; Run CTest
|
||
([f7] . cmake-integration-run-last-target) ;; Run the target (using any previously set command line parameters)
|
||
([S-f7] . kill-compilation)
|
||
([C-f7] . cmake-integration-debug-last-target) ;; Debug the target (using any previously set command line parameters)
|
||
([M-f7] . cmake-integration-run-last-target-with-arguments) ;; Ask for command line parameters to run the target
|
||
([M-f8] . cmake-integration-select-configure-preset) ;; Ask for a preset name and call CMake to configure the project
|
||
([f8] . cmake-integration-cmake-reconfigure) ;; Call CMake to configure the project using the last chosen preset
|
||
)
|
||
)
|
||
|
||
(define-globalized-minor-mode global-cmake-integration-keybindings-mode
|
||
cmake-integration-keybindings-mode cmake-integration-keybindings-mode-turn-on-in-cmake-projects)
|
||
|
||
|
||
(global-cmake-integration-keybindings-mode)
|
||
|
||
;; Extend project.el to recognize local projects based on a .project file
|
||
(cl-defmethod project-root ((project (head local)))
|
||
(cdr project))
|
||
|
||
(defun mu--project-files-in-directory (dir)
|
||
"Use `fd' to list files in DIR."
|
||
(let* ((default-directory dir)
|
||
(localdir (file-local-name (expand-file-name dir)))
|
||
(command (format "fd -t f -0 . %s" localdir)))
|
||
(project--remote-file-names
|
||
(sort (split-string (shell-command-to-string command) "\0" t)
|
||
#'string<))))
|
||
|
||
(cl-defmethod project-files ((project (head local)) &optional dirs)
|
||
"Override `project-files' to use `fd' in local projects."
|
||
(mapcan #'mu--project-files-in-directory
|
||
(or dirs (list (project-root project)))))
|
||
|
||
(defun mu-project-try-local (dir)
|
||
"Determine if DIR is a non-Git project.
|
||
DIR must include a .project file to be considered a project."
|
||
(let ((root (locate-dominating-file dir ".project")))
|
||
(and root (cons 'local root))))
|
||
|
||
(use-package project
|
||
:defer t
|
||
:config
|
||
(add-to-list 'project-find-functions 'mu-project-try-local)
|
||
)
|
||
#+end_src
|
||
* Direnv
|
||
Loading of environment for the buffers
|
||
#+begin_src emacs-lisp
|
||
(use-package direnv
|
||
:ensure t
|
||
:config
|
||
(direnv-mode))
|
||
#+end_src
|
||
|
||
Function to enable it for project
|
||
#+begin_src emacs-lisp
|
||
(defun kylekrein/project-enable-direnv-flake ()
|
||
"Add `use flake` to .envrc and run `direnv allow` in the project root."
|
||
(interactive)
|
||
(let* ((project (project-current t))
|
||
(root (project-root project))
|
||
(envrc-path (expand-file-name ".envrc" root)))
|
||
(unless (file-exists-p envrc-path)
|
||
(with-temp-buffer
|
||
(insert "use flake\n")
|
||
(write-file envrc-path)))
|
||
(unless (string-match-p "use flake" (with-temp-buffer
|
||
(insert-file-contents envrc-path)
|
||
(buffer-string)))
|
||
(with-temp-buffer
|
||
(insert-file-contents envrc-path)
|
||
(goto-char (point-max))
|
||
(insert "\nuse flake\n")
|
||
(write-file envrc-path)))
|
||
(let ((default-directory root))
|
||
(direnv-allow))
|
||
(message "Added 'use flake' to .envrc and ran direnv allow in %s" root)))
|
||
#+end_src
|
||
* Language support
|
||
Emacs has built-in programming language modes for Lisp, Scheme, DSSSL, Ada, ASM, AWK, C, C++, Fortran, Icon, IDL (CORBA), IDLWAVE, Java, Javascript, M4, Makefiles, Metafont, Modula2, Object Pascal, Objective-C, Octave, Pascal, Perl, Pike, PostScript, Prolog, Python, Ruby, Simula, SQL, Tcl, Verilog, and VHDL. Other languages will require you to install additional modes.
|
||
** Nix
|
||
#+begin_src emacs-lisp
|
||
(use-package nix-ts-mode
|
||
:ensure t
|
||
:mode "\\.nix\\'"
|
||
:hook
|
||
(nix-ts-mode . lsp-deferred) ;; So that envrc mode will work
|
||
:custom
|
||
(lsp-disabled-clients '((nix-ts-mode . nix-nil))) ;; Disable nil so that nixd will be used as lsp-server
|
||
:config
|
||
(setq lsp-nix-nixd-server-path "nixd"
|
||
lsp-nix-nixd-formatting-command [ "alejandra" ]
|
||
lsp-nix-nixd-nixpkgs-expr "import <nixpkgs> { }"
|
||
lsp-nix-nixd-nixos-options-expr "(builtins.getFlake \"github:kylekrein/nixos-config\".nixosConfigurations.kylekrein-homepc.options"
|
||
lsp-nix-nixd-home-manager-options-expr "(builtins.getFlake \"github:kylekrein/nixos-config\".nixosConfigurations.kylekrein-homepc.options.home-manager.users.type.getSubOptions []"))
|
||
#+end_src
|
||
|
||
[[https://github.com/emacs-twist/nix3.el][nix3.el]]
|
||
#+begin_src emacs-lisp
|
||
(use-package promise :ensure t) ;; nix3 dependency
|
||
(git-package "https://github.com/emacs-twist/nix3.el")
|
||
(use-package nix3
|
||
:init
|
||
(let* ((mainpkg-dir (file-name-directory (locate-library "nix3")))
|
||
(subpkg-dir (expand-file-name "extra" mainpkg-dir)))
|
||
(add-to-list 'load-path subpkg-dir)))
|
||
|
||
(use-package magit-nix3
|
||
:after magit-status
|
||
:config
|
||
(magit-nix3-flake-mode t))
|
||
#+end_src
|
||
** GLSL
|
||
#+begin_src emacs-lisp
|
||
(use-package glsl-mode
|
||
:ensure t)
|
||
#+end_src
|
||
** QML
|
||
#+begin_src emacs-lisp
|
||
(git-package "https://github.com/xhcoding/qml-ts-mode")
|
||
(use-package qml-ts-mode
|
||
:after lsp-mode
|
||
:config
|
||
(add-to-list 'lsp-language-id-configuration '(qml-ts-mode . "qml-ts"))
|
||
(add-to-list 'auto-mode-alist '("\\.qml\\'" . qml-ts-mode))
|
||
(lsp-register-client
|
||
(make-lsp-client :new-connection (lsp-stdio-connection '("qmlls"))
|
||
:activation-fn (lsp-activate-on "qml-ts")
|
||
:server-id 'qmlls))
|
||
(add-hook 'qml-ts-mode-hook (lambda ()
|
||
(setq-local electric-indent-chars '(?\n ?\( ?\) ?{ ?} ?\[ ?\] ?\; ?,))
|
||
(lsp-deferred))))
|
||
#+end_src
|
||
** RmlUi
|
||
#+begin_src emacs-lisp
|
||
(add-to-list 'auto-mode-alist '("\\.rml\\'" . html-ts-mode))
|
||
(add-to-list 'auto-mode-alist '("\\.rcss\\'" . css-ts-mode))
|
||
#+end_src
|
||
** CMake
|
||
#+begin_src emacs-lisp
|
||
(add-to-list 'auto-mode-alist '("CMakeLists\\.txt\\'" . cmake-ts-mode))
|
||
(add-to-list 'auto-mode-alist '("\\.cmake\\'" . cmake-ts-mode))
|
||
#+end_src
|
||
** Global treesitter
|
||
#+begin_src emacs-lisp
|
||
(use-package treesit-auto
|
||
:ensure t
|
||
:demand t
|
||
:config
|
||
(global-treesit-auto-mode))
|
||
#+end_src
|
||
** Eglot
|
||
*** Base
|
||
#+begin_src emacs-lisp
|
||
(use-package eldoc
|
||
:init
|
||
(global-eldoc-mode))
|
||
|
||
(use-package eglot
|
||
:hook (prog-mode . eglot-ensure)
|
||
;;:init
|
||
;;(setq eglot-stay-out-of '(flymake))
|
||
:bind (:map
|
||
eglot-mode-map
|
||
("C-c c a" . eglot-code-actions)
|
||
;;("C-c c o" . eglot-code-actions-organize-imports)
|
||
("C-c c r" . eglot-rename)
|
||
("C-c c f" . eglot-format)))
|
||
|
||
(use-package flymake
|
||
:hook (prog-mode . flymake-mode)
|
||
:bind (:map flymake-mode-map
|
||
("C-c ! n" . flymake-goto-next-error)
|
||
("C-c ! p" . flymake-goto-prev-error)
|
||
("C-c ! l" . flymake-show-buffer-diagnostics)))
|
||
#+end_src
|
||
*** C++ / C
|
||
#+begin_src emacs-lisp
|
||
(with-eval-after-load 'eglot
|
||
(add-to-list 'eglot-server-programs
|
||
'((c-ts-mode c++-ts-mode)
|
||
. ("clangd"
|
||
"-j=8"
|
||
"--log=error"
|
||
"--malloc-trim"
|
||
"--background-index"
|
||
"--clang-tidy"
|
||
"--cross-file-rename"
|
||
"--completion-style=detailed"
|
||
"--pch-storage=memory"
|
||
"--header-insertion=never"
|
||
"--header-insertion-decorators=0")))
|
||
(add-hook 'c-ts-mode-hook #'eglot-ensure)
|
||
(add-hook 'c++-ts-mode-hook #'eglot-ensure))
|
||
#+end_src
|
||
*** C#
|
||
#+begin_src emacs-lisp
|
||
(with-eval-after-load 'eglot
|
||
(add-to-list 'eglot-server-programs
|
||
'(csharp-ts-mode
|
||
. ("csharp-ls")))
|
||
(add-hook 'csharp-ts-mode-hook #'eglot-ensure))
|
||
#+end_src
|
||
*** Python
|
||
#+begin_src emacs-lisp
|
||
(with-eval-after-load 'eglot
|
||
(add-to-list 'eglot-server-programs
|
||
'(python-ts-mode
|
||
. ("ty")))
|
||
(add-hook 'python-ts-mode-hook #'eglot-ensure))
|
||
#+end_src
|
||
*** Lobster
|
||
Made from [[https://github.com/lite-xl/lite-xl-plugins/blob/master/plugins/language_lobster.lua]]
|
||
#+begin_src emacs-lisp
|
||
(require 'font-lock)
|
||
|
||
(defgroup lobster-mode nil
|
||
"Major mode for editing Lobster language code."
|
||
:group 'languages)
|
||
|
||
(defvar lobster-keywords
|
||
'("import" "from" "def" "fn" "return" "program" "private" "resource"
|
||
"if" "guard" "for" "while" "else" "enum" "enum_flags"
|
||
"int" "float" "string" "any" "void" "is" "typeof" "var" "let"
|
||
"pakfile" "switch" "case" "default" "namespace" "constructor"
|
||
"operator" "super" "abstract" "attribute" "member" "member_frame"
|
||
"static" "static_frame" "not" "and" "or" "struct" "class")
|
||
"Lobster keywords.")
|
||
|
||
(defvar lobster-keywords-regexp (regexp-opt lobster-keywords 'words))
|
||
|
||
(defvar lobster-font-lock-keywords
|
||
`((,"//.*$" . font-lock-comment-face) ;; Single-line comments
|
||
(,"/\*\(.\|
|
||
\)*?\*/" . font-lock-comment-face) ;; Multi-line comments
|
||
(,"\<\(0x[0-9A-Fa-f]+\|[0-9]+\(\.[0-9]*\)?\([eE][-+]?[0-9]+\)?f?\)\>" . font-lock-constant-face) ;; Numbers
|
||
(,"\"\(\\.\|[^\"]\)*\"" . font-lock-string-face) ;; Strings
|
||
(,"'\\?.'" . font-lock-string-face) ;; Character literals
|
||
(,lobster-keywords-regexp . font-lock-keyword-face) ;; Keywords
|
||
("[a-zA-Z_][a-zA-Z0-9_]*\s-*\(?:(\)" . (1 font-lock-function-name-face))) ;; Functions
|
||
"Syntax highlighting for Lobster.")
|
||
|
||
(define-derived-mode lobster-mode prog-mode "Lobster"
|
||
"Major mode for editing Lobster language."
|
||
(setq font-lock-defaults '((lobster-font-lock-keywords))))
|
||
|
||
;;;###autoload
|
||
(add-to-list 'auto-mode-alist '("\\.lobster\\'" . lobster-mode))
|
||
|
||
(provide 'lobster-mode)
|
||
#+end_src
|
||
* Nerd Icons
|
||
#+begin_src emacs-lisp
|
||
(use-package nerd-icons
|
||
:ensure t
|
||
;; :custom
|
||
;; The Nerd Font you want to use in GUI
|
||
;; "Symbols Nerd Font Mono" is the default and is recommended
|
||
;; but you can use any other Nerd Font if you want
|
||
;; (nerd-icons-font-family "Symbols Nerd Font Mono")
|
||
)
|
||
#+end_src
|
||
** Nerd Icons Completion
|
||
[[https://github.com/rainstormstudio/nerd-icons-completion]]
|
||
#+begin_src emacs-lisp
|
||
(use-package nerd-icons-completion
|
||
:ensure t
|
||
:after marginalia
|
||
:config
|
||
(nerd-icons-completion-mode)
|
||
(add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))
|
||
#+end_src
|
||
* Persist state
|
||
#+begin_src emacs-lisp
|
||
(use-package persist-state
|
||
:ensure t
|
||
:after server
|
||
:if server-process
|
||
:config
|
||
(persist-state-mode))
|
||
#+end_src
|
||
* Multiple cursors
|
||
#+begin_src emacs-lisp
|
||
(use-package multiple-cursors
|
||
:ensure t
|
||
:bind (
|
||
("C-S-c C-S-c" . mc/edit-lines)
|
||
("C->" . mc/mark-next-like-this)
|
||
("C-<" . mc/mark-previous-like-this)
|
||
("C-C C-<" . mc/mark-all-like-this)
|
||
("C-\"" . mc/skip-to-next-like-this)
|
||
("C-:" . mc/skip-to-previous-like-this)
|
||
("C-C C->" . mc/mark-more-like-this-extended)
|
||
("C-S-<mouse-1>" . mc/add-cursor-on-click)
|
||
))
|
||
#+end_src
|
||
* Buffer Move
|
||
Creating some functions to allow us to easily move windows (splits) around. The following block of code was taken from buffer-move.el found on the EmacsWiki:
|
||
https://www.emacswiki.org/emacs/buffer-move.el
|
||
#+begin_src emacs-lisp
|
||
(require 'windmove)
|
||
|
||
;;;###autoload
|
||
(defun buf-move-up ()
|
||
"Swap the current buffer and the buffer above the split.
|
||
If there is no split, ie now window above the current one, an
|
||
error is signaled."
|
||
;; "Switches between the current buffer, and the buffer above the
|
||
;; split, if possible."
|
||
(interactive)
|
||
(let* ((other-win (windmove-find-other-window 'up))
|
||
(buf-this-buf (window-buffer (selected-window))))
|
||
(if (null other-win)
|
||
(error "No window above this one")
|
||
;; swap top with this one
|
||
(set-window-buffer (selected-window) (window-buffer other-win))
|
||
;; move this one to top
|
||
(set-window-buffer other-win buf-this-buf)
|
||
(select-window other-win))))
|
||
|
||
;;;###autoload
|
||
(defun buf-move-down ()
|
||
"Swap the current buffer and the buffer under the split.
|
||
If there is no split, ie now window under the current one, an
|
||
error is signaled."
|
||
(interactive)
|
||
(let* ((other-win (windmove-find-other-window 'down))
|
||
(buf-this-buf (window-buffer (selected-window))))
|
||
(if (or (null other-win)
|
||
(string-match "^ \\*Minibuf" (buffer-name (window-buffer other-win))))
|
||
(error "No window under this one")
|
||
;; swap top with this one
|
||
(set-window-buffer (selected-window) (window-buffer other-win))
|
||
;; move this one to top
|
||
(set-window-buffer other-win buf-this-buf)
|
||
(select-window other-win))))
|
||
|
||
;;;###autoload
|
||
(defun buf-move-left ()
|
||
"Swap the current buffer and the buffer on the left of the split.
|
||
If there is no split, ie now window on the left of the current
|
||
one, an error is signaled."
|
||
(interactive)
|
||
(let* ((other-win (windmove-find-other-window 'left))
|
||
(buf-this-buf (window-buffer (selected-window))))
|
||
(if (null other-win)
|
||
(error "No left split")
|
||
;; swap top with this one
|
||
(set-window-buffer (selected-window) (window-buffer other-win))
|
||
;; move this one to top
|
||
(set-window-buffer other-win buf-this-buf)
|
||
(select-window other-win))))
|
||
|
||
;;;###autoload
|
||
(defun buf-move-right ()
|
||
"Swap the current buffer and the buffer on the right of the split.
|
||
If there is no split, ie now window on the right of the current
|
||
one, an error is signaled."
|
||
(interactive)
|
||
(let* ((other-win (windmove-find-other-window 'right))
|
||
(buf-this-buf (window-buffer (selected-window))))
|
||
(if (null other-win)
|
||
(error "No right split")
|
||
;; swap top with this one
|
||
(set-window-buffer (selected-window) (window-buffer other-win))
|
||
;; move this one to top
|
||
(set-window-buffer other-win buf-this-buf)
|
||
(select-window other-win))))
|
||
#+end_src
|
||
#+begin_src emacs-lisp
|
||
(use-package windmove
|
||
:bind
|
||
(("<C-up>" . windmove-up)
|
||
("<C-down>" . windmove-down)
|
||
("<C-left>" . windmove-left)
|
||
("<C-right>" . windmove-right)
|
||
("<C-M-S-up>" . buf-move-up)
|
||
("<C-M-S-down>" . buf-move-down)
|
||
("<C-M-S-left>" . buf-move-left)
|
||
("<C-M-S-right>" . buf-move-right)))
|
||
#+end_src
|
||
* Completions
|
||
** Corfu
|
||
#+begin_src emacs-lisp
|
||
(use-package corfu
|
||
:ensure t
|
||
;; Optional customizations
|
||
:custom
|
||
(corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
|
||
(corfu-auto t)
|
||
(corfu-auto-prefix 2)
|
||
(corfu-quit-at-boundary 'separator)
|
||
(corfu-echo-documentation 0.25)
|
||
(corfu-preselect-first nil)
|
||
(corfu-popupinfo-delay '(1.0 . 0.3)) ;;default '(2.0 . 1.0)
|
||
;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match
|
||
;; (corfu-preview-current nil) ;; Disable current candidate preview
|
||
;; (corfu-preselect 'prompt) ;; Preselect the prompt
|
||
;; (corfu-on-exact-match nil) ;; Configure handling of exact matches
|
||
|
||
;; Enable Corfu only for certain modes. See also `global-corfu-modes'.
|
||
;; :hook ((prog-mode . corfu-mode)
|
||
;; (shell-mode . corfu-mode)
|
||
;; (eshell-mode . corfu-mode))
|
||
:bind (:map corfu-map
|
||
("M-SPC" . corfu-insert-separator)
|
||
("RET" . nil)
|
||
("TAB" . corfu-next)
|
||
([tab] . corfu-next)
|
||
("SHIFT-TAB" . corfu-previous)
|
||
([backtab] . corfu-previous)
|
||
("S-<return>" . corfu-insert))
|
||
|
||
;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can
|
||
;; be used globally (M-/). See also the customization variable
|
||
;; `global-corfu-modes' to exclude certain modes.
|
||
:init
|
||
(global-corfu-mode)
|
||
(corfu-history-mode)
|
||
(corfu-popupinfo-mode))
|
||
|
||
;; A few more useful configurations...
|
||
(use-package emacs
|
||
:custom
|
||
;; TAB cycle if there are only few candidates
|
||
;; (completion-cycle-threshold 3)
|
||
|
||
;; Enable indentation+completion using the TAB key.
|
||
;; `completion-at-point' is often bound to M-TAB.
|
||
(tab-always-indent 'complete)
|
||
|
||
;; Emacs 30 and newer: Disable Ispell completion function.
|
||
;; Try `cape-dict' as an alternative.
|
||
(text-mode-ispell-word-completion nil)
|
||
|
||
;; Hide commands in M-x which do not apply to the current mode. Corfu
|
||
;; commands are hidden, since they are not used via M-x. This setting is
|
||
;; useful beyond Corfu.
|
||
(read-extended-command-predicate #'command-completion-default-include-p))
|
||
#+end_src
|
||
** Cape
|
||
#+begin_src emacs-lisp
|
||
(use-package cape
|
||
:ensure t
|
||
:defer 10
|
||
:init
|
||
(add-to-list 'completion-at-point-functions #'cape-file))
|
||
#+end_src
|
||
** Vertico
|
||
[[https://github.com/minad/vertico][Vertico]] provides a performant and minimalistic vertical completion UI based on the default completion system.
|
||
#+begin_src emacs-lisp
|
||
;; Enable vertico
|
||
(use-package vertico
|
||
:ensure t
|
||
:custom
|
||
;; (vertico-scroll-margin 0) ;; Different scroll margin
|
||
;; (vertico-count 20) ;; Show more candidates
|
||
;; (vertico-resize t) ;; Grow and shrink the Vertico minibuffer
|
||
(vertico-cycle t) ;; Enable cycling for `vertico-next/previous'
|
||
:init
|
||
(vertico-mode))
|
||
|
||
(vertico-mode t) ;; enable vertico for all buffers
|
||
;; Persist history over Emacs restarts. Vertico sorts by history position.
|
||
(use-package savehist
|
||
:init
|
||
(savehist-mode))
|
||
|
||
;; A few more useful configurations...
|
||
(use-package emacs
|
||
:custom
|
||
;; Support opening new minibuffers from inside existing minibuffers.
|
||
(enable-recursive-minibuffers t)
|
||
;; Hide commands in M-x which do not work in the current mode. Vertico
|
||
;; commands are hidden in normal buffers. This setting is useful beyond
|
||
;; Vertico.
|
||
(read-extended-command-predicate #'command-completion-default-include-p)
|
||
:init
|
||
;; Add prompt indicator to `completing-read-multiple'.
|
||
;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
|
||
(defun crm-indicator (args)
|
||
(cons (format "[CRM%s] %s"
|
||
(replace-regexp-in-string
|
||
"\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
|
||
crm-separator)
|
||
(car args))
|
||
(cdr args)))
|
||
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
|
||
|
||
;; Do not allow the cursor in the minibuffer prompt
|
||
(setq minibuffer-prompt-properties
|
||
'(read-only t cursor-intangible t face minibuffer-prompt))
|
||
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode))
|
||
#+end_src
|
||
** Orderless
|
||
Better searching
|
||
#+begin_src emacs-lisp
|
||
;; Optionally use the `orderless' completion style.
|
||
(use-package orderless
|
||
:ensure t
|
||
:custom
|
||
;; Configure a custom style dispatcher (see the Consult wiki)
|
||
;; (orderless-style-dispatchers '(+orderless-consult-dispatch orderless-affix-dispatch))
|
||
;; (orderless-component-separator #'orderless-escapable-split-on-space)
|
||
(completion-styles '(orderless flex basic partial-completion))
|
||
|
||
(completion-category-defaults nil)
|
||
(completion-category-overrides '((file (styles partial-completion)))))
|
||
#+end_src
|
||
** Consult
|
||
#+begin_src emacs-lisp
|
||
;; Example configuration for Consult
|
||
(use-package consult
|
||
:ensure t
|
||
;; Replace bindings. Lazily loaded by `use-package'.
|
||
:bind (;; C-c bindings in `mode-specific-map'
|
||
("C-c M-x" . consult-mode-command)
|
||
("C-c h" . consult-history)
|
||
("C-c k" . consult-kmacro)
|
||
("C-c m" . consult-man)
|
||
("C-c i" . consult-info)
|
||
([remap Info-search] . consult-info)
|
||
;; C-x bindings in `ctl-x-map'
|
||
("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command
|
||
("C-x b" . consult-buffer) ;; orig. switch-to-buffer
|
||
("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
|
||
("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
|
||
("C-x t b" . consult-buffer-other-tab) ;; orig. switch-to-buffer-other-tab
|
||
("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
|
||
("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer
|
||
;; Custom M-# bindings for fast register access
|
||
("M-#" . consult-register-load)
|
||
("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated)
|
||
("C-M-#" . consult-register)
|
||
;; Other custom bindings
|
||
("M-y" . consult-yank-pop) ;; orig. yank-pop
|
||
;; M-g bindings in `goto-map'
|
||
("M-g e" . consult-compile-error)
|
||
("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
|
||
("M-g g" . consult-goto-line) ;; orig. goto-line
|
||
("M-g M-g" . consult-goto-line) ;; orig. goto-line
|
||
("M-g o" . consult-outline) ;; Alternative: consult-org-heading
|
||
("M-g m" . consult-mark)
|
||
("M-g k" . consult-global-mark)
|
||
("M-g i" . consult-imenu)
|
||
("M-g I" . consult-imenu-multi)
|
||
;; M-s bindings in `search-map'
|
||
("M-s d" . consult-find) ;; Alternative: consult-fd
|
||
("M-s c" . consult-locate)
|
||
("M-s g" . consult-grep)
|
||
("M-s G" . consult-git-grep)
|
||
("M-s r" . consult-ripgrep)
|
||
("M-s l" . consult-line)
|
||
("M-s L" . consult-line-multi)
|
||
("M-s k" . consult-keep-lines)
|
||
("M-s u" . consult-focus-lines)
|
||
;; Isearch integration
|
||
("M-s e" . consult-isearch-history)
|
||
:map isearch-mode-map
|
||
("M-e" . consult-isearch-history) ;; orig. isearch-edit-string
|
||
("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
|
||
("M-s l" . consult-line) ;; needed by consult-line to detect isearch
|
||
("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch
|
||
;; Minibuffer history
|
||
:map minibuffer-local-map
|
||
("M-s" . consult-history) ;; orig. next-matching-history-element
|
||
("M-r" . consult-history)) ;; orig. previous-matching-history-element
|
||
|
||
;; Enable automatic preview at point in the *Completions* buffer. This is
|
||
;; relevant when you use the default completion UI.
|
||
:hook (completion-list-mode . consult-preview-at-point-mode)
|
||
|
||
;; The :init configuration is always executed (Not lazy)
|
||
:init
|
||
|
||
;; Tweak the register preview for `consult-register-load',
|
||
;; `consult-register-store' and the built-in commands. This improves the
|
||
;; register formatting, adds thin separator lines, register sorting and hides
|
||
;; the window mode line.
|
||
(advice-add #'register-preview :override #'consult-register-window)
|
||
(setq register-preview-delay 0.5)
|
||
|
||
;; Use Consult to select xref locations with preview
|
||
(setq xref-show-xrefs-function #'consult-xref
|
||
xref-show-definitions-function #'consult-xref)
|
||
|
||
;; Configure other variables and modes in the :config section,
|
||
;; after lazily loading the package.
|
||
:config
|
||
|
||
;; Optionally configure preview. The default value
|
||
;; is 'any, such that any key triggers the preview.
|
||
;; (setq consult-preview-key 'any)
|
||
;; (setq consult-preview-key "M-.")
|
||
;; (setq consult-preview-key '("S-<down>" "S-<up>"))
|
||
;; For some commands and buffer sources it is useful to configure the
|
||
;; :preview-key on a per-command basis using the `consult-customize' macro.
|
||
(consult-customize
|
||
consult-theme :preview-key '(:debounce 0.2 any)
|
||
consult-ripgrep consult-git-grep consult-grep consult-man
|
||
consult-bookmark consult-recent-file consult-xref
|
||
consult--source-bookmark consult--source-file-register
|
||
consult--source-recent-file consult--source-project-recent-file
|
||
;; :preview-key "M-."
|
||
:preview-key '(:debounce 0.4 any))
|
||
|
||
;; Optionally configure the narrowing key.
|
||
;; Both < and C-+ work reasonably well.
|
||
(setq consult-narrow-key "<") ;; "C-+"
|
||
|
||
;; Optionally make narrowing help available in the minibuffer.
|
||
;; You may want to use `embark-prefix-help-command' or which-key instead.
|
||
;; (keymap-set consult-narrow-map (concat consult-narrow-key " ?") #'consult-narrow-help)
|
||
)
|
||
(require 'consult)
|
||
;;(setq read-file-name-function #'consult-find-file-with-preview)
|
||
|
||
;;Previewing files in find-file
|
||
(defun consult-find-file-with-preview (prompt &optional dir default mustmatch initial pred)
|
||
(interactive)
|
||
(let ((default-directory (expand-file-name (or dir default-directory)))
|
||
(minibuffer-completing-file-name t))
|
||
(consult--read #'read-file-name-internal :state (consult--file-preview)
|
||
:prompt prompt
|
||
:initial initial
|
||
:require-match mustmatch
|
||
:predicate pred)))
|
||
|
||
;;Previewing files for project-find-file
|
||
(setq project-read-file-name-function #'consult-project-find-file-with-preview)
|
||
|
||
(defun consult-project-find-file-with-preview (prompt all-files &optional pred hist _mb)
|
||
(let ((prompt (if (and all-files
|
||
(file-name-absolute-p (car all-files)))
|
||
prompt
|
||
( concat prompt
|
||
( format " in %s"
|
||
(consult--fast-abbreviate-file-name default-directory)))))
|
||
(minibuffer-completing-file-name t))
|
||
(consult--read (mapcar
|
||
(lambda (file)
|
||
(file-relative-name file))
|
||
all-files)
|
||
:state (consult--file-preview)
|
||
:prompt (concat prompt ": ")
|
||
:require-match t
|
||
:history hist
|
||
:category 'file
|
||
:predicate pred)))
|
||
#+end_src
|
||
** Descriptions
|
||
*** Marginalia
|
||
[[https://github.com/minad/marginalia/]]
|
||
Descriptions for completions
|
||
#+begin_src emacs-lisp
|
||
;; Enable rich annotations using the Marginalia package
|
||
(use-package marginalia
|
||
:ensure t
|
||
;; Bind `marginalia-cycle' locally in the minibuffer. To make the binding
|
||
;; available in the *Completions* buffer, add it to the
|
||
;; `completion-list-mode-map'.
|
||
:bind (:map minibuffer-local-map
|
||
("M-A" . marginalia-cycle))
|
||
|
||
;; The :init section is always executed.
|
||
:init
|
||
|
||
;; Marginalia must be activated in the :init section of use-package such that
|
||
;; the mode gets enabled right away. Note that this forces loading the
|
||
;; package.
|
||
(marginalia-mode))
|
||
#+end_src
|
||
* Communication
|
||
* Theme
|
||
[[https://emacsfodder.github.io/emacs-theme-editor/][Emacs Theme Editor]]
|
||
** Theme loading
|
||
#+begin_src emacs-lisp
|
||
(use-package doom-themes
|
||
:ensure t
|
||
:config
|
||
;; Global settings (defaults)
|
||
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
|
||
doom-themes-enable-italic t) ; if nil, italics is universally disabled
|
||
(load-theme 'doom-one t)
|
||
|
||
;; Enable flashing mode-line on errors
|
||
(doom-themes-visual-bell-config)
|
||
;; Enable custom neotree theme (nerd-icons must be installed!)
|
||
(doom-themes-neotree-config)
|
||
;; or for treemacs users
|
||
(setq doom-themes-treemacs-theme "doom-atom") ; use "doom-colors" for less minimal icon theme
|
||
(doom-themes-treemacs-config)
|
||
;; Corrects (and improves) org-mode's native fontification.
|
||
(doom-themes-org-config))
|
||
#+end_src
|
||
* Transparency
|
||
With Emacs version 29, true transparency has been added.
|
||
#+begin_src emacs-lisp
|
||
(unless (kylekrein/detect-wsl)
|
||
(add-to-list 'default-frame-alist '(alpha-background . 90))) ; For all new frames henceforth
|
||
#+end_src
|
||
* WHICH-KEY
|
||
#+begin_src emacs-lisp
|
||
(use-package which-key
|
||
:ensure t
|
||
:init
|
||
(which-key-mode 1)
|
||
:config
|
||
(setq which-key-side-window-location 'bottom
|
||
which-key-sort-order #'which-key-key-order-alpha
|
||
which-key-sort-uppercase-first nil
|
||
which-key-add-column-padding 1
|
||
which-key-max-display-columns nil
|
||
which-key-min-display-lines 6
|
||
which-key-side-window-slot -10
|
||
which-key-side-window-max-height 0.25
|
||
which-key-idle-delay 0.8
|
||
which-key-max-description-length 25
|
||
which-key-allow-imprecise-window-fit nil
|
||
which-key-separator " → " ))
|
||
#+end_src
|
||
|
||
* Emacs on Android
|
||
** Fonts
|
||
All fonts on Android must be in *~/fonts* directory
|
||
** Settings
|
||
#+begin_src emacs-lisp
|
||
(when (kylekrein/is-android)
|
||
;;Write all android settings here
|
||
(setq touch-screen-keyboard-function t)
|
||
(setq touch-screen-display-keyboard t)
|
||
|
||
(menu-bar-mode 1) ;; Enable the menu bar
|
||
(scroll-bar-mode 1) ;; Enable the scroll bar
|
||
(tool-bar-mode 1) ;;Enable the tool bar
|
||
(setq use-file-dialog t) ;; file dialog
|
||
(setq use-dialog-box t) ;; dialog box
|
||
(setq pop-up-windows t) ;; popup windows
|
||
(server-start)
|
||
)
|
||
#+end_src
|
||
* Emacs on WSL
|
||
** Clipboard fix
|
||
Found the fix [[https://www.lukas-barth.net/blog/emacs-wsl-copy-clipboard/][here]]
|
||
#+begin_src emacs-lisp
|
||
(when (kylekrein/detect-wsl)
|
||
(setq select-active-regions nil)
|
||
(setq select-enable-clipboard 't)
|
||
(setq select-enable-primary nil)
|
||
(setq interprogram-cut-function #'gui-select-text)
|
||
)
|
||
#+end_src
|