Skip to content
Permalink
8691ac41f0
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time

+TITLE: Emacs Configuration

See .init.el

.init.el set up the magic that is use-package and org-babel-load-file to allow for confirguration to be literate.

Configure use-package

Use use-package to install and configure packages. My init.el includes the initial setup for package.el and ensures that use-package is installed.

This makes sure that use-package will install the package if it’s not already available.

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

I use this on windows as well and things are just flakier over there so there I am going to turn off package signature check

(if (string-equal system-type "windows-nt")
    (setq package-check-signature nil))

Always compile packages, and use the newest version available.

(use-package auto-compile
  :config (auto-compile-on-load-mode))

(setq load-prefer-newer t)

Personal Details Setup

Sets up some personal information sucha as email

(setq user-full-name "Donald Brady" user-mail-address "donald.brady@gmail.com")

Set up savefile, backup, and autosave directories

(defconst dbrady-savefile-dir (expand-file-name "savefile" user-emacs-directory))

;; create the savefile dir if it doesn't exist
(unless (file-exists-p dbrady-savefile-dir) (make-directory dbrady-savefile-dir))

;; store all backup and autosave files in the tmp dir
(setq backup-directory-alist `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))

;; saveplace remembers your location in a file when saving files
(use-package saveplace
  :config
  (setq save-place-file (expand-file-name "saveplace" dbrady-savefile-dir))
  ;; activate it for all buffers
  (setq-default save-place t))

(use-package savehist
  :config
  (setq savehist-additional-variables
        ;; search entries
        '(search-ring regexp-search-ring)
        ;; save every minute
        savehist-autosave-interval 60
        ;; keep the home clean
        savehist-file (expand-file-name "savehist" dbrady-savefile-dir))
  (savehist-mode +1))

Basic Configurations

Place for a grab bag of basic settings

(setq inhibit-startup-screen t)
(when (fboundp 'tool-bar-mode) (tool-bar-mode -1))
(setq ring-bell-function 'ignore)
(line-number-mode t)
(column-number-mode t)
(size-indication-mode t)
(fset 'yes-or-no-p 'y-or-n-p)
(setq require-final-newline t)
(setq-default fill-column 80)
(add-hook 'text-mode-hook 'auto-fill-mode)
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq-default indent-tabs-mode nil)   
(setq-default tab-width 4)            
;; smart tab behavior - indent or complete
(setq tab-always-indent 'complete)
(global-display-line-numbers-mode 0) ; line number in margin
(global-hl-line-mode 0) ; highlight current line
(global-auto-revert-mode 1)
;; scroll to the bottom of repls on output
(add-hook 'comint-output-filter-functions 'comint-postoutput-scroll-to-bottom)

(defvar default-gc-cons-threshold most-positive-fixnum
  "for startup make hella big during startup.")

;; make garbage collector less invasive
(setq gc-cons-threshold default-gc-cons-threshold gc-cons-percentage 0.6)

;; ediff in same window
(setq ediff-window-setup-function 'ediff-setup-windows-plain)

Custom Packages

Packages here don’t have any major configuration and are loaded vanilla.

(defvar my-packages '(
                      eglot
                      elec-pair
                      flycheck            
                      git-timemachine
                      gnuplot 
                      s                   ; some nice easy string manipulation functions
                      ))

Loop over the above list, loading using use-package

(dolist (p my-packages)
  (unless (package-installed-p p)
    (package-refresh-contents)
    (package-install p))
  (add-to-list 'package-selected-packages p))

Additional Path Setup

There are some nuances with environment variables especially on windows.

(use-package exec-path-from-shell
  :config
  (when (memq window-system '(mac ns x))
    (exec-path-from-shell-initialize)))

Handling url’s under WSL2

Cudos to this article

(when (and (eq system-type 'gnu/linux)
           (string-match
            "Linux.*Microsoft.*Linux"
            (shell-command-to-string "uname -a")))
  (setq
   browse-url-generic-program  "/mnt/c/Windows/System32/cmd.exe"
   browse-url-generic-args     '("/c" "start")
   browse-url-browser-function #'browse-url-generic))

Recent File Saving

(use-package recentf
  :config
  (setq recentf-save-file (expand-file-name "recentf" dbrady-savefile-dir))
  (setq recentf-max-saved-items 50)
  (setq recentf-max-menu-items 15)
  (setq recentf-auto-cleanup 'never)
  (recentf-mode +1))

Paren Matching

Configuration for a bunch of built in packages.

(use-package paren
  :config
  (show-paren-mode +1))

Avy

Avy has one really useful function avy-goto-line which supports multiple buffers

(use-package avy
  :bind (("M-g f" . avy-goto-line)))

Dired Mode

Dired mode is built in and powerful but easy to forget the commands and capabilities. Make things a bit easier to remember for me

;; dired-x comes with emacs but isn't loaded by default.
(require 'dired-x)

(setq-default dired-omit-files-p t) ; Buffer-local variable
(setq dired-omit-files (concat dired-omit-files "\\|^\\..+$"))
(setq dired-dwim-target t) ;; guess destination
(setq dired-recursive-copies 'always)
(setq dired-recursive-deletes 'always)

(define-key dired-mode-map (kbd "% f") 'find-name-dired)
(define-key dired-mode-map (kbd "% .") 'dired-omit-mode)


;; Changes to prevent navigating in dired mode from creating a bunch of buffers for every directory
(put 'dired-find-alternate-file 'disabled nil)
(add-hook 'dired-mode-hook
          (lambda ()
            (define-key dired-mode-map (kbd "^")
              (lambda () (interactive) (find-alternate-file "..")))
            (define-key dired-mode-map (kbd "e")
              (lambda () (interactive) (find-alternate-file (dired-copy-filename-as-kill))))
            (define-key dired-mode-map (kbd "f")
              (lambda () (interactive) (find-alternate-file (dired-copy-filename-as-kill))))))

Text Scaling

default-text-scale allows you to quickly resize text. By default binds to C-M-= and C-M– to increase and decrease the face size

(use-package default-text-scale
  :config
  (default-text-scale-mode))

Ivy

Ivy is a completion framework

(use-package ivy
  :config
  (setq ivy-use-virtual-buffers t)
  (setq ivy-use-selectable-prompt t)
  (setq enable-recursive-minibuffers t)
  (ivy-mode 1))

Swiper

A generic completion front end

(use-package swiper
  :bind (("C-s" . swiper)))

Spray Speed Reader

Speed reading mode. Just enter the mode and use keys h/left arrow, l/right arrow, f and s for faster and slower, q quits

(require 'spray)
(setq spray-wpm 200)

PDF Tools

PDF Tools is a much better pdf viewer

(use-package pdf-tools
  :config
  (pdf-loader-install))

(Yas) Snippets

Use yas-snippets for handy text completion

(use-package yasnippet
  :ensure yasnippet-snippets
  :config
  (yas-global-mode 1))

Org Mode

Set up for all things org-mode

Org and Extensions

Load org and other related packages.

(use-package org :ensure org-plus-contrib)
(use-package org-superstar)
(use-package org-edna)
(use-package org-super-agenda)
(use-package org-ql)
(use-package counsel)
(require 'org-habit)

Some basic configuration for Org Mode beginning with minor modes for spell checking and replacing the *’s with various types of bullets.

(add-hook 'org-mode-hook (lambda () (org-superstar-mode 1)))
(define-key org-mode-map (kbd "C-c l") 'org-store-link)
(define-key org-mode-map (kbd "C-x n s") 'org-toggle-narrow-to-subtree)
(define-key org-mode-map (kbd "C-c C-j") 'counsel-org-goto)

(setq org-image-actual-width nil)
(setq org-modules (append '(org-protocol) org-modules))
(setq org-modules (append '(habit) org-modules))
(setq org-catch-invisible-edits 'smart)
(setq org-ctrl-k-protect-subtree t)
(set-face-attribute 'org-headline-done nil :strike-through t)
(setq org-return-follows-link t)

Org File Locations

My setup now includes two org-directories under an umberlla OrgDocuments directory. They are personal and dcllp (work). The default opening setup is to default to personal.

(setq org-directory-personal "~/OrgDocuments/personal")
(setq org-directory-work "~/OrgDocuments/dcllp")
(setq org-directory org-directory-personal)
(setq org-agenda-files (directory-files-recursively org-directory "org$"))
(setq org-default-notes-file (concat org-directory "/index.org"))

Org Roam

Likewise org-roam defaults to personal.

(setq org-roam-v2-ack t)
(use-package org-roam :ensure t
  :custom
  (org-roam-directory org-directory-personal)
  :hook
  (after-init . org-roam-setup))
;; required for org-roam bookmarklet 
(require 'org-roam-protocol)

Org-roam Capture Templates

Starter pack. If there is only one, it uses automatically without asking.

(setq org-roam-capture-templates
      '(("d" "default" plain "%?"
         :if-new (file+head"%(format-time-string \"%Y-%m-%d--%H-%M-%SZ--${slug}.org\" (current-time) t)"
         "#+title: ${title}\n#+filetags %^G:\n")
        :unnarrowed t)
        ("y" "yank" plain "%?"
         :if-new (file+head"%(format-time-string \"%Y-%m-%d--%H-%M-%SZ--${slug}.org\" (current-time) t)"
                           "#+title: ${title}\n#+filetags: %^G\n%c\n")
         :unnarrowed t)
        ("o" "org-roam-it" plain "%?"
         :if-new (file+head"%(format-time-string \"%Y-%m-%d--%H-%M-%SZ--${slug}.org\" (current-time) t)"
                           "#+title: ${title}\n#+filetags:\n{ref}\n")
         :unnarrowed t)))

Language Support

Setup babel to evaluate the languages / scripts I use.

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (ruby . t)
   (python . t)
   (sql . t)
   (shell . t)
   (clojure . t)
   (gnuplot . t)))

Don’t ask before evaluating code blocks.

(setq org-confirm-babel-evaluate nil)

htmlize is used to ensure that exported code blocks use syntax highlighting.

Translate regular ol’ straight quotes to typographically-correct curly quotes when exporting.

(setq org-export-with-smart-quotes t)

Settings related to source code blocks

(setq org-src-fontify-natively t) ;; syntax highlighting in source blocks
(setq org-src-tab-acts-natively t) ;; Make TAB act as if language's major mode.
(setq org-src-window-setup 'current-window) ;; Use the current window rather than popping open a new onw

Task Handling and Agenda

Establishes the states and other settings related to task handling.

(setq org-enforce-todo-dependencies t)
(setq org-enforce-todo-checkbox-dependencies t)
(setq org-deadline-warning-days 7)

(setq org-todo-keywords '((sequence
                           "TODO(t)"
                           "STARTED(s)"
                           "WAITING(w)" "|"
                           "DONE(d)"
                           "SUSPENDED(u)"
                           "SKIPPED(k)")))
(setq org-log-done 'time)
(setq org-log-into-drawer t)
(setq org-log-reschedule 'note)

;; agenda settings
(setq org-agenda-span 1)
(setq org-agenda-start-on-weekday nil)

;; Normally bound to org-agenda-sunrise-sunset which is kinda useless
(add-hook 'org-agenda-mode-hook (lambda ()
                                  (define-key org-agenda-mode-map (kbd "S") 'org-agenda-schedule)))
;; Normally bound to toggle diary inclusion which would never really do
(add-hook 'org-agenda-mode-hook (lambda ()
                                  (define-key org-agenda-mode-map (kbd "D") 'org-agenda-deadline)))

Diary Settings

I’ve don’t use the diary file but it’s useful for holidays.

(setq calendar-bahai-all-holidays-flag nil)
(setq calendar-christian-all-holidays-flag t)
(setq calendar-hebrew-all-holidays-flag t)
(setq calendar-islamic-all-holidays-flag t)

Calfw

Calfw generates useful calendar views suitable for printing or providing a more visual outlook on the day, week, two weeks, or month

(use-package calfw)
(use-package calfw-org)
(require 'calfw)
(require 'calfw-org)

(defun db:my-open-calendar ()
  (interactive)
  (cfw:open-calendar-buffer
   :contents-sources
   (list
    (cfw:org-create-source "Green")  ; orgmode source
;;    (cfw:howm-create-source "Blue")  ; howm source
;;    (cfw:cal-create-source "Orange") ; diary source
;;    (cfw:ical-create-source "Moon" "~/moon.ics" "Gray")  ; ICS source1
;;    (cfw:ical-create-source "gcal" "https://..../basic.ics" "IndianRed") ; google calendar ICS
   )))

Org Edna

Org Edna provides more powerful org dependency management.

(org-edna-mode)

(defun db/org-edna-blocked-by-descendants ()
  "Adds PROPERTY blocking this tasks unless descendants are DONE"
  (interactive)
  (org-set-property "BLOCKER" "descendants"))

(defun db/org-edna-blocked-by-ancestors ()
  "Adds PROPERTY blocking this tasks unless ancestors are DONE"
  (interactive)
  (org-set-property "BLOCKER" "ancestors"))

(defun db/org-edna-current-id ()
  "Get the current ID to make it easier to set up BLOCKER ids"
  (interactive)
  (set-register 'i (org-entry-get (point) "ID"))
  (message "ID stored"))

(defun db/org-edna-blocked-by-id ()
  "Adds PROPERTY blocking task at point with specific task ID"
  (interactive)
  (org-set-property "BLOCKER" (s-concat "ids(" (get-register 'i) ")")))

(define-key org-mode-map (kbd "C-c C-x <up>") 'db/org-edna-blocked-by-ancestors)
(define-key org-mode-map (kbd "C-c C-x <down>") 'db/org-edna-blocked-by-descendants)
(define-key org-mode-map (kbd "C-c C-x <left>") 'db/org-edna-current-id)
(define-key org-mode-map (kbd "C-c C-x <right>") 'db/org-edna-blocked-by-id)
(define-key org-mode-map (kbd "C-c C-x i") 'org-id-get-create)
;; override y (agenda year) with more useful todo yesterday for marking habits done prior day 
(define-key org-agenda-mode-map (kbd "y") 'org-agenda-todo-yesterday)

Filter Refile Targets

I have monthly log files used to take notes / journal that are sources of refile items but not targets. They are named YYYY-MM(w).org

(defun db-filtered-refile-targets ()
  "Removes month journals as valid refile targets"
  (remove nil (mapcar (lambda (x)
                        (if (string-match-p "2[0-9]*\-[0-9]+w?" x)
                            nil x)) org-agenda-files)))

(setq org-refile-targets '((db-filtered-refile-targets :maxlevel . 10)))

Super Agenda Setup

Super Agenda allows for grouping of items that appear on the agenda. It doesn’t alter what will appear.

     (setq org-agenda-skip-scheduled-if-done t
           org-agenda-skip-deadline-if-done t
           org-agenda-include-deadlines t
           org-agenda-include-diary t
           org-agenda-block-separator nil
           org-agenda-compact-blocks t
           org-agenda-start-with-log-mode nil)


     (setq org-super-agenda-groups
              '((:name "Today" :time-grid t :scheduled today :order 1)
                (:name "Inflight Projects" :and (:deadline t :not (:todo "TODO") :regexp("PROJECT:") ) :order 2)
                (:name "Important" :priority "A" :order 3)
                (:name "Quick Picks" :effort< "0:15" :order 4)
;;                (:name "With Caden" :and (:property ("OWNER" "caden") :scheduled future) :order 4)
                (:name "Nice" :and (:priority<= "B" :scheduled future) :order 9)
                (:name "Habits" :habit)))


     (add-hook 'org-agenda-mode-hook 'org-super-agenda-mode)

Org Capture Setup

Org capture templates for Chrome org-capture from site.

Added this file: /.local/share/applications/org-protocol.desktop using the following command:

cat > "${HOME}/.local/share/applications/org-protocol.desktop" << EOF
[Desktop Entry]
Name=org-protocol
Exec=emacsclient %u
Type=Application
Terminal=false
Categories=System;
MimeType=x-scheme-handler/org-protocol;
EOF

and then run

update-desktop-database ~/.local/share/applications
(require 'org-protocol)

Setting up org-protocol handler. This page has best description:

This page has the best description. This is working in linux only, hence the todo.

(defun transform-square-brackets-to-round-ones(string-to-transform)
  "Transforms [ into ( and ] into ), other chars left unchanged."
  (concat 
   (mapcar #'(lambda (c) (if (equal c ?[) ?\( (if (equal c ?]) ?\) c))) string-to-transform))
  )

(defvar my/org-contacts-template "* %(org-contacts-template-name)
  :PROPERTIES:
  :ADDRESS: %^{289 Cleveland St. Brooklyn, 11206 NY, USA}
  :BIRTHDAY: %^{yyyy-mm-dd}
  :EMAIL: %(org-contacts-template-email)
  :NOTE: %^{NOTE}
  :END:" "Template for org-contacts.")

;; if you set this variable you have to redefine the default t/Todo.
(setq org-capture-templates 
      `(
        ;; TODO     (t) Todo template
        ("t" "Todo" entry (file+headline ,org-default-notes-file "Refile")
         "* TODO %?"
         :empty-lines 1)

        ;; Note (n) template
        ("n" "Note" entry (file+headline ,org-default-notes-file "Refile")
         "* %? %(%i)"
         :empty-lines 1)

        ;; Protocol (p) template
        ("p" "Protocol" entry (file+headline ,org-default-notes-file "Refile")
         "* %^{Title}
              Source: %u, %c
             #+BEGIN_QUOTE
             %i
             #+END_QUOTE
             %?"
         :empty-lines 1)

        ;; Protocol Link (L) template
        ("L" "Protocol Link" entry (file+headline ,org-default-notes-file "Refile")
         "* %? [[%:link][%(transform-square-brackets-to-round-ones \"%:description\")]]"
         :empty-lines 1)

        ;; Goal (G) template
        ("G" "Goal" entry (file+headline ,org-default-notes-file "Refile")
         "* GOAL %^{Describe your goal}
Added on %U - Last reviewed on %U
     :SMART:
     :Sense: %^{What is the sense of this goal?}
:Measurable: %^{How do you measure it?}
   :Actions: %^{What actions are needed?}
 :Resources: %^{Which resources do you need?}
   :Timebox: %^{How much time are you spending for it?}
       :END:"
         :empty-lines 1)
        ;; Contact (c) template
        ("c" "Contact" entry (file+headline ,(concat org-directory "/contacts.org") "Contacts")
         "* %(org-contacts-template-name)
:PROPERTIES:
 :ADDRESS: %^{289 Cleveland St. Brooklyn, 11206 NY, USA}
:BIRTHDAY: %^{yyyy-mm-dd}
   :EMAIL: %(org-contacts-template-email)
     :TEL: %^{NUMBER}
    :NOTE: %^{NOTE}
:END:"
         :empty-lines 1)
        ))

