#+TITLE: Emacs Configuration File #+AUTHOR: Pierce Wang #+BABEL: :cache yes #+PROPERTY: header-args :tangle yes :results silent #+STARTUP: content indent #+SEQ_TODO: TODO(t) | DISABLED(D) #+SETUPFILE: ~/.emacs.d/org-mode/templates/general/web.org * Credits and Notes Inspired by [[https://github.com/freetonik/emacs-dotfiles][freetonik]]'s setup. Check out his podcast! *See the original =org-mode= file that this website was generated from [[https://raw.githubusercontent.com/piercegwang/emacsd/master/init.org][here]].* * Installing This config works best with [[https://github.com/d12frosted/homebrew-emacs-plus][emacs-plus]] (27.1) #+begin_src sh :tangle no brew tap d12frosted/emacs-plus brew install emacs-plus ln -s /usr/local/opt/emacs-plus/Emacs.app /Applications/Emacs.app #+end_src ** Dependencies #+begin_src sh :tangle no brew install ispell brew cask install mactex #+end_src ** Meta When this configuration is loaded for the first time, the =init.el= is the file that is loaded. It looks like this: #+BEGIN_SRC emacs-lisp :tangle no ;; This file replaces itself with the actual configuration at first run. ;; We can't tangle without org! (require 'org) ;; Open the configuration (find-file (concat user-emacs-directory "init.org")) ;; tangle it (org-babel-tangle) ;; load it (load-file (concat user-emacs-directory "init.el")) ;; finally byte-compile it (byte-compile-file (concat user-emacs-directory "init.el")) #+END_SRC ** Headers Lexical scoping for the init-file is needed, it can be specified in the header. This is the first line of the actual configuration: #+BEGIN_SRC emacs-lisp ;;; -*- lexical-binding: t -*- #+END_SRC Tangle and compile this file on save automatically: #+BEGIN_SRC emacs-lisp (defun tangle-init () "If the current buffer is 'init.org' the code-blocks are tangled, and the tangled file is compiled." (when (equal (buffer-file-name) (expand-file-name (concat user-emacs-directory "init.org"))) ;; Avoid running hooks when tangling. (let ((prog-mode-hook nil)) (org-babel-tangle) (byte-compile-file (concat user-emacs-directory "init.el"))))) (add-hook 'after-save-hook 'tangle-init) #+END_SRC This helps get rid of =functions might not be defined at runtime= warnings. See https://github.com/jwiegley/use-package/issues/590 #+BEGIN_SRC emacs-lisp (eval-when-compile (defvar use-package-expand-minimally byte-compile-current-file)) #+END_SRC * Startup ** Garbage Collection For faster startup times, according to [[https://github.com/hlissner/doom-emacs/blob/develop/docs/faq.org#how-does-doom-start-up-so-quickly][hlissner]], #+begin_quote The GC eats up quite a bit of time, easily doubling startup time. The trick is to turn up the memory threshold as early as possible. #+end_quote #+begin_src emacs-lisp (setq gc-cons-threshold most-positive-fixnum ; 2^61 bytes gc-cons-percentage 0.6) (defvar better-gc-cons-threshold 16777216 ; 16mb "The default value to use for `gc-cons-threshold'. If you experience freezing, decrease this. If you experience stuttering, increase this.") (add-hook 'emacs-startup-hook (lambda () (setq gc-cons-threshold better-gc-cons-threshold gc-cons-percentage 0.1))) ; Default value for `gc-cons-percentage' #+end_src gc and minibuffer (also from doom) #+begin_src emacs-lisp (defun pgw/defer-garbage-collection-h () (setq gc-cons-threshold most-positive-fixnum)) (defun pgw/restore-garbage-collection-h () "Defer it so that commands launched immediately after will enjoy the benefits." (run-at-time 1 nil (lambda () (setq gc-cons-threshold better-gc-cons-threshold)))) (add-hook 'minibuffer-setup-hook #'pgw/defer-garbage-collection-h) (add-hook 'minibuffer-exit-hook #'pgw/restore-garbage-collection-h) #+end_src ** Package Setup Initialize package and add Melpa, GNU, and Org sources. #+begin_src emacs-lisp (require 'package) (setq package-archives '(("melpa" . "https://melpa.org/packages/") ("gnu" . "https://elpa.gnu.org/packages/") ("org" . "https://orgmode.org/elpa/") )) (package-initialize) #+end_src Sometimes, if there's an error refreshing packages, you just need to re-run this code segment. ** Use package Add custom load path: #+begin_src emacs-lisp (add-to-list 'load-path "~/.emacs.d/custom_load/") #+end_src Install use-package. #+BEGIN_SRC emacs-lisp (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (eval-when-compile (require 'use-package)) (setq use-package-always-ensure t) #+END_SRC use-package.el no longer needed at runtime #+begin_src emacs-lisp (eval-when-compile (require 'use-package)) (require 'bind-key) ;; if you use any :bind variant #+end_src No need for "Package cl deprecated" warning on startup. #+begin_src emacs-lisp (setq byte-compile-warnings '(cl-functions)) (require 'cl-lib) (eval-when-compile (require 'cl)) #+end_src ** OS Integration #+begin_src emacs-lisp (use-package exec-path-from-shell) (when (memq window-system '(mac ns x)) (exec-path-from-shell-initialize)) ;;; Change shell process (from bash to zsh) ;; (setq shell-file-name "/bin/zsh") #+end_src * Configurations ** Bookmarks #+begin_src emacs-lisp (global-set-key (kbd "C-x r D") 'bookmark-delete) #+end_src ** Emacs Stuff *** Startup Time Test #+begin_src emacs-lisp (add-hook 'emacs-startup-hook (lambda () (message "Emacs ready in %s with %d garbage collections." (format "%.2f seconds" (float-time (time-subtract after-init-time before-init-time))) gcs-done))) #+end_src *** Custom Set Variables Store custom-file separately, don't freek out when it's not found. #+begin_src emacs-lisp (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) (load custom-file 'noerror) #+end_src *** Confirm Kill Emacs Make Emacs confirm when quitting: #+begin_src emacs-lisp (setq confirm-kill-emacs 'yes-or-no-p) #+end_src ** =tab-bar-mode= #+begin_src emacs-lisp ;; (tab-bar-mode 1) (setq tab-bar-show nil) #+end_src *** Tab Switching Keybinds :keybinds: #+begin_src emacs-lisp (global-set-key (kbd "s-{") (lambda () (interactive) (tab-next -1))) (global-set-key (kbd "s-}") (lambda () (interactive) (tab-next 1))) #+end_src ** Custom Functions *** append-to-list #+begin_src emacs-lisp (defun append-to-list (list-var elements) "Append ELEMENTS to the end of LIST-VAR. The return value is the new value of LIST-VAR." (unless (consp elements) (error "ELEMENTS must be a list")) (let ((list (symbol-value list-var))) (if list (setcdr (last list) elements) (set list-var elements))) (symbol-value list-var)) #+end_src *** Increment/Decrement Numbers #+begin_src emacs-lisp ;;; Increment Numbers (defun increment-number-at-point () "Increments numbers at cursor" (interactive) (skip-chars-backward "0-9") (or (looking-at "[0-9]+") (error "No number at point")) (replace-match (number-to-string (1+ (string-to-number (match-string 0)))))) ;;; Decrement Numbers (defun decrement-number-at-point () "Decrements numbers at cursor" (interactive) (skip-chars-backward "0-9") (or (looking-at "[0-9]+") (error "No number at point")) (replace-match (number-to-string (1- (string-to-number (match-string 0)))))) ;;; Binding (global-set-key (kbd "C-; C-=") 'increment-number-at-point) (global-set-key (kbd "C-; C--") 'decrement-number-at-point) #+end_src *** Insert Directory (obsolete?) #+begin_src emacs-lisp (defun insertdirectory () "Insert current directory for macro use" (interactive) (insert default-directory)) #+end_src *** Ignore Error Wrapping Function For some functions that I don't need to give errors: #+begin_src emacs-lisp (defun ignore-error-wrapper (fn) "Funtion return new function that ignore errors. The function wraps a function with `ignore-errors' macro." (lexical-let ((fn fn)) (lambda () (interactive) (ignore-errors (funcall fn))))) #+end_src *** Insert Org-mode Image #+begin_src emacs-lisp (defun insert-org-image (&optional swindow) "Prompt user for name of file, append time and date string, then use the Mac OSX `screencapture` feature to take a photo and place it in the relative ./figures directory." (interactive "P") (unless (not (memq system-type '(gnu gnu/linux darwin))) (let* ((outdir "figures") (givenname (read-string "Enter File Name: ")) (namefile (concat (format-time-string "%Y%m%d_%H%M%S") (if (not (string= givenname "")) (concat "_" givenname) "") ".jpeg")) (program (cond ((if (memq system-type '(gnu gnu/linux)) "gnome-screenshot" nil)) ((if (eq system-type 'darwin) "screencapture" "")))) (argument (cond ((string= program "screencapture") (if swindow "-w" "-i")) ((string= program "gnome-screenshot") (if swindow "-w" "-a")))) (outfile (concat outdir "/" namefile))) (unless (file-directory-p outdir) (make-directory outdir t)) (if (memq system-type '(gnu gnu/linux)) (setq outfile (concat "--file=" outfile))) (message "Program: %s\nArgument: %s\nOutfile: %s" program argument outfile) (call-process program nil nil nil argument outfile) (message namefile) (insert (concat (concat "[[file:./figures/" (file-name-nondirectory outfile)) "]]"))))) #+end_src *** Keyboard Coding System #+begin_src emacs-lisp (set-keyboard-coding-system nil) #+end_src *** Dired Open File #+begin_src emacs-lisp (defun pgw/dired-open-file () "In dired, open the file named on this line using the default application in the system." (interactive) (let ((file (dired-get-filename nil t)) ; Full path (filename (dired-get-filename t t))) ; File name for display (message "Opening %s..." filename) (cond ((memq window-system '(mac ns)) (call-process "open" nil 0 nil file)) ((memq window-system '(x)) (call-process "xdg-open" nil 0 nil file))) (message "Opening %s done" filename))) #+end_src *** Copy MLA org-file #+begin_src emacs-lisp (defun pgw/copy-mla-file () "Copy MLA_OrgFile.org to current directory for use in school essays." (interactive) (copy-file "~/Dropbox/org/templates/school/MLA_OrgFile.org" default-directory) ) #+end_src *** Lookup in Dictionary (Apple) #+begin_src emacs-lisp (when (eq system-type 'darwin) (defun pgw/lookup-dictionary () "Function to open a dictionary searching the highlighted word No spaces are allowed in the input of this function" (interactive) (let ((word (read-from-minibuffer "Word query: "))) (call-process "open" nil nil nil (concat "dict://" word))) ) (global-set-key (kbd "M-#") 'pgw/lookup-dictionary) ) #+end_src *** Test network (internet-up-p) Test if network is up and running #+begin_src emacs-lisp (defun internet-up-p (&optional host) (= 0 (call-process "ping" nil nil nil "-c" "1" "-W" "1" (if host host "1.1.1.1")))) #+end_src *** Get org link :keybinds: #+begin_src emacs-lisp (defun pgw/org-get-link-at-point () "Get the link from an org heading" (interactive) (let* ((context (org-element-context)) (link (if (eq (car context) 'link) (org-element-property :path context) nil))) (if link (kill-new (concat (org-element-property :type context) ":" link))))) (global-set-key (kbd "C-c s-l") 'pgw/org-get-link-at-point) #+end_src *** Make-shell Make a shell instance with name https://stackoverflow.com/questions/2540997/create-more-than-one-eshell-instance-in-emacs/2541530#2541530 #+begin_src emacs-lisp (defun make-shell (name) "Create a shell buffer named NAME." (interactive "sName: ") (setq name (concat "$" name)) (eshell 4) (rename-buffer name)) #+end_src ** Modifier Keys #+begin_src emacs-lisp (when (eq system-type 'darwin) (with-no-warnings (setq mac-option-modifier 'meta) (setq mac-control-modifier 'control) (setq ns-function-modifier 'hyper))) (when (eq system-type 'gnu/linux) (with-no-warnings (setq x-super-keysym 'hyper))) #+end_src ** Visuals #+begin_src emacs-lisp ;(load-theme 'tango-dark t) ;; (load-theme 'monokai) ;; ; ;; Frame (add-to-list 'default-frame-alist '(height . 46)) (add-to-list 'default-frame-alist '(width . 146)) ;;; Visual line mode (for text wrapping) (global-set-key (kbd "C-x v v") 'visual-line-mode) ;; Darkroom-tentative-mode (global-set-key (kbd "C-x v d") 'darkroom-tentative-mode) ;; (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)) (add-to-list 'default-frame-alist '(ns-appearance . dark)) ;; assuming you are using a dark theme ;; (setq ns-use-proxy-icon nil) ;; (setq frame-title-format nil) (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) (setq visual-line-fringe-indicators '(left-curly-arrow hollow-square)) ;; '(left-curly-arrow right-curly-arrow) for both left and right ;; Testing freetonik's fringe indicator alist (setq-default fringe-indicator-alist '((truncation left-arrow right-arrow) (continuation nil right-arrow) (overlay-arrow . right-triangle) (up . up-arrow) (down . down-arrow) (top top-left-angle top-right-angle) (bottom bottom-left-angle bottom-right-angle top-right-angle top-left-angle) (top-bottom left-bracket right-bracket top-right-angle top-left-angle) (empty-line . empty-line) (unknown . question-mark))) #+end_src *** All the Icons #+begin_src emacs-lisp (use-package all-the-icons) #+end_src *** Doom Theme Favorite themes: 1. outrun-electric 2. challenger-deep 3. snazzy 4. molokai 5. solarized-dark Light themes: - solarized-light - doom-acario-light - gruvbox-light #+begin_src emacs-lisp :tangle yes (use-package doom-themes :config ;; Global settings (defaults) (setq doom-themes-enable-bold t ; if nil, bold is universally disabled doom-themes-enable-italic t) ; if nil, italics is universally disabled ;; Load the theme (doom-one, doom-molokai, etc); keep in mind that each theme ;; may have their own settings. (load-theme 'doom-snazzy t) ;; (load-theme 'modus-operandi) ;; Enable flashing mode-line on errors (doom-themes-visual-bell-config) ;; Enable custom neotree theme (all-the-icons must be installed!) ;; (doom-themes-neotree-config) ;; or for treemacs users (setq doom-themes-treemacs-theme "doom-colors") ; use the colorful treemacs theme (doom-themes-treemacs-config) ;; Doom themes fontifies #hashtags and @at-tags by default. ;; To disable this: (setq doom-org-special-tags nil) ;; Corrects (and improves) org-mode's native fontification. (doom-themes-org-config) ) #+end_src **** Set Orgmode Agenda Stuff #+begin_src emacs-lisp :tangle no ;; this must be used after loading the theme with (load-theme THEME-NAME t) (custom-set-faces `(org-time-grid ((t (:foreground ,(doom-blend 'yellow 'fg 0.6))))) `(org-time-grid ((t (:foreground ,(doom-blend 'yellow 'fg 0.6))))) `(org-habit-ready-face ((t (:foreground ,(doom-blend 'blue 'fg 0.1))))) `(org-habit-alert-face ((t (:foreground ,(doom-blend 'yellow 'fg 0.1))))) `(org-habit-overdue-face ((t (:foreground ,(doom-blend 'red 'fg 0.1))))) ) #+end_src *** DISABLED Light Theme CLOSED: [2020-11-29 Sun 11:28] #+begin_src emacs-lisp :tangle no (load-theme 'modus-operandi) #+end_src *** DISABLED Regular Theme CLOSED: [2021-05-20 Thu 21:32] #+begin_src emacs-lisp :tangle no (load-theme 'tango-dark) #+end_src *** Frame Resize Pixelwise Make Emacs play nice with my window manager and resizing around other windows. #+begin_src emacs-lisp (setq frame-resize-pixelwise t) #+end_src *** Line Numbers #+begin_src emacs-lisp ;; (global-visual-line-mode t) (setq display-line-numbers-type 'visual) (global-display-line-numbers-mode 1) ;; (setq-default display-line-numbers 'visual) (set-default 'truncate-lines t) #+end_src ** Windows and Frames *** Movement Between Windows Windows and Frames are different than one would now intuitively think. Windows exist inside subdivided frames which we call windows now. The following code makes windows and frames easier to navigate: #+begin_src emacs-lisp (when (fboundp 'windmove-default-keybindings) (global-set-key (kbd "H-h") (ignore-error-wrapper 'windmove-left)) (global-set-key (kbd "H-l") (ignore-error-wrapper 'windmove-right)) (global-set-key (kbd "H-k") (ignore-error-wrapper 'windmove-up)) (global-set-key (kbd "H-j") (ignore-error-wrapper 'windmove-down)) ) ;; Disabled, Doesn't really work for me - going to use s-left and s-right instead ;; (use-package framemove ;; :load-path "custom_load" ;; :config ;; (require 'framemove) ;; (global-set-key (kbd "C-e-") 'fm-down-frame) ;; (global-set-key (kbd "C-s-") 'fm-up-frame) ;; (global-set-key (kbd "C-s-") 'fm-left-frame) ;; (global-set-key (kbd "C-s-") 'fm-right-frame) ;; (setq framemove-hook-into-windmove t) ;; ) #+end_src *** Window Management #+begin_src emacs-lisp (use-package rotate) #+end_src ** Treemacs #+begin_src emacs-lisp (use-package treemacs) (use-package treemacs-evil) (use-package treemacs-magit) #+end_src ** ztree (Tool for diffing and merging directories) #+begin_src emacs-lisp (use-package ztree) #+end_src ** Fonts *** DISABLED Chinese Font with English Font :ARCHIVE: CLOSED: [2020-11-29 Sun 11:28] Special Fonts config for ease of zooming chinese and english fonts at same rate. #+begin_src emacs-lisp :tangle no (when (display-graphic-p) (if (eq system-type 'darwin) (set-face-attribute 'default nil :font "Menlo")) (defvar emacs-english-font "Menlo" "The font name for English.") (defvar emacs-cjk-font "WenQuanYi Micro Hei Mono" "The font name for CJK.") (find-font (font-spec :name "WenQuanYi Micro Hei Mono")) (font-family-list) (if (eq system-type 'windows-nt) (setq emacs-cjk-font "WenQuanYi Micro Hey Mono" emacs-english-font "Menlo") (setq emacs-cjk-font "WenQuanYi Micro Hei Mono")) (defvar emacs-font-size-pair '(12 . 14) ; Old '(12 . 14) "Default font size pair for (english . chinese)") (defvar emacs-font-size-pair-list '((5 . 6) (9 . 10) (10 . 12) (12 . 14) (13 . 16) (15 . 18) (17 . 20) (19 . 22) (20 . 24) (21 . 26) (24 . 28) (26 . 32) (28 . 34) (30 . 36) (34 . 40) (36 . 44)) "This list is used to store matching (english . chinese) font-size.") (defun font-exist-p (fontname) "Test if this font is exist or not." (if (or (not fontname) (string= fontname "")) nil (if (not (x-list-fonts fontname)) nil t))) (defun set-font (english chinese size-pair) "Setup emacs English and Chinese font on x window-system." (if (font-exist-p english) (set-frame-font (format "%s:pixelsize=%d" english (car size-pair)) t)) (if (font-exist-p chinese) (dolist (charset '(kana han symbol cjk-misc bopomofo)) (set-fontset-font (frame-parameter nil 'font) charset (font-spec :family chinese :size (cdr size-pair)))))) ;; Setup font size based on emacs-font-size-pair (set-font emacs-english-font emacs-cjk-font emacs-font-size-pair) (defun emacs-step-font-size (step) "Increase/Decrease emacs's font size." (let ((scale-steps emacs-font-size-pair-list)) (if (< step 0) (setq scale-steps (reverse scale-steps))) (setq emacs-font-size-pair (or (cadr (member emacs-font-size-pair scale-steps)) emacs-font-size-pair)) (when emacs-font-size-pair (message "emacs font size set to %.1f" (car emacs-font-size-pair)) (set-font emacs-english-font emacs-cjk-font emacs-font-size-pair)))) (defun increase-emacs-font-size () "Decrease emacs's font-size acording emacs-font-size-pair-list." (interactive) (emacs-step-font-size 1)) (defun decrease-emacs-font-size () "Increase emacs's font-size acording emacs-font-size-pair-list." (interactive) (emacs-step-font-size -1)) (global-set-key (kbd "C-=") 'increase-emacs-font-size) (global-set-key (kbd "C--") 'decrease-emacs-font-size) ) (set-face-attribute 'default nil :font emacs-english-font :height 120) (dolist (charset '(kana han symbol cjk-misc bopomofo)) (set-face-attribute charset (font-spec :family emacs-cjk-font :size (cdr emacs-font-size-pair)))) (set-font emacs-english-font emacs-cjk-font emacs-font-size-pair) #+end_src *** Set default font and configure font resizing Credit to Harry R. Schwartz [[https://github.com/hrs/dotfiles/blob/master/emacs/.emacs.d/configuration.org#set-default-font-and-configure-font-resizing][github]] The standard =text-scale-= functions just resize the text in the current buffer; I’d generally like to resize the text in every buffer, and I usually want to change the size of the modeline, too (this is especially helpful when presenting). These functions and bindings let me resize everything all together! Note that this overrides the default font-related keybindings from sensible-defaults. #+begin_src emacs-lisp ;; (cond ((memq system-type '(gnu/linux gnu)) ;; (setq pgw/default-font "Monoid")) ;; ((memq system-type '(darwin)) ;; (setq pgw/default-font "Menlo"))) (setq pgw/default-font "Monoid") (setq pgw/default-font-size 12) (setq pgw/current-font-size pgw/default-font-size) (setq pgw/font-change-increment 1.1) (defun pgw/font-code () "Return a string representing the current font (like \"Inconsolata-14\")." (concat pgw/default-font "-" (number-to-string pgw/current-font-size))) (defun pgw/set-font-size () "Set the font to `pgw/default-font' at `pgw/current-font-size'. Set that for the current frame, and also make it the default for other, future frames." (interactive) (let ((font-code (pgw/font-code))) (if (assoc 'font default-frame-alist) (setcdr (assoc 'font default-frame-alist) font-code) (add-to-list 'default-frame-alist (cons 'font font-code))) (set-frame-font font-code))) (defun pgw/reset-font-size () "Change font size back to `pgw/default-font-size'." (interactive) (setq pgw/current-font-size pgw/default-font-size) (pgw/set-font-size)) (defun pgw/increase-font-size () "Increase current font size by a factor of `pgw/font-change-increment'." (interactive) (setq pgw/current-font-size (ceiling (* pgw/current-font-size pgw/font-change-increment))) (pgw/set-font-size)) (defun pgw/decrease-font-size () "Decrease current font size by a factor of `pgw/font-change-increment', down to a minimum size of 1." (interactive) (setq pgw/current-font-size (max 1 (floor (/ pgw/current-font-size pgw/font-change-increment)))) (pgw/set-font-size)) (define-key global-map (kbd "C-)") 'pgw/reset-font-size) (define-key global-map (kbd "C-H-0") 'pgw/set-font-size) (define-key global-map (kbd "C-+") 'pgw/increase-font-size) (define-key global-map (kbd "C-=") 'pgw/increase-font-size) (define-key global-map (kbd "C-_") 'pgw/decrease-font-size) (define-key global-map (kbd "C--") 'pgw/decrease-font-size) (add-hook 'emacs-startup-hook (lambda () (interactive) (pgw/reset-font-size))) #+end_src *** Variable Pitch Default Font #+begin_src emacs-lisp (set-face-attribute 'variable-pitch nil :family "Avenir Next") #+end_src *** Mixed Pitch Mixed pitch package for mixing variable and monospace fonts where appropriate (replacing buffer-face-mode). I copied mixed-pitch.el from [[https://gitlab.com/jabranham/mixed-pitch/][this]] repository because of [[https://gitlab.com/jabranham/mixed-pitch/issues/6][this]] issue. I will hopefully be changing it back at some point (or coming up with a better fix because the fonts don't seem to work great together) but for now this will be the fix. #+begin_src emacs-lisp (use-package mixed-pitch :load-path "custom_load" :config ;; (set-face-attribute 'variable-pitch :height 160) (dolist (face '(line-number line-number-current-line org-list-dt org-link)) (add-to-list 'mixed-pitch-fixed-pitch-faces face)) ;; (add-hook 'text-mode-hook 'mixed-pitch-mode) (global-set-key (kbd "C-x v f") 'mixed-pitch-mode) ) #+end_src *** Unicode-fonts Setup Can add a few seconds to startup time, may want to check "Startup Speed" on this page: [[https://github.com/rolandwalker/unicode-fonts/tree/e3942fe40b418bfb2dc4e73633e09195437fef01#customization][unicode fonts github]] #+begin_src emacs-lisp (use-package unicode-fonts :ensure t :config (unicode-fonts-setup)) #+end_src ** GPG #+begin_src emacs-lisp ;; (require 'epa-file) (epa-file-enable) (setf epa-pinentry-mode 'loopback) #+end_src ** Passwords #+begin_src emacs-lisp (load-file "~/.passwords.el") #+end_src ** Mode Line Still figuring this out, just switched to powerline! *** DISABLED Smart Mode Line CLOSED: [2020-11-29 Sun 11:30] #+begin_src emacs-lisp :tangle no (use-package smart-mode-line :config (setq rm-blacklist '(" hl-p" " WK" " yas" " Undo-Tree" " hs") ;; sml/theme 'light sml/name-width 30 ) (add-to-list 'sml/replacer-regexp-list '("^~/Google Drive/OHS/\\([0-9]\\{2\\}\\)th Grade/Classes/Semester [0-9]/\\([0-9A-Z]*\\)/" ":\\2:")) (add-hook 'after-init-hook 'sml/setup) ) #+end_src *** Powerline #+begin_src emacs-lisp (use-package powerline :ensure t :config (powerline-default-theme)) #+end_src *** Other Configuration #+begin_src emacs-lisp (size-indication-mode 1) (line-number-mode -1) #+end_src *** DISABLED Time display CLOSED: [2020-11-29 Sun 11:30] #+begin_src emacs-lisp :tangle no (setq display-time-format "%a %m/%d %H:%M") (display-time-mode) #+end_src *** DISABLED Battery display CLOSED: [2020-11-29 Sun 11:30] #+begin_src emacs-lisp :tangle no (setq battery-mode-line-format " [%b%p%%]") (display-battery-mode) #+end_src ** Narrowing Frameworks *** DISABLED Helm CLOSED: [2020-11-29 Sun 11:31] #+begin_src emacs-lisp :tangle no (use-package helm :config (require 'helm-config) (helm-mode 1) (define-key global-map [remap find-file] 'helm-find-files) (define-key global-map [remap occur] 'helm-occur) (define-key global-map [remap list-buffers] 'helm-buffers-list) (define-key global-map [remap dabbrev-expand] 'helm-dabbrev) (define-key global-map [remap execute-extended-command] 'helm-M-x) (unless (boundp 'completion-in-region-function) (define-key lisp-interaction-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point) (define-key emacs-lisp-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point)) ) #+end_src *** Counsel Dependency for ~ivy~ #+begin_src emacs-lisp (use-package counsel) #+end_src *** Ivy #+begin_src emacs-lisp :tangle yes (use-package ivy :config (ivy-mode 1) (setq ivy-use-virtual-buffers t) (setq enable-recursive-minibuffers t) ;; enable this if you want `swiper' to use it ;; (setq search-default-mode #'char-fold-to-regexp) (global-set-key "\C-s" 'swiper) (global-set-key (kbd "C-c C-r") 'ivy-resume) (global-set-key (kbd "") 'ivy-resume) (global-set-key (kbd "M-x") 'counsel-M-x) (global-set-key (kbd "C-x C-f") 'counsel-find-file) (global-set-key (kbd " f") 'counsel-describe-function) (global-set-key (kbd " v") 'counsel-describe-variable) (global-set-key (kbd " o") 'counsel-describe-symbol) (global-set-key (kbd " l") 'counsel-find-library) (global-set-key (kbd " i") 'counsel-info-lookup-symbol) (global-set-key (kbd " u") 'counsel-unicode-char) (global-set-key (kbd "C-c g") 'counsel-git) (global-set-key (kbd "C-c j") 'counsel-git-grep) (global-set-key (kbd "C-c k") 'counsel-ag) (global-set-key (kbd "C-x l") 'counsel-locate) (global-set-key (kbd "C-S-o") 'counsel-rhythmbox) (define-key minibuffer-local-map (kbd "C-r") 'counsel-minibuffer-history) (define-key ivy-minibuffer-map (kbd "S-SPC") (insert " ")) (define-key ivy-minibuffer-map (kbd "S-C-SPC") 'ivy-restrict-to-matches)) #+end_src ** Diary *** Diary file #+begin_src emacs-lisp ;(setq org-agenda-include-diary t) (setq diary-file "~/Dropbox/org/diary") #+end_src *** Appointments Setup #+begin_src emacs-lisp (appt-activate -1) (setq appt-message-warning-time 15) (setq diary-comment-start "##") #+end_src ** Org-mode *** Setting orgmode directories: #+begin_src emacs-lisp (setq org-directory "~/Dropbox/org") (setq org-default-notes-file (concat org-directory "/inbox.org")) #+end_src *** Startup Settings Make org-mode files automatically indent. #+begin_src emacs-lisp (setq org-startup-indented t) #+end_src *** org-roam #+begin_src emacs-lisp (use-package org-roam :ensure t :hook (after-init . org-roam-mode) :bind ((("C-c n I" . org-roam-insert-immediate)) :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) ("C-c n d ." . org-roam-dailies-capture-today) ("C-c n d p" . org-roam-dailies-capture-yesterday) ("C-c n d n" . org-roam-dailies-capture-tomorrow) ("C-c n d j" . org-roam-dailies-capture-date) ("C-c n d g" . org-roam-dailies-find-date) ("C-c n d f" . org-roam-dailies-find-next-note) ("C-c n d b" . org-roam-dailies-find-previous-note) ("C-c n c" . org-roam-capture) ("C-c n !" . pgw/org-roam-refresh)) :map org-mode-map (("C-c n i" . org-roam-insert))) :config (setq org-roam-directory "~/Dropbox/org-roam/" org-roam-db-location "~/Dropbox/org-roam/org-roam.db" org-roam-dailies-directory "daily/" org-roam-db-update-method 'immediate ;; could change later if it gets slow org-roam-tag-sources '(prop vanilla) org-roam-encrypt-files t org-roam-graph-viewer "/Applications/Firefox.app/Contents/MacOS/firefox-bin" org-roam-dailies-capture-templates '(("j" "Journal" entry #'org-roam-capture--get-point "* %?\n:PROPERTIES:\n:LOGGED: %U\n:END:" :file-name "daily/daily-%<%Y-%m-%d>" :head "#+setupfile: ~/.emacs.d/org-mode/templates/school/name_email.org ,#+setupfile: ~/.emacs.d/org-mode/templates/general/web.org ,#+roam_tags: ,#+category: ,#+title: [%<%Y-%m-%d %a>]\n\n") ("s" "Sermon" plain #'org-roam-capture--get-point "* %? :sermon:faith:\n:PROPERTIES:\n:CATEGORY: faith\n:PASSAGE: \n:END:" :file-name "daily/daily-%<%Y-%m-%d>" :head "#+setupfile: ~/.emacs.d/org-mode/templates/school/name_email.org ,#+setupfile: ~/.emacs.d/org-mode/templates/general/web.org ,#+roam_tags: ,#+category: ,#+title: [%<%Y-%m-%d %a>]\n\n") ("c" "Conducting Lesson" plain #'org-roam-capture--get-point "* %? :conducting:" :file-name "daily/daily-%<%Y-%m-%d>" :head "#+setupfile: ~/.emacs.d/org-mode/templates/general/note.org ,#+setupfile: ~/.emacs.d/org-mode/templates/school/name_email.org ,#+setupfile: ~/.emacs.d/org-mode/templates/general/web.org ,#+title: [%<%Y-%m-%d>]\n\n") ("v" "Violin" entry #'org-roam-capture--get-point "* %?\n:PROPERTIES:\n:CATEGORY: %^{Category}\n:END:" :file-name "daily/daily-%" :head "#+title: [%<%Y-%m-%d>]\n\n" :olp ("Violin"))) org-roam-capture-templates '(("d" "Default" plain #'org-roam-capture--get-point "%?" :file-name "%<%Y%m%d%H%M%S>-${slug}" :head "#+setupfile: ~/.emacs.d/org-mode/templates/general/note.org ,#+setupfile: ~/.emacs.d/org-mode/templates/school/name_email.org ,#+setupfile: ~/.emacs.d/org-mode/templates/general/web.org ,#+roam_tags: ,#+title: ${title}\n#+category: \n" :unnarrowed t) ("e" "Entry" entry #'org-roam-capture--get-point "* %?\n%U\n" :file-name "%<%Y%m%d%H%M%S>-${slug}" :head "#+setupfile: ~/.emacs.d/org-mode/templates/general/note.org ,#+setupfile: ~/.emacs.d/org-mode/templates/school/name_email.org ,#+setupfile: ~/.emacs.d/org-mode/templates/general/web.org ,#+roam_tags: ,#+title: ${title}\n#+category: \n" :unnarrowed t))) (org-roam-mode 1) (defun pgw/org-roam-refresh () (interactive) (org-roam-db-build-cache :force) (org-roam-buffer--update-maybe :redisplay))) #+end_src Simpler setup #+begin_src emacs-lisp :tangle no (use-package org-roam :ensure t :hook (after-init . org-roam-mode) :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) ("C-c n d ." . org-roam-dailies-capture-today) ("C-c n d p" . org-roam-dailies-capture-yesterday) ("C-c n d n" . org-roam-dailies-capture-tomorrow) ("C-c n d j" . org-roam-dailies-capture-date) ("C-c n d g" . org-roam-dailies-find-date) ("C-c n d f" . org-roam-dailies-find-next-note) ("C-c n d b" . org-roam-dailies-find-previous-note) ("C-c n c" . org-roam-capture) ("C-c n !" . pgw/org-roam-refresh)) :map org-mode-map (("C-c n i" . org-roam-insert)) (("C-c n I" . org-roam-insert-immediate)))) #+end_src *** Todo keywords #+begin_src emacs-lisp (setq org-todo-keywords '((sequence "NEXT(n)" "TODO(t)" "IN-PROGRESS(i)" "WAITING(w)" "|" "DONE(d)" "CANCELLED(c)" "DELEGATED(g)"))) #+end_src *** Keybinds #+begin_src emacs-lisp (define-key global-map "\C-cc" 'org-capture) (global-set-key (kbd "H-c o") (lambda () (interactive) (find-file (concat org-directory "/school.org")))) (global-set-key (kbd "H-c p") (lambda () (interactive) (dired "~/Google Drive/OHS/11th Grade/Semester 2/"))) (global-set-key (kbd "H-c i") (lambda () (interactive) (find-file (concat org-directory "/projects.org")))) (global-set-key (kbd "H-c v") (lambda () (interactive) (find-file (concat org-directory "/violin.org")))) (global-set-key (kbd "H-c n") (lambda () (interactive) (find-file (concat org-directory "/notes.org")))) (global-set-key (kbd "H-c m") (lambda () (interactive) (find-file (concat org-directory "/music.org")))) (global-set-key (kbd "H-c k") (lambda () (interactive) (find-file (concat org-directory "/links.org")))) ;;; Agenda key (C-c a) and other settings (global-set-key "\C-cl" 'org-store-link) (global-set-key "\C-ca" 'org-agenda) (global-set-key "\C-cc" 'org-capture) (global-set-key "\C-cb" 'org-switchb) (evil-define-key 'normal org-mode-map "<<" 'org-promote-subtree) (evil-define-key 'normal org-mode-map ">>" 'org-demote-subtree) #+end_src *** Tags #+begin_src emacs-lisp (setq org-tag-persistent-alist '(("email" . ?e) ("noexport" . ?N)) org-complete-tags-always-offer-all-agenda-tags nil) #+end_src *** Log when tasks are marked as done: #+begin_src emacs-lisp (setq org-log-done 'time) ; Log when task marked as done #+end_src *** Org Refile: #+begin_src emacs-lisp (setq pgw/refile-targets (file-expand-wildcards "~/Dropbox/org/*.org")) (setq org-refile-targets '((nil :maxlevel . 9) (org-agenda-files :maxlevel . 9) (pgw/refile-targets :maxlevel . 9))) (setq org-refile-use-outline-path 'file) (setq org-outline-path-complete-in-steps nil) (setq org-refile-allow-creating-parent-nodes 'confirm) #+end_src *** Agenda #+begin_src emacs-lisp ;; org-agenda-auto-exclude-function (defun pgw/org-my-auto-exclude-function (tag) (if (string= tag "officehours") (concat "-" tag))) (setq org-agenda-auto-exclude-function 'pgw/org-my-auto-exclude-function) ;(setq org-agenda-overriding-columns-format "%28ITEM %TODO %SCHEDULED %DEADLINE %TAGS") ;; Re-align tags when window shape changes (add-hook 'org-agenda-mode-hook (lambda () (add-hook 'window-configuration-change-hook 'org-agenda-align-tags nil t))) ;(add-hook 'org-agenda-finalize-hook ; 'org-agenda-align-tags) (setq org-deadline-warning-days 7) (add-hook 'org-agenda-finalize-hook (lambda () (display-line-numbers-mode -1) )) ;; Org entries (setq org-agenda-max-entries nil) #+end_src **** DISABLED Hydra for Filtering :ARCHIVE: CLOSED: [2020-11-29 Sun 11:31] A hydra to quickly use different filter presets. Presents: - School-related items - Class - Violin #+begin_src emacs-lisp :tangle no (defhydra pgw/org-agenda-filter-presets () "A hydra to make filter presets for the org-agenda" ("S" (progn (org-agenda-filter-remove-all) (org-agenda-filter-apply '("+OHS") 'tag)) "OHS") ("o" (progn (org-agenda-filter-remove-all) (org-agenda-filter-apply '("-OHS") 'tag)) "Everything but OHS") ("n" (org-agenda-filter-remove-all) "Remove all") ("q" nil "exit" :exit t) ) (define-key org-agenda-mode-map (kbd "H-/") 'pgw/org-agenda-filter-presets/body) #+end_src **** Custom Commands Custom commands, testing sorting strategy variable #+begin_src emacs-lisp (setq org-agenda-custom-commands '(("o" . "OHS") ("oA" "OHS/General Tasks (-roam)" agenda "" ((org-agenda-span 1) (org-agenda-files (append (file-expand-wildcards "~/Dropbox/org/*.org") (file-expand-wildcards "~/Dropbox/org/calendars/*.org"))))) ("of" . "OHS Friend Schedules") ("ofa" "Audrey's Schedule" agenda "" ((org-agenda-span 7) (org-agenda-files (file-expand-wildcards "~/Dropbox/org/notes/OHS/202021/audrey_classes.org")))) ("ofj" "Josie's Schedule" agenda "" ((org-agenda-span 7) (org-agenda-files (file-expand-wildcards "~/Dropbox/org/notes/OHS/202021/josie_classes.org")))) ("ofA" "Ariana Schedule" agenda "" ((org-agenda-span 7) (org-agenda-files (file-expand-wildcards "~/Dropbox/org/notes/OHS/202021/ariana_classes.org")))) ("l" "Logging View" agenda "" ((org-agenda-span 1) (org-agenda-files (file-expand-wildcards "~/Dropbox/org/*.org")))) ("A" "General Agenda" agenda "" ((org-agenda-span 1) (org-agenda-sorting-strategy '((agenda habit-down time-up deadline-up))))) ("D" "College Deadlines" tags-todo "+collegeapps") ("Q" . "Custom queries") ("Qa" "Query all (Archive included)" search "" ((org-agenda-files (append (file-expand-wildcards (concat org-directory "/*.org")) (file-expand-wildcards (concat org-directory "/*.org_archive")))))) ("Ql" "Query Links" search "" ((org-agenda-files (list (concat org-directory "/links.org") (concat org-directory "/links.org_archive"))))))) #+end_src **** Files #+begin_src emacs-lisp (setq org-agenda-files (append (file-expand-wildcards "~/Dropbox/org/*.org") (file-expand-wildcards "~/Dropbox/org/*.org.gpg") (file-expand-wildcards "~/Dropbox/org/calendars/*.org"))) ;; (define-key org-agenda-mode-map (kbd "s-r") 'pgw/org-agenda-reload-files) (defun pgw/org-agenda-reload-files () (interactive) (setq org-agenda-files (append (file-expand-wildcards "~/Dropbox/org/*.org") (file-expand-wildcards "~/Dropbox/org/*.org.gpg") (file-expand-wildcards "~/Dropbox/org/calendars/*.org")))) #+end_src **** Time Grid Variable #+begin_src emacs-lisp (setq org-agenda-time-grid '((daily today require-timed) (600 800 1000 1200 1400 1600 1800 2000 2200) "......" "----------------")) #+end_src *** DISABLED org-super-agenda CLOSED: [2019-10-08 Tue 19:00] Testing out org-super-agenda. Code kept here in case I want to experiemnt in the future. However, for now, I've decided that tags and filtering is the best option for me. #+begin_src emacs-lisp :tangle no (use-package org-super-agenda :config (org-super-agenda-mode) ) (setq org-agenda-custom-commands '(("z" "Super zaen view" ((agenda "" ((org-agenda-span 'day) (org-super-agenda-groups '((:name "Text" :time-grid t :date today :todo "TODO" :scheduled today :deadline today :order 1) (:name "School Stuff" :tag "OHS" :order 2) )))) (alltodo "" ((org-agenda-overriding-header "") (org-super-agenda-groups '((:name "Due Today" :deadline today :order 2) (:name "OHS" :tag "OHS" :order 10) (:name "Due Soon" :deadline future :order 8) (:name "Overdue" :deadline past :order 9) (:name "Issues" :tag "Issue" :order 12) (:name "Emacs" :tag "Emacs" :order 13) (:name "Waiting" :todo "WAITING" :order 20) (:name "trivial" :priority<= "C" :tag "someday" :order 90) (:discard (:habit t) ))))))) ) ) #+end_src *** Quick Capture #+begin_src emacs-lisp (defun pgw/year-month () "Custom function to return date in format: YYYY-MM" (format-time-string "%Y-%m")) (defun pgw/U () "Custom function to return date in org inactive timestamp format" (format-time-string "[%Y-%m-%d %a]")) (defun pgw/add-12 () "Custom function return active org timestamp with exactly 24 hour difference" (format-time-string "%Y-%m-%d %a %H:%M" (time-add (current-time) 85500))) (defun pgw/headline_date () "Function to find the date as headline for Violin capture template" (goto-char (point-min)) (let ((searchresults (search-forward (format-time-string "[%Y-%m-%d %a]") nil t))) (if searchresults 'searchresults (error "Not found! Use Vc to create today's practice first.") ) ) ) (setq org-capture-templates '( ("i" "Inbox") ("ii" "Inbox Entry" entry (file "~/Dropbox/org/inbox.org") "* NEXT %? ") ("il" "Inbox w/ Link" entry (file "~/Dropbox/org/inbox.org") "* NEXT %? %a ") ("in" "Quick Note" entry (file "~/Dropbox/org/inbox.org") "* %? %U") ("e" "Events") ("ef" "Emacs Event (Not synced)" entry (file "~/Dropbox/org/events.org") "* %?") ("ee" "Emacs Calendar" entry (file "~/Dropbox/org/calendars/cal_emacs.org") "* %^{Title of event} SCHEDULED: %^{Scheduled time + duration}T :PROPERTIES: :calendar-id: ihfv2u5n9uf5ksj5484vbe7mj4@group.calendar.google.com :END: :org-gcal:%? :END:" :jump-to-captured nil) ("ep" "Gmail Calendar (Limbo)" entry (file "~/Dropbox/org/events.org") "* %^{Title of event} SCHEDULED: %^{Scheduled time + duration}T :PROPERTIES: :calendar-id: pierce.g.wang@gmail.com :END: :org-gcal:%? :END:" :jump-to-captured t) ("es" "SFCM Calendar (Limbo)" entry (file "~/Dropbox/org/sfcm.org") "* %^{Title of event} SCHEDULED: %^{Scheduled time + duration}T :PROPERTIES: :calendar-id: taiu2dsr8o29c09m7nn1n21t9o@group.calendar.google.com :END: :org-gcal:%? :END:" :jump-to-captured t) ("L" "Link" entry (file+headline "~/Dropbox/org/links.org" "!Inbox") "* [[%?%:link][%:description]] :PROPERTIES: :CREATED: %U :END:" :prepend t) ("g" "Manual" entry (file "~/Dropbox/org/notes.org") "* %? :PROPERTIES: :CREATED: %U :END:" :empty-lines 1) ("b" "Book" entry (file+headline "~/Dropbox/org/notes.org" "Books") "* %^{RATING}p%^{Book Title}") ("j" "Journal" entry (file+olp+datetree "~/Dropbox/org/orgjournal.org.gpg") "* %? :PROPERTIES: :LOGGED: %^{Logged Time}U :END: " :kill-buffer t) ("m" "Mail") ("mt" "Mail task" entry (file "~/Dropbox/org/inbox.org") "* NEXT %? :email: :PROPERTIES: :EMAIL: %a :SENDER: %:from :END:\n") ("mn" "Mail note" entry (file "~/Dropbox/org/inbox.org") "* %? :email: :PROPERTIES: :EMAIL: %a :SENDER: %:from :END:\n") ("S" "School") ("St" "School Tasks") ("Stj" "OCS15 - T/Th" entry (file+headline "~/Dropbox/org/school.org" "_OCS15_") "* NEXT %? DEADLINE: %^{Deadline}T\n") ("Stm" "UM53A - T/Th" entry (file+headline "~/Dropbox/org/school.org" "_UM53A_") "**** NEXT %? DEADLINE: %^{Deadline}T\n") ("Sts" "OPS10 - M/W" entry (file+headline "~/Dropbox/org/school.org" "_OPS10_") "* NEXT %? DEADLINE: %^{Deadline}T\n") ("Stp" "OP053 - M/W" entry (file+headline "~/Dropbox/org/school.org" "_OP053_") "* NEXT %? DEADLINE: %^{Deadline}T\n") ("Stc" "OCRA1 - M/W" entry (file+headline "~/Dropbox/org/school.org" "_OCRA1_") "* NEXT %? DEADLINE: %^{Deadline}T\n") ("Sr" "School Readings") ("Srj" "OCS15 - T/Th" entry (file+headline "~/Dropbox/org/school.org" "_OCS15_") "* NEXT %? DEADLINE: <%<%Y-%m-%d %a 07:15>>\n") ("Srm" "UM53A - T/Th" entry (file+headline "~/Dropbox/org/school.org" "_UM53A_") "**** NEXT %? DEADLINE: <%<%Y-%m-%d %a 08:30>>\n") ("Srs" "OPS10 - M/W" entry (file+headline "~/Dropbox/org/school.org" "_OPS10_") "* NEXT %? DEADLINE: <%<%Y-%m-%d %a 11:00>>\n") ("Srp" "OP053 - M/W" entry (file+headline "~/Dropbox/org/school.org" "_OP053_") "* NEXT %? DEADLINE: <%<%Y-%m-%d %a 14:45>>\n") ("Src" "OCRA1 - M/W" entry (file+headline "~/Dropbox/org/school.org" "_OCRA1_") "* NEXT %? DEADLINE: <%<%Y-%m-%d %a 09:45>>\n") ("M" "Music") ("Mc" "Conducting Homework" entry (file+headline "~/Dropbox/org/music.org" "Homework") "* TODO Conducting Homework DEADLINE: %^t - %?") ("V" "Violin") ("Vc" "Create Practice Entry" entry (file+olp "~/Dropbox/org/violin.org" "Practice Log") "* [%<%Y-%m-%d %a>] %t%?") ("Vd" "Add practice details" item (file+function "~/Dropbox/org/violin.org" pgw/headline_date) "%?") ("f" "Fun") ("fc" "Cookie Clicker Save" entry (file+olp "~/Dropbox/org/notes.org" "Cookie Clicker Run [2020-09-14 Mon]") "* %U %? : %c ") ("q" "Quotes" entry (file+olp "~/Dropbox/org/notes.org" "Quotes") "* %? :PROPERTIES: :DATE: %U :END: %^{FROM}p ") ("s" "Stuff") ("si" "Inbox" entry (file "/Users/piercewang/Dropbox/org/notes/stuff_and_things/organizing_temp.org") "* DECIDE %? %U "))) #+end_src *** MobileOrg #+begin_src emacs-lisp ;; Set to the name of the file where new notes will be stored (setq org-mobile-inbox-for-pull "~/Dropbox/Apps/MobileOrg/index.org") ;; Set to /MobileOrg. (setq org-mobile-directory "~/Dropbox/Apps/MobileOrg") #+end_src *** Crypt #+begin_src emacs-lisp (use-package org-crypt :load-path "elpa/org-9.2.3" :config (org-crypt-use-before-save-magic) (setq org-tags-exclude-from-inheritance (quote ("crypt"))) (setq org-crypt-key "3C44F187958295E4") ;; GPG key to use for encryption ;; Either the Key ID or set to nil to use symmetric encryption. (setq auto-save-default nil) ;; Auto-saving does not cooperate with org-crypt.el: so you need ;; to turn it off if you plan to use org-crypt.el quite often. ;; Otherwise, you'll get an (annoying) message each time you ;; start Org. ;; To turn it off only locally, you can insert this: ;; ;; # -*- buffer-auto-save-file-name: nil; -*- :bind (("C-c s-d e" . org-encrypt-entry) ("C-c s-d d" . org-decrypt-entry)) ) #+end_src *** Babel #+begin_src emacs-lisp (with-eval-after-load 'org (org-babel-do-load-languages 'org-babel-load-languages '((python . t) ))) #+end_src *** Org-drill #+begin_src emacs-lisp ;;; org-drill (use-package org-drill) #+end_src *** Latex #+begin_src emacs-lisp (require 'ox-latex) #+end_src **** CDLatex #+begin_src emacs-lisp (use-package cdlatex :after org :config (define-key org-cdlatex-mode-map (kbd "H-d") 'cdlatex-dollar) (define-key cdlatex-mode-map (kbd "H-d") 'cdlatex-dollar) (add-hook 'org-mode-hook #'org-cdlatex-mode) ) #+end_src **** Fragments #+begin_src emacs-lisp (setq org-format-latex-options ;; '(:foreground "#000000" :background default ;; light theme '(:foreground "#d6d6d4" :background default ;; dark theme :scale 1.4 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0 :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))) #+end_src Fix color handling in org-preview-latex-fragment #+begin_src emacs-lisp (let ((dvipng--plist (alist-get 'dvipng org-preview-latex-process-alist))) (plist-put dvipng--plist :use-xcolor t) (plist-put dvipng--plist :image-converter '("dvipng -D %D -T tight -o %O %f"))) #+end_src #+begin_src emacs-lisp :tangle no (global-set-key (kbd "C-c C-x C-l") 'org-toggle-latex-fragment) #+end_src *** Org Superstar (Bullets revamped) #+begin_src emacs-lisp (use-package org-superstar :config (setq org-superstar-prettify-item-bullets t) :hook (org-mode . org-superstar-mode)) #+end_src *** Export **** Async Init File: #+begin_src emacs-lisp (setq org-export-async-init-file "~/.emacs.d/orgasyncinit.el") #+end_src **** Export Publishing #+begin_src emacs-lisp (require 'ox-publish) (setq org-publish-project-alist '(("pages-notes" :base-directory "~/Dropbox/org_publish/" :base-extension "org" :publishing-directory "~/Documents/Projects/Github/github_pages/" :recursive t :publishing-function org-html-publish-to-html :headline-levels 4 ; Just the default for this project. ;; :html-head "" :auto-preamble t ) ("pages-static" :base-directory "~/Dropbox/org_publish/" :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|jpeg" :publishing-directory "~/Documents/Projects/Github/github_pages/" :recursive t :publishing-function org-publish-attachment ) ("pages" :components ("pages-notes" "pages-static")) )) #+end_src **** HTML #+begin_src emacs-lisp (setq org-html-validation-link nil) #+end_src *** org-noter: PDF Annotation #+begin_src emacs-lisp (use-package org-noter :after org :ensure t :config (setq org-noter-default-notes-file-names '("notes.org") org-noter-notes-search-path '("~/Dropbox/org/notes")) ) #+end_src *** TODO Diary Use =(org-agenda-to-appt)= to add events to reminders. *** org-gcal: Calendar Integration Calendar Setup: #+begin_src emacs-lisp :tangle yes (use-package org-gcal :ensure t :demand t :bind (("C-c s-g p" . org-gcal-post-at-point) ("C-c s-g s" . org-gcal-sync) ("C-c s-g f" . org-gcal-fetch) ("C-c s-g d" . org-gcal-delete-at-point) ("C-c s-g b s" . org-gcal-sync-buffer) ("C-c s-g b f" . org-gcal-sync-buffer)) :config (setq org-gcal-client-id pgw/org-gcal-client-id org-gcal-client-secret pgw/org-gcal-client-secret org-gcal-file-alist pgw/org-gcal-file-alist) (setq org-gcal-notify-p nil) (setq org-gcal-remove-api-cancelled-events t)) #+end_src *** org-reveal #+begin_src emacs-lisp (setq org-reveal-root "file:///Users/piercewang/Documents/projects/revealjs/reveal.js-4.1.0") #+end_src *** ~Darkroom~ for Writing #+begin_src emacs-lisp (use-package darkroom :load-path "site-lisp/darkroom") #+end_src ** LaTeX #+begin_src emacs-lisp (setq TeX-engine 'xetex) (setq latex-run-command "xetex") #+end_src *** AUCTEX #+begin_src emacs-lisp (use-package tex :ensure auctex :defer t :config (setq TeX-auto-save t)) #+end_src *** Classes - Adding Academic XeTeX Times New Roman Class #+begin_src emacs-lisp (unless (with-no-warnings (find "Times" org-latex-classes :key 'car :test 'equal)) (add-to-list 'org-latex-classes '("Times" "\\documentclass[12pt]{article} \\usepackage{fontspec} \\setmainfont{Times New Roman} \\usepackage{hyperref}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))) #+end_src ** Evil #+begin_src emacs-lisp (use-package evil :config (evil-mode t) (dolist (mode '(dired-mode calendar-mode image-mode timer-list-mode messages-buffer-mode bufler-list-mode 2048-mode)) (add-to-list 'evil-emacs-state-modes mode))) #+end_src *** Normal Mode Keybinds #+begin_src emacs-lisp ;; (define-key evil-normal-state-map (kbd "") [?m ?` ?o escape ?` ?`]) ;; (define-key evil-normal-state-map (kbd "") [?m ?` ?O escape ?` ?`]) (define-key evil-motion-state-map (kbd "k") 'evil-previous-visual-line) (define-key evil-motion-state-map (kbd "j") 'evil-next-visual-line) (define-key evil-motion-state-map (kbd "g k") 'evil-previous-line) (define-key evil-motion-state-map (kbd "g j") 'evil-next-line) (define-key evil-insert-state-map (kbd "C-a") 'beginning-of-visual-line) (define-key evil-insert-state-map (kbd "C-e") 'end-of-visual-line) #+end_src ** Programming Environments Hide-show minor mode for collapsing functions #+begin_src emacs-lisp (add-hook 'prog-mode-hook #'hs-minor-mode) (electric-pair-mode) #+end_src *** Python **** python-docstring Smart Python Docstring Formatting #+begin_src emacs-lisp (use-package python-docstring :load-path "site-lisp/python-docstring-mode") #+end_src **** Elpy #+begin_src emacs-lisp (use-package elpy :config (elpy-enable) (add-hook 'elpy-mode-hook 'python-docstring-mode) (setq elpy-rpc-backend "jedi")) #+end_src *** Octave #+begin_src emacs-lisp (setq auto-mode-alist (cons '("\\.m$" . octave-mode) auto-mode-alist)) (add-hook 'octave-mode-hook (lambda () (abbrev-mode 1) (auto-fill-mode 1) (if (eq window-system 'x) (font-lock-mode 1)))) #+end_src *** Java #+begin_src emacs-lisp (use-package projectile) (use-package flycheck) (use-package yasnippet :config (yas-global-mode)) (use-package lsp-mode :hook ((lsp-mode . lsp-enable-which-key-integration)) :config (setq lsp-completion-enable-additional-text-edit nil)) (use-package hydra) (use-package company) (use-package lsp-ui) (use-package lsp-java :config (add-hook 'java-mode-hook 'lsp)) (use-package dap-mode :after lsp-mode :config (dap-auto-configure-mode)) (use-package dap-java :ensure nil) (use-package lsp-ivy) (use-package lsp-treemacs) #+end_src ** Macros #+begin_src emacs-lisp (fset 'setupworkspace [?\C-c ?a ?A ?. ?\C-x ?0 ?\C-x ?3 ?\H-l ?\H-\C-x ?o ?\C-x ?2 ?\C-u ?7 ?\C-x ?^ ?\H-j ?\H-c ?i ?\H-h ?\H-c ?o ?\H-l]) (global-set-key (kbd "C-x C-k 1") 'setupworkspace) ;;(fset 'OHSFigureSave ;; [?# ?+ ?C ?A ?P ?T ?I ?O ?N ?: ? ?\C-x ?Q return return tab ?\[ ?\[ ?f ?i ?l ?e ?: ?. ?/ ?W ?e ?e ?k ? ?\C-x ?Q return ?/ ?\C-x ?Q return ?_ ?\C-u ?\M-! ?d ?a ?t ?e ? ?+ ?% ?H ?% ?M ?% ?S return escape ?e ?a ?. ?p ?n ?g escape ?v ?B ?F ?/ ?l ?y escape ?A ?\] ?\] return escape ?p ?0 ?i ?\M-x ?i ?n ?s ?e ?r ?t ?d ?i ?r ?e ?c ?t ?o ?r ?y return escape ?V ?d ?i ?\C-x ?\C-f ?\C- ?\C-a backspace ?/ ?U ?s ?e ?r ?s ?/ ?p ?i ?e ?r ?c ?e ?w ?a ?n ?g ?/ ?S ?c ?r ?e ?e ?n ?s ?h ?o ?t ?s return ?s ?\M-< ?\C-z ?/ ?S ?c ?r ?e ?e ?n ? ?S ?h ?o ?t return ?R ?\C- ?\C-a backspace ?\s-v backspace return ?\C-x ?k return]) ;;(global-set-key (kbd "") 'OHSFigureSave) ;; (defun pgw/disable-helm () ;; "Disable Helm" ;; (interactive) ;; (helm-mode 0)) ;; (defun pgw/enable-helm () ;; "Enable Helm" ;; (interactive) ;; (helm-mode)) ;; (global-set-key (kbd "H-x H-h d") 'pgw/disable-helm) ;; (global-set-key (kbd "H-x H-h e") 'pgw/enable-helm) ;; ;(fset 'importChine ; [return ?\C-p ?* ?* ? ?I ?t ?e ?m ?\C-c ?\C-c ?d ?r ?i ?l ?l return ?\C-n ?\C-a ?\C-z ?f ?= ?x ?x ?\C-z ?\C-k ?\C-n ?\C-a return return ?\C-p ?* ?* ? ?A ?n ?s ?w ?e ?r ?\C-a ?* ?\C-n ?\C-a ?\C-y ?\; ? ?\C-a ?\C-n ?\C-n]) (fset 'convertQuizlet [?I ?* ?* ?\S- ?I ?t ?e ?m ? ?: ?d ?r ?i ?l ?l ?: return escape ?/ ?= ?= return ?x ?x ?i return return ?* ?* ?* ? ?A ?n ?s ?w ?e ?r return escape ?\M-\}]) (global-set-key (kbd "") 'convertQuizlet) (fset 'addqtest1 [?\C-s ?a ?d ?d ?q ?\( return ?\C-a ?\C- ?\C-\M-f ?\C-\M-f ?\C-f ?\C-\M-$ ?\C-q ?\C-j ?\[ ? ?\] ?* return return ?\C-e ?\C-r ?a ?d ?d ?q ?\( return ?\C-x ?r ? ?a ?\C- ?\M-f ?\C-\M-f ?\C-f ?\C-x ?r ? ?e ?\C-\M-$ ?\[ ?^ ?\\ ?\\ ?\] ?\\ ?\{ ?2 ?\\ ?\} ?' ?, ? return ?\" ?, ? return ?\C-x ?r ?j ?a ?\C- ?\C-x ?r ?j ?e ?\C-\M-$ ?, ? ?\[ ?\' ?\| ?\" ?\] return ?n ?i ?l ?e ?x ?i ?s ?t return ?\C-e ?\C-r ?\( return ?\C-a ?\C-s ?\( return ?\C-0 ?\C-k ?\{ return ?\" ?s ?e ?r ?v ?e ?r ?\" ? ?: ? ?\C-s ?n ?i ?l ?e ?x ?i ?s ?t return ?\C-u ?8 backspace ?, return ?\" ?q ?u ?e ?s ?t ?i ?o ?n ?\" ? ?: ? ?\" ?\C-s ?n ?i ?l ?e ?x ?i ?s ?t return ?\C-u ?8 backspace ?, return ?\" ?a ?n ?s ?w ?e ?r ?\" ? ?: ? ?\" ?\C-s ?n ?i ?l ?e ?x ?i ?s ?t return ?\C-u ?8 backspace ?, return ?\" ?q ?_ ?c ?o ?m ?p ?o ?n ?e ?n ?t ?s ?\" ? ?: ? ?\[ ?\" ?\C-e ?\C-b ?\C-r ?, return ?\] ?\C-f ?\C- ?\C-a ?\C-\M-$ ?n ?i ?l ?e ?x ?i ?s ?t return ?, ? ?\" return ?\C-e ?\C-r ?, ?\C-f return ?\" ?f ?a ?i ?l ?\" ? ?: ?\C-k ? ?T ?r ?u ?e return ?\}]) (global-set-key (kbd "C-x C-k 2") 'addqtest1) (fset 'convert_time_to_clock [?f ?\[ ?f ?\[ ?d ?0 ?I tab ?C ?L ?O ?C ?K ?: ? escape ?j ?d ?0 ?i backspace ?- ?- ?\C-c ?\C-c escape ?0 ?j]) (global-set-key (kbd "C-x C-k 3") 'convert_time_to_clock) (fset 'journal_convert [?\C- ?\M-f ?\M-f ?\M-f ?\M-w ?\M-! ?e ?c ?h ?o ? ?\" ?* ? ?\s-v ?\" ? ?> ?> ? ?j ?o ?u ?r ?n ?a ?l ?. ?o ?r ?g return ?! ?p ?a ?n ?d ?o ?c ? ?- ?f ? ?d ?o ?c ?x ? ?- ?t ? ?o ?r ?g ? ?? ? ?> ?> ? ?j ?o ?u ?r ?n ?a ?l ?. ?o ?r ?g return ?g ?n]) (global-set-key (kbd "C-x C-k 4") 'journal_convert) #+end_src *** Macro Query #+begin_src emacs-lisp (defun my-macro-query (arg) "Prompt for input using minibuffer during kbd macro execution. With prefix argument, allows you to select what prompt string to use. If the input is non-empty, it is inserted at point." (interactive "P") (let* ((query (lambda () (kbd-macro-query t))) (prompt (if arg (read-from-minibuffer "PROMPT: ") "Input: ")) (input (unwind-protect (progn (add-hook 'minibuffer-setup-hook query) (read-from-minibuffer prompt)) (remove-hook 'minibuffer-setup-hook query)))) (unless (string= "" input) (insert input)))) (global-set-key "\C-xQ" 'my-macro-query) #+end_src ** Magit #+begin_src emacs-lisp (use-package magit :config (global-set-key (kbd "C-x g") 'magit-status)) #+end_src ** yasnippet - Yet Another Snippet Extension #+begin_src emacs-lisp (use-package yasnippet :config (yas-global-mode 1) ;; or M-x yas-reload-all if you've started YASnippet already. ) #+end_src ** Backups #+begin_src emacs-lisp (setq backup-directory-alist '(("." . "~/org/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 ) #+end_src ** Daemon #+begin_src emacs-lisp ;;(if 'server-process ;; (server-start)) (load "server") (unless (server-running-p) (server-start)) #+end_src ** Revert Mode For files changed by dropbox and also dired buffers. #+begin_src emacs-lisp (global-auto-revert-mode 1) #+end_src ** Calendar #+begin_src emacs-lisp (setq calendar-latitude 37.759995) (setq calendar-longitude -122.427046) (setq calendar-location-name "San Francisco, CA") (add-hook 'calendar-mode-hook (lambda () (evil-emacs-state) )) #+end_src *** Date Style Set date style to ISO #+begin_src emacs-lisp (calendar-set-date-style 'iso) #+end_src ** Artist Mode Artist mode is amazing! Configure some quick keybinds... #+begin_src emacs-lisp (add-hook 'artist-mode-hook (lambda () (display-line-numbers-mode -1) (evil-emacs-state) (local-set-key (kbd "") 'artist-select-op-poly-line) (local-set-key (kbd "") 'artist-select-op-pen-line) (local-set-key (kbd "") 'artist-select-op-line) (local-set-key (kbd "") 'artist-select-op-square) (local-set-key (kbd "") 'artist-select-op-ellipse)) ) #+end_src Also remember, can use to see the menu of options. ** Image Mode #+begin_src emacs-lisp (add-hook 'image-mode-hook (lambda () (display-line-numbers-mode -1) (evil-emacs-state)) ) #+end_src ** Flyspell mode Activate =flyspell-mode= automatically in all school files. #+begin_src elisp (defun pgw/turn-on-flyspell-hook () (if (or (string-match "^/Users/piercewang/Google Drive/OHS/" (if (eq buffer-file-name nil) "" buffer-file-name)) (string-match "^/Users/piercewang/Dropbox/org/notes/college/" (if (eq buffer-file-name nil) "" buffer-file-name))) (flyspell-mode 1))) (add-hook 'text-mode-hook 'pgw/turn-on-flyspell-hook) #+end_src ** Games *** Tetris I love Emacs Tetris! #+begin_src emacs-lisp (require 'tetris) (define-key tetris-mode-map (kbd "z") 'tetris-rotate-prev) (define-key tetris-mode-map (kbd "x") 'tetris-rotate-next) (define-key tetris-mode-map (kbd "k") 'tetris-move-bottom) (define-key tetris-mode-map (kbd "h") 'tetris-move-left) (define-key tetris-mode-map (kbd "j") 'tetris-move-down) (define-key tetris-mode-map (kbd "l") 'tetris-move-right) #+end_src *** DISABLED Retris CLOSED: [2021-04-10 Sat 22:54] Doesn't work as of Emacs 27.1 :( maybe someday... #+begin_src emacs-lisp :tangle no (use-package retris :load-path "site-lisp/retris") #+end_src *** 2048 #+begin_src emacs-lisp (use-package 2048-game :bind (:map 2048-mode-map ("h" . 2048-left) ("j" . 2048-down) ("k" . 2048-up) ("l" . 2048-right))) #+end_src ** Desktop Save #+begin_src emacs-lisp (desktop-save-mode 1) (setq desktop-restore-frames nil) (setq desktop-restore-eager 5) (setq desktop-dirname "~/.emacs.d/desktopsave/") (setq desktop-path (list "~/.emacs.d/desktopsave/")) (setq desktop-files-not-to-save "\\(^/[^/:]*:\\|(ftp)$\\|\.gpg$\\|\.org_archive\\)") #+end_src ** ERC #+begin_src emacs-lisp (setq erc-log-channels-directory "~/logs/") (setq erc-save-buffer-on-part t) (global-set-key (kbd "H-M-e") (lambda () (interactive) (erc :server "irc.freenode.net" :port 6667 :nick "tesrodome" :password passwords_ERC))) #+end_src ** Keybinds #+begin_src emacs-lisp ;;; replace-regexp (global-set-key (kbd "C-M-$") 'replace-regexp) ;;; Open .emacs.d (global-set-key (kbd "H-C-M-e") (lambda () (interactive) (dired "~/.emacs.d/"))) ;;; Regular find-file (global-set-key (kbd "H-C-x o") (lambda () (interactive) (switch-to-buffer "*Org Agenda*"))) ;;; Close window (global-set-key (kbd "s-0") 'delete-window) #+end_src Insert Org-mode Image #+begin_src emacs-lisp (global-set-key (kbd "") 'insert-org-image) #+end_src *** which-key #+begin_src emacs-lisp (use-package which-key :config (which-key-mode) (setq which-key-popup-type 'side-window) (setq which-key-side-window-location 'bottom) (setq which-key-idle-delay 8.0)) #+end_src *** Scrolling #+begin_src emacs-lisp (global-set-key (kbd "C-v") (lambda () (interactive) (scroll-up-command 1))) (global-set-key (kbd "M-v") (lambda () (interactive) (scroll-down-command 1))) #+end_src ** Hydra for Resizing Windows Functions to change: ~(enlarge-window)~ ~(shrink-window-horizontally)~ ~(enlarge-window-horizontally)~ #+begin_src emacs-lisp (defhydra hydra-windowmanage (global-map "H-c ^") "Hydra for window management." ("=" enlarge-window "+Vertical") ("-" (enlarge-window -1) "-Vertical") ("]" enlarge-window-horizontally "+Horizontal") ("[" shrink-window-horizontally "-Horizontal") ("q" nil "Quit")) (global-set-key (kbd "C-c C-6") 'hydra-windowmanage/body) #+end_src ** User Configuration #+begin_src emacs-lisp (setq user-full-name "Pierce Wang" user-mail-address "pierce.g.wang@gmail.com") #+end_src ** Buffer Mangement *** DISABLED IBuffer CLOSED: [2020-11-24 Tue 00:50] #+begin_src emacs-lisp :tangle no (use-package ibuffer :config (global-set-key (kbd "C-x C-b") 'ibuffer)) (setq ibuffer-saved-filter-groups '(("default" ("emacs-config" (or (filename . "/.emacs.d/") (filename . ".emacs.d/init.el"))) ("OHS" (filename . "/Google Drive/OHS/")) ("Org" (filename . "/Dropbox/org/")) ("planner" (or (name . "\*Calendar\*") (name . "\*Org Agenda\*") (name . "^diary$"))) ;; ("Helm" (name . "\*helm.*")) ("Magit" (mode . Magit)) ("ERC" (mode . erc-mode)) ("Help" (or (name . "\*Help\*") (name . "\*info\*") (name . "\*GNU Emacs\*")))))) (add-hook 'ibuffer-mode-hook (lambda () (ibuffer-switch-to-saved-filter-groups "default"))) (define-key ibuffer-mode-map (kbd "P") nil) #+end_src *** Bufler - Alphapapa #+begin_src emacs-lisp (use-package bufler :bind (("C-x C-b" . bufler)) ;; ("C-x b" . bufler-switch-buffer)) :config (setf bufler-groups (bufler-defgroups (group ;; Subgroup collecting all named workspaces. (auto-workspace)) (group ;; Subgroup collecting all `help-mode' and `info-mode' buffers. (group-or "*Help/Info*" (mode-match "*Help*" (rx bos "help-")) (mode-match "*Info*" (rx bos "info-")))) (group ;; Subgroup collecting all special buffers (i.e. ones that are not ;; file-backed), except `magit-status-mode' buffers (which are allowed to fall ;; through to other groups, so they end up grouped with their project buffers). (group-and "*Special*" (lambda (buffer) (unless (or (funcall (mode-match "Magit" (rx bos "magit-status")) buffer) (funcall (mode-match "Dired" (rx bos "dired")) buffer) (funcall (auto-file) buffer)) "*Special*"))) (group ;; Subgroup collecting these "special special" buffers ;; separately for convenience. (name-match "**Special**" (rx bos "*" (or "Messages" "Warnings" "scratch" "Backtrace") "*"))) (group ;; Subgroup collecting all other Magit buffers, grouped by directory. (mode-match "*Magit* (non-status)" (rx bos (or "magit" "forge") "-")) (auto-directory)) ;; Remaining special buffers are grouped automatically by mode. (auto-mode)) ;; All buffers under "~/.emacs.d" (or wherever it is). (dir user-emacs-directory) (group ;; Subgroup collecting buffers in `org-directory' (or "~/org" if ;; `org-directory' is not yet defined). (dir (if (bound-and-true-p org-directory) org-directory "~/org")) (dir "~/Dropbox/org/notes/") (dir "~/Dropbox/org/notes/college/essays/" 1) (group ;; Subgroup collecting indirect Org buffers, grouping them by file. ;; This is very useful when used with `org-tree-to-indirect-buffer'. (auto-indirect) (auto-file)) ;; Group remaining buffers by whether they're file backed, then by mode. (group-not "*special*" (auto-file)) (auto-mode)) (group ;; Subgroup for OHS things (dir "~/Google Drive/OHS/") (dir "~/Google Drive/OHS/12th Grade/Classes/" 1) (dir "~/Google Drive/OHS/11th Grade/" 2) ;; Group remaining buffers by whether they're file backed, then by mode. (group-not "*special*" (auto-file)) (auto-mode)) (dir "/Volumes/" 1) (group ;; Subgroup collecting buffers in a projectile project. (auto-projectile)) (group ;; Subgroup collecting buffers in a version-control project, ;; grouping them by directory. (auto-project)) ;; Group remaining buffers by directory, then major mode. (auto-directory) (auto-mode)))) #+end_src ** Dired #+begin_src emacs-lisp (setq delete-by-moving-to-trash t) (setq trash-directory "~/.Trash") (setq insert-directory-program "/usr/local/bin/gls" dired-use-ls-dired t) #+end_src Make moving files easier between two split buffers. #+begin_src emacs-lisp (setq dired-dwim-target t) #+end_src Remove print option to not accidentally print #+begin_src emacs-lisp (define-key dired-mode-map (kbd "P") nil) #+end_src Custom dired open file function #+begin_src emacs-lisp (define-key dired-mode-map (kbd "O") 'pgw/dired-open-file) #+end_src Symlinking #+begin_src emacs-lisp (define-key dired-mode-map (kbd "Y") 'dired-do-symlink) #+end_src Move *** dired-quick-sort.el #+begin_src emacs-lisp (use-package dired-quick-sort :load-path "custom_load" :config (dired-quick-sort-setup) ) #+end_src *** Human readable format for ls switches (=-h=) #+begin_src emacs-lisp (setq dired-listing-switches "-alh") (setq dired-actual-switches "-alh") #+end_src ** Disabled Functions Gotta sort this out later... #+begin_src emacs-lisp (put 'upcase-region 'disabled nil) (put 'downcase-region 'disabled nil) (put 'scroll-left 'disabled nil) (put 'dired-find-alternate-file 'disabled nil) (put 'narrow-to-page 'disabled nil) (put 'narrow-to-region 'disabled nil) (put 'list-timers 'disabled nil) #+end_src ** browse-url-firefox-program Allow the function =browse-url-firefox= to open links in firefox using bin. One could probably also accomplish this using =brew='s version of firefox, but I didn't want to install firefox again. #+begin_src emacs-lisp (setq browse-url-firefox-program "/Applications/Firefox.app/Contents/MacOS/firefox-bin") #+end_src ** DISABLED mu4e CLOSED: [2021-04-25 Sun 23:53] I love email in Emacs <3 #+begin_src emacs-lisp :tangle no ; add the source shipped with mu to load-path (add-to-list 'load-path (expand-file-name "/usr/local/Cellar/mu/1.4.13/share/emacs/site-lisp/mu/mu4e/")) ; require mu4e (require 'mu4e) (setq mu4e-maildir (expand-file-name "~/Maildir")) ; get mail (setq mu4e-get-mail-command "mbsync -c ~/.emacs.d/mu4e/.mbsyncrc -a" ;; mu4e-html2text-command "w3m -T text/html" ;;using the default mu4e-shr2text mu4e-view-prefer-html t mu4e-update-interval 300 mu4e-headers-auto-update t mu4e-compose-signature-auto-include nil mu4e-compose-format-flowed t); tell mu4e to use w3m for html rendering ;; Speed up indexing (setq mu4e-index-cleanup nil ;; don't do a full cleanup check mu4e-index-lazy-check t) ;; don't consider up-to-date dirs ;; don't save message to Sent Messages, Gmail/IMAP takes care of this (setq mu4e-sent-messages-behavior 'delete) ;; enable inline images (setq mu4e-view-show-images t) ;; from info manual (add-to-list 'mu4e-view-actions '("ViewInBrowser" . mu4e-action-view-in-browser) t) ;; to navigate to links, to open them in browser (add-hook 'mu4e-view-mode-hook (lambda() ;; try to emulate some of the eww key-bindings (local-set-key (kbd "") 'mu4e~view-browse-url-from-binding) (local-set-key (kbd "") 'shr-next-link) (local-set-key (kbd "") 'shr-previous-link))) ;; from https://www.reddit.com/r/emacs/comments/bfsck6/mu4e_for_dummies/elgoumx (add-hook 'mu4e-headers-mode-hook (defun my/mu4e-change-headers () (interactive) (setq mu4e-headers-fields `((:human-date . 25) ;; alternatively, use :date (:flags . 6) (:from . 22) (:thread-subject . ,(- (window-body-width) 70)) ;; alternatively, use :subject (:size . 7))))) ;; if you use date instead of human-date in the above, use this setting ;; give me ISO(ish) format date-time stamps in the header list ;(setq mu4e-headers-date-format "%Y-%m-%d %H:%M") ;; spell check (add-hook 'mu4e-compose-mode-hook (defun pgw/do-compose-stuff () "My settings for message composition." (visual-line-mode) (org-mu4e-compose-org-mode) (use-hard-newlines -1) (flyspell-mode))) (add-hook 'mu4e-view-mode-hook #'visual-line-mode) ;; every new email composition gets its own frame! (setq mu4e-compose-in-new-frame nil) (require 'smtpmail) ;;rename files when moving ;;NEEDED FOR MBSYNC (setq mu4e-change-filenames-when-moving t) ;;set up queue for offline email ;;use mu mkdir ~/Maildir/acc/queue to set up first (setq smtpmail-queue-mail nil) ;; start in normal mode ;;from the info manual (setq mu4e-attachment-dir "~/Documents") (setq message-kill-buffer-on-exit t) (setq mu4e-compose-dont-reply-to-self t) (require 'org-mu4e) ;; convert org mode to HTML automatically (setq org-mu4e-convert-to-html t) ;;from vxlabs config ;; show full addresses in view message (instead of just names) ;; toggle per name with M-RET (setq mu4e-view-show-addresses 't) ;; don't ask when quitting (setq mu4e-confirm-quit nil) ;; mu4e-context (setq mu4e-context-policy 'pick-first) (setq mu4e-compose-context-policy 'always-ask) (setq mu4e-contexts (list (make-mu4e-context :name "personal" ;;for pierce.g.wang :enter-func (lambda () (mu4e-message "Entering context personal")) :leave-func (lambda () (mu4e-message "Leaving context personal")) :match-func (lambda (msg) (when msg (mu4e-message-contact-field-matches msg '(:from :to :cc :bcc) "pierce.g.wang@gmail.com"))) :vars '((user-mail-address . "pierce.g.wang@gmail.com") (user-full-name . "Pierce Wang") (mu4e-sent-folder . "/pierce.g.wang/[pierce.g.wang].Sent Mail") (mu4e-drafts-folder . "/pierce.g.wang/[pierce.g.wang].drafts") (mu4e-trash-folder . "/pierce.g.wang/[pierce.g.wang].Trash") (mu4e-refile-folder . "/pierce.g.wang/[pierce.g.wang].All Mail") (mu4e-compose-signature . (concat "Formal Signature\n" "Emacs 27, org-mode 9, mu4e 1.14\n")) (mu4e-compose-format-flowed . t) (smtpmail-queue-dir . "~/Maildir/pierce.g.wang/queue/cur") (message-send-mail-function . smtpmail-send-it) (smtpmail-smtp-user . "pierce.g.wang") (smtpmail-starttls-credentials . (("smtp.gmail.com" 587 nil nil))) (smtpmail-auth-credentials . (expand-file-name "~/.authinfo.gpg")) (smtpmail-default-smtp-server . "smtp.gmail.com") (smtpmail-smtp-server . "smtp.gmail.com") (smtpmail-smtp-service . 587) (smtpmail-debug-info . t) (smtpmail-debug-verbose . t) (mu4e-maildir-shortcuts . ( ("/pierce.g.wang/INBOX" . ?i) ("/pierce.g.wang/[pierce.g.wang].Sent Mail" . ?s) ("/pierce.g.wang/[pierce.g.wang].Trash" . ?t) ("/pierce.g.wang/[pierce.g.wang].All Mail" . ?a) ("/pierce.g.wang/[pierce.g.wang].Starred" . ?r) ("/pierce.g.wang/[pierce.g.wang].drafts" . ?d) )))) (make-mu4e-context :name "OHS" ;;for pgwang@ohs.stanford.edu :enter-func (lambda () (mu4e-message "Entering context, OHS")) :leave-func (lambda () (mu4e-message "Leaving context, OHS")) :match-func (lambda (msg) (when msg (mu4e-message-contact-field-matches msg '(:from :to :cc :bcc) "pgwang@ohs.stanford.edu"))) :vars '((user-mail-address . "pgwang@ohs.stanford.edu") (user-full-name . "Pierce Wang") (mu4e-sent-folder . "/pierce.g.wang/[pierce.g.wang].Sent Mail") (mu4e-drafts-folder . "/pierce.g.wang/[pierce.g.wang].drafts") (mu4e-trash-folder . "/pierce.g.wang/[pierce.g.wang].Trash") (mu4e-refile-folder . "/pierce.g.wang/[pierce.g.wang].All Mail") (mu4e-compose-signature . (concat "Formal Signature\n" "Emacs 27, org-mode 9, mu4e 1.14\n")) (mu4e-compose-format-flowed . t) (smtpmail-queue-dir . "~/Maildir/pierce.g.wang/queue/cur") (message-send-mail-function . smtpmail-send-it) (smtpmail-smtp-user . "pierce.g.wang") (smtpmail-starttls-credentials . (("smtp.gmail.com" 587 nil nil))) (smtpmail-auth-credentials . (expand-file-name "~/.authinfo.gpg")) (smtpmail-default-smtp-server . "smtp.gmail.com") (smtpmail-smtp-server . "smtp.gmail.com") (smtpmail-smtp-service . 587) (smtpmail-debug-info . t) (smtpmail-debug-verbose . t) (mu4e-maildir-shortcuts . ( ("/pierce.g.wang/INBOX" . ?i) ("/pierce.g.wang/[pierce.g.wang].Sent Mail" . ?s) ("/pierce.g.wang/[pierce.g.wang].Trash" . ?t) ("/pierce.g.wang/[pierce.g.wang].All Mail" . ?a) ("/pierce.g.wang/[pierce.g.wang].Starred" . ?r) ("/pierce.g.wang/[pierce.g.wang].drafts" . ?d) )))) (make-mu4e-context :name "work" ;;for pierce.wang.violin :enter-func (lambda () (mu4e-message "Entering context work")) :leave-func (lambda () (mu4e-message "Leaving context work")) :match-func (lambda (msg) (when msg (mu4e-message-contact-field-matches msg '(:from :to :cc :bcc) "pierce.wang.violin@gmail.com"))) :vars '((user-mail-address . "pierce.wang.violin@gmail.com") (user-full-name . "Pierce Wang") (mu4e-sent-folder . "/pierce.wang.violin/[pierce.wang.violin].Sent Mail") (mu4e-drafts-folder . "/pierce.wang.violin/[pierce.wang.violin].drafts") (mu4e-trash-folder . "/pierce.wang.violin/[pierce.wang.violin].Trash") (mu4e-refile-folder . "/pierce.wang.violin/[pierce.wang.violin].All Mail") (mu4e-compose-signature . (concat "Formal Signature\n" "Emacs 27, org-mode 9, mu4e 1.14\n")) (mu4e-compose-format-flowed . t) (smtpmail-queue-dir . "~/Maildir/pierce.wang.violin/queue/cur") (message-send-mail-function . smtpmail-send-it) (smtpmail-smtp-user . "pierce.wang.violin") (smtpmail-starttls-credentials . (("smtp.gmail.com" 587 nil nil))) (smtpmail-auth-credentials . (expand-file-name "~/.authinfo.gpg")) (smtpmail-default-smtp-server . "smtp.gmail.com") (smtpmail-smtp-server . "smtp.gmail.com") (smtpmail-smtp-service . 587) (smtpmail-debug-info . t) (smtpmail-debug-verbose . t) (mu4e-maildir-shortcuts . ( ("/pierce.wang.violin/INBOX" . ?i) ("/pierce.wang.violin/[pierce.wang.violin].Sent Mail" . ?s) ("/pierce.wang.violin/[pierce.wang.violin].Trash" . ?t) ("/pierce.wang.violin/[pierce.wang.violin].All Mail" . ?a) ("/pierce.wang.violin/[pierce.wang.violin].Starred" . ?r) ("/pierce.wang.violin/[pierce.wang.violin].drafts" . ?d) )))) )) #+end_src *** mu4e-alert #+begin_src emacs-lisp :tangle no (use-package mu4e-alert :ensure t :after mu4e :init (setq mu4e-alert-interesting-mail-query (concat "flag:unread maildir:/pierce.wang.violin/INBOX " "OR " "flag:unread maildir:/pierce.g.wang/INBOX" )) (mu4e-alert-set-default-style 'notifier) (add-hook 'after-init-hook #'mu4e-alert-enable-notifications) (add-hook 'after-init-hook #'mu4e-alert-enable-mode-line-display) (defun pgw/fetch-mail-and-mu4e () (interactive) (if (internet-up-p) (mu4e-update-mail-and-index t)) ) ;; (run-with-timer 60 300 'pgw/fetch-mail-and-mu4e) ) #+end_src *** mu4e keybinds :keybinds: Unset default compose message and set personal keybinds. #+begin_src emacs-lisp :tangle no (global-unset-key (kbd "C-x m")) (global-set-key (kbd "C-x m n") (lambda () "Open mu4e in a new frame" (interactive) (make-frame '((name . "Mail: mu4e"))) (mu4e))) (global-set-key (kbd "C-x m b") (lambda () "Open mu4e in the background" (interactive) (mu4e t))) (global-set-key (kbd "C-x m m") 'mu4e) (global-set-key (kbd "C-x m c") 'mu4e-compose-new) #+end_src ** OHS *** DISABLED Schoolyear Calculation for sexp Diary Entries :ARCHIVE: CLOSED: [2020-11-29 Sun 11:41] Attempt two: macro to make and statements #+begin_src emacs-lisp :tangle no (defun pgw/ohs-schoolyear-class-sched (date event days time) (let ((dayname (calendar-day-of-week date))) (when (and (if (equal days 1) (or (memq dayname '(1 3)) (diary-date 2021 1 22)) ;; Monday on Friday (MLK Makeup) (memq dayname '(2 4))) (diary-block 2020 8 19 2021 5 13)) ;; Class Period (when (not (or (diary-date 2020 9 7) ;; Labor Day (diary-date 2020 9 11) ;; Back to School Night (diary-block 2020 10 28 2020 10 30) ;; Parent-Teacher Conferences (no classes) (diary-block 2020 11 25 2020 11 27) ;; Thanksgiving Holiday (diary-block 2020 12 9 2020 12 11) ;; Study Days (no classes) (diary-block 2020 12 14 2020 12 19) ;; Fall Semester Finals (diary-block 2020 12 19 2021 1 3) ;; Winter Closure (diary-block 2021 1 4 2021 1 8) ;; Reading Week (diary-date 2021 1 18) ;; MLK Holiday (diary-date 2021 2 15) ;; Presidents Day (diary-date 2021 2 16) ;; Reading Day (No classes) (diary-block 2021 3 22 2021 3 26) ;; Spring Break (diary-block 2021 5 17 2021 5 19) ;; Study Days (diary-block 2021 5 20 2021 5 21) ;; Spring Semester Finals (diary-block 2021 5 24 2021 5 27) ;; Spring Semester Finals (diary-date 2021 5 31))) ;; Memorial Day Holiday (format "%s %s" time event))))) #+end_src *** Generate OHS Class Calendar This is super messy, any tips on making this kind of code cleaner? The identified problem was that in general, for class schedules, I've used a repeating event. However, repeating events (in =org-mode= or otherwise) are not holiday-aware. So, the point of this code is to generate a list of scheduled org headlines for all of my classes which is 100% accurate and does not put classes on holidays or no-class study week days. #+begin_src emacs-lisp :results silent (defun pgw/date-block (absolute y1 m1 d1 y2 m2 d2) "Block date entry. An adapted version of the `diary-block' function from the diary-lib." (let ((date1 (calendar-absolute-from-gregorian (diary-make-date y1 m1 d1))) (date2 (calendar-absolute-from-gregorian (diary-make-date y2 m2 d2))) (d absolute)) (and (<= date1 d) (<= d date2)))) (defun pgw/date-date (absolute year month day) "Check for equality of date" (equal absolute (calendar-absolute-from-gregorian (diary-make-date year month day)))) (defun pgw/check-ohs-class (absolute classname semesters days times fallstart fallend springstart mononfri springend holidays noclasses) "Returns a list with formatted strings: (classname curdate headline). These can then be used to create the headline. The curdate is in the form of a list" (let* ((dayname (calendar-day-of-week (calendar-gregorian-from-absolute absolute))) (curdate (calendar-gregorian-from-absolute absolute)) (periods '("06:00-07:15" "07:15-08:30" "08:30-09:45" "09:45-11:00" "11:00-12:15" "12:15-13:30" "13:30-14:45" "14:45-16:00" "16:00-17:15" "17:15-18:30" "18:30-19:45" "19:45-21:00" "21:00-22:15")) (time (if (equal (type-of times) 'integer) ;; Checks if the times argument is an integer or list of times as strings (nth (1- times) periods) (nth (- (length days) (length (memq dayname days))) times)))) (when (and (cond ((equal days '(1 3)) (or (memq dayname '(1 3)) (pgw/date-date absolute (nth 0 mononfri) (nth 1 mononfri) (nth 2 mononfri)))) ;; Account for MLK Monday on Friday (t (memq dayname days))) (or (if (memq 1 semesters) (pgw/date-block absolute (nth 0 fallstart) (nth 1 fallstart) (nth 2 fallstart) (nth 0 fallend) (nth 1 fallend) (nth 2 fallend))) (if (memq 2 semesters) (pgw/date-block absolute (nth 0 springstart) (nth 1 springstart) (nth 2 springstart) (nth 0 springend) (nth 1 springend) (nth 2 springend))))) (if (equal (type-of times) 'integer) ;; Classes will always be in periods, OH and other events will not (when (and (not (memq 't (mapcar (lambda (holiday) (if (> (length holiday) 3) (pgw/date-block absolute (nth 0 holiday) (nth 1 holiday) (nth 2 holiday) (nth 3 holiday) (nth 4 holiday) (nth 5 holiday)) (pgw/date-date absolute (nth 0 holiday) (nth 1 holiday) (nth 2 holiday)))) holidays))) (not (memq 't (mapcar (lambda (noclass) (if (> (length noclass) 3) (pgw/date-block absolute (nth 0 noclass) (nth 1 noclass) (nth 2 noclass) (nth 3 noclass) (nth 4 noclass) (nth 5 noclass)) (pgw/date-date absolute (nth 0 noclass) (nth 1 noclass) (nth 2 noclass)))) noclasses)))) (list classname curdate time)) (when (not (memq 't (mapcar (lambda (holiday) (if (> (length holiday) 3) (pgw/date-block absolute (nth 0 holiday) (nth 1 holiday) (nth 2 holiday) (nth 3 holiday) (nth 4 holiday) (nth 5 holiday)) (pgw/date-date absolute (nth 0 holiday) (nth 1 holiday) (nth 2 holiday)))) holidays))) (list classname curdate time)))))) (defun pgw/create-entry (classname semesters days times &optional desc) "Creates headlines for class schedule. CLASSNAME: a string with the class name (to appear on agenda) SEMESTERS: a list of integers. e.g. for both just a first semester: '(1) or for both semesters '(1 2) DAYS: the days of the class. Normally it will be M/W or T/Th but in order to have flexibility, the function takes an input of another list of integers representing days of the week. Monday starts on 1 and Sunday is 0 TIMES: Either an integer with the period number or a cons list containing a list of the times which should be the same length as the list of days optional DESC: string containing a description for the event This function uses the variable `pgw/ohs-schoolyear-dates' for the value of holidays" (let ((current (calendar-absolute-from-gregorian (diary-make-date 2020 8 19))) (desc (if desc (setq desc (format "\n%s\n" desc)) (setq desc ""))) (fallstart (gethash "fallstart" pgw/ohs-schoolyear-dates)) (fallend (gethash "fallend" pgw/ohs-schoolyear-dates)) (springstart (gethash "springstart" pgw/ohs-schoolyear-dates)) (mononfri (gethash "mononfri" pgw/ohs-schoolyear-dates)) (springend (gethash "springend" pgw/ohs-schoolyear-dates)) (holidays (gethash "holidays" pgw/ohs-schoolyear-dates)) (noclasses (gethash "noclasses" pgw/ohs-schoolyear-dates))) (goto-char (point-max)) (insert (format "\n* %s" classname)) (while (pgw/date-block current (nth 0 fallstart) (nth 1 fallstart) (nth 2 fallstart) (nth 0 springend) (nth 1 springend) (nth 2 springend)) ; Make sure we're within starting and ending dates of school (let ((info (pgw/check-ohs-class current classname semesters days times fallstart fallend springstart mononfri springend holidays noclasses))) (when info (let* ((headline (nth 0 info)) (days-of-week '("Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat")) (fulldate (nth 1 info)) (year (nth 2 fulldate)) (month (nth 0 fulldate)) (day (nth 1 fulldate)) (dayofweek (nth (calendar-day-of-week fulldate) days-of-week)) (time (nth 2 info))) (goto-char (point-max)) ;; (insert (format "\n** %s\n:PROPERTIES:\n:TIMEZONE: UTC\n:END:\n<%d-%02d-%02d %s %s>\n%s" ;; headline year month day dayofweek time desc))))) (insert (format "\n** %s\n<%d-%02d-%02d %s %s>\n%s" headline year month day dayofweek time desc))))) (setq current (+ current 1))))) (setq pgw/ohs-schoolyear-dates #s(hash-table size 7 test equal data ("fallstart" (2020 8 19) "fallend" (2020 12 19) "springstart" (2021 1 4) "mononfri" (2021 1 19) "springend" (2021 5 13) "holidays" ((2020 9 7 2020 9 8) ;; Labor Day (2020 11 25 2020 11 27) ;; Thanksgiving Holiday (2020 12 19 2021 1 3) ;; Winter Closure (2021 1 18 2021 1 19) ;; MLK Holiday (2021 2 15) ;; Presidents Day (2021 2 16) ;; Reading Day (No classes) (2021 3 22 2021 3 26) ;; Spring Break (2021 5 31 2021 6 1)) ;; Memorial Day Holiday "noclasses" ((2020 10 28 2020 10 30) ;; Parent-Teacher Conferences (no classes) (2020 12 9 2020 12 11) ;; Study Days (no classes) (2020 12 14 2020 12 19) ;; Fall Semester Finals (2021 1 4 2021 1 8) ;; Reading Week (2021 5 17 2021 5 19) ;; Study Days (2021 5 20 2021 5 21) ;; Spring Semester Finals (2021 5 24 2021 5 27) ;; Spring Semester Finals )))) #+end_src Example usage (run in a dedicated file) #+begin_src emacs-lisp :tangle no (pgw/create-entry "UM51A: Linear Algebra" '(1 2) '(1 3) 3 "Adobe connect class link") #+end_src *** Sync gcal Bash Script This runs a bash script which in turn 1. curls the calendar file from the Canvas website 2. runs a python program which parses the calendar file into =ohs_gcal.org= according to the class. In doing so, it takes into account whether the timestamp should be a deadline or not. See [[https://github.com/piercegwang/ohsics_to_org][https://github.com/piercegwang/ohsics_to_org]] for more info. #+begin_src emacs-lisp :results silent (defun pgw/sync-ohs-cal () (interactive) (start-process-shell-command "Running ~/QScripts/syncgcal.sh" nil "bash ~/QScripts/syncgcal.sh")) (global-set-key (kbd "C-c s-g o") 'pgw/sync-ohs-cal) #+end_src