#+TITLE: Emacs Configuration #+AUTHOR: Mitchell Tishmack #+STARTUP: hidestars #+STARTUP: odd #+BABEL: :cache yes #+PROPERTY: header-args :cache yes #+PROPERTY: header-args :padline no #+PROPERTY: header-args :mkdirp yes #+PROPERTY: header-args :comments no #+PROPERTY: header-args :results replace #+PROPERTY: header-args :tangle tmp/.emacs.d/init.el * prelude Startup related tasks/setup that might be used later on. *** emacs package setup Setup the builtin emacs package manager. #+BEGIN_SRC emacs-lisp :tangle tmp/.emacs.d/init.el :mkdirp yes (require 'package) (package-initialize) #+END_SRC This is out of place but to catch the gui elements early. #+BEGIN_SRC emacs-lisp (tool-bar-mode -1) (scroll-bar-mode -1) (when (not (window-system)) (menu-bar-mode -1)) #+END_SRC Add in standard package archive urls. Marmalade is gone as its ssl cert expired in 2018, so don't think its even worth using. #+BEGIN_SRC emacs-lisp (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t) (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t) (add-to-list 'package-archives '("stable-melpa" . "https://stable.melpa.org/packages/") t) (add-to-list 'package-archives '("gnu" . "https://elpa.gnu.org/packages/") t) #+END_SRC *** tangle functions Duplicated from tangle.el just to make using org easier. TODO: make this stuff work sanely in emacs org mode and via external tangling. Not tangled for now. #+BEGIN_SRC emacs-lisp (defun tangle/yn (p) (if (bound-and-true-p p) "yes" "no")) (defun tangle/file (file p) (if (bound-and-true-p p) (concat "tmp/" file) "no")) #+END_SRC *** emacs gc speedup #+BEGIN_SRC emacs-lisp (defun my-minibuffer-setup-hook () (setq gc-cons-threshold most-positive-fixnum)) (defun my-minibuffer-exit-hook () (setq gc-cons-threshold 8000000)) (add-hook 'minibuffer-setup-hook #'my-minibuffer-setup-hook) (add-hook 'minibuffer-exit-hook #'my-minibuffer-exit-hook) #+END_SRC *** use-package bootstrap This configuration is using *use-package* extensively. Install it early so we can use it elsewhere. First strip out any existing org load-path prior to package initialization. #+BEGIN_SRC emacs-lisp (require 'cl) (setq load-path (remove-if (lambda (x) (string-match-p "org$" x)) load-path)) (setq load-path (remove-if (lambda (x) (string-match-p "org-" x)) load-path)) #+END_SRC #+BEGIN_SRC emacs-lisp (unless (package-installed-p 'use-package) (progn (package-refresh-contents) (package-install 'use-package) (package-initialize))) (require 'use-package) (setq use-package-verbose t) #+END_SRC Then, before doing *ANY* package initialization, make use-package setup/use org from the package repos and pin it so that other packages can't muck that up. #+BEGIN_SRC emacs-lisp (use-package org :ensure org-plus-contrib :pin org) #+END_SRC *** auto-package-update Make updating use-package installed package.el packages easy peasy. #+BEGIN_SRC emacs-lisp (use-package auto-package-update :ensure t :defer t) #+END_SRC *** match end of string function #+BEGIN_SRC emacs-lisp (defun string/ends-with (string suffix) "Return t if STRING ends with SUFFIX." (and (string-match (rx-to-string `(: ,suffix eos) t) string) t) ) #+END_SRC *** debug on error Not having to start *emacs* with *--debug-init* is useful. #+BEGIN_SRC emacs-lisp (setq-default debug-on-error t) #+END_SRC *** emacs server Start up the emacs server if it isn't running. #+BEGIN_SRC emacs-lisp (load "server") (unless (server-running-p) (server-start)) #+END_SRC *** theme Sick of solarized, going back to good old black on white minimalism like paper. TODO: Maybe get this to go dark automagically? #+BEGIN_SRC emacs-lisp (use-package minimal-theme :ensure t :config (load-theme 'minimal-light t)) #+END_SRC *** os detection Make it easier to determine what os we're running on. #+BEGIN_SRC emacs-lisp (defvar on-mswindows (string-match "windows" (symbol-name system-type)) "Am I running under windows?") (defvar on-osx (string-match "darwin" (symbol-name system-type)) "Am I running under osx?") (defvar on-linux (string-match "gnu/linux" (symbol-name system-type)) "Am I running under linux?") #+END_SRC *** disable pointless startup stuff Like the startup screen and the echo hooey. #+BEGIN_SRC emacs-lisp (custom-set-variables '(inhibit-startup-screen t) '(inhibit-startup-message t) '(inhibit-startup-echo-area-message t) '(initial-scratch-message nil) ) #+END_SRC *** temporary files Keep temporary stuff isolated from everyone else. It infects everything otherwise. As bad as the .DS_Store files on osx. #+BEGIN_SRC emacs-lisp (custom-set-variables '(temporary-file-directory "/tmp") '(backup-directory-alist `((".*" . ,temporary-file-directory))) '(auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) '(create-lockfiles nil) '(make-backup-files nil) '(auto-save-default nil) '(backup-by-copying t) '(auto-save-list-file-prefix temporary-file-directory) '(backup-directory-alist `((".*" . ,temporary-file-directory))) '(auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) ) #+END_SRC *** auto revert Update files in open buffers as they're changed on disk, freaking annoying without this on. #+BEGIN_SRC emacs-lisp (custom-set-variables '(global-auto-revert-mode t)) #+END_SRC *** dired Use dired-x. #+BEGIN_SRC emacs-lisp (add-hook 'dired-load-hook (function (lambda () (load "dired-x")))) #+END_SRC *** ediff For those rare times I use it, make it a bit less derp on output. #+BEGIN_SRC emacs-lisp (setq ediff-window-setup-function 'ediff-setup-windows-plain) (setq ediff-split-window-function 'split-window-horizontally) #+END_SRC *** always remove trailing whitespace Trailing whitespace is not normally useful. Remove it always on save in the *before-save-hook*. #+BEGIN_SRC emacs-lisp (add-hook 'before-save-hook 'delete-trailing-whitespace) #+END_SRC *** chmod u+x on save for scripts Because its derp to have to chmod 755 stuff after I save. Honestly, do it for me kthxbai. #+BEGIN_SRC emacs-lisp (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p) #+END_SRC *** misc text related #+BEGIN_SRC emacs-lisp (put 'upcase-region 'disabled nil) #+END_SRC *** line wrap Line wrapping is useful. Enable it globally for a start. Need word-wrap so kill line kills the line, not the displayed line. #+BEGIN_SRC emacs-lisp (global-visual-line-mode t) (custom-set-variables '(word-wrap t)) #+END_SRC *** default major mode So if we don't know, call it text-mode. #+BEGIN_SRC emacs-lisp (custom-set-variables '(default-major-mode 'text-mode)) #+END_SRC *** encoding utf8 is the best. Default to it. #+BEGIN_SRC emacs-lisp (use-package unicode-escape :init (set-language-environment "UTF-8") :ensure t) #+END_SRC #+BEGIN_SRC emacs-lisp (custom-set-variables '(locale-coding-system 'utf-8)) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-selection-coding-system 'utf-8) (prefer-coding-system 'utf-8) #+END_SRC *** text selection If I selected text, delete the selection, I probably meant it emacs. #+BEGIN_SRC emacs-lisp (delete-selection-mode 1) #+END_SRC *** line width 80 char line columns not 72. #+BEGIN_SRC emacs-lisp (custom-set-variables '(fill-column 80)) #+END_SRC *** we aren't banging rocks together anymore emacs Double spacing after a line isn't needed. We aren't animals emacs, we have computers. #+BEGIN_SRC emacs-lisp (set-default 'sentence-end-double-space nil) #+END_SRC *** long line speedups Improve the performance of emacs with files that contain long lines. Disable left to right and right to left in the same buffer support. Until or if I learn a language that needs this I can deal with it then. #+BEGIN_SRC emacs-lisp (setq-default bidi-paragraph-direction 'left-to-right) #+END_SRC Also disable this algorithm, which may unbalance ()'s in bidirectional language detection. But again as I don't use/speak/read them. Ok tradeoff. #+BEGIN_SRC emacs-lisp (if (version<= "27.1" emacs-version) ((setq bidi-inhibit-bpa t) (global-so-long-mode 1))) #+END_SRC Ref: https://200ok.ch/posts/2020-09-29_comprehensive_guide_on_handling_long_lines_in_emacs.html *** sentence end Semi related to the above, make the sentence endings a bit more code-ish. #+BEGIN_SRC emacs-lisp (custom-set-variables '(sentence-end "[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*") '(sentence-end-double-space nil) ) #+END_SRC *** default tab-width Two seems sensible, cause well, tabs are evil incarnate. Lets use a tab width of 2 by default. #+BEGIN_SRC emacs-lisp (custom-set-variables '(default-tab-width 2)) #+END_SRC *** whitespace Customize whitespace mode to make tabs obvious as boxes, and to highlight lines over 80 characters in length. #+BEGIN_SRC emacs-lisp (require 'whitespace) (setq whitespace-style '(face tabs trailing)) (set-face-attribute 'whitespace-tab nil :foreground "#2075c7" :background "lightgrey") (set-face-attribute 'whitespace-line nil :foreground "#2075c7" :background "lightgrey") (add-hook 'prog-mode 'whitespace-mode) (add-hook 'prog-mode 'hl-line-mode) (add-hook 'prog-mode 'visual-line-mode) #+END_SRC *** uncategorized I have no idea how to label these. Highlight parens. #+BEGIN_SRC emacs-lisp (show-paren-mode) #+END_SRC Typing out *yes* or *no* is stupid. #+BEGIN_SRC emacs-lisp (fset 'yes-or-no-p 'y-or-n-p) #+END_SRC Disable the stupid prompt added in 23.2 that asks if you want to kill a buffer with a process attached. Yes, obviously, shut up and do it. #+BEGIN_SRC emacs-lisp (setq kill-buffer-query-functions (remq 'process-kill-buffer-query-function kill-buffer-query-functions)) #+END_SRC TESTING tooltip mode Puts all tooltips in the echo arear. #+BEGIN_SRC emacs-lisp (tooltip-mode -1) (custom-set-variables '(tooltip-use-echo-area t)) #+END_SRC TESTING redisplay Have emacs not redraw the display before processing input events. #+BEGIN_SRC emacs-lisp (custom-set-variables '(redisplay-dont-pause t)) #+END_SRC *** osx specific **** no yes-or-no gui windows On osx, don't ever display the gui dialog box. Taken from http://superuser.com/questions/125569/how-to-fix-emacs-popup-dialogs-on-mac-os-x #+BEGIN_SRC emacs-lisp (when (and on-osx (window-system)) (defadvice yes-or-no-p (around prevent-dialog activate) "Prevent yes-or-no-p from activating a dialog" (let ((use-dialog-box nil)) ad-do-it)) (defadvice y-or-n-p (around prevent-dialog-yorn activate) "Prevent y-or-n-p from activating a dialog" (let ((use-dialog-box nil)) ad-do-it)) ) #+END_SRC **** make osx gui emacs keyboard setup match console Command should be meta on cocoa emacs like the old carbon/macports version. #+BEGIN_SRC emacs-lisp (when (and on-osx (window-system)) (custom-set-variables '(mac-command-key-is-meta t) '(mac-option-key-is-meta nil) '(mac-command-key-is-meta t) '(mac-command-modifier 'meta) '(mac-option-modifier 'none) ) ) #+END_SRC *** global key bindings Global key bindings. #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-x ,") 'kill-whole-line) (global-set-key (kbd "C-x C-m") 'compile) #+END_SRC *** x copy/paste #+BEGIN_SRC emacs-lisp (when (and on-linux (window-system)) (progn (setq interprogram-paste-function 'x-cut-buffer-or-selection-value) (setq x-select-enable-clipboard t) ) ) #+END_SRC * appearance *** TODO fonts setup doesn't work :broken: Trying something new here. #+BEGIN_SRC emacs-lisp (setq default-frame-alist (append (list '(right-fringe . 0) '(font . "Comic Code 14") '(min-height . 1) '(height . 42) '(foreground-color . "#333333") '(background-color . "#ffffff") '(cursor-color . "black") '(internal-border-width . 1) '(tool-bar-lines . 0) '(menu-bar-lines . 0)))) #+END_SRC List of fonts in order of preference. Set preferred font list when we're in a gui emacs session. TODO is this doesn't loop through the gui fonts right and set based on the alist order of the first matching font in macos. #+BEGIN_SRC emacs-lisp :tangle no (defvar my/gui-fonts '( "ComicCode" "Comic Code" "PragmataPro" "Pragmata Pro" ;; Seems to register differently on osx than X "Source Code Pro" "Menlo" "Monaco" ) ) (with-no-warnings (when window-system (if (find-font (font-spec :name (car my/gui-fonts))) (progn (set-frame-font (car my/gui-fonts)) (set-face-attribute 'default nil :height 180)) (progn (set-gui-font (cdr my/gui-fonts)))) ) ) #+END_SRC *** tty Enable mouse mode for the console and use the mousewheel if possible. #+BEGIN_SRC emacs-lisp (unless window-system (require 'mouse) (xterm-mouse-mode t) (global-set-key [mouse-4] '(lambda () (interactive) (scroll-down 1))) (global-set-key [mouse-5] '(lambda () (interactive) (scroll-up 1))) (defun track-mouse (e)) ) #+END_SRC * packages All the packages I use. *** editorconfig If editorconfig is around use it. #+BEGIN_SRC emacs-lisp (use-package editorconfig :ensure t :config (editorconfig-mode 1)) #+END_SRC *** tramp #+BEGIN_SRC emacs-lisp (use-package tramp :defer 5 :custom (tramp-default-method "ssh") :config (add-to-list 'tramp-default-proxies-alist '(".*" "\`root\'" "/ssh:%h:")) ) #+END_SRC *** exec-path-from-shell Turns out that someone wrote this exact thing already. Yay get to drop my own crap. #+BEGIN_SRC emacs-lisp (use-package exec-path-from-shell :ensure t :if (memq window-system '(mac ns)) :config (exec-path-from-shell-initialize) ) #+END_SRC *** osx-clipboard-mode #+BEGIN_SRC emacs-lisp (use-package osx-clipboard :if (memq window-system '(mac ns)) :ensure t :config (osx-clipboard-mode +1)) #+END_SRC *** mode-line setup Using some hacked together minimal mode line stuff now, spaceline too too much oomph with all the crap it did. #+BEGIN_SRC emacs-lisp (defun my-flycheck-lighter (state) "formats the mode-line fycheck error/warning/note junk" (let* ((counts (flycheck-count-errors flycheck-current-errors)) (errorp (flycheck-has-current-errors-p state)) (err (or (cdr (assq state counts)) "?")) (running (eq 'running flycheck-last-status-change))) (if (or errorp running) (format "•%s" err)))) #+END_SRC TODO: Use or ditch? #+BEGIN_SRC emacs-lisp :tangle no (use-package org-protocol-capture-html :after quelpa-use-package :quelpa (org-protocol-capture-html :repo "alphapapa/org-protocol-capture-html" :fetcher github)) #+END_SRC #+BEGIN_SRC emacs-lisp (use-package quelpa-use-package :ensure t) (use-package s :ensure t) (use-package mini-modeline :ensure t :after quelpa-use-package :quelpa (mini-modeline :repo "kiennq/emacs-mini-modeline" :fetcher github) :config (mini-modeline-mode) :custom (mini-modeline-truncate-p nil) (mini-modeline-echo-duration 5) (mini-modeline-face-attr '(:background "white" :weight normal :box (:line-width 2 :color "#ffffff"))) (mini-modeline-display-gui-line nil) (mini-modeline-r-format '((:eval (when (and (bound-and-true-p flycheck-mode) (or flycheck-current-errors (eq 'running flycheck-last-status-change))) (concat " " (cl-loop for state in '((error . "#FB4933") (warning . "#FABD2F") (info . "#83A598")) as lighter = (my-flycheck-lighter (car state)) when lighter concat (propertize lighter 'face `(:foreground ,(cdr state)))) ))) "%e %b %c" (:eval (if (use-region-p) (if (eq (point) (region-beginning)) (format "%%l … %d" (line-number-at-pos (region-end))) (format "%d … %%l" (line-number-at-pos (region-beginning)))) ":%l"))))) #+END_SRC *** yasnippet #+BEGIN_SRC emacs-lisp (use-package yasnippet :ensure t :init (setq yas-snippet-dirs '("~/.emacs.d/snippets" "~/.emacs.d/snippets-upstream" )) :config (yas/reload-all) :hook ((prog-mode . yas-minor-mode) (org-mode . yas-minor-mode)) ) #+END_SRC *** semantic Note that not all these functions are defined at package install time #+BEGIN_SRC emacs-lisp (use-package semantic :ensure t :config (add-to-list 'semantic-default-submodes 'global-semantic-stickyfunc-mode) (custom-set-variables '(global-semantic-decoration-mode t) '(global-semantic-highlight-func-mode t) '(global-semantic-idle-scheduler-mode t) '(global-semantic-idle-local-symbol-highlight-mode t) ) :init (semantic-mode t)) #+END_SRC *** expand-region #+BEGIN_SRC emacs-lisp (use-package expand-region :ensure t :bind ("C-]" . er/expand-region)) #+END_SRC *** ivy/swiper/projectile Switching to ivy mode+swiper #+BEGIN_SRC emacs-lisp (use-package projectile :ensure t :init (projectile-global-mode)) (use-package counsel :ensure t :bind (("C-x C-f" . counsel-find-file) ("C-c g" . counsel-git) ("C-c j" . counsel-git-grep) ("C-c k" . counsel-ag) ("C-x l" . counsel-locate) ("C-S-o" . counsel-rhythmbox) ("C-c C-r" . ivy-resume)) :custom (counsel-find-file-at-point t)) (use-package swiper :ensure t :bind (("C-s" . swiper) ("M-x" . counsel-M-x)) :config (ivy-mode 1) :custom (projectile-completion-system 'ivy) (magit-completing-read-function 'ivy-completing-read) (ivy-use-virtual-buffers t) (ivy-height 10) (ivy-count-format "(%d/%d) ")) #+END_SRC *** magit Make git not ass to use. At least in emacs. magit is the best git interface... in the world. #+BEGIN_SRC emacs-lisp (use-package magit :ensure t :commands (magit-init magit-status magit-diff magit-commit) :bind ("C-x m" . magit-status) :custom (magit-auto-revert-mode nil) (magit-last-seen-setup-instructions "1.4.0") :config (defadvice magit-status (around magit-fullscreen activate) (window-configuration-to-register :magit-fullscreen) ad-do-it (delete-other-windows)) (defadvice magit-quit-window (around magit-restore-screen activate) ad-do-it (jump-to-register :magit-fullscreen))) #+END_SRC And add TODO detection to the magit buffer. That way they get bubbled up to the top to look at. #+BEGIN_SRC emacs-lisp (use-package magit-todos :ensure t :after magit :hook (magit-mode . magit-todos-mode)) #+END_SRC *** TODO workgroups2 :broken: Save workgroup layouts. Similar..ish to desktop-save. #+BEGIN_SRC emacs-lisp :tangle no (use-package workgroups2 :ensure t :custom (wg-session-file "~/.emacs.d/workgroups") (wg-prefix-key (kbd "C-c C-w")) (wg-mode-line-display-on nil) :init (workgroups-mode 1) ) #+END_SRC *** autopair Highlight matching ()'s []'s etc... #+BEGIN_SRC emacs-lisp (use-package autopair :ensure t :custom (autopair-blink 'nil) ) #+END_SRC *** TODO org-mode :validation:testing: Org-mode keybindings and settings, pretty sparse really. Todo is to figure out what needs to happen for the capture templates and validate the agenda changes. #+BEGIN_SRC emacs-lisp ;; (defun org-roam-monolith-capture-date-file(path &optional extension) ;; (mkdir-base-path path) ;; (format "%s/%s%s" base (format-time-string "%Y-%m-%d:%H:%M:%S") ;; )) ;; (defun org-roam-monolith-base-path(path) ;; (expand-file-name (concat path (format-time-string "/%Y/%B")))) ;; (defun org-roam-monolith-mkdir-base-path(path) ;; (mkdir (base-path path) t)) ;; (defun org-roam-monolith-file-extension(extension) ;; (if (eq extension nil) "" ;; (if (string-match-p "\\." extension) ;; extension ;; (concat "." extension)))) ;; (defun org-roam-monolith-ref-url(url path) ;; (setq base (org-roam-monolith-base-path path)) ;; ;; (setq file-string (format-time-string "%Y-%m-%d:%H:%M:%S")) ;; (setq file-string "test") ;; (org-roam-monolith-mkdir-base-path(base)) ;; (setq file-prefix (format "%s/%s" base, file-string)) ;; (setq title (org-web-tools--html-title url)) ;; (setq ) ;; (append-to-file ;; (format "#+TITLE: %s\n#+ROAM_KEY: %s\n\n Monolith archive [[%s][%s]]\n" title url ;; title url (mt/insert-url-as-org url)) ;; nil ;; reffile) ;; (find-file-other-window reffile) ;; ) ;; (defun mt/roam-ref-url() ;; (interactive) ;; (progn ;; (setq url (read-string "url: ")) ;; (setq reffile (capture-date-file "~/src/org/ref/url")) ;; (append-to-file ;; (format "#+TITLE: %s\n#+ROAM_KEY: %s\n\n\n* Content\n%s" ;; (org-web-tools--html-title url) url (mt/insert-url-as-org url)) ;; nil ;; reffile) ;; (find-file-other-window reffile))) ;; (defun mt/insert-url-as-org(url) ;; (org-web-tools--html-to-org-with-pandoc ;; (org-web-tools--get-url url))) (defun capture-file-extension(extension) (if (eq extension nil) "" (if (string-match-p "\\." extension) extension (concat "." extension)))) (defun capture-date-file(path &optional extension) (setq prefix (expand-file-name (concat path (format-time-string "/%Y/%B")))) (mkdir prefix t) (setq file-name (format-time-string "%Y-%m-%d:%H:%M:%S")) (format "%s/%s%s" prefix file-name (capture-file-extension extension))) (use-package org :ensure org-plus-contrib :pin org :bind (("C-c a" . org-agenda) ("C-c b" . org-iswitchb) ("C-c c" . org-capture) ("C-c l" . org-store-link) ("C-c p" . org-latex-export-to-pdf)) :config (add-to-list 'org-structure-template-alist '("el" . "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC")) (add-to-list 'org-structure-template-alist '("hs" . "#+BEGIN_SRC haskell\n?\n#+END_SRC")) (add-to-list 'org-structure-template-alist '("pl" . "#+BEGIN_SRC perl\n?\n#+END_SRC")) (add-to-list 'org-structure-template-alist '("py" . "#+BEGIN_SRC python\n?\n#+END_SRC")) (add-to-list 'org-structure-template-alist '("sh" . "#+BEGIN_SRC sh\n?\n#+END_SRC")) (org-babel-do-load-languages 'org-babel-load-languages (append org-babel-load-languages '( (C . t) (ditaa . t) (emacs-lisp . t) (haskell . t) (latex . t) (perl . t) (python . t) (ruby . t) (shell . t) ))) :custom (org-directory "~/src/org") ;; Don't sort-lines ^^^ (org-agenda-span 'fortnight) (org-archive-directory "~/src/org/attic") (org-confirm-babel-evaluate nil) (org-default-notes-file (concat org-directory "/notes.org")) (org-fontify-done-headline t) (org-hide-emphasis-markers t) (org-hide-leading-stars t) (org-log-done t) (org-pretty-entities t) (org-src-preserve-indentation t) (org-src-strip-leading-and-trailing-blank-lines t) ;; Ref https://orgmode.org/manual/Template-elements.html for more detail. (org-agenda-files (list "~/src/org" "~/src/git.mitchty.net/mitchty/dotfiles")) ;; "#+TITLE: %a\n#+ROAM_KEY: %U\n\n [[%U][%U]]\n" (org-capture-templates '( ;; TODO: make this crap work somehow ;; ("w" "website" ;; entry (file (capture-date-file "~/src/org/ref/url" "org")) ;; ;; "#+TITLE: %a\n#+ROAM_KEY: %U\n\n%? [[%U][%U]]\n" ;; "%?" ;; :prepend t :empty-lines 1) ;; ("u" "unsorted note" ;; entry (file capture-date-file "~/src/org/unsorted" "org") ;; "\n* %?\nRandom Note entered on %U\n %i\n %a\n" ;; :prepend t :empty-lines 1) ;; ("r" "ref url" ;; entry (file capture-date-file "~/src/org/ref/url") ;; "\n* %?\nRandom Note entered on %U\n %i\n %a\n" ;; :prepend t :empty-lines 1) ("d" "deadline" entry (file+headline org-default-notes-file "Todos") "* PRIO %? \nDEADLINE: %t" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("t" "todo" entry (file+headline org-default-notes-file "Todos") "* TODO %?\n %i\n %a\n" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("n" "note" entry (file+headline org-default-notes-file "Notes") "\n* %?\nRandom Note entered on %U\n %i\n %a\n" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("m" "email todo" entry (file+headline org-default-notes-file "Inbox") "\n* TODO %?, Link: %a\n" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("u" "urls" entry (file+headline org-default-notes-file "Urls") "\n** TODO read url :url:\n[[%?]]\n" :prepend t :empty-lines 1) ("i" "interruption" entry (file+headline org-default-notes-file "Interruptions") "\n* BLOCKED by %? :BLOCKED:\n%t" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ("j" "journal" entry (file (concat org-directory "/journal.org")) "* %?\n%U\n" :prepend t :empty-lines 1 :clock-in t :clock-resume t) ))) #+END_SRC **** Org-roam testing Ref: - https://github.com/org-roam/org-roam - https://www.orgroam.com/manual/ Starting out simple..ish. #+BEGIN_SRC emacs-lisp (use-package org-roam :after org :ensure t :hook after-init :custom (org-roam-directory "~/src/org") (org-roam-index-file "~/src/org/roam.org") (org-roam-tag-sources '(prop all-directories)) (org-roam-capture-templates '(("d" "default" plain (function org-roam--capture-get-point) "%?" :file-name "~/src/org/${slug}" :unnarrowed t :head "#+TITLE: ${title}\n"))) (org-roam-capture-ref-templates '(("r" "ref" plain (function org-roam-capture--get-point) "%?" :file-name "~/src/org/ref/${slug}") :unnarrowed t :head "#+TITLE: ${title}\n#+ROAM_KEY: ${ref}\n- source :: ${ref}\n")) :bind (:map org-roam-mode-map (("C-c n l" . org-roam) ("C-c n f" . org-roam-find-file) ("C-c n g" . org-roam-graph)) :map org-mode-map (("C-c n i" . org-roam-insert)) (("C-c n I" . org-roam-insert-immediate)))) #+END_SRC **** TODO org babel ob-async testing :validation: Validate that this installs from scratch fine, blocking babel executions is ass. #+BEGIN_SRC emacs-lisp (use-package ob-async :after org :ensure t) #+END_SRC **** TODO org-habit customization :testing: Figure out the customization needed here. #+BEGIN_SRC emacs-lisp (use-package org-habit :after org :ensure t :custom (org-habit-graph-column 44) (org-habit-preceding-days 31) (org-habit-following-days 7)) #+END_SRC **** TODO org-bullets review if alternative is worth it :validation: https://github.com/integral-dw/org-superstar-mode #+BEGIN_SRC emacs-lisp (use-package org-bullets :after org :ensure t :custom (org-bullets-bullet-list '("◉" "○" "✸" "✿" "✜" "◆" "▶")) (org-ellipsis "↴") :hook (org-mode . org-bullets-mode) :config (when window-system (let* ((variable-tuple (cond ((x-list-fonts "Source Sans Pro") '(:font "Source Sans Pro")) ((x-list-fonts "Lucida Grande") '(:font "Lucida Grande")) ((x-list-fonts "Verdana") '(:font "Verdana")) ((x-family-fonts "Sans Serif") '(:family "Sans Serif")) (nil (warn "Cannot find a Sans Serif Font.")))) (base-font-color (face-foreground 'default nil 'default)) (headline `(:inherit default :weight bold :foreground ,base-font-color))) (custom-theme-set-faces 'user `(org-level-8 ((t (,@headline ,@variable-tuple)))) `(org-level-7 ((t (,@headline ,@variable-tuple)))) `(org-level-6 ((t (,@headline ,@variable-tuple)))) `(org-level-5 ((t (,@headline ,@variable-tuple)))) `(org-level-4 ((t (,@headline ,@variable-tuple :height 1.1)))) `(org-level-3 ((t (,@headline ,@variable-tuple :height 1.25)))) `(org-level-2 ((t (,@headline ,@variable-tuple :height 1.5)))) `(org-level-1 ((t (,@headline ,@variable-tuple :height 1.75)))) `(org-document-title ((t (,@headline ,@variable-tuple :height 1.5 :underline nil))))))) (font-lock-add-keywords 'org-mode '(("^ +\\([-*]\\) " (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•")))))) ) #+END_SRC TODO: testing #+BEGIN_SRC emacs-lisp :tangle no (use-package org-num :load-path "lisp/" :after org :hook (org-mode . org-num-mode)) #+END_SRC **** TODO Keep ox-latex in org setup? :validation:broken: Its tangle is set to no... #+BEGIN_SRC emacs-lisp :tangle no (require 'ox-latex) ox-latex (unless (boundp 'org-latex-classes) (setq org-latex-classes nil)) nil (add-to-list 'org-latex-classes '("article" "\\documentclass{article}" ("\\section{%s}" . "\\section*{%s}"))) #+END_SRC *** flycheck Flycheck for on the fly checking of code. #+BEGIN_SRC emacs-lisp (use-package flycheck :ensure t :custom (flycheck-indication-mode 'left-fringe) :hook (prog-mode . flycheck-mode)) #+END_SRC TODO: see if this is better for error messages #+BEGIN_SRC emacs-lisp :tangle no (use-package pos-tip :after flycheck :hook (flycheck-mode . flycheck-pos-tip-mode)) #+END_SRC **** TODO pkg-config lib stuff for flycheck :broken: Need to vet this, used it more when I did more c. But its handy for non standard pkg-config setups. Not tangled into the config intentionally. #+BEGIN_SRC emacs-lisp :tangle no (defun pkg-config-add-lib-cflags (pkg-config-lib) "This function will add necessary header file path of a specified by `pkg-config-lib' to `flycheck-clang-include-path', which make it completionable by auto-complete-clang" (interactive "spkg-config lib: ") (if (executable-find "pkg-config") (if (= (shell-command (format "pkg-config %s" pkg-config-lib)) 0) (setq flycheck-clang-include-path (append flycheck-clang-include-path (split-string (shell-command-to-string (format "pkg-config --cflags-only-I %s" pkg-config-lib))))) (message "Error, pkg-config lib %s not found." pkg-config-lib)) (message "Error: pkg-config tool not found."))) #+END_SRC *** TODO auto-complete not tangled :validation:broken: Auto complete functionality is nice to have. #+BEGIN_SRC emacs-lisp (use-package auto-complete :ensure t :init (require 'auto-complete-config) (ac-config-default) (global-auto-complete-mode t) ) #+END_SRC *** smartparens Helpfully inserts matching parens, can be a pita too. #+BEGIN_SRC emacs-lisp (use-package smartparens :ensure t :hook (prog-mode . smartparens-mode)) #+END_SRC *** rainbow delimiters Makes matching parens easier. #+BEGIN_SRC emacs-lisp (use-package rainbow-delimiters :ensure t :hook (prog-mode . rainbow-delimiters-mode)) #+END_SRC *** uniquify Make buffer names unique based on their directory and not have or other nonsense. #+BEGIN_SRC emacs-lisp (require 'uniquify) (custom-set-variables '(uniquify-buffer-name-style 'post-forward)) #+END_SRC *** desktop-save Desktop saving of session information handy to keep the same buffers between sessions. #+BEGIN_SRC emacs-lisp (require 'desktop) (desktop-save-mode 1) (custom-set-variables '(desktop-restore-eager 5) '(desktop-path '("~/.emacs.d")) '(desktop-dirname "~/.emacs.d") '(desktop-base-file-name "desktop") ) (defun local-desktop-save () (interactive) (if (eq (desktop-owner) (emacs-pid)) (desktop-save desktop-dirname))) #+END_SRC *** TODO super-save :validation:testing: REMOVE ME && TODO IF THIS WORKS Saves buffers like with auto-save but on focus loss, when idle etc... #+BEGIN_SRC emacs-lisp (use-package super-save :ensure t :config (super-save-mode +1) (setq super-save-auto-save-when-idle t) (setq auto-save-default nil) ) #+END_SRC *** TODO fic-mode :broken: Highlight TODO/FIXME type messages in comments. #+BEGIN_SRC emacs-lisp :tangle no (use-package fic-mode :ensure t :hook (prog-mode . fic-mode)) #+END_SRC *** git gutter #+BEGIN_SRC emacs-lisp (use-package git-gutter :ensure t :config (global-git-gutter-mode t) ) #+END_SRC *** clang-format #+BEGIN_SRC emacs-lisp (use-package clang-format :ensure t :bind (([C-M-tab] . clang-format-region)) ) #+END_SRC *** hideshow #+BEGIN_SRC emacs-lisp (use-package hideshow :ensure t :bind ("C-c s" . hs-toggle-hiding) ) #+END_SRC *** TODO ggtags :broken: #+BEGIN_SRC emacs-lisp :tangle no (use-package ggtags :ensure t) #+END_SRC *** company-mode Completion tips. #+BEGIN_SRC emacs-lisp :tangle no (use-package company :ensure t :hook (after-init . global-company-mode)) #+END_SRC *** yaml-mode For.. yaml #+BEGIN_SRC emacs-lisp (use-package yaml-mode :ensure t) #+END_SRC *** writegood-mode So I write gooder. Me fail English? Thats unpossible. #+BEGIN_SRC emacs-lisp (use-package writegood-mode :ensure t) #+END_SRC *** rust-mode #+BEGIN_SRC emacs-lisp (use-package rust-mode :commands rust-mode :defer t) #+END_SRC *** TODO python-mode :broken: Compress down python configuration a bit. #+BEGIN_SRC emacs-lisp :tangle no (use-package python :after company-mode :commands python-mode :mode ("\\.py\\'" . python-mode) :config (add-hook 'python-mode-hook' (lambda () (push '("lambda" . ?λ) prettify-symbols-alist) (push '("<=" . ?≤) prettify-symbols-alist) (push '(">=" . ?≥) prettify-symbols-alist) (push '("==" . ?≡) prettify-symbols-alist) (push '("/=" . ?≢) prettify-symbols-alist) (push '("&&" . ?∧) prettify-symbols-alist) (push '("||" . ?∨) prettify-symbols-alist) (push '("not" . ?¬) prettify-symbols-alist) (push '("None" . ?⊥) prettify-symbols-alist) (prettify-symbols-mode) ) ) ) (use-package company-anaconda :after python :config (add-to-list 'company-backends 'company-anaconda) (add-hook 'python-mode-hook 'anaconda-mode) ) (use-package pytest :after python :bind ("C-c t" . pytest-one) ) (use-package pymacs :after python) #+END_SRC *** haskell-mode Need to make haskell source be all pretty. #+BEGIN_SRC emacs-lisp (use-package haskell-mode :defer t :config (add-hook 'haskell-mode-hook 'interactive-haskell-mode) (add-hook 'haskell-mode-hook 'turn-on-haskell-indentation) (add-hook 'haskell-mode-hook' (lambda () (push '("()" . ?∅) prettify-symbols-alist) (push '("\\" . ?λ) prettify-symbols-alist) (push '("pi" . ?π) prettify-symbols-alist) (push '("=>" . ?⇒) prettify-symbols-alist) (push '("->" . ?→) prettify-symbols-alist) (push '("<-" . ?←) prettify-symbols-alist) (push '("<=" . ?≤) prettify-symbols-alist) (push '(">=" . ?≥) prettify-symbols-alist) (push '("==" . ?≡) prettify-symbols-alist) (push '("/=" . ?≢) prettify-symbols-alist) (push '("!!" . "‼") prettify-symbols-alist) (push '("&&" . ?∧) prettify-symbols-alist) (push '("||" . ?∨) prettify-symbols-alist) (push '("~>" . ?⇝) prettify-symbols-alist) (push '("-<" . ?↢) prettify-symbols-alist) (push '("not" . ?¬) prettify-symbols-alist) (push '("forall" . ?∀) prettify-symbols-alist) (push '("sqrt" . ?√) prettify-symbols-alist) (push '("undefined" . ?⊥) prettify-symbols-alist) (prettify-symbols-mode) ) ) (add-to-list 'completion-ignored-extensions ".hi") :custom (haskell-program-name "ghci") (haskell-process-type 'cabal-repl) (haskell-tags-on-save t) ) (use-package dante :after haskell-mode :config (add-hook 'haskell-mode-hook 'dante-mode) ) (use-package hindent :if (executable-find "hindent") :after haskell-mode :config (add-hook 'haskell-mode-hook 'hindent-mode) ) (use-package flycheck-haskell :after haskell-mode) (use-package flycheck-hdevtools :after haskell-mode :config (add-hook 'haskell-mode-hook 'flycheck-mode) ) (use-package ghc :if (executable-find "ghc-mod") :after haskell-mode :config (autoload 'ghc-init "ghc" nil t) (autoload 'ghc-debug "ghc" nil t) (add-hook 'haskell-mode-hook (lambda () (ghc-init))) ) #+END_SRC *** idris-mode #+BEGIN_SRC emacs-lisp (use-package idris-mode :defer t :config (add-to-list 'completion-ignored-extensions ".ibc") (add-hook 'idris-mode-hook' (lambda () (push '("()" . ?∅) prettify-symbols-alist) (push '("\\" . ?λ) prettify-symbols-alist) (push '("pi" . ?π) prettify-symbols-alist) (push '("=>" . ?⇒) prettify-symbols-alist) (push '("->" . ?→) prettify-symbols-alist) (push '("<-" . ?←) prettify-symbols-alist) (push '("<=" . ?≤) prettify-symbols-alist) (push '(">=" . ?≥) prettify-symbols-alist) (push '("==" . ?≡) prettify-symbols-alist) (push '("/=" . ?≢) prettify-symbols-alist) (push '("!!" . "‼") prettify-symbols-alist) (push '("&&" . ?∧) prettify-symbols-alist) (push '("||" . ?∨) prettify-symbols-alist) (push '("~>" . ?⇝) prettify-symbols-alist) (push '("-<" . ?↢) prettify-symbols-alist) (push '("not" . ?¬) prettify-symbols-alist) (push '("forall" . ?∀) prettify-symbols-alist) (push '("sqrt" . ?√) prettify-symbols-alist) (push '("undefined" . ?⊥) prettify-symbols-alist) (prettify-symbols-mode) ) ) ) #+END_SRC *** undo-tree Make undo more useful, and treelike. #+BEGIN_SRC emacs-lisp (use-package undo-tree :ensure t :config (global-undo-tree-mode) (defadvice undo-tree-visualize (around undo-tree-split-side-by-side activate) "Split undo-tree side-by-side" (let ((split-height-threshold nil) (split-width-threshold 0)) ad-do-it) ) :bind ("C-x u" . undo-tree-visualize) ) #+END_SRC *** color-identifiers-mode Color variables for easy identification, its like a rainbow puked over everything opened in prog-mode-hook. #+BEGIN_SRC emacs-lisp :tangle no (use-package color-identifiers-mode :defer t :hook (prog-mode . color-identifiers-mode)) #+END_SRC *** idle-highlight-mode Highlight a variable when you're selecting it, helps in reviewing code to see where it exists. #+BEGIN_SRC emacs-lisp :tangle no (use-package idle-highlight-mode :hook (prog-mode . idle-highlight-mode)) #+END_SRC *** nix Instead of text might as well get a decent mode hook going here. #+BEGIN_SRC emacs-lisp (use-package nixos-options :defer t) (use-package company-nixos-options :after company :defer t) #+END_SRC **** TODO nix-mode :broken: #+BEGIN_SRC emacs-lisp :tangle no (use-package nix-mode :config (setq flycheck-command-wrapper-function (lambda (command) (apply 'nix-shell-command (nix-current-sandbox) command)) flycheck-executable-find (lambda (cmd) (nix-executable-find (nix-current-sandbox) cmd))) (add-to-list 'company-backends 'company-nixos-options) ) #+END_SRC *** docker-mode #+BEGIN_SRC emacs-lisp (use-package dockerfile-mode :defer t) #+END_SRC *** TODO cscope or rtags or nuke :testing:validation: Switch to rtags, or maybe even nuke entirely? #+BEGIN_SRC emacs-lisp (use-package xcscope :defer t :config (cscope-setup)) #+END_SRC *** rg #+BEGIN_SRC emacs-lisp (use-package rg :ensure t :defer t) #+END_SRC * mode related *** common defaults Common mode defaults I think are sensible. ***** c #+BEGIN_SRC emacs-lisp (add-to-list 'auto-mode-alist '("\\.[chm]\\'" . c-mode)) (add-hook 'c-mode-common-hook '(lambda () (global-set-key "\C-x\C-m" 'compile) (setq flycheck-clang-language-standard "c11") (setq flycheck-idle-change-delay 2) (setq flycheck-highlighting-mode 'symbols) ;; later... ;; (add-hook 'before-save-hook 'clang-format-buffer nil t) (c-toggle-auto-state 1) (setq-default c-basic-offset 2 tab-width 2 indent-tabs-mode nil c-electric-flag t indent-level 2 c-default-style "bsd" backward-delete-function nil) )) #+END_SRC ***** TODO elisp :broken: Why is this broken? Figure out why its tangle is no. #+BEGIN_SRC emacs-lisp :tangle no (add-hook 'emacs-lisp-hook (lambda () (define-key emacs-lisp-map "\C-x\C-e" 'pp-eval-last-sexp) (define-key emacs-lisp-map "\r" 'reindent-then-newline-and-indent))) #+END_SRC ***** python-mode #+BEGIN_SRC emacs-lisp (add-hook 'python-mode-hook '(lambda () (flycheck-select-checker 'python-flake8) ) ) #+END_SRC ***** shell #+BEGIN_SRC emacs-lisp (autoload 'sh--mode "sh-mode" "mode for shell stuff" t) (add-to-list 'auto-mode-alist '("\\.sh$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("\\.[zk]sh$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("\\.bash$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("\\[.].*shrc$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("sourceme$\\'" . sh-mode)) (add-hook 'sh-mode-hook '(lambda () (setq sh-basic-offset 2 sh-indentation 4 sh-indent-for-case-label 0 sh-indent-for-case-alt '+))) #+END_SRC ***** perl #+BEGIN_SRC emacs-lisp (fset 'perl-mode 'cperl-mode) (add-hook 'cperl-mode-hook '(lambda () (setq indent-tabs-mode t) (setq tab-width 8) (setq cperl-indent-level 4) (setq tab-stop-list (number-sequence 4 200 4)) (setq cperl-tab-always-indent t) (setq cperl-indent-parens-as-block t) ) ) #+END_SRC *** TODO auto-insert-mode new file templates :broken: Review if this is worth keeping around, methinks there should be something better like yasnippet out there, this is all old af hacks Use auto-insert-mode to insert in templates for blank files. So first up, add auto-insert to *find-file-hooks* so we insert straight away. Also setup the copyright bit to minimally put in name. #+BEGIN_SRC emacs-lisp (add-hook 'find-file-hooks 'auto-insert) (defvar auto-insert-copyright (user-full-name)) #+END_SRC Create *auto-insert-alist* so all the mode lists are the same #+BEGIN_SRC emacs-lisp (defvar auto-insert-alist '(())) #+END_SRC ***** c #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '( ((c-mode . "c") nil "/*\n" "File: " (file-name-nondirectory buffer-file-name) "\n" "Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" "Description: " _ "\n" "*/\n" "#include \n" "#include \n\n" "int main(int argc, char **argv) {\n" " return 0;\n" "}\n" ) ) auto-insert-alist) ) #+END_SRC ***** elisp #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '( ((emacs-lisp-mode . "elisp") nil ";;-*-mode: emacs-lisp; coding: utf-8;-*-\n" ";; File: " (file-name-nondirectory buffer-file-name) "\n" ";; Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" ";; Description: " _ "\n" ) ) auto-insert-alist) ) #+END_SRC ***** python #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '(((python-mode . "python") nil "#!/usr/bin/env python\n" "# -*-mode: Python; coding: utf-8;-*-\n" "# File: " (file-name-nondirectory buffer-file-name) "\n" "# Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" "# Description: " _ "\n\n" ) ) auto-insert-alist) ) #+END_SRC ***** shell #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '( ((sh-mode . "sh") nil "#!/usr/bin/env sh\n" "#-*-mode: Shell-script; coding: utf-8;-*-\n" "# File: " (file-name-nondirectory buffer-file-name) "\n" "# Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" "# Description: " _ "\n" "_base=$(basename \"$0\")\n" "_dir=$(cd -P -- \"$(dirname -- \"$(command -v -- \"$0\")\")\" && pwd -P || exit 126)\n" "export _base _dir\n" ) ) auto-insert-alist) ) #+END_SRC * custom Load this up last to allow for local customization if needed and to keep from custom writing to the init.el file. #+BEGIN_SRC emacs-lisp (setq custom-file "~/.emacs.d/custom.el") (load custom-file 'noerror) #+END_SRC * TODO Load any local definitions :broken: Probably need to check if this file exists first... #+BEGIN_SRC emacs-lisp :tangle no (load-file "~/.emacs.d/local.el") #+END_SRC * TESTING Stuff thats getting tested... Iffy.... Does some jank ass wack stuff in fullscreen mode on cocoa emacs in macos. #+BEGIN_SRC emacs-lisp :tangle no (use-package mini-frame :ensure t :config (mini-frame-mode t) :custom (mini-frame-show-parameters '((top . 10)))) ;; (width . 0.7) ;; (left . 0.5)))) #+END_SRC