emacs-config/config.org

43 KiB
Raw Blame History

KyleKrein's GNU Emacs Config

IMPORTANT PROGRAMS TO LOAD FIRST

Evil Mode

(use-package evil
    :ensure t
    :init      ;; tweak evil's configuration before loading it
    (setq evil-want-integration t) ;; This is optional since it's already set to t by default.
    (setq evil-want-keybinding nil)
    (setq evil-vsplit-window-right t)
    (setq evil-split-window-below t)
    (setq evil-undo-system 'undo-redo)  ;; Adds vim-like C-r redo functionality
    (evil-mode))
  (use-package evil-collection
    :ensure t
    :after evil
    :config
    ;; Do not uncomment this unless you want to specify each and every mode
    ;; that evil-collection should works with.  The following line is here 
    ;; for documentation purposes in case you need it.  
    ;; (setq evil-collection-mode-list '(calendar dashboard dired ediff info magit ibuffer))
    (add-to-list 'evil-collection-mode-list 'help) ;; evilify help mode
    (evil-collection-init))
  (use-package evil-tutor
  :ensure t)

;; Using RETURN to follow links in Org/Evil 
;; Unmap keys in 'evil-maps if not done, (setq org-return-follows-link t) will not work
(with-eval-after-load 'evil-maps
  (define-key evil-motion-state-map (kbd "SPC") nil)
  (define-key evil-motion-state-map (kbd "RET") nil)
  (define-key evil-motion-state-map (kbd "TAB") nil))
;; Setting RETURN key in org-mode to follow links
  (setq org-return-follows-link  t)

Recent Files

(recentf-mode t)

General Keybindings

        (use-package general
          :ensure t
          :config
          (general-evil-setup)
        )
        (require 'general) ;; If i do this in :config, it says that function is wrong
          ;; set up 'SPC' as the global leader key
          (general-create-definer kylekrein/leader-keys
            :states '(normal insert visual emacs)
            :keymaps 'override
            :prefix "SPC" ;; set leader
            :global-prefix "M-SPC") ;; access leader in insert mode
            (kylekrein/leader-keys
          "." '(find-file :wk "Find file")
          "f r" '(recentf-open :wk "Open recent file")
	  "f d" '(find-grep-dired :wk "Search for string in files in DIR")
          "TAB TAB" '(comment-line :wk "Comment lines"))
    (kylekrein/leader-keys
        "b" '(:ignore t :wk "buffer")
        "b b" '(switch-to-buffer :wk "Switch buffer")
        "b i" '(ibuffer :wk "Ibuffer")
        "b k" '(kill-current-buffer :wk "Kill current buffer")
        "b n" '(next-buffer :wk "Next buffer")
        "b p" '(previous-buffer :wk "Previous buffer")
        "b r" '(revert-buffer :wk "Reload buffer"))

      (kylekrein/leader-keys
"e" '(:ignore t :wk "Eshell/Ediff/Evaluate")    
    "e b" '(eval-buffer :wk "Evaluate elisp in buffer")
    "e d" '(eval-defun :wk "Evaluate defun containing or after point")
    "e e" '(eval-expression :wk "Evaluate and elisp expression")
    "e l" '(eval-last-sexp :wk "Evaluate elisp expression before point")
    "e r" '(eval-region :wk "Evaluate elisp in region")
    "e s" '(eshell :which-key "Eshell")
    "e f" '(ediff-files :wk "Run ediff on a pair of files"))

       (kylekrein/leader-keys
        "h" '(:ignore t :wk "Help")
        "h f" '(describe-function :wk "Describe function")
        "h v" '(describe-variable :wk "Describe variable"))
        ;;"h r r" '((lambda () (interactive) (load-file "~/.config/emacs/init.el")) :wk "Reload emacs config"))
        ;;"h r r" '(reload-init-file :wk "Reload emacs config"))

       (kylekrein/leader-keys
        "t" '(:ignore t :wk "Toggle")
        "t l" '(display-line-numbers-mode :wk "Toggle line numbers")
        "t t" '(visual-line-mode :wk "Toggle truncated lines")
	"t v" '(vterm-toggle :wk "Toggle vterm"))
(kylekrein/leader-keys
  "o" '(:ignore t :wk "Open")
  "o a" '(org-agenda :wk "Agenda")
 )
(kylekrein/leader-keys
  "n" '(:ignore t :wk "Notes")
  "n r" '(:ignore t :wk "Roam")
  "n r f" '(org-roam-node-find :wk "Find and open")
  "n r i" '(org-roam-node-insert :wk "Insert link")
  "n r l" '(org-roam-buffer-toggle :wk "Show backlinks")
  "n r m" '(org-roam-dailies-map :wk "Dailies")
  "n r s" '(org-roam-db-sync :wk "Sync Notes DB (After changes on another device)")
  )
(kylekrein/leader-keys
    "d" '(:ignore t :wk "Dired")
    "d d" '(dired :wk "Open dired")
    "d j" '(dired-jump :wk "Dired jump to current")
    "d n" '(neotree-dir :wk "Open directory in neotree")
    "d p" '(peep-dired :wk "Peep-dired"))

  (kylekrein/leader-keys
      "w" '(:ignore t :wk "Windows")
      ;; Window splits
      "w c" '(evil-window-delete :wk "Close window")
      "w n" '(evil-window-new :wk "New window")
      "w s" '(evil-window-split :wk "Horizontal split window")
      "w v" '(evil-window-vsplit :wk "Vertical split window")
      ;; Window motions
      "w h" '(evil-window-left :wk "Window left")
      "w j" '(evil-window-down :wk "Window down")
      "w k" '(evil-window-up :wk "Window up")
      "w l" '(evil-window-right :wk "Window right")
      "w w" '(evil-window-next :wk "Goto next window")
      ;; Move Windows
      "w H" '(buf-move-left :wk "Buffer move left")
      "w J" '(buf-move-down :wk "Buffer move down")
      "w K" '(buf-move-up :wk "Buffer move up")
      "w L" '(buf-move-right :wk "Buffer move right"))

Startup Time

;; Startup time
(defun efs/display-startup-time ()
  (message
   "Emacs loaded in %s with %d garbage collections."
   (format
    "%.2f seconds"
    (float-time
     (time-subtract after-init-time before-init-time)))
   gcs-done))

(add-hook 'emacs-startup-hook #'efs/display-startup-time)

Support functions

Emacs function launcher

Launches emacs function as a window

(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))))

Copy to clipboard

Copies to both kill ring and system clipboard

;;(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))))

App Launcher

This code creates a menu to launch linux apps, that have Desktop entry. Code was taken from this awesome repo

(require 'xdg)
(require 'cl-seq)

(defcustom app-launcher-apps-directories
  (mapcar (lambda (dir) (expand-file-name "applications" dir))
	  (cons (xdg-data-home)
		(xdg-data-dirs)))
  "Directories in which to search for applications (.desktop files)."
  :type '(repeat directory))

(defcustom app-launcher--annotation-function #'app-launcher--annotation-function-default
  "Define the function that genereate the annotation for each completion choices."
  :type 'function)

(defcustom app-launcher--action-function #'app-launcher--action-function-default
  "Define the function that is used to run the selected application."
  :type 'function)

(defvar app-launcher--cache nil
  "Cache of desktop files data.")

(defvar app-launcher--cache-timestamp nil
  "Time when we last updated the cached application list.")

(defvar app-launcher--cached-files nil
  "List of cached desktop files.")

(defun app-launcher-list-desktop-files ()
  "Return an alist of all Linux applications.
Each list entry is a pair of (desktop-name . desktop-file).
This function always returns its elements in a stable order."
  (let ((hash (make-hash-table :test #'equal))
	result)
    (dolist (dir app-launcher-apps-directories)
      (when (file-exists-p dir)
	(let ((dir (file-name-as-directory dir)))
	  (dolist (file (directory-files-recursively dir ".*\\.desktop$"))
	    (let ((id (subst-char-in-string ?/ ?- (file-relative-name file dir))))
	      (when (and (not (gethash id hash)) (file-readable-p file))
		(push (cons id file) result)
		(puthash id file hash)))))))
    result))

(defun app-launcher-parse-files (files)
  "Parse the .desktop files to return usable informations."
  (let ((hash (make-hash-table :test #'equal)))
    (dolist (entry files hash)
      (let ((file (cdr entry)))
	(with-temp-buffer
	  (insert-file-contents file)
	  (goto-char (point-min))
	  (let ((start (re-search-forward "^\\[Desktop Entry\\] *$" nil t))
		(end (re-search-forward "^\\[" nil t))
		(visible t)
		name comment exec)
	    (catch 'break
	      (unless start
		(message "Warning: File %s has no [Desktop Entry] group" file)
		(throw 'break nil))

	      (goto-char start)
	      (when (re-search-forward "^\\(Hidden\\|NoDisplay\\) *= *\\(1\\|true\\) *$" end t)
		(setq visible nil))
	      (setq name (match-string 1))

	      (goto-char start)
	      (unless (re-search-forward "^Type *= *Application *$" end t)
		(throw 'break nil))
	      (setq name (match-string 1))

	      (goto-char start)
	      (unless (re-search-forward "^Name *= *\\(.+\\)$" end t)
		(push file counsel-linux-apps-faulty)
		(message "Warning: File %s has no Name" file)
		(throw 'break nil))
	      (setq name (match-string 1))

	      (goto-char start)
	      (when (re-search-forward "^Comment *= *\\(.+\\)$" end t)
		(setq comment (match-string 1)))

	      (goto-char start)
	      (unless (re-search-forward "^Exec *= *\\(.+\\)$" end t)
		;; Don't warn because this can technically be a valid desktop file.
		(throw 'break nil))
	      (setq exec (match-string 1))

	      (goto-char start)
	      (when (re-search-forward "^TryExec *= *\\(.+\\)$" end t)
		(let ((try-exec (match-string 1)))
		  (unless (locate-file try-exec exec-path nil #'file-executable-p)
		    (throw 'break nil))))

	      (puthash name
		       (list (cons 'file file)
			     (cons 'exec exec)
			     (cons 'comment comment)
			     (cons 'visible visible))
		       hash))))))))

(defun app-launcher-list-apps ()
  "Return list of all Linux .desktop applications."
  (let* ((new-desktop-alist (app-launcher-list-desktop-files))
	 (new-files (mapcar 'cdr new-desktop-alist)))
    (unless (and (equal new-files app-launcher--cached-files)
		 (null (cl-find-if
			(lambda (file)
			  (time-less-p
			   app-launcher--cache-timestamp
			   (nth 5 (file-attributes file))))
			new-files)))
      (setq app-launcher--cache (app-launcher-parse-files new-desktop-alist))
      (setq app-launcher--cache-timestamp (current-time))
      (setq app-launcher--cached-files new-files)))
  app-launcher--cache)

(defun app-launcher--annotation-function-default (choice)
  "Default function to annotate the completion choices."
  (let ((str (cdr (assq 'comment (gethash choice app-launcher--cache)))))
    (when str (concat " - " (propertize str 'face 'completions-annotations)))))

(defun app-launcher--action-function-default (selected)
  "Default function used to run the selected application."
  (let* ((exec (cdr (assq 'exec (gethash selected app-launcher--cache))))
	 (command (let (result)
		    (dolist (chunk (split-string exec " ") result)
		      (unless (or (equal chunk "%U")
				  (equal chunk "%F")
				  (equal chunk "%u")
				  (equal chunk "%f"))
			(setq result (concat result chunk " ")))))))
    (call-process-shell-command command nil 0 nil)))

;;;###autoload
(defun app-launcher-run-app (&optional arg)
  "Launch an application installed on your machine.
When ARG is non-nil, ignore NoDisplay property in *.desktop files."
  (interactive)
  (let* ((candidates (app-launcher-list-apps))
	 (result (completing-read
		  "Run app: "
		  (lambda (str pred flag)
		    (if (eq flag 'metadata)
			'(metadata
			  (annotation-function . (lambda (choice)
						   (funcall
						    app-launcher--annotation-function
						    choice))))
		      (complete-with-action flag candidates str pred)))
		  (lambda (x y)
		    (if arg
			t
		      (cdr (assq 'visible y))))
		  t nil 'app-launcher nil nil)))
    (funcall app-launcher--action-function result)))

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)

(defun emacs-run-app-launcher()
  (emacs-run-launcher 'app-launcher-run-app))

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 lets tell Emacs to put all backups that it creates in the TRASH directory.

(setq backup-directory-alist '((".*" . "~/.local/share/Trash/files")))

Company

Company is a text completion framework for Emacs. The name stands for “complete anything”. Completion will start automatically after you type a few letters. Use M-n and M-p to select, <return> to complete or <tab> to complete the common part.

  (use-package company
    :ensure t
    :defer 2
    :diminish
    :custom
    (company-begin-commands '(self-insert-command))
    (company-idle-delay .1)
    (company-minimum-prefix-length 2)
    (company-show-numbers t)
    (company-tooltip-align-annotations 't)
    (global-company-mode t))

  (use-package company-box
    :ensure t
    :after company
    :diminish
    :hook (company-mode . company-box-mode))

Dashboard

Emacs Dashboard is an extensible startup screen showing you recent files, bookmarks, agenda items and an Emacs banner.

(use-package dashboard
  :ensure t 
  :init
  (setq initial-buffer-choice 'dashboard-open)
  (setq dashboard-set-heading-icons t)
  (setq dashboard-set-file-icons t)
  (setq dashboard-banner-logo-title "Emacs Is More Than A Text Editor!")
  ;;(setq dashboard-startup-banner 'logo) ;; use standard emacs logo as banner
  ;;(setq dashboard-startup-banner "/home/dt/.config/emacs/images/emacs-dash.png")  ;; use custom image 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)))
  :custom
  (dashboard-modify-heading-icons '((recents . "file-text")
                                    (bookmarks . "book")))
  :config
  (dashboard-setup-startup-hook))

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.

(use-package diminish :ensure t)

DIRED (File manager)

(use-package dired-open
  :ensure t
  :config
  (setq dired-open-extensions '(("gif" . "gwenview")
                                ("jpg" . "gwenview")
                                ("png" . "gwenview")
                                ("mkv" . "vlc")
                                ("mp4" . "vlc"))))

(use-package peep-dired
  :ensure t
  :after dired
  :hook (evil-normalize-keymaps . peep-dired-hook)
  :config
    (evil-define-key 'normal dired-mode-map (kbd "h") 'dired-up-directory)
    (evil-define-key 'normal dired-mode-map (kbd "l") 'dired-open-file) ; use dired-find-file instead if not using dired-open package
    (evil-define-key 'normal peep-dired-mode-map (kbd "j") 'peep-dired-next-file)
    (evil-define-key 'normal peep-dired-mode-map (kbd "k") 'peep-dired-prev-file)
)

;;(add-hook 'peep-dired-hook 'evil-normalize-keymaps)

EDIFF

ediff is a diff program that is built into Emacs. By default, ediff splits files vertically and places the help frame in its own window. I have changed this so the two files are split horizontally and the help frame appears as a lower split within the existing window. Also, I create my own dt-ediff-hook where I add j/k for moving to next/prev diffs. By default, this is set to n/p.

(setq ediff-split-window-function 'split-window-horizontally
      ediff-window-setup-function 'ediff-setup-windows-plain)

(defun dt-ediff-hook ()
  (ediff-setup-keymap)
  (define-key ediff-mode-map "j" 'ediff-next-difference)
  (define-key ediff-mode-map "k" 'ediff-previous-difference))

(add-hook 'ediff-mode-hook 'dt-ediff-hook)

Emoji

Copy to clipboard

(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)))))

Standalone emoji picker

To use it, create a global keyboard shortcut with the following code emacsclient -cF "((visibility . nil))" -e "(emacs-run-emoji-picker)

(defun emacs-run-emoji-picker ()
  (interactive)
  (emacs-run-launcher (lambda () (progn (kylekrein/copy-emoji-to-clipboard)
((sleep-for 60))))))

FLYCHECK

Install luacheck from your Linux distros repositories for flycheck to work correctly with lua files. Install python-pylint for flycheck to work with python files. Haskell works with flycheck as long as haskell-ghc or haskell-stack-ghc is installed. For more information on language support for flycheck, read this.

(use-package flycheck
  :ensure t
  :defer t
  :diminish
  :init (global-flycheck-mode))

Fonts

Defining the various fonts that Emacs will use.

(set-face-attribute 'default nil
  :font "JetBrains Mono"
  :height 110
  :weight 'medium)
(set-face-attribute 'variable-pitch nil
  :font "Ubuntu"
  :height 120
  :weight 'medium)
(set-face-attribute 'fixed-pitch nil
  :font "JetBrains Mono"
  :height 110
  :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 . "JetBrains Mono-11"))

;; Uncomment the following line if line spacing needs adjusting.
(setq-default line-spacing 0.12)

Zooming In/Out

You can use the bindings CTRL plus =/- for zooming in/out. You can also use CTRL plus the mouse wheel for zooming in/out.

(global-set-key (kbd "C-=") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
(global-set-key (kbd "<C-wheel-up>") 'text-scale-increase)
(global-set-key (kbd "<C-wheel-down>") 'text-scale-decrease)

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.

(delete-selection-mode 1)    ;; You can select text and delete it by typing.
(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
(global-visual-line-mode t)  ;; Enable truncated lines
(menu-bar-mode -1)           ;; Disable the menu bar 
(scroll-bar-mode -1)         ;; Disable the scroll bar
(tool-bar-mode -1)           ;; Disable the tool bar
(setq org-edit-src-content-indentation 0) ;; Set src block automatic indent to 0 instead of 2.
(setq use-file-dialog nil)   ;; No file dialog
(setq use-dialog-box nil)    ;; No dialog box
(setq pop-up-windows nil)    ;; No popup windows
(setq save-interprogram-paste-before-kill t)

Battery info

(unless (equal "Battery status not available"
               (battery))
  (display-battery-mode 1))

MAGIT

Magit is a full-featured git client for Emacs.

  (use-package magit
    :ensure t)

Minibuffer escape

By default, Emacs requires you to hit ESC three times to escape quit the minibuffer.

(global-set-key [escape] 'keyboard-escape-quit)

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: Doom Modeline

(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 t   ;; adds perspective name to modeline
	doom-modeline-time t         ;; shows time
        doom-modeline-persp-icon t)) ;; adds folder icon next to persp name

PROJECTILE

Projectile is a project interaction library for Emacs. It should be noted that many projectile commands do not work if you have set “fish” as the “shell-file-name” for Emacs.

  (use-package projectile
    :ensure t
    :config
    (projectile-mode 1))

PDF Tools

pdf-tools is a replacement of DocView for viewing PDF files inside Emacs. It uses the poppler library, which also means that pdf-tools can by used to modify PDFs. I use to disable display-line-numbers-mode in pdf-view-mode because line numbers crash it.

  (use-package pdf-tools
    :ensure t
    :defer t
    :commands (pdf-loader-install)
    :mode "\\.pdf\\'"
    :bind (:map pdf-view-mode-map
                ("j" . pdf-view-next-line-or-next-page)
                ("k" . pdf-view-previous-line-or-previous-page)
                ("C-=" . pdf-view-enlarge)
                ("C--" . pdf-view-shrink))
    :init (pdf-loader-install)
    :config (add-to-list 'revert-without-query ".pdf"))

  (add-hook 'pdf-view-mode-hook #'(lambda () (interactive) (display-line-numbers-mode -1)
                                                           (blink-cursor-mode -1)
                                                           (doom-modeline-mode -1)))

RAINBOW DELIMITERS

Adding rainbow coloring to parentheses.

  (use-package rainbow-delimiters
    :ensure t
    :hook ((emacs-lisp-mode . rainbow-delimiters-mode)
           (clojure-mode . rainbow-delimiters-mode)))

ORG MODE

Enabling Table of Contents

  (setq org-directory "~/Documents/org")
  (use-package toc-org
    :ensure t
      :commands toc-org-enable
      :init (add-hook 'org-mode-hook 'toc-org-enable))

Enabling Org Bullets

Org-bullets gives us attractive bullets rather than asterisks.

  (add-hook 'org-mode-hook 'org-indent-mode)
  (use-package org-bullets :ensure t)
  (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))

Org Level Headers

(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)))))

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'
(require 'org-tempo)

ORG ROAM

Org Roam itself

    (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)
  	))
      (org-roam-dailies-capture-templates
       '(("d" "default" entry "* %<%I:%M %p>: %?"
         :if-new (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n"))))
      :config
      (require 'org-roam-dailies) ;; Ensure the keymap is available
      (org-roam-db-autosync-mode)
      (org-roam-setup))

Org Roam UI

 (use-package org-roam-ui
   :ensure t
   :after org-roam)

Org Agenda

(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")))

  ;; Build the agenda list the first time for the session
  (kylekrein/org-roam-refresh-agenda-list)



  (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
        )

Inbox

(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")))))

Todos in Today

Automatically copies all DONE TODOs to Today's daily

(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))))

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.

  (use-package rainbow-mode
    :ensure t
    :hook 
    ((org-mode prog-mode) . rainbow-mode))

SHELLS AND TERMINALS

Eshell

Eshell is an Emacs 'shell' that is written in Elisp.

  (use-package eshell-syntax-highlighting
    :ensure t
    :after esh-mode
    :config
    (eshell-syntax-highlighting-global-mode +1))

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.

  (use-package vterm
    :ensure t
  ;;:config
)

Vterm-Toggle

vterm-toggle toggles between the vterm buffer and whatever buffer you are editing.

  (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))))

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.

  (use-package sudo-edit
    :ensure t
    :config
      (kylekrein/leader-keys
        "fu" '(sudo-edit-find-file :wk "Sudo find file")
        "fU" '(sudo-edit :wk "Sudo edit file")))

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

(use-package nix-mode
  :ensure t
  :mode ("\\.nix\\'" "\\.nix.in\\'"))
(use-package nix-drv-mode
  :ensure nix-mode
  :mode "\\.drv\\'")
(use-package nix-shell
  :ensure nix-mode
  :commands (nix-shell-unpack nix-shell-configure nix-shell-build))
(use-package nix-repl
  :ensure nix-mode
  :commands (nix-repl))

Nerd Icons

  (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")
    )

Nerd Icons Completion

https://github.com/rainstormstudio/nerd-icons-completion

  (use-package nerd-icons-completion
    :ensure t
    :after marginalia
    :config
    (nerd-icons-completion-mode)
    (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))

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

(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))))

Vertico

Vertico provides a performant and minimalistic vertical completion UI based on the default completion system.

  ;; 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'
    :bind (:map vertico-map
		("C-j" . vertico-next)
		("C-k" . vertico-previous)
		:map minibuffer-local-map
		("C-h" . backward-kill-word)
		)
    :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))
  
;; 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 basic))
  (completion-category-defaults nil)
  (completion-category-overrides '((file (styles partial-completion)))))

Consult

A collection of commands (like Counsel for Ivy), which provide additional completions.

Embark

Provides actions for the current selection in Vertico completion list (ex. Remove/Rename file in find-file)

Descriptions

Marginalia

https://github.com/minad/marginalia/ Descriptions for completions

  ;; 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))

Theme

Emacs Theme Editor

Theme loading

(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))

TLDR

Too long didn't read - documentation

(use-package tldr :ensure t)

Transparency

With Emacs version 29, true transparency has been added.

(add-to-list 'default-frame-alist '(alpha-background . 90)) ; For all new frames henceforth

WHICH-KEY

  (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 " → " ))