/emacs

My Emacs Config

Primary LanguageEmacs LispMIT LicenseMIT

Adrian Danao-Schroeder config

Set background

So the white startup screen doesn’t blind me
(set-background-color "#000000")

System .emacs Setup

Setting default file and directory locations, these are all defined in the default startup .emacs file to work on different computers see .emacs for an example of what it normally looks like

Emacs Directory

Define the user emacs directory: ads/user-dir-emacs

defined in the default .emacs file used for emacs init to work on various computers

Org Directory

User org-mode file directory: ads/user-dir-org defined in default .emacs config file

Personal Org Directory

Personal org directory (see all tasks on work computer and shared inbox) ads/personal-dir-org

Readme config file

ads/user-dir-readme - this files full path

init.el config file

ads/user-dir-config directory for the actual config file used when running

Computer id

set ads/computer-id currently: work Personal

Load Path

(add-to-list 'load-path ads/user-dir-emacs)
(add-to-list 'load-path ads/user-dir-org)
  

Debug on Error

Nice to load it early, makes troubleshooting a problem easier
(setq debug-on-error t)
  

Package System Setup

Package setup

;; Initialize package sources
(require 'package)

(setq package-archives '(("melpa" . "https://melpa.org/packages/")
                         ("gnu" . "https://elpa.gnu.org/packages/")
                         ("nongnu" . "https://elpa.nongnu.org/nongnu/")
                         ("org" . "https://orgmode.org/elpa/")
                         ("elpa" . "https://elpa.gnu.org/packages/")
			 ))
(if (not package--initialized)
    (package-initialize))

(unless package-archive-contents
     (package-refresh-contents))

;; Initialize use-package on non-Linux platforms
(unless (package-installed-p 'use-package)
(package-install 'use-package))

(require 'use-package)
(setq use-package-always-ensure t)
  

Better Defaults

Setup some default startup parameters
(setq-default
 cursor-in-non-selected-windows nil     ; Hide the cursor in inactive windows
 require-final-newline t                ; Newline at end of file
 scroll-margin 3                        ; Add a margin when scrolling vertically
 scroll-conservatively 10               ; Avoid recentering when scrolling far
 help-window-select t                   ; Focus new help windows when opened
 initial-scratch-message "Welcome back"             ; Empty the initial *scratch* buffer
 visible-bell nil                       ; set up the visible bell (no annoying beeping sounds)
 inhibit-startup-echo-area-message t
 inhibit-startup-screen t
 )

(blink-cursor-mode 0)                   ; Prefer a still cursor
(fset 'yes-or-no-p 'y-or-n-p)           ; Replace yes/no prompts with y/n
(global-subword-mode 1)                 ; Iterate through CamelCase words
(put 'downcase-region 'disabled nil)    ; Enable downcase-region
(put 'upcase-region 'disabled nil)      ; Enable upcase-region
(scroll-bar-mode -1)                    ; Disable the visible scrollbar
(tool-bar-mode -1)                      ; Disablet the toolbar
(tooltip-mode -1)                       ; Disable tooltips
(menu-bar-mode -1)                      ; Disable the menu bar
(set-fringe-mode 10)                    ; Add some breathing room

Backup Directory

(setq backup-directory-alist '(("." . "~/.emacs.d/backup"))
  backup-by-copying t    ; Don't delink hardlinks
  version-control t      ; Use version numbers on backups
  delete-old-versions t  ; Automatically delete excess backups
  kept-new-versions 20   ; how many of the newest versions to keep
  kept-old-versions 5    ; and how many of the old
  )

Backup Predicate

(setq backup-enable-predicate
      (lambda (name)
        (and (normal-backup-enable-predicate name)
             (not
              (let ((method (file-remote-p name 'method)))
                (when (stringp method)
                  (member method '("su" "sudo"))))))))

Async shell commands in background

when calling async shell it’s annoying to have stuff pop up int hte
(add-to-list 'display-buffer-alist
  (cons "\\*Async Shell Command\\*.*" (cons #'display-buffer-no-window nil)))

Basic Functions

Read only directories

some directories I want to files to be opened in read-only mode because they are usually used for reference rather than
(setq read-only-directories '( ) )
(defun find-file-read-only-directories ()
"""
start buffer in read only mode if file in a child directory
 of in any of the directores defined in read-only-directories
"""
  (dolist (read-only-directory read-only-directories)
  ;; (print read-only-directory)
  (when
      (string-search read-only-directory buffer-file-name)
      (read-only-mode)
      ;; (print "open normally")
    )
  ))

(add-hook 'find-file-hook 'find-file-read-only-directories)

F Strings

Python F strings are a great way to format strings while being able to see what’s going on inside code taken from John Kitchin’s f-strings in emacs-lisp
(defmacro f-string (fmt)
  "Like `s-format' but with format fields in it.
FMT is a string to be expanded against the current lexical
environment. It is like what is used in `s-lex-format', but has
an expanded syntax to allow format-strings. For example:
${user-full-name 20s} will be expanded to the current value of
the variable `user-full-name' in a field 20 characters wide.
  (let ((f (sqrt 5)))  (f-string \"${f 1.2f}\"))
  will render as: 2.24
This function is inspired by the f-strings in Python 3.6, which I
enjoy using a lot.
"
  (let* ((matches (s-match-strings-all"${\\(?3:\\(?1:[^} ]+\\) *\\(?2:[^}]*\\)\\)}" fmt))
         (agetter (cl-loop for (m0 m1 m2 m3) in matches
                        collect `(cons ,m3  (format (format "%%%s" (if (string= ,m2 "")
                                                                      (if s-lex-value-as-lisp "S" "s")
                                                                   ,m2))
                                                  (symbol-value (intern ,m1)))))))

    `(s-format ,fmt 'aget (list ,@agetter))))

Basic UI Config

Font configuration

Setting up font properties, I like Et bembo, but for some reason can’t find where I got Etbembo from on my windows machines
(if (string= system-type "gnu/linux")
    (setq
     serif "Etbb"
     mono "Fira Code Nerd Font")
    (setq
     serif "EtBembo"
     mono "FiraCode Nerd Font"))
(setq sans "Cantarell")

;; Set Font sizes
(defvar ads/default-font-size 160)
(defvar ads/default-variable-font-size 160)

;Set line spacing
(setq line-spacing .2)

;; Set default font
(set-face-attribute 'default nil :font mono :height ads/default-font-size)

;; Set the fixed pitch face
(set-face-attribute 'fixed-pitch nil :font mono :height ads/default-font-size)

;; Set the variable pitch fa
(set-face-attribute 'variable-pitch nil :font serif :height ads/default-variable-font-size :weight 'regular)

Line Numbers

;; Enable line numbers
;; (global-display-line-numbers-mode nil)

;; Disable lines in some modes
(dolist (mode '(prog-mode-hook
		   ))
	   (add-hook mode(lambda () (display-line-numbers-mode 1))))
  

Column Numbers

Enable column numbers
(column-number-mode)

  

Rainbow Delimiters

GitHub - Fanael/rainbow-delimiters: Emacs rainbow delimiters mode
(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))
  

Unbind Hide/kill emacs session C-x

In my clumsyness I’ve hit theste too many times

(global-set-key (kbd "C-x C-c") 'nil)
(global-set-key (kbd "C-x C-z") 'nil)

Unbind Emacs help stuff

I don’t need to open:
  • tutorial
  • hello
  • help for help
(global-set-key (kbd "C-h t") 'nil)
(global-set-key (kbd "C-h h") 'nil)
(global-set-key (kbd "C-h C-h") 'nil)

Hide Modeline Mode

(defvar-local hidden-mode-line-mode nil)

(define-minor-mode hidden-mode-line-mode
  "Minor mode to hide the mode-line in the current buffer."
  :init-value nil
  :global t
  :variable hidden-mode-line-mode
  :group 'editing-basics
  (if hidden-mode-line-mode
      (setq hide-mode-line mode-line-format
            mode-line-format nil)
    (setq mode-line-format hide-mode-line
          hide-mode-line nil))
  (force-mode-line-update)
  ;; Apparently force-mode-line-update is not always enough to
  ;; redisplay the mode-line
  (redraw-display)
  (when (and (called-interactively-p 'interactive)
             hidden-mode-line-mode)
    (run-with-idle-timer
     0 nil 'message
     (concat "Hidden Mode Line Mode enabled.  "
             "Use M-x hidden-mode-line-mode to make the mode-line appear."))))

Keybinding Config

Global Esc

;;Make ESC quit prompts (why wouldn't you want that?)
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)

  

General Leader Keys

(define-key global-map (kbd "C-SPC") 'nil)
(use-package general
 :after evil
 :config
 (general-create-definer ads/leader-keys
   :keymaps '(normal insert visual emacs)
   :prefix "SPC"
   :global-prefix "C-SPC")

 (ads/leader-keys
   "t" '(:ignore t :wk "toggles")

   "j" '(:ignore t :which-key "org")

   "er" '(lambda () (interactive)
	   (find-file (concat ads/user-dir-readme))
           :wk "Readme Config")

   "ew" '(lambda () (interactive)
	   (find-file "c:/users/adanaos/git/emacs-work/work-config.org")
           :wk "Work Config")

   "e." '(lambda () (interactive)
	   (find-file ads/user-dir-config)
           :wk ".emacs Config")

   "ei" '(lambda () (interactive) (find-file (concat ads/user-dir-emacs "init.el"))
           :which-key "ORG init")

   "ez" '(lambda () (interactive)
	   (find-file (concat ads/git-dir "zmk-config/config/corne.keymap"))
           :wk "ZMK Config")
   "eZ" '(lambda () (interactive)
	   (counsel-find-file (concat ads/git-dir "zmk-config/"))
           :wk "ZMK Config")

   "e" '(:ignore t :whch-key "eval")
   "eb" '(eval-buffer :which-key "eval-buffer")
   "ep" '(eval-last-sexp :which-key "eval-last-sexp")
   "eo" '(org-mode-restart :which-key "org-mode-restart")

   "k" '(:ignore t :wk "kill")
   "kj" '(kill-buffer-and-window :which-key "kill-buffer-and-window")
   "kk" '(kill-this-buffer :which-key "kill-this-buffer")
   "kl"'(delete-window :wk "delete-window")
   ))

Register keybinding

I don’t use mark so much because of Evil’s visual mode, but the register functionality with space is very useful
(define-key global-map (kbd "C-SPC C-SPC") 'jump-to-register)
(define-key global-map (kbd "C-SPC C-;") 'point-to-register)

Evil

(use-package evil
  :init
  (setq evil-want-integration t)
  (setq evil-want-keybinding nil)
  (setq evil-want-C-u-scroll nil)
  (setq evil-want-C-i-jump nil)
  (setq evil-want-C-w-delete nil)
  :config
  (evil-mode 1)
  (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
  (define-key evil-normal-state-map (kbd "q") 'nil)
  ;; Use visual line motions even outside of visual-line mode buffers
  (evil-global-set-key 'motion "j" 'evil-next-visual-line)
  (evil-global-set-key 'motion "k" 'evil-previous-visual-line)

  ;; ;; Use C-<hjkl> to move around in insert
  ;; (evil-global-set-key 'insert (kbd "C-h") 'evil-backward-char)
  ;; (evil-global-set-key 'insert (kbd "C-l") 'evil-forward-char)
  ;; (evil-global-set-key 'insert (kbd "C-k") 'evil-previous-line)
  ;; (evil-global-set-key 'insert (kbd "C-j") 'evil-next-line)


  (evil-set-initial-state 'messages-buffer-mode 'normal)
  (evil-set-initial-state 'dashboard-mode 'normal))

(use-package evil-collection
  :after evil
  :config
  (evil-collection-init))



  

Toggle line width

(defun ads/toggle-lines ()
  (interactive)
  (toggle-truncate-lines)
  ;; (visual-line-mode)
  (when (eq major-mode 'org-mode)
    (visual-fill-column-mode `toggle)))

(ads/leader-keys
   "tl" '(ads/toggle-lines :wk"toggle truncate")
)

Normal mode after save

(add-hook 'after-save-hook 'evil-normal-state)

Fix trailing whitespace on save

(setq delete-trailing-lines nil)
(add-hook 'before-save-hook 'delete-trailing-whitespace)

Evil Buffer control

(evil-global-set-key 'normal (kbd "C-M-j")  'counsel-switch-buffer)

Evil Window Control

I don’t want to have to stop pressing ctrl also go back to normal mode if in insert mode
(evil-global-set-key 'normal (kbd "C-w C-h") 'evil-window-left)
(evil-global-set-key 'insert (kbd "C-w C-h") (lambda () (interactive)
					       ;; (normal-mode)
					       (call-interactively 'evil-window-left)))


(evil-global-set-key 'normal (kbd "C-w C-j") 'evil-window-down)
(evil-global-set-key 'insert (kbd "C-w C-j") (lambda () (interactive)
					       ;; (normal-mode)
					       (call-interactively 'evil-window-down)))


(evil-global-set-key 'normal (kbd "C-w C-k") 'evil-window-up)
(evil-global-set-key 'insert (kbd "C-w C-k") (lambda () (interactive)
					       ;; (normal-mode)
					       (call-interactively 'evil-window-up)))


(evil-global-set-key 'normal (kbd "C-w C-l") 'evil-window-right)
(evil-global-set-key 'insert (kbd "C-w C-l") (lambda () (interactive)
					       ;; (normal-mode)
					       (call-interactively 'evil-window-right)))

(evil-global-set-key 'normal (kbd "C-w C-e") 'balance-windows)
(evil-global-set-key 'insert (kbd "C-w C-e") (lambda () (interactive)
					       ;; (normal-mode)
					       (call-interactively 'balance-windows)))

Tear Off Window

(evil-global-set-key 'normal (kbd "C-w C-n") 'tear-off-window)

Undo tree visualizer

GNU ELPA - undo-tree
(use-package undo-tree
  :diminish undo-tree-mode
  :config
  (progn
    (global-undo-tree-mode)
    (setq evil-undo-system 'undo-tree)
    (setq undo-tree-visualizer-timestamps t)
    (setq undo-tree-visualizer-diff t)
    (setq undo-tree-history-directory-alist '(("." . "~/.undo-tree-history")))))

(evil-global-set-key 'normal (kbd "C-x C-u") 'undo-tree-visualize)

Remove Line breaks in region

(defun ads/remove-newlines-in-region ()
  "Removes all newlines in the region."
  (interactive)
  (save-restriction
    (narrow-to-region (point) (mark))
    (goto-char (point-min))
    (while (search-forward "\n" nil t) (replace-match " " nil t))))

Fix file dir formatting for win

this is always so annoying
(defun ads/format-dir-winstyle ()
  "Removes all newlines in the region."
  (interactive)
  (save-restriction
    (narrow-to-region (point) (mark))
    (goto-char (point-min))
    (while (search-forward "\\" nil t) (replace-match "\\\\" nil t))))

Regex Replace Keybindings

(ads/leader-keys
    "r"  '(:ignore t :wk "replace")
    "rr" 'replace-regexp
    "rn" '(ads/remove-newlines-in-region :wk "remove new lines")
    "rs" '(ads/format-dir-winstyle :wk "format dir style windows")
)
  

Toggle comment

Normally insert enables overtype, but I’ve never once wanted that
(evil-global-set-key 'normal (kbd "M-;") 'comment-line)
(evil-global-set-key 'insert (kbd "M-;") 'comment-line)
(evil-global-set-key 'visual (kbd "M-;") 'comment-line)

Theme Setup

Set Custom Theme Directory

A little annoying that I have to specify this and it isn’t loaded from load path and that each theme file must be named foo-theme.el but I’m not about to rewrite something minor
(setq custom-theme-directory ads/user-dir-emacs)
  

Color theme list

(defvar ads/switch-themes-var
  (let ((themes-list (list
			    'ads-dark
			    'ads-light
)))
    (nconc themes-list themes-list))
  "A circular list of themes to keep switching between.
  Make sure that the currently enabled theme is at the head of this
  list always.

  A nil value implies no custom theme should be enabled.")

Color Theme

(use-package doom-themes
    :init
(load-theme (car ads/switch-themes-var) t)
    )

  

Toggle Theme

Toggle between themes, bound to SCP-tt

If on windows toggle app theme as well

(defun ads/quick-switch-theme ()
  "Switch between to commonly used faces in Emacs.
One for writing code and the other for reading articles."
  (interactive)
  (dolist (theme custom-enabled-themes)
    (disable-theme theme))
  (if-let* ((next-theme (cadr ads/switch-themes-var)))
      (progn (when-let* ((current-theme (car ads/switch-themes-var)))
               (disable-theme (car ads/switch-themes-var)))
             (load-theme next-theme t)
             (message "Loaded theme: %s" next-theme))
    ;; Always have the dark mode-line theme
    (mapc #'disable-theme (delq 'smart-mode-line-dark custom-enabled-themes)))
  (setq ads/switch-themes-var (cdr ads/switch-themes-var))
  (when
      (string= system-type "windows-nt")
      (ads/windows-align-emacs-darkmode))
  )


(ads/leader-keys
    "tt" '(ads/quick-switch-theme :wk "toggle theme"))

Refresh Theme

(defun ads/refresh-theme ()
  (interactive)
  (load-theme (car custom-enabled-themes) t)
)
(ads/leader-keys "tj" 'ads/refresh-theme)

Auto Refresh Theme

Check if the current theme matches the file being edited on save, if so refresh the current theme
(defun ads/refresh-theme-auto()
  (when (cl-search
     (symbol-name (car custom-enabled-themes))
     (file-name-base buffer-file-name))
    (ads/refresh-theme)))
(add-hook 'after-save-hook #'ads/refresh-theme-auto)

Transparency Toggle

(defun ads/toggle-transparency ()
   (interactive)
   (let ((alpha (frame-parameter nil 'alpha)))
     (set-frame-parameter
      nil 'alpha
      (if (eql (cond ((numberp alpha) alpha)
                     ((numberp (cdr alpha)) (cdr alpha))
                     ;; Also handle undocumented (<active> <inactive>) form.
                     ((numberp (cadr alpha)) (cadr alpha)))
               100)
          '(92 . 92) '(100 . 100)))))

(ads/leader-keys "tr"'(ads/toggle-transparency :wk "toggle transparency"))

Doom Modeline

   (use-package all-the-icons)

   ;; Doom modeline config
   (use-package doom-modeline
     :ensure t
     :init (doom-modeline-mode 1)
   )

(set-face-attribute 'doom-modeline nil :font mono)

  

Set window title

(setq frame-title-format "%b")

UI Config

Which key

(use-package which-key
 :defer 0
 :diminish which-key-mode
 :config
 (which-key-mode)
 (setq which-key-idle-delay 0.3))


  

Counsel

   (use-package counsel
     :bind (("C-M-j" . 'counsel-switch-buffer)
         :map minibuffer-local-map
         ("C-r" . 'counsel-minibuffer-history))
     :custom
     (counsel-linux-app-format-function #'counsel-linux-app-format-function-name-only)
     :config
     (counsel-mode 1))

(defun counsel-find-file-read-only (fpath)
  (interactive)
  (counsel-find-file fpath)
  (read-only-mode))


  

Ivy

   (use-package ivy
    :diminish ;; Hides from the mode line
    :bind (("C-s" . swiper)
         :map ivy-minibuffer-map
         ("TAB" . ivy-alt-done)
         ("C-l" . ivy-alt-done)
         ("C-j" . ivy-next-line)
         ("C-k" . ivy-previous-line)
         :map ivy-switch-buffer-map
         ("C-k" . ivy-previous-line)
         ("C-l" . ivy-done)
         ("C-d" . ivy-switch-buffer-kill)
         :map ivy-reverse-i-search-map
         ("C-k" . ivy-previous-line)
         ("C-d" . ivy-reverse-i-search-kill))
    :config
    (ivy-mode 1))


   (use-package ivy-rich
     :after ivy
     :init
     (ivy-rich-mode 1))


(define-key ivy-minibuffer-map (kbd "S-SPC") 'nil) ;
  

Ivy Prescient

Still not working ¯\_(ツ)_/¯ not sure why though, saying Ivy Prescient is not on melpa

(use-package ivy-prescient
  :after counsel
  :custom
  (ivy-prescient-enable-filtering nil)
  :config
   ;; Uncomment the following line to have sorting remembered across sessions!
  (prescient-persist-mode 1)
  (ivy-prescient-mode 1))
  

Helpful

   (use-package helpful
     :ensure t
     :commands (helpful-callable helpful-variable helpful-command helpful-key)
     :custom
       (counsel-describe-function-function #'helpful-callable)
       (counsel-describe-variable-function #'helpful-variable)
     :bind
       ([remap describe-function] . counsel-describe-function)
       ([remap describe-command] . helpful-command)
       ([remap describe-variable] . counsel-describe-variable)
       ([remap describe-key] . helpful-key))

(global-set-key (kbd "C-h C-v") 'describe-variable)
(global-set-key (kbd "C-h C-f") 'describe-function)
(global-set-key (kbd "C-h C-b") 'describe-bindings)
(global-set-key (kbd "C-h C-c") 'describe-key-briefly)
(global-set-key (kbd "C-h C-k") 'describe-key)
(global-set-key (kbd "C-h C-e") 'view-echo-area-messages)
(global-set-key (kbd "C-h C-j") 'describe-face)
  

Browse Kill-Ring

(use-package browse-kill-ring
  :ensure t
  :config
  ;; (browse-kill-ring-default-keybindings) ended up setting this myself down below same thing but I know what idiot set it
  (setq browse-kill-ring-highlight-current-entry t)
  )
(global-set-key (kbd "M-y") 'browse-kill-ring)

;; I like my evil bindings
(define-key browse-kill-ring-mode-map (kbd "j") 'browse-kill-ring-forward)
(define-key browse-kill-ring-mode-map (kbd "k") 'browse-kill-ring-previous)

Hydra Text Scaling

(use-package hydra
  :defer t)

(defhydra hydra-text-scale (:timeout 2)
  "scale text"
  ("j" text-scale-increase "in")
  ("k" text-scale-decrease "out")
  ("f" nil "finished" :exit t))

(ads/leader-keys
  "ts" '(hydra-text-scale/body :which-key "scale text"))

Hydra window adjust

(defhydra hydra-window-adjust (:timeout 5)
  ("k" (evil-window-increase-height 5) "increase height")
  ("j" (evil-window-decrease-height 5) "decrease height")
  ("h" (evil-window-increase-width 10) "increase width")
  ("l" (evil-window-decrease-width 10) "decrease width")
  ("e" balance-windows "balance windows")
  ("f" nil "finished" :exit t)
  )

(ads/leader-keys "C-w" '(hydra-window-adjust/body :wk "hydra window adjust"))

Smart Parens

Smartparens Github Evil Smartparens
(use-package evil-smartparens)

(use-package smartparens-config
  :ensure smartparens
  :config (progn (show-smartparens-global-mode t)))
(require 'smartparens-config)

(add-hook 'prog-mode-hook 'turn-on-smartparens-strict-mode)
(add-hook 'markdown-mode-hook 'turn-on-smartparens-strict-mode)
(add-hook 'smartparens-enabled-hook #'evil-smartparens-mode)
(show-paren-mode t)

Emojify 🎉 :

I think emojis are 🏆 Also Using emojis as labels is a great way to quickly identify things
(use-package emojify
  :hook (after-init . global-emojify-mode)
  :config
  (setq emojify-emoji-styles '(unicode))
  )
(add-hook 'after-init-hook #'global-emojify-mode)

(setq emojify-emoji-styles '(ascii unicode))
(ads/leader-keys
       ";" '(emojify-insert-emoji :wk "insert emoji")
     )

Org Mode

Org mode is wonderful, not sure how I would live without this for notekeeping and todos anymore. For me it’s become a hill I’d threaten to quit over.

Org Mode Setup

  (defun ads/org-mode-setup ()
      (interactive)
      ;; (org-indent-mode t)
      (variable-pitch-mode 1)
      (visual-line-mode 1)
      (setq org-image-actual-width (/ (car (window-text-pixel-size)) 1.5))
      ;; (org-redisplay-inline-images)
      ;; Replace list hyphen with dots
      (font-lock-add-keywords 'org-mode
			      '(("^ *\\([-]\\) "
				 (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) ""))))))
      )


(add-hook 'org-mode-hook 'ads/org-mode-setup)

(ads/leader-keys "of" '(ads/org-mode-setup :wk "org mode setup fn"))

Keybindings

(ads/leader-keys
    "o" '(:ignore t :wk "org")
    "oc" '(org-capture :wk "capture")
    "oj" '(org-store-link :wk "org-store-link")
    "oi" '(org-insert-last-stored-link :wk "org-insert-last-stored-link")
)
  

Unbind Cx Cn

useful for narrowing headers
(global-set-key (kbd "C-x C-n") 'nil)

Narrow Commands

org-toggle-narrow-to-subree does not work for some reason when I call it, using general, same code but this works
(defun ads/org-toggle-narrow ()
  (interactive)
  (if (buffer-narrowed-p)
      (widen)
    (org-narrow-to-subtree)))

(ads/leader-keys
    "n" '(:ignore t :wk "org Narrow")
    "C-n" '(ads/org-toggle-narrow :wk "Toggle Narrow")
    "ns" '(org-narrow-to-subtree :wk "Subtree")
    "ne" '(org-narrow-to-element :wk "Element")
    "nb" '(org-narrow-to-block :wk "Block")
    "nd" '(narrow-to-defun :wk "Defun")
    "nn" '(narrow-to-region :wk "Region")
    "nw" '(widen :wk "Widen")
)

General Org

Some general org config stuff, may be worth cleaning up at some point and splitting up all of this into different headings
  (use-package org
	:config
	(setq org-ellipsis ""
	      org-directory ads/user-dir-org
	      org-agenda-start-with-log-mode t
	      org-log-done 'time
	      org-log-into-drawer t
	      org-pretty-entities t
	      org-pretty-entities-include-sub-superscripts nil
	      org-hidden-keywords '(title)
	      org-hide-emphasis-markers t
	      org-src-preserve-indentation t
	      org-image-actual-width (/ (car (window-text-pixel-size)) 2)
	      org-startup-with-inline-images t
	      org-startup-indented t
	      org-startup-folded t
	      org-agenda-block-separator ""
	      org-fontify-whole-heading-line t
	      org-fontify-done-headline t
	      org-fontify-quote-and-verse-blocks t
	      org-bullets-bullet-list '(" ") ;; no bullets, needs org-bullets package
	      org-cycle-separator-lines 0
	      org-id-link-to-org-use-id t
	      org-blank-before-new-entry '((heading . nil)
					   (plain-list-item . nil))
	      )

	;:hook (org-mode . ads/org-mode-setup)
	(require 'org-habit)
	(require 'org-attach)
	(add-to-list 'org-modules 'org-habit 'org-checklist)
	(setq org-habit-graph-column 60)

	(setq org-todo-keywords
	  '((sequence "TODO(t)" "|" "DONE(d!)")
	    (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)"
		      "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANC(k@)")))

	;; Save Org buffers after refiling!
	(advice-add 'org-refile :after 'org-save-all-org-buffers)

	(setq org-tag-alist
	  '((:startgroup)
	     ; Put mutually exclusive tags here
	     (:endgroup)
	     ("@errand" . ?E)
	     ("@home" . ?H)
	     ("@work" . ?W)
	     ("agenda" . ?a)
	     ("planning" . ?p)
	     ("publish" . ?P)
	     ("batch" . ?b)
	     ("note" . ?n)
	     ("idea" . ?i)))

	(org-indent-mode t)
	(variable-pitch-mode 1)
	(visual-line-mode 1)

	(put 'narrow-to-region 'disabled nil)
	)


  

Add IDs headings

I haven’t decided if I want this to be adding them on every save
(defun ads/org-add-ids-to-headlines-in-file ()
  "Add ID properties to all headlines in the current file which
do not already have one."
  (interactive)
  (org-map-entries 'org-id-get-create))


(add-hook 'org-mode-hook
	  (lambda ()
	    (add-hook 'before-save-hook
	    'ads/org-add-ids-to-headlines-in-file nil 'local)))

Hide :PROPERTIES: Drawer

emacs - Completely hide the :PROPERTIES: drawer in org-mode - Stack Overflow

(defun org-cycle-hide-drawers (state)
  "Re-hide all drawers after a visibility state change."
  (when (and (derived-mode-p 'org-mode)
             (not (memq state '(overview folded contents))))
    (save-excursion
      (let* ((globalp (memq state '(contents all)))
             (beg (if globalp
                    (point-min)
                    (point)))
             (end (if globalp
                    (point-max)
                    (if (eq state 'children)
                      (save-excursion
                        (outline-next-heading)
                        (point))
                      (org-end-of-subtree t)))))
        (goto-char beg)
        (while (re-search-forward org-drawer-regexp end t)
          (save-excursion
            (beginning-of-line 1)
            (when (looking-at org-drawer-regexp)
              (let* ((start (1- (match-beginning 0)))
                     (limit
                       (save-excursion
                         (outline-next-heading)
                           (point)))
                     (msg (format
                            (concat
                              "org-cycle-hide-drawers:  "
                              "`:END:`"
                              " line missing at position %s")
                            (1+ start))))
                (if (re-search-forward "^[ \t]*:END:" limit t)
                  (outline-flag-region start (point-at-eol) t)
                  (user-error msg))))))))))

;;(org-cycle-hide-drawers 'overview)

Copy ID to clipboard for linking

(defun ads/copy-id-to-clipboard()
  "Copy the ID property value
to killring, if no ID is there then create a new unique ID.
This function works only in org-mode buffers.
The purpose of this function is to easily construct id:-links to
org-mode items. If its assigned to a key it saves you marking the
text and copying to the killring."
  (interactive)
  (when (eq major-mode 'org-mode) ; do this only in org-mode buffers
    (setq mytmpid (funcall 'org-id-get-create))
    (kill-new mytmpid)
    (message "Copied %s to killring (clipboard)" mytmpid)
    ))
(ads/leader-keys "C-l" '(ads/copy-id-to-clipboard :wk "ID to clipboard"))

Org Refile Targets

Refile targets dependant on computer id
(setq ads/conf-task-file (concat ads/personal-dir-org "conf-tasks.org"))
(setq ads/work-task-file (concat ads/user-dir-org "work.org"))
  (if (string= ads/computer-id "personal")
	  (setq org-refile-targets
		(list
		  '("personal.org" :maxlevel . 1)
		  '(ads/conf-task-file :maxlevel . 1))))


    (if (string= ads/computer-id "work")
	  (setq org-refile-targets
		(list
		  '(ads/work-task-file :maxlevel . 1)
		  '(ads/conf-task-file :maxlevel . 1))))

	      ;; Save Org buffers after refiling!
	  ;; Save Org buffers after refiling!
(advice-add 'org-refile :after 'org-save-all-org-buffers)

Org Archive

(setq org-archive-location "archive.org::datetree/")
(ads/leader-keys
    "C-a" '(org-archive-subtree :wk "org-archive-subtree"))

Org Appear mode

Make it less of a pain to edit emphasized text in org mode awth13/org-appear
(use-package org-appear)
(add-hook 'org-mode-hook 'org-appear-mode)
(setq  org-appear-autolinks t)
(setq org-appear-autoentities t)
(setq org-appear-autosubmarkers t)
(setq org-appear-autokeywords t)

(add-hook 'evil-insert-state-exit-hook
	  (lambda ()
	    (setq org-appear-delay 2)))

(add-hook 'evil-insert-state-entry-hook
	  (lambda ()
	    (setq org-appear-delay .3)))

Org Agenda

Files

Check computer ID before setting org agenda

(setq org-agenda-files (list
    (concat ads/personal-dir-org "dates.org")
    (concat ads/personal-dir-org "inbox.org")
    ;(concat ads/personal-dir-org "conf-tasks.org")
))

(if (string= ads/computer-id "work")
    (add-to-list 'org-agenda-files
	  (concat ads/user-dir-org "work.org")))

(if (string= ads/computer-id "personal")
    (progn
	  (add-to-list 'org-agenda-files
		(concat ads/personal-dir-org "habits.org"))
	  (add-to-list 'org-agenda-files
		(concat ads/personal-dir-org "personal.org"))))

Agenda Open

split window and focus down on agenda open
(defun ads/org-agenda-open ()
    (interactive)
    ;; (evil-window-split)
    ;; (evil-window-down 1)
    (org-agenda nil "a"))
(ads/leader-keys
      "oa"'(ads/org-agenda-open :wk "org-agenda"))

Agenda Quit

Close window on quitting agenda
(defun ads/org-agenda-quit ()
    (interactive)
    (org-agenda-quit)
    (delete-window))
(evil-define-key 'motion org-agenda-mode-map
    (kbd "q") 'ads/org-agenda-quit)

Agenda interaction

Don’ move windows and set org span to 1 day
(setq org-agenda-window-setup 'current-window)
(setq org-agenda-span 1)
(setq org-agenda-restore-windows-after-quit t)
(setq org-agenda-persistent-filter t)
  

Agenda Scheduled Leaders

Formatting for scheduled __ : if today otherwise ## :
(setq org-agenda-scheduled-leaders '("__ :" "%02d :"))

Org Prettify

(defun ads/org-prettify-symbols-alist ()
  ;; I'm not happy with how these look, I'll have to figure out somethings at a future date
  ;; (push '("[ ]" . "☐" ) prettify-symbols-alist)
  ;; (push '("[X]" . "☑" ) prettify-symbols-alist)
  ;; (push '("[-]" . "❍" ) prettify-symbols-alist)
  (push '("#+BEGIN_QUOTE" . "") prettify-symbols-alist)
  (push '("#+END_QUOTE" . "") prettify-symbols-alist)
  (push '("#+begin_quote" . "") prettify-symbols-alist)
  (push '("#+end_quote" . "") prettify-symbols-alist)
  (push '("#+BEGIN_SRC" . "«") prettify-symbols-alist)
  (push '("#+END_SRC" . "»") prettify-symbols-alist)
  (push '("#+begin_example" . "«") prettify-symbols-alist)
  (push '("#+end_example" . "»") prettify-symbols-alist)
  (push '("#+begin_src" . "«") prettify-symbols-alist)
  (push '("#+end_src" . "»") prettify-symbols-alist)
  (push '("#+options:" . "") prettify-symbols-alist)
  (push '("#+RESULTS:" . "🠶") prettify-symbols-alist)
  (push '(":PROPERTIES:" ."" ) prettify-symbols-alist)
  (push '("emacs-lisp" ."ε" ) prettify-symbols-alist)

  (prettify-symbols-mode))
(add-hook 'org-mode-hook 'ads/org-prettify-symbols-alist)

Org Diary File

(setq diary-file (concat ads/user-dir-org "diary.org"))
  

Org Capture

Inbox

(setq  org-capture-templates
   (list  '( "c" "Task" entry
	(file+headline (lambda () (concat ads/personal-dir-org "inbox.org"))"Inbox")
 "* TODO %^{Task}
 SCHEDULED: %t
 :PROPERTIES:
 :ID:     \t%(org-id-new)
 :CREATED:\t%U
 :REF:\t%a
 %i
 :END:
 %?\n
 "
	:kill-buffer t)))
  

Work

(if (string= ads/computer-id "work")
(add-to-list  'org-capture-templates
    '("w" "Work Task" entry
	 (file+headline (lambda () (concat ads/user-dir-org "work.org"))"Tasks")
 "* TODO %^{Work Task}
 SCHEDULED: %t
 :PROPERTIES:
 :ID:     \t%(org-id-new)
 :CREATED:\t%U
 :REF:\t%a
 %i
 :END:
 %?\n
 "
   :kill-buffer t)
))
  

Personal

(add-to-list  'org-capture-templates
    '("p" "Personal Task" entry
	 (file+headline (lambda () (concat ads/personal-dir-org "personal.org"))"Tasks")
 "* TODO %^{Personal Task}
 SCHEDULED: %t
 :PROPERTIES:
 :ID:     \t%(org-id-new)
 :CREATED:\t%U
 :REF:\t%a
 %i
 :END:
 %?\n
 "
   :kill-buffer t)
)
  

Quick Inbox

(add-to-list  'org-capture-templates
    '("i" "Quick Inbox" entry
	 (file+headline (lambda () (concat ads/personal-dir-org "inbox.org"))"Inbox")
 "* TODO %^{Task to inbox}
 SCHEDULED: %t\n
 :PROPERTIES:
 :ID:     \t%(org-id-new)
 :CREATED:\t%U
 :REF:\t%a
 %i
 :END:
 "
   :immediate-finish t
   :kill-buffer t)
)
  

Quick Capture

Quickly capture something to inbox with leader C-c
(ads/leader-keys
    "c" '(lambda () (interactive) (org-capture nil "i") :wk "Capture to Inbox"))
  

Clipboard Link

(add-to-list  'org-capture-templates
    '("k" "Clipboard Link to Inbox" entry
	 (file+headline (lambda () (concat ads/personal-dir-org "inbox.org"))"Inbox")
 "* TODO %(org-cliplink-capture)
 SCHEDULED: %t\n
 :PROPERTIES:
 :ID:     \t%(org-id-new)
 :CREATED:\t%U
 :REF:\t%a
 %i
 :END:
 "
   :immediate-finish t
   :kill-buffer t)
)
  

Project

(add-to-list  'org-capture-templates
    '("P" "Project" entry
	 (file+headline (lambda () (concat ads/personal-dir-org "personal.org"))"Projects")
 "* TODO %^{Project Name}
 :PROPERTIES:
 :ID:     \t%(org-id-new)
 :CREATED:\t%U
 :REF:\t%a
 :Effort: \t%^{effort|1:00|2:00|4:00|8:00|16:00}
 :Cost-est:\t%^{Cost estimate}
 %i
 :END:
 %?\n
   "
   :kill-buffer t)
)
  

Book

(add-to-list  'org-capture-templates
    '("B" "Book" entry
	 (file+headline (lambda () (concat ads/personal-dir-org "books.org"))"Endless Pile")
 "* PILE %^{Book Title}
 :PROPERTIES:
 :ID:     \t%(org-id-new)
 :CREATED:\t%U
 :AUTHOR:
 :RECCOMMENDER:
 :END:
 %?\n
   "
   :kill-buffer t)
)
  

Quote

(add-to-list  'org-capture-templates
    '("t" "Quote" entry
	 (file (lambda () (concat ads/personal-dir-org "quotes.org")))
 "* %^{Quote or Note}
 :PROPERTIES:
 :ID:     \t%(org-id-new)
 :CREATED:\t%U
 :SOURCE: %^{Source}
 :REF: \t%a
 :END:
 %?\n
   "
   :kill-buffer t))
  

Log to archive.org

Quickly log note to archive under datetree, good CYA if you need it, also nice for seeing progress during a workday
(add-to-list  'org-capture-templates
    '("l" "Log to Archive" entry
	 (file+datetree (lambda () (concat ads/user-dir-org "archive.org")) )
 "* %U
:PROPERTIES:
:ID:\t%(org-id-new)
:REF:\t%a
:FILE:\t%f
:TASK_CLOCK:\t%K
:END:
 \n%?\n
 "
   :kill-buffer t)
)

(defun ads/log-to-archive ()
    (interactive)
    (org-capture nil "l")
    (evil-insert-state)
    )

(ads/leader-keys
    "l" '(ads/log-to-archive :wk "Log to Archive"))

Log to archive.org with subject

Quickly log note to archive under datetree, header only timesetamp, intended to just be a quck status of what I’m working on
(add-to-list  'org-capture-templates
    '("L" "Log to Archive Subject" entry
	 (file+datetree (lambda () (concat ads/user-dir-org "archive.org")) )
 "* %^{Subject} %U
:PROPERTIES:
:ID:\t%(org-id-new)
:REF:\t%a
:FILE:\t%f
:TASK_CLOCK:\t%K
:END:
 \n%?\n
 "
   :kill-buffer t)
)

(defun ads/log-to-archive-subject ()
    (interactive)
    (org-capture nil "L")
    (evil-insert-state)
    )

(ads/leader-keys
    "L" '(ads/log-to-archive-subject :wk "Log to Archive"))

Org Bullets

 (use-package org-bullets
	  :after org
	  :hook (org-mode . org-bullets-mode)
	 )
  

Org Visual fill

(setq fill-column 90)

(defun ads/org-mode-visual-fill ()
  (setq visual-fill-column-width 90
	visual-fill-column-center-text t
	visual-fill-column-enable-sensible-window-split t
	;; header-line-format ""
	)
  (visual-fill-column-mode 1))

(use-package visual-fill-column
  :hook (org-mode . ads/org-mode-visual-fill))

  

Babel Languages

   (with-eval-after-load 'org
     (org-babel-do-load-languages
         'org-babel-load-languages
         '((emacs-lisp . t)
           (python . t))))

    (setq org-confirm-babel-evaluate nil)

(setq org-babel-default-header-args:python
	     '((:results . "output")
	       ))
  

Org Block Structure Templates

(with-eval-after-load 'org
 ;; This is needed as of Org 9.2
 (require 'org-tempo)

 (add-to-list 'org-structure-template-alist '("sh" . "src shell\n"))
 (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp\n"))
 (add-to-list 'org-structure-template-alist '("py" . "src python\n"))
 (add-to-list 'org-structure-template-alist '("ht" . "src html\n"))
 (add-to-list 'org-structure-template-alist '("html" . "src html\n"))
 (add-to-list 'org-structure-template-alist '("css" . "src css\n"))
 (add-to-list 'org-structure-template-alist '("cc" . "src C\n"))
 (add-to-list 'org-structure-template-alist '("cp" . "src C++\n"))
 (add-to-list 'org-structure-template-alist '("js" . "src js\n"))
 (add-to-list 'org-structure-template-alist '("jj" . "src java\n"))
 (add-to-list 'org-structure-template-alist '("sql" . "src sql\n"))
 (add-to-list 'org-structure-template-alist '("sq" . "src sql\n"))
 )
  

Evil Org

Maybe this will be better somewhere else but it works here for now Evil Org Github
(use-package evil-org
  :ensure t
  :after org
  :hook (org-mode . (lambda () evil-org-mode))
  :config
  (require 'evil-org-agenda)
  (evil-org-agenda-set-keys))

Org Cliplink

GitHub - rexim/org-cliplink: Insert org-mode links from clipboard
(use-package org-cliplink)
(ads/leader-keys
    "ok" '(org-cliplink :wk "org-cliplink")
)

  

Replace Link

(defun org-replace-link-by-link-description ()
    "Replace an org link by its description or if empty its address"
  (interactive)
  (if (org-in-regexp org-link-bracket-re 1)
      (save-excursion
        (let ((remove (list (match-beginning 0) (match-end 0)))
              (description
               (if (match-end 2)
                   (org-match-string-no-properties 2)
                 (org-match-string-no-properties 1))))
          (apply 'delete-region remove)
          (insert description)))))

Org Transclusion

This package seems like a godsend, I do need to spend some time looking into it. Org-transclusion User Manual

(use-package org-transclusion
  :after org
  ;; :init

  )

Insert Image from clipboard

Same thing as the insert screenshot but works faster and can use with Win-S from clipboard

(defun ads/org-clip-image ()
  "Take a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive)
  (setq temp-image-filename
	  (make-temp-file
	   (concat
	    (file-relative-name buffer-file-name)
	    "_"
	    (format-time-string "%Y%m%d_%H%M%S_"))
	   nil
	   ".png"))
    (shell-command (concat
		    "powershell -command \"Add-Type -AssemblyName System.Windows.Forms;"
		    "if ($([System.Windows.Forms.Clipboard]::ContainsImage())) {$image = [System.Windows.Forms.Clipboard]::GetImage();[System.Drawing.Bitmap]$image.Save('"
		    temp-image-filename
		    "',[System.Drawing.Imaging.ImageFormat]::Png); Write-Output 'clipboard content saved as file'} else {Write-Output 'clipboard does not contain image data'}\""))
    (org-attach-attach
     temp-image-filename
     nil
     `mv)
    (insert (concat
	     "[[file:"
	     (org-attach-dir)
	     "/"
	     (file-name-nondirectory temp-image-filename)
	     "]]"))
    (org-display-inline-images))


(ads/leader-keys
    "s" '(ads/org-clip-image :wk "org-insert-clipboard-image")
)

Org Find File

Counsel find file in my org directory
(defun ads/org-find-file ()
    "Find file in ads/user-dir-org"
    (interactive)
    (counsel-find-file ads/user-dir-org)
)
(ads/leader-keys "f" '(ads/org-find-file :wk "Org Find File"))

Org Normal on C-c C-c

Return to normal state after C-c C-c
(add-hook 'org-ctrl-c-ctrl-c-hook 'evil-normal-state)

Next item in checkilist on C-c C-c

(defun ads/org-checkbox-next ()
  (interactive)
    (when (org-at-item-checkbox-p)
      (org-toggle-checkbox)
      (re-search-forward "\\[ \\]")
      (evil-normal-state))
  )

;; (add-hook 'org-ctrl-c-ctrl-c-hook 'ads/org-checkbox-next)

Async Tangling Config

I don’t want to have to wait after saving a file to continue working
(use-package async
  :config
  (defun ads/init-hook ()
    "If the current buffer is 'readme.org' the code-blocks
are tangled."
    (when (string= buffer-file-truename ads/user-dir-readme)
      (async-start
       `(lambda ()
          (require 'org)
	  (let ((org-confirm-babel-evaluate nil)))
          (org-babel-tangle-file ,ads/user-dir-readme))
       (lambda (result)
         (message "Tangled file compiled.")))))
  (add-hook 'after-save-hook 'ads/init-hook))

;; (use-package dired-async
;;   :after async
;;   :config
;;   (dired-async-mode 1))

New org note

Quick fn to define a new org note
(defun ads/new-org-note ()
  (interactive)
  (setq input (read-string "Enter new Filename:\t"))
  ;; (setq input "test file NaMe")
  (setq input (replace-regexp-in-string "\s" "-" input))
  (setq input (downcase input))
  (setq input (concat ads/user-dir-org input ".org"))
  (find-file input)
  (evil-insert-state)
  )
(ads/leader-keys
  "on" '(ads/new-org-note :wk "new-org-note")
)

Open Scratch.org

leader C-s Open and go to scratch.org
(ads/leader-keys
    "C-s" '(lambda () (interactive) (
    find-file (concat ads/user-dir-org "scratch.org"))
    :wk "ORG Config")
)

Development

Languages

Auto Mode alist

(add-to-list 'auto-mode-alist '("\\.keymap\\'" . c-or-c++-mode))

Projectile

(use-package projectile
	:diminish projectile-mode
	:config (projectile-mode)
	:custom ((projectile-completion-system 'ivy))
	:bind-keymap
	("C-c p" . projectile-command-map)
	:init
	(when (file-directory-p "c:/Users/Adrian/Documents/GitHub/")
	;; Specify folder where you keep your coding projects
	    (setq projectile-project-search-path '("c:/Users/Adrian/Documents/GitHub/")))
	(setq projectile-switch-project-action #'projectile-dired))

    (use-package counsel-projectile
	:after projectile
	:config (counsel-projectile-mode))

Magit

Painful and super slow on windows, a large reason why I often use the <leader> git commands defined later

(use-package magit
  :commands magit-status
  ;; display the diff from git in the same window (may be worth trying different options as well
  :custom
  (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1))


;(use-package evil-magit
;   :after magit)
(global-set-key (kbd "C-c g") 'magit-file-dispatch)
(global-set-key (kbd "C-c C-g") 'magit-file-dispatch)
(global-set-key (kbd "C-x C-g") 'magit-status)

Magit Diff Paths

Might be worth submitting a PR for this, seems like it would be a helpful thing to have
(defun magit-diff-paths-buffer-file (a)
  "Show changes between buffer file and another file on disk"
  (interactive (list (read-file-name "File to compare" nil nil t)
		     ))
  (message a)
  (magit-diff-setup-buffer nil "--no-index"
                           nil (list (magit-convert-filename-for-git
                                      (expand-file-name a))
                                     (magit-convert-filename-for-git
                                      (expand-file-name buffer-file-name))))
    )

Shell Git Commands

Windows commands for git becaue magit is almost unusably slow due to windows issues

Git stage

(defun ads/git-stage ()
  (interactive)
  (save-buffer)
  (shell-command (concat "git stage " buffer-file-name) )
  (message
    (concat "Staging file : " buffer-file-name)))
(ads/leader-keys
    "gs"'(ads/git-stage :wk "git stage file"))

Git stage all

(defun ads/git-stage-all ()
  (interactive)
  (shell-command "git stage --all")
  (message
    (concat "Staging all changed files in: " (file-name-directory buffer-file-name))))
(ads/leader-keys
    "gS"'(ads/git-stage-all :wk "git stage all"))

Git commit

(defun ads/git-commit-file ()
  (interactive)
  (save-buffer)
  (shell-command (concat "git stage " buffer-file-name) )
  (magit-diff-staged)
  (shell-command (concat "git commit -m \"" (read-string "Commit Message:\t") "\""))
  (magit-mode-bury-buffer))

(ads/leader-keys
    "gk"'(ads/git-commit-file :wk "git commit"))

Git stage commit and push

Useful I’m only writng code for me and I’m lazy AF and testing somewhere else.. git lazy
(defun ads/git-stage-commit-push ()
  (interactive)
  (save-buffer)
  (shell-command (concat "git stage " buffer-file-name) )
  (magit-diff-staged)
  (delete-other-windows)
  (shell-command (concat "git commit -m \"" (read-string "Commit Message:\t") "\""))
  ;; (message
  ;;  (concat "Pushing Upstream: " (file-name-directory buffer-file-name)))
  (async-shell-command "git push")
  (magit-mode-bury-buffer))

(ads/leader-keys
    ; gl - Git Lazy
    "gl"'(ads/git-stage-commit-push :wk "git commit"))

Git commit all

(defun ads/git-commit-all ()
  (interactive)
  (magit-diff-staged)
  (shell-command (concat "git commit -am \"" (read-string "Commit Message:\t") "\""))
  (magit-mode-bury-buffer))

(ads/leader-keys
    "gK"'(ads/git-commit-all :wk "git commit all"))

Git Push

(defun ads/git-push ()
  (interactive)
  (message
   (concat "Pushing Upstream: " (file-name-directory buffer-file-name)))
  (async-start
   (message
    (shell-command-to-string
     (concat
      "cd "
      (file-name-directory buffer-file-name)
      " && git push ")))
   (message "done")))
(ads/leader-keys
    "gp"'(ads/git-push :wk "git push"))

Git Pull

(defun ads/git-pull ()
  (interactive)
  (message
   (concat "Pulling from Upstream: " (file-name-directory buffer-file-name)))
  (async-start
   (message
    (shell-command-to-string
     (concat
      "cd "
      (file-name-directory buffer-file-name)
      " && git pull ")))
   (message "done")))
(ads/leader-keys
    "gP"'(ads/git-pull :wk "git pull"))

Git Fetch

(defun ads/git-fetch ()
  (interactive)
  (shell-command "git fetch --all")
  (message
    (concat "Fetching Upstream" (file-name-directory buffer-file-name))))
(ads/leader-keys
    "gf"'(ads/git-fetch :wk "git fetch"))

Git Restore file

I did an oopsies restore file to last commit
(defun ads/git-restore-file ()
  (interactive)
  (shell-command (concat "git restore " buffer-file-name) )
  (message
    (concat "Restoring file: " buffer-file-name))
  (revert-buffer))
(ads/leader-keys
    "gr"'(ads/git-restore-file :wk "git restore file"))

Prettify Code

Inspiration taken from GitHub - mcraveiro/cunene: My dot emacs, most of this will probably go away once I update to EMACS 28 and can use ligatures

(defun ads/prog-mode-configure-prettify-symbols-alist ()
  "Set prettify symbols alist."
  (setq prettify-symbols-alist '(("lambda" . "λ")
                                 ("->" . "")
                                 ("->>" . "")
                                 ("=>" . "")
                                 ("map" . "")
                                 ("/=" . "")
                                 ("!=" . "")
                                 ("==" . "")
                                 ("<=" . "")
                                 (">=" . "")
                                 ("=<<" . "=≪")
                                 (">>=" . "≫=")
                                 ("<=<" . "")
                                 (">=>" . "")
                                 ("&&" . "")
                                 ("||" . "")
                                 ("not" . "¬")))
  (prettify-symbols-mode))

(add-hook 'prog-mode-hook 'ads/prog-mode-configure-prettify-symbols-alist)

Protobuf

(use-package protobuf-mode)

Anki

(use-package anki-connect)
(use-package anki-editor
  :after org
  ;; :bind (:map org-mode-map
  ;;             ("<f12>" . anki-editor-cloze-region-auto-incr)
  ;;             ("<f11>" . anki-editor-cloze-region-dont-incr)
  ;;             ("<f10>" . anki-editor-reset-cloze-number)
  ;;             ("<f9>"  . anki-editor-push-tree))
  :hook (org-capture-after-finalize . anki-editor-reset-cloze-number) ; Reset cloze-number after each capture.
  :config
  (setq anki-editor-create-decks t ;; Allow anki-editor to create a new deck if it doesn't exist
        anki-editor-org-tags-as-anki-tags t)

  (defun anki-editor-cloze-region-auto-incr (&optional arg)
    "Cloze region without hint and increase card number."
    (interactive)
    (anki-editor-cloze-region my-anki-editor-cloze-number "")
    (setq my-anki-editor-cloze-number (1+ my-anki-editor-cloze-number))
    (forward-sexp))
  (defun anki-editor-cloze-region-dont-incr (&optional arg)
    "Cloze region without hint using the previous card number."
    (interactive)
    (anki-editor-cloze-region (1- my-anki-editor-cloze-number) "")
    (forward-sexp))
  (defun anki-editor-reset-cloze-number (&optional arg)
    "Reset cloze number to ARG or 1"
    (interactive)
    (setq my-anki-editor-cloze-number (or arg 1)))
  (defun anki-editor-push-tree ()
    "Push all notes under a tree."
    (interactive)
    (anki-editor-push-notes '(4))
    (anki-editor-reset-cloze-number))
  ;; Initialize
  (anki-editor-reset-cloze-number)
  )

Hugo

ox-hugo

(use-package ox-hugo :ensure t ;Auto-install the package from Melpa :pin melpa ;`package-archives’ should already have (“melpa” . “https://melpa.org/packages/”) :after ox (setq org-hugo-base-dir “~/git/hugo-site/content/” ) )

File Management

Dired

(use-package dired
      :ensure nil
      :commands (dired dired-jump)
      :bind (("C-x C-j" . dired-jump))
      :custom ((dired-listing-switches "-agho --group-directories-first"))
      :hook (dired-mode . dired-hide-details-mode)
      :config
      (evil-collection-define-key 'normal 'dired-mode-map
	"h" 'dired-single-up-directory
	"l" 'dired-single-buffer)
      (evil-global-set-key 'normal (kbd "C-x C-d") 'dired)

       (setq delete-by-moving-to-trash t)
       (setq-default dired-hide-details-mode t)
       (setq dired-kill-when-opening-new-dired-buffer t))

(use-package dired-single
      :commands (dired dired-jump))

(use-package dired-git-info
      :ensure t
      ;:hook (dired-mode . (local-set-key ")" 'dired-git-info-mode))
      :bind (:map dired-mode-map (")" . dired-git-info-mode)))

(use-package diredfl
    :ensure t
    :config
    (diredfl-global-mode 1))
  ;(use-package dired-open
  ;    :commands (dired dired-jump)
  ;    :config
  ;    ;; Doesn't work as expected!
  ;    ;;(add-to-list 'dired-open-functions #'dired-open-xdg t)
  ;    (setq dired-open-extensions '(("pdf" . "feh")
				   ;; ("mkv" . "mpv"))))

Counsel Find File External Extensions

When using counsel-find-file tries to open a document if the extension is in this list open using the external program
(setq counsel-find-file-extern-extensions
        '("xlsx"
          "xls"
          "mkv"
          "mp4"
          "pdf"
          "doc"
          "docx"
          "ppt"
          "pptx"
          "wmv"
          "mp3"))

UTF-8

From http://www.wisdomandwonder.com/wordpress/wp-content/uploads/2014/03/C3F.html
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(when (display-graphic-p)
  (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))

Treemacs

(use-package treemacs
  :ensure t
  :defer t
  ;; :init

  :config
  (progn
    (setq
          treemacs-file-event-delay              1000
          treemacs-file-follow-delay             0.1
          treemacs-follow-after-init             nil
          treemacs-expand-after-init             nil
          treemacs-indentation                   1
          treemacs-missing-project-action        'remove
          treemacs-persist-file                  (if (string= ads/computer-id "work")
						         "c:/users/adanaos/git/emacs-work/treemacs-persist"
						          (expand-file-name ".cache/treemacs-persist" user-emacs-directory))
          treemacs-width                         30)

    (treemacs-resize-icons 15) ; Smaller icons

    (treemacs-filewatch-mode             t       )
    (treemacs-fringe-indicator-mode      t       )
    (treemacs-fringe-indicator-mode      'always )

    (pcase (cons (not (null (executable-find "git")))
                 (not (null treemacs-python-executable)))
      (`(t . t)
       (treemacs-git-mode 'deferred))
      (`(t . _)
       (treemacs-git-mode 'simple))))
  (define-key treemacs-mode-map (kbd "C-c C-p C-a") 'treemacs-add-project-to-workspace)
  (define-key treemacs-mode-map (kbd "C-c C-p C-d") 'treemacs-remove-project-from-workspace)
  (define-key treemacs-mode-map (kbd "C-SPC C-t") 'treemacs-quit)

  )

Treemacs Evil

(use-package treemacs-evil
  :after treemacs evil
  :ensure t)

Treemacs Projectile

(use-package treemacs-projectile
  :after treemacs projectile
  :ensure t)

Treemacs Dired

(use-package treemacs-icons-dired
  :after treemacs dired
  :ensure t
  :config (treemacs-icons-dired-mode))

Treemacs magit

(use-package treemacs-magit
  :after treemacs magit
  :ensure t)

Treemacs Persp

(use-package treemacs-persp
  :after treemacs persp-mode
  :ensure t

  :config (treemacs-set-scope-type 'Perspectives))

LSP Treemacs

Currently unused

Treemacs Keybindings

(ads/leader-keys
    "C-t" '(treemacs :wk "treemacs"))

Treemacs Laptop Mode

(defun treemacs-laptop-mode-toggle ()
  (interactive)
  (if treemacs-laptop-mode-status
      (treemacs-laptop-mode-off)
      (treemacs-laptop-mode-on)
      )
  ;; (setq treemacs-laptop-mode-status (not ads/treemacs-laptop-mode-status))
  )

(defun treemacs-laptop-mode-on  ()
  (interactive)
  (setq treemacs-laptop-mode-status t)
  (setq treemacs-width                  25
	treemacs-indentation             1
	treemacs-default-visit-action    'treemacs-visit-node-close-treemacs	     )
  (message "treemacs-laptop-mode-on")
  )

(defun treemacs-laptop-mode-off ()
  (interactive)
  (setq treemacs-laptop-mode-status nil)
  (setq treemacs-width                  35
	treemacs-indentation             2
	treemacs-default-visit-action    'treemacs-visit-node-no-split
	)
  (message "treemacs-laptop-mode-off")
  )

;; (if (> (frame-width) 200)
;;     (treemacs-laptop-mode-off)
;;     (treemacs-laptop-mode-on)
;;     )

;; (print ads/treemacs-laptop-mode-status)
(display-monitor-attributes-list)
(if (> (frame-width) 200)
    (setq treemacs-laptop-mode-status nil)
    (setq treemacs-laptop-mode-status t)
    )
(print treemacs-laptop-mode-status)

Personal Linux

Load my deimos config stuff
(when
  (string= system-name "deimos")
  (org-babel-load-file (concat ads/user-dir-emacs "linux.org"))
  (org-babel-load-file (concat ads/user-dir-org "python-development-setup.org")
))

Work

(load-file (concat ads/user-dir-org "work.el"))

Disable Debug on Error

If config loaded without issue I don’t need it enabled in normal usage I’ve moved this to the end of my .emacs after all config files have been loaded
;; (setq debug-on-error nil)