Org Reveal

(use-package ox-reveal
  :ensure ox-reveal
  :ensure htmlize)

Exporting

Allow export to markdown and beamer (for presentations).

(require 'ox-md)
(require 'ox-beamer)

Presentations with org-tree-slide

(when (require 'org-tree-slide nil t)
  (global-set-key (kbd "<f8>") 'org-tree-slide-mode)
  (global-set-key (kbd "S-<f8>") 'org-tree-slide-skip-done-toggle)
  (define-key org-tree-slide-mode-map (kbd "<f9>")
    'org-tree-slide-move-previous-tree)
  (define-key org-tree-slide-mode-map (kbd "<f10>")
    'org-tree-slide-move-next-tree)
  (define-key org-tree-slide-mode-map (kbd "<f11>")
    'org-tree-slide-content)
  (setq org-tree-slide-skip-outline-level 4)
  (org-tree-slide-narrowing-control-profile)
  (setq org-tree-slide-skip-done nil)
  (setq org-image-actual-width nil))

Personal and Work Toggle

Need to add mode line display of context

(defun db/org-work-context ()
  (interactive)
  (setq org-directory org-directory-work)
  (db/org-switch-context))

(defun db/org-personal-context ()
  (interactive)
  (setq org-directory org-directory-personal)
  (db/org-switch-context))

(defun db/org-switch-context ()
  (setq org-agenda-files (directory-files-recursively org-directory "org$"))
  (setq org-default-notes-file (concat org-directory "/index.org"))
  (setq org-roam-directory org-directory)
  (setq org-roam-db-location (expand-file-name "org-roam.db" org-roam-directory))
  (org-roam-db-sync))

Add a CREATED timestamp property to all TODOs

All of this comes from this gist. Would be nice if org mode just offered this as a local set up option.

;; Allow automatically handing of created/expired meta data.
(require 'org-expiry)

;; Configure it a bit to my liking
(setq
  org-expiry-created-property-name "CREATED" ; Name of property when an item is created
  org-expiry-inactive-timestamps   t         ; Don't have everything in the agenda view
)

(defun db/insert-created-timestamp()
  "Insert a CREATED property using org-expiry.el for TODO entries"
  (org-expiry-insert-created)
  (org-back-to-heading)
  (org-end-of-line)
  (insert " "))

;; Whenever a TODO entry is created, I want a timestamp
;; Advice org-insert-todo-heading to insert a created timestamp using org-expiry
(defadvice org-insert-todo-heading (after db/created-timestamp-advice activate)
  "Insert a CREATED property using org-expiry.el for TODO entries"
  (db/insert-created-timestamp))

;; Make it active
(ad-activate 'org-insert-todo-heading)

(defadvice org-capture (after db/created-timestamp-advice activate)
  "Insert a CREATED property using org-expiry.el for TODO entries"
  ; Test if the captured entry is a TODO, if so insert the created
  ; timestamp property, otherwise ignore
  (when (member (org-get-todo-state) org-todo-keywords-1)
    (db/insert-created-timestamp)))

(ad-activate 'org-capture)

;; Add feature to allow easy adding of tags in a capture window
(defun db/add-tags-in-capture()
  (interactive)
  "Insert tags in a capture window without losing the point"
  (save-excursion
    (org-back-to-heading)
    (org-set-tags)))

Other Customizations

This section is for additional customizations.

Reading Email with mu4e

Load mu4e

So, mu4e isn’t in melpa (wtf) and has to be installed. Since switching to Fedora 34 (wayland) now…

sudo dnf install mu4e  
(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu4e")
(require 'mu4e)

Contexts

I just have one context which is gmail.

(setq mu4e-contexts
   `( ,(make-mu4e-context
     :name "gmail"
     :enter-func (lambda () (mu4e-message "Entering gmail context"))
         :leave-func (lambda () (mu4e-message "Leaving gmail Context"))
     ;; we match based on the contact-fields of the message
     :match-func (lambda (msg)
           (when msg
             (mu4e-message-contact-field-matches msg
               :to "donald.brady@gmail.com")))
     :vars '( ( user-mail-address	    . "donald.brady@gmail.com"  )
          ( user-full-name	    . "Donald Brady" )
          ( mu4e-compose-signature .
            (concat
              "Donald Brady\n"
              "e: donald.brady@gmail.com\n"))))))
(setq mu4e-context-policy 'pick-first)
;; use mu4e for e-mail in emacs
(setq mail-user-agent 'mu4e-user-agent)

;; these must start with a "/", and must exist
;; (i.e.. /home/user/Maildir/gmail/Sent must exist) you use e.g. 'mu mkdir' and
;; 'mu init' to make the Maildirs if they don't already exist.

(setq mu4e-sent-folder   "/gmail/Sent")
(setq mu4e-drafts-folder "/gmail/Drafts")
(setq mu4e-trash-folder  "/gmail/Trash")
(setq mu4e-refile-folder "/gmail/Archive")

Fetching

Use mbsync for fetching email.

(setq mu4e-get-mail-command "mbsync -V gmail")

Composing

Reading

Save attachments to Downloads

(setq mu4e-attachment-dir "~/Downloads")  

Use C-c C-o to open links

(define-key mu4e-view-mode-map (kbd "C-c C-o") 'mu4e~view-browse-url-from-binding)  

View images inline

(setq mu4e-view-show-images t)
(when (fboundp 'imagemagick-register-types)
  (imagemagick-register-types))

Archiving

Encryption

Sending

You will need to install msmtp and configure that as needed.

(setq message-send-mail-function 'message-send-mail-with-sendmail)
(setq message-sendmail-extra-arguments '("--read-envelope-from"))
(setq message-sendmail-f-is-evil 't)
(setq sendmail-program "msmtp") 

Org Agena Integration

org-mu4e lets me store links to emails. I use this to reference emails in my TODO list while keeping my inbox empty. When storing a link to a message in the headers view, link to the message instead of the search that resulted in that view.

(require 'org-mu4e)
(setq org-mu4e-link-query-in-headers-mode nil)

Org Contacts

Use an org-contacts file to manage my address book.

(use-package org-contacts
  :ensure nil
  :after org
  :custom (org-contacts-files '("~/OrgDocuments/personal/contacts.org")))

(setq mu4e-org-contacts-file (car org-contacts-files))
(add-to-list 'mu4e-headers-actions
             '("org-contact-add" . mu4e-action-add-org-contact) t)
(add-to-list 'mu4e-view-actions
             '("org-contact-add" . mu4e-action-add-org-contact) t)

Key Bindings

(global-set-key (kbd "C-c m") 'mu4e)

Openwith

Maps file extensions to applications

;; (use-package openwith)
;; (openwith-mode t)
;; (add-to-list  'mm-inhibit-file-name-handlers 'openwith-file-handler)
;; (setq openwith-associations '(("\\.pdf\\'" "pdfstudio2020" (file))))

Projectile

Use projectile for projects navigation

(use-package projectile
:config
(setq projectile-switch-project-action #'projectile-dired)
(projectile-mode +1)
:bind ("C-c p p" . projectile-switch-project))

Magit

(use-package magit
:config
(setq magit-push-always-verify nil)
:bind 
(("C-x g" . magit-status)))

Hippie Expand Setup

This is a more powerful completion system.

;; hippie expand is dabbrev expand on steroids
(setq hippie-expand-try-functions-list '(try-expand-dabbrev
                                         try-expand-dabbrev-all-buffers
                                         try-expand-dabbrev-from-kill
                                         try-complete-file-name-partially
                                         try-complete-file-name
                                         try-expand-all-abbrevs
                                         try-expand-list
                                         try-expand-line
                                         try-complete-lisp-symbol-partially
                                         try-complete-lisp-symbol))

;; use hippie-expand instead of dabbrev
(global-set-key (kbd "M-/") #'hippie-expand)
(global-set-key (kbd "s-/") #'hippie-expand)

Blogging with Wordpress and Org2Blog

Org2Blog is a package for blogging directly from org-mode to wordpress which is about all I need to manage an online presence.

http://donald-brady.wordpress.com

(use-package org2blog
  :ensure t
  :config
  (setq org2blog/wp-blog-alist
        '(
          ("wordpress"
           :url "https://donaldbrady.wordpress.com/xmlrpc.php"
           :username "donald.brady@gmail.com")))
  (setq org2blog/wp-image-upload t)
  (setq org2blog/wp-image-thumbnails t)
  :bind
  (("C-c h" . org2blog-user-interface)))

RSS with elfeed

Install elfeed and load up my feeds stored in ~OrgDocuments/rss-feeds.org.

(use-package elfeed
  :ensure elfeed-org
  :config
  (setq elfeed-set-max-connections 32)
  (setq rmh-elfeed-org-files (list (expand-file-name "rss-feeds.org" org-directory-personal)))
  (elfeed-org)
  :bind
  (("C-c r" . elfeed)
   :map elfeed-show-mode-map
   ("o" . elfeed-show-visit)
   :map elfeed-search-mode-map
  ("o" . elfeed-search-browse-url)))

Programming

Python

(use-package python
  :hook
  (python-mode . flycheck-mode)
  (python-mode . db/activate-pyvenv)
  (python-mode . hs-minor-mode))
(use-package elpy
  :ensure t
  :init
  (elpy-enable))

Use pyvenv to support multiple python environments

(use-package pyvenv
  :after python
  :config
  (defun db/activate-pyvenv ()
    "Activate python environment according to the `.venv' file."
    (interactive)
    (pyvenv-mode)
    (let* ((pdir (projectile-project-root)) (pfile (concat pdir ".venv")))
      (if (file-exists-p pfile)
          (pyvenv-workon (with-temp-buffer
                           (insert-file-contents pfile)
                           (nth 0 (split-string (buffer-string)))))))))

Clojure

(use-package clojure-mode)
(use-package cider)

Globally Set Keys

This section has all globally set keys unless they are related to a package or mode config.

;; use hippie-expand instead of dabbrev
(global-set-key (kbd "M-/") 'hippie-expand)

;; keyboard macros
(global-set-key (kbd "<f1>") 'start-kbd-macro)
(global-set-key (kbd "<f2>") 'end-kbd-macro)
(global-set-key (kbd "<f3>") 'call-last-kbd-macro)

;; org and org-roam keys
;; some should be mode local but I spend most of my in org mode so being lazy 
(define-key global-map (kbd "\C-ca") 'org-agenda)
(define-key global-map (kbd "\C-cc") 'org-capture)
(define-key global-map (kbd "C-c n b") 'org-roam-buffer-toggle)
(define-key global-map (kbd "C-c n f") 'org-roam-node-find)
(define-key global-map (kbd "C-c n c") 'org-roam-capture)              
(define-key global-map (kbd "C-c n g") 'org-roam-graph)
(define-key global-map (kbd "C-\\") 'org-previous-link)
(define-key global-map (kbd "C-c n i") 'org-roam-insert)
(define-key global-map (kbd "C-<return>") 'org-next-link)
(define-key global-map (kbd "C-c n d") 'org-roam-dailies-goto-today)
(define-key global-map (kbd "C-c n y") 'org-roam-dailies-goto-yesterday)
(define-key global-map (kbd "C-c n t") 'org-roam-dailies-goto-tomorrow)
(define-key global-map (kbd "C-c n i") 'org-roam-node-insert)

;; replace buffer-menu with ibuffer
(global-set-key (kbd "C-x C-b") 'ibuffer)

;; Lenovo Function Key Bindings
(global-set-key (kbd "<XF86Favorites>") 'bury-buffer) ;; The Star on F12
(global-set-key (kbd "<f12>") 'bury-buffer) ;; F12 on logi keybpard

;; M-0 to toggle hiding
(global-set-key (kbd "M-0") 'hs-toggle-hiding)

;; toggle line numbers
(global-set-key (kbd "C-c l") 'display-line-numbers-mode)

Load any Custom Code

If there is a file custom.el in .emacs directory load it

;; config changes made through the customize UI will be stored here
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (file-exists-p custom-file)
  (load custom-file))
;; load any custom code for work.
(if (file-directory-p "~/OrgDocuments/dcllp")
    (load (expand-file-name "lisp/deloitte.el" user-emacs-directory)))

Theme

Kinda like this theme

(load-theme 'modus-operandi t)
(setq modus-themes-variable-pitch-ui t)
(setq modus-themes-variable-pitch-headings t)

Test Garbage Collection Optimization

When entering the minibuffer sets it large so gc doesn’t happen when interacting. Once exited sets back to a smaller number to force more frequent collection.

(defun my-minibuffer-setup-hook ()
  (setq gc-cons-threshold most-positive-fixnum))

(defun my-minibuffer-exit-hook ()
  (setq gc-cons-threshold 800000))

(add-hook 'minibuffer-setup-hook #'my-minibuffer-setup-hook)
(add-hook 'minibuffer-exit-hook #'my-minibuffer-exit-hook)

Start a server

Finally start a server

(server-start)