Hopefully only need to change these to get setup on a new machine.
(defconst jmn-config-location "~/dotfiles/emacs.org"
"Location of literate org file used to automaitically tangle to init.el")
(let ((gtd-path '((gnu/linux . "~/Documents/gtd/")
(windows-nt . "c:/Users/nehlsj/OneDrive/Documents/gtd/"))))
(defconst jmn-gtd-directory (alist-get system-type gtd-path)
"Location of gtd org files: projects, inbox, next, whip, journal, and habits"))
(defconst jmn-connected-systems '("lat" "dsk" "xps")
"Systems which should download packages. Others get the 'pure' configuration.")
(defconst jmn-connected-extras t
"Flag of weather to use the purely astetic packages or not on connected system")
(defconst jmn-pureplus-systems '("lat" "testbed")
"Systems which use the pure setup with the plus packages")
(defconst jmn-dark-mode t
"Do we want Emacs in a dark mode? Note: no dark-mode for windows as of now")
(defconst jmn-font-height-alist '(("xps" . 110)
("dsk" . 110)
("lat" . 115))
"Set text-hight for each machine-- default will be 100");; Automatically tangle our Emacs.org config file when we save it
(defun efs/org-babel-tangle-config ()
(when (string-equal (buffer-file-name)
(expand-file-name jmn-config-location))
;; Dynamic scoping to the rescue
(let ((org-confirm-babel-evaluate nil))
(org-babel-tangle))))
(add-hook 'org-mode-hook
(lambda () (add-hook 'after-save-hook #'efs/org-babel-tangle-config)))Archives: elpa is default, melpa is community.
- Use-package is macro that is used like a package manager. Use-Package Documentation
- Update all packages with
M-x package-upgrade-all
(if (member system-name jmn-connected-systems)
(defconst jmn-pure nil "Indicating if we are pure or using packages")
(if (member system-name jmn-pureplus-systems)
(defconst jmn-pure "plus" "Indicating we are using pure config with plus packages")
(defconst jmn-pure t "Indicating if we are pure, not using any packages")))
;; flag
(defconst jmn-term (not (display-graphic-p (selected-frame)))
"Indicating if emacs is being run within a terminal or not")
(defun jmn-connect-to-repositories ()
(require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("elpa" . "https://elpa.gnu.org/packages/")))
(if (version< emacs-version "29")
(progn
(setq package-check-signature nil) ;; bugfix: keys are not installed
(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3"))) ;; to load melpa
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(unless (package-installed-p 'use-package)
(package-install 'use-package));; Initialize use-package on non-Linux platforms
(require 'use-package)
(setq use-package-always-ensure t) ; no need for :ensure t for each package.
(setq use-package-verbose t)) ; log configure/loading messages in *Messages*
(if jmn-pure
(defmacro use-package (&rest _)) ;; define use-package macro to do nothing
(jmn-connect-to-repositories)) ;; connect to repos and use use-package macros to config belowCode above is for pure (offline) and non-pure (online). The below is for a pure = ‘plus’, when we include a few packages.
(defun jmn-install-plus-packages()
(interactive)
(jmn-connect-to-repositories)
;;install for all versions
(dolist (pluslist '(which-key undo-tree ws-butler prescient ivy ivy-rich ivy-prescient counsel htmlize evil-nerd-commenter))
(package-install pluslist 1))
;; install if version 27 and above
(if (version<= "27" emacs-version)
(progn
;; For emacs 28
;; magit requires ver >= 2.24 which is greater than built in version
;; Warnings buffer gives the following advice
;; TODO -- need it install seq-2.24 by hand in package-list-packages
(setq package-install-upgrade-built-in t)
(dolist (pluslist '(seq magit markdown-mode))
(package-install pluslist 1))
(unload-feature 'seq t)
(require 'seq))))If it fails here, we need to add the packages to ~/.emacs.d/elpa
(if (string= jmn-pure "plus") ;; turn on all of the plus modes
(progn
(package-initialize)
(require 'prescient)
(dolist (pluslist '(which-key-mode undo-tree-mode ws-butler-mode prescient-persist-mode ivy-mode ivy-rich-mode ivy-prescient-mode counsel-mode))
(funcall pluslist 1))
;; evil nerd commenter
(global-set-key (kbd "C-;") 'evilnc-comment-or-uncomment-lines)))TODO can the above do list be replaced with (package-initialize)?
;;;; Basic ;;;;
(setq inhibit-startup-message t) ; inhibit startup message
(tool-bar-mode -1) ; remove toolbar
(menu-bar-mode -1) ; Disable the menu bar
(scroll-bar-mode -1) ; remove side scrollbar
(tooltip-mode -1) ; Disable tooltips
(set-fringe-mode 6) ; Give some breathing room
(setq visible-bell t) ; Set up the visible bell
(save-place-mode 1) ; Open file where last visited
(setq Buffer-menu-name-width 35) ; give name more room
(setq-default indicate-empty-lines t) ; indicate long lines
(defalias 'yes-or-no-p 'y-or-n-p) ; Make =yes or no= prompts shorter
(column-number-mode 1) ; show column number in modeline
(winner-mode 1) ; redo and undo window changes
(if (version<= "28" emacs-version)
(repeat-mode 1)) ; multi-key sequences can be repeated
;; hooks
;; This modifies too much and makes git/diffs difficult-- need to find better solution
;; (if jmn-pure
;; (add-hook 'before-save-hook 'whitespace-cleanup)); non-pure uses ws-butler
(unless (eq system-type 'windows-nt)
(add-hook 'text-mode-hook 'flyspell-mode)) ; enable spellcheck on text mode
;; The following help syncing
(global-auto-revert-mode 1) ; refresh buffer if changed on disk
(setq auto-revert-use-notify nil) ; don't notify?
(setq auto-revert-verbose nil) ;
;; Mouse
(setq mouse-yank-at-point t) ;; yank at cursor not click location
;; By default Emacs prefers `.elc' to `.el' in all cases, `load-prefer-newer's
;; alway prefers the last-edited file, preventing this problem.
(setq load-prefer-newer t)
;; Buffer Menu
(add-hook 'Buffer-menu-mode-hook 'hl-line-mode)
(add-hook 'bookmark-bmenu-mode-hook 'hl-line-mode)Save backups in .emacs.d.
(setq backup-directory-alist
'( ("." . "~/.emacs.d/filebackups")))Set transparency
(defun transparency (value)
"Sets the transparency of the frame window. 0=transparent/100=opaque"
(interactive "nTransparency Value 0 - 100 opaque:")
(if (version<= "29" emacs-version)
(set-frame-parameter nil 'alpha-background value)
(set-frame-parameter (selected-frame) 'alpha value)));;;; Scrolling ;;;;
;; Fully redraw the display before it processes queued input events.
(setq redisplay-dont-pause t)
;; Number of lines of continuity to retain when scrolling by full screens
(setq next-screen-context-lines 2) ;; golden ration pkg will replaced this if loaded
;; only 'jump' when moving this far off the screen
(setq scroll-conservatively 100)
(setq scroll-step 1) ;; Keyboard scroll one line at a time
(setq mouse-wheel-progressive-speed nil) ;; Don't accelerate scrolling
(setq mouse-wheel-follow-mouse t) ;; Scroll window under mouse
(setq fast-but-imprecise-scrolling t) ;; No (setq less) lag while scrolling lots.
(setq auto-window-vscroll nil) ;; Cursor move faster
(setq pixel-scroll-precision-mode 1) ;; pixel based scrollingTo ensure scrolling is fast in Emacs, disable non-essential things while the window is being scrolled:
(use-package fast-scroll
:defer 2
:config
(add-hook 'fast-scroll-start-hook (lambda () (flycheck-mode -1)))
(add-hook 'fast-scroll-end-hook (lambda () (flycheck-mode 1)))
(fast-scroll-config)
(fast-scroll-mode 1))C-x uvisualizes undo history as a tree for easy navigationC-_undoM-_redo Archive: elpa
(use-package undo-tree
:defer 2
:config
(global-undo-tree-mode 1)
(setq undo-tree-auto-save-history nil)) ;; don't save ~undo-tree~ fileNOTE: The first time you load your configuration on a new machine, you’ll need to run M-x all-the-icons-install-fonts so that mode line icons display correctly. (Fixed?)
;;;; Modeline ;;;;
(if jmn-connected-extras
(use-package all-the-icons
:defer 1
:init
(when (and (not (member "all-the-icons" (font-family-list))) ;; autoinstall fonts
(window-system))
(all-the-icons-install-fonts t))))
(use-package doom-modeline
:init (doom-modeline-mode 1)
:custom ((doom-modeline-height 10)
(doom-modeline-vcs-max-length 20))) ;; default is 12Archive: melpa
;;;; Cleanup whitespace only on lines I touched ;;;;
(use-package ws-butler
:defer 4
:hook ((text-mode . ws-butler-mode)
(prog-mode . ws-butler-mode)))- Eventually I will assume
repeat-modeis builtin and remove theC-obindings to'other-window- repeat mode is built in starting in Emacs 28
;; general improvements
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
(global-set-key (kbd "C-x C-b") 'buffer-menu) ;; open buffer menue in current buffer
(global-set-key (kbd "C-x C-k") 'kill-current-buffer) ;; "C-x k" asks which buffer
(global-set-key (kbd "C-o") 'other-window) ;; default is "C-x o"
(global-set-key (kbd "M-o") 'previous-multiframe-window)
(global-set-key (kbd "C-c C-c") 'eval-buffer)
(global-set-key (kbd "C-c C-r") 'eval-region)
;; make font bigger/smaller.
(global-set-key (kbd "C-=") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
(global-set-key (kbd "C-0") 'text-scale-adjust)
;; f1 is a leader key for help
;; f2 is a leader key for 2 columns
;; f3 is kmacro-start-macro-or-insert-counter -- start recording a macro
;; f4 ends the macro recording
;; f5-f10 are clear by default
;; f11 is toggle full screen
;; f12 is clear by default
;; See recentfiles
(global-set-key (kbd "<f5>") 'compile)
;; See recentfiles
(global-set-key (kbd "<f6>") 'recentf-open-files)
;; writing/editing
(global-set-key (kbd "<f9>") 'ispell-word)
(global-set-key (kbd "<f10>") 'dictionary-lookup-definition)
;; Buffer-menu-mode
(define-key Buffer-menu-mode-map (kbd "C-o") 'other-window)
(define-key Buffer-menu-mode-map (kbd "M-o") 'previous-multiframe-window)
;; "o" opens in another buffer and moves focus
;; "C-M-o" opens in another buffer and keeps focus in the Buffer-menu
(define-key Buffer-menu-mode-map (kbd "C-M-o") 'Buffer-menu-switch-other-window)
;; xref
(with-eval-after-load 'xref
(define-key xref--xref-buffer-mode-map (kbd "C-o") 'other-window)
(define-key xref--xref-buffer-mode-map (kbd "o") 'xref-show-location-at-point))
;; bookmark-bmenue
(with-eval-after-load 'bookmark
(define-key bookmark-bmenu-mode-map (kbd "C-o") 'other-window)
(define-key bookmark-bmenu-mode-map (kbd "M-o") 'previous-multiframe-window)
(define-key bookmark-bmenu-mode-map (kbd "C-M-o") 'bookmark-bmenu-switch-other-window))
;; compilation-modes
(defun jmn-compilation-keybindings()
(define-key compilation-mode-map (kbd "C-o") 'other-window)
(define-key compilation-mode-map (kbd "C-M-o") 'compilation-display-error))
(add-hook 'compilation-mode-hook 'jmn-compilation-keybindings)
;; grep-mode
(defun jmn-grep-keybindings()
(define-key grep-mode-map (kbd "o") 'compilation-display-error)
(define-key grep-mode-map (kbd "C-o") 'other-window))
(add-hook 'grep-mode-hook #'jmn-grep-keybindings)
;; adjust windows with keybindings
(global-set-key (kbd "C-<up>") 'enlarge-window)
(global-set-key (kbd "C-<down>") 'shrink-window)
(global-set-key (kbd "C-<right>") 'enlarge-window-horizontally)
(global-set-key (kbd "C-<left>") 'shrink-window-horizontally)
;; non-org C-c <blank> bindings
(global-set-key (kbd "C-c r") 'revert-buffer)
(global-set-key (kbd "C-c =") 'vc-diff) ;; also bound to "C-x v ="More to do at here: dired-open
- “W” will open file in native environment (including another Emacs)
- ”(” toggle file info
- M-x du shows the size of the files in the buffer (toggle for human readable)
;;;; Dired ;;;;
(add-hook 'dired-mode-hook 'dired-hide-details-mode) ;; hide default -- '(' to toggle
(add-hook 'dired-mode-hook 'hl-line-mode)
(with-eval-after-load 'dired
(require 'dired-x) ;; may need to be (load "dired-x" for old versions
(setq dired-auto-revert-buffer t) ;; auto-revert dired when revisiting
(setq dired-vc-rename-file t) ;; renamed files are under version control
;; good for my persional machine
;; (setq dired-listing-switches "-agho --group-directories-first" )
;; good as a user of
(setq dired-listing-switches "-alh --group-directories-first" )
(setq find-ls-option '("-print0 | xargs -0 ls -agho" . ""))
(setq dired-dwim-target t) ;; guess other dired directory for copy and rename
(setq wdired-allow-to-change-permissions t)
(define-key dired-mode-map (kbd "C-o") 'other-window)
(setq dired-guess-shell-alist-user '(
("\\.png\\'" "shotwell")
("\\.jpg\\'" "shotwell")
("\\.jpeg\\'" "shotwell")
("\\.mp4\\'" "vlc")
("\\.avi\\'" "vlc")
("\\.iso\\'" "vlc")
("\\.webm\\'" "vlc")
("\\.mkv\\'" "vlc")
("\\.odt\\'" "libreoffice")
("\\.docx\\'" "libreoffice")
("\\.mp3\\'" "rhythmbox")
("\\.html\\'" "firefox")
("\\.epub\\'" "ebook-viewer")
("\\.pdf\\'" "evince")
("\\.ipynb\\'" "code")
("\\.py\\'" "python")
("\\.sh\\'" "bash")))
;;;; maybe use again in the future -- does not align with pure emacs
;; (if (version<= "28" emacs-version)
;; (setf dired-kill-when-opening-new-dired-buffer t))
)
;; use a single dired session ;; needed for emacs version < 28
;; (use-package dired-single
;; :after dired
;; :defer t
;; :hook (dired-mode .
;; (lambda () (define-key dired-mode-map [remap dired-find-file]
;; 'dired-single-buffer)
;; (define-key dired-mode-map
;; [remap dired-mouse-find-file-other-window]
;; 'dired-single-buffer-mouse)
;; (define-key dired-mode-map [remap dired-up-directory]
;; 'dired-single-up-directory))))
(if jmn-connected-extras
(use-package all-the-icons-dired
:after dired
:defer t
:hook (dired-mode . all-the-icons-dired-mode)))
;;;; Proced ;;;;
(defun proced-settings ()
(proced-toggle-auto-update 5)) ;; auto update every 4 seconds
(add-hook 'proced-mode-hook 'proced-settings)Suppress compilation warnings
;;;; Native comp ;;;;
(setq native-comp-async-report-warnings-errors nil)Check with other environments to settle on “C-;” or “M-;” – the other us used for evil-nerd comment
- we cleared “C-;” from Flyspell above
(use-package goto-last-change
:ensure t
:bind ("C-c g" . goto-last-change))Ivy displays vertical completions of input buffer.
- When we want the text accepted over the suggest completion use “C-M-j” which executes (ivy-immediate-done) source
(use-package ivy
:after counsel
:defer t
:config
(ivy-mode 1)
;; remove ^ on the inputbuffer
(setq ivy-initial-inputs-alist nil))Ivy-rich provides information to display in input buffer to counsel.
(use-package ivy-rich
:after counsel
:init
(ivy-rich-mode 1))prescient.el provides some helpful behavior for sorting Ivy completion candidates based on how recently or frequently you select them. This can be especially helpful when using M-x to run commands that you don’t have bound to a key but still need to access occasionally.
(use-package ivy-prescient
:after counsel
:custom
(ivy-prescient-enable-filtering nil)
:config
;; Uncomment the following line to have sorting remembered across sessions!
(prescient-persist-mode 1)
(ivy-prescient-mode 1))Counsel displays ivy-rich info along with suggestions in input buffer.
M-oallows access to help in input buffer. Archive: elpa, melpa
(use-package counsel
:defer t
:bind (("M-x" . counsel-M-x) ; displays ivy-rich info in minibuffer
("C-x C-f" . counsel-find-file)
:map minibuffer-local-map
("C-r" . 'counsel-minibuffer-history)
))Better version of help. We remap normal help keys to Helpful’s versions. Archive: melpa
(use-package helpful
:defer 3
:commands (helpful-callable helpful-variavle helpful-command helpful-key)
:custom
(counsel-describe-function-function #'helpful-callable)
(counsel-describe-variable-function #'helpful-variable)
:bind
([remap describe-function] . counsel-describe-function)
([remap describe-command] . helpful-command)
([remap describe-variable] . counsel-describe-variable)
([remap describe-key] . helpful-key))Archive: elpa, melpa
(use-package which-key
:defer 1
:config(which-key-mode)
(setq which-key-idle-delay 0.8))(defun jmn-set-font-height(value)
(interactive "nFont height (default is 100): ")
(set-face-attribute 'default nil :height value))
(jmn-set-font-height (alist-get (system-name) jmn-font-height-alist
100 nil 'string=)) ;; default is 100
(setq text-scale-mode-step 1.05)Defined earlier in the init so it will load even if there is an error later in the config
(defun jmn-load-init ()
(interactive)
(if (version<= "27" emacs-version)
(load "~/.emacs.d/init.el")
(load "~/.emacs")))(defun jmn-vscode-current-buffer-file-at-point ()
(interactive)
(start-process-shell-command "code"
nil
(concat "code --goto "
(buffer-file-name)
":"
(number-to-string (line-number-at-pos))
":"
;; +1 who knows why
(number-to-string (+ 1 (current-column))))))
(defun jmn-vscode-current-project-root ()
(interactive)
(start-process-shell-command "code" nil (concat "code -r " (project-root (project-current t)))))
(defun jmn-vscode-current-buffer-in-project-root ()
(interactive)
(start-process-shell-command "code" nil (concat "code -r " (project-root (project-current t))
" --goto "
(buffer-file-name)
":"
(number-to-string (line-number-at-pos))
":"
;; +1 who knows why
(number-to-string (+ 1 (current-column))))))
(define-key global-map (kbd "<f12>")
'jmn-vscode-current-buffer-in-project-root)Clear up to allow the tab-bar keybindings.
(defun jmn-remove-M-1-9-from-mode-map (modemap)
"remove 'M-[d]' keybinding from a mode-map"
(dolist (num '("1" "2" "3" "4" "5" "6" "7" "8" "9"))
(define-key modemap (kbd (concat "M-" num)) nil))) (defun remove-function-sexps (functionName)
"Remove all sexps with the input car in the current buffer."
(save-excursion
(goto-char (point-min))
;; break up the string so it is not replaced here
(while (re-search-forward (concat "(" functionName) nil t)
(backward-sexp)
(backward-char)
(kill-sexp))))
(defun remove-if-var-sexps (varName)
"Remove all sexps which start with 'if input' in the current buffer."
(save-excursion
(goto-char (point-min))
;; break up the string so it is not replaced here
(while (re-search-forward (concat "(if " varName) nil t)
(backward-sexp)
(backward-sexp)
(backward-char)
(kill-sexp))))
(defun jmn-purify-my-config-and-save ()
"Create a 'pure' configuration file '~/.emacs.d/pure_init.el' by removing impure configuration sexps."
(interactive)
(find-file "~/.emacs.d/init.el")
(remove-function-sexps "use-package")
(remove-if-var-sexps "jmn-connected-extras")
(set-visited-file-name "~/.emacs.d/pure_init.el")
(save-buffer)
(kill-current-buffer))(if (and jmn-term (version<= "29" emacs-version))
(progn
(xterm-mouse-mode 1)
(setopt mode-line-end-spaces nil) ;; Only matters for jmn-pure, doom-modeline is uneffected
(set-display-table-slot standard-display-table 'vertical-border (make-glyph-code ?│)))) ;; Suppress Async Shell Command buffers
(add-to-list 'display-buffer-alist '("*Async Shell Command*" display-buffer-no-window (nil)))
;; Could use this instead
;; (setq async-shell-command-display-buffer nil)
;; Only have one Async Shell Command buffer and it holds most recent output
(setq async-shell-command-buffer 'rename-buffer)
Guess the indentation offset and ‘indent-tabs-mode’ from the file using internal heuristics.
(use-package dtrt-indent
:hook (prog-mode . (lambda () (dtrt-indent-mode 1))));;Prog-mode
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(add-hook 'prog-mode-hook 'visual-line-mode)
(add-hook 'prog-mode-hook 'hs-minor-mode) ;; hide show, use C-c @ prefix
(unless (eq system-type 'windows-nt)
(add-hook 'prog-mode-hook 'flyspell-prog-mode)) ;; flyspell-comments(show-paren-mode 1) ; Highlight parentheses pairs.Need to test the org-mode hook Archive: melpa
(use-package rainbow-delimiters
:defer t
:hook ((prog-mode . rainbow-delimiters-mode)
(org-mode . (lambda () (rainbow-delimiters-mode 0)))))Auto-creates closing parenthesis and bar and, smartly, writes it over if it is typed. Archive: melpa
(use-package smartparens
:hook (prog-mode . smartparens-mode))Magit Documentation Archive: melpa
(use-package magit
:commands (magit-status)
:custom
(magit-display-buffer-function
#'magit-display-buffer-same-window-except-diff-v1))
;; moved here incase magit installed on a pure machine ;; replace original keybinding?
(with-eval-after-load 'magit
(add-hook 'magit-status-mode-hook
(lambda () (define-key magit-mode-map (kbd "C-<tab>") nil)))
(jmn-remove-M-1-9-from-mode-map magit-mode-map))- [ ] replace with diff-hl mode?
Git-gutter-fringe displays git-gutter in the fringe
(use-package git-gutter
:hook ((prog-mode . git-gutter-mode)
;; (text-mode . git-gutter-mode) ;; effects org-ellipsis
)
:config (setq git-gutter:update-interval 0.02))
(use-package git-gutter-fringe
:after git-gutter
:config
(set-face-background 'git-gutter-fr:deleted (face-background 'default))
(set-face-foreground 'git-gutter-fr:deleted "red"))(if jmn-connected-extras
(use-package highlight-indent-guides
:defer 2
:hook prog-mode
:config
(setq highlight-indent-guides-method 'fill)
(setq highlight-indent-guides-auto-odd-face-perc -7)
(setq highlight-indent-guides-auto-even-face-perc 7)))Currently company-mode gets called by lsp-mode by default, providing the auto-complete box that lsp presents it’s suggestions in.
(use-package company
:ensure t
:hook (eglot-managed-mode . company-mode)
:custom
(company-minimum-prefix-length 1)
(company-idle-delay 0.5))Brings up a another box with information about the highlighted recommended item in the company/lsp box.
(use-package company-box
:after company
:hook (company-mode . company-box-mode))Help in sorting the completion results.
(use-package company-prescient
:after company
:config
(company-prescient-mode +1))(use-package treemacs
:ensure t
:defer t
:bind (("C-c t" . treemacs ))
:config
(treemacs-project-follow-mode t) ;; open root of selected file in treemacs
(setq treemacs-width 30))Combines with flymake, eldoc, company-mode, and xref to make an IDE experience.
- can search in a company completion box!
- Flymake shows underlines: errors in red, warnings in blue
- “C-h .” provides eldoc info at the point
Function/keybinding learning area:
- eglot
- eglot find declaration
- eglot find definition
- eglot format buffer or region
- eglot rename
- xref (uses eglot for the backend)
- xrf-find-defintions “M-.” –return back with “M-,”
- [ ] uses tags so replace?
- xrf-find-references “M-?”
- xrf-find-defintions “M-.” –return back with “M-,”
(if jmn-connected-extras
(use-package eglot
:defer 1
:ensure-system-package
((bash-language-server . "sudo dnf install -y nodejs-bash-language-server")
(pyright . "pip install pyright")
(clangd . "sudo dnf install -y clang-tools-extra")
(texlab . "cargo install --git https://github.com/latex-lsp/texlab --locked --tag v5.22.0") ;; ensure texlab is added to bash PATH
)
:hook ((sh-mode . eglot-ensure)
(python-mode . eglot-ensure)
(c-mode . eglot-ensure)
(c++-mode . eglot-ensure)
(haskell-mode . eglot-ensure)
(LaTeX-mode . eglot-ensure))
:config
;; make shorter ones later?
;; use "M-." for xref-find-definitions
;; use "M-?" for xref-find-references
;; use "M-g n" and "M-g p" to go to next and previous location
;; use ... for xref-pop-marker-stack
(define-prefix-command 'eglot-prefix)
(global-set-key (kbd "C-x e") 'eglot-prefix)
(define-key eglot-prefix (kbd "r") 'eglot-rename)
(define-key eglot-prefix (kbd "o") 'eglot-code-action-organize-imports)
(define-key eglot-prefix (kbd "h") 'eldoc)
(define-key eglot-prefix (kbd "d") 'eglot-find-declaration)
(define-key eglot-prefix (kbd "a") 'eglot-format-buffer)
(define-key eglot-prefix (kbd "n") 'flymake-goto-next-error)
(define-key eglot-prefix (kbd "p") 'flymake-goto-prev-error)
(define-key eglot-prefix (kbd "b") 'flymake-show-buffer-diagnostics)))Add breadcrumbs to the top of buffers. Works great with Eglot.
(use-package breadcrumb
:ensure t
:config
(breadcrumb-mode))Lsp-mode requires the language server on the system:
pip install cmake-language-server.
Archive: melpa
(use-package cmake-mode
:defer t
:ensure-system-package ((cmake . "sudo dnf install -y cmake"))
:mode ("CMakeLists\\.txt\\'" "\\.cmake\\'"))
(use-package cmake-font-lock
:ensure t
:after cmake-mode
:config (cmake-font-lock-activate))In the source directory containing CMakeLists.txt run M-x cmake-project-configure-project.
As a preference, use the /bin/ option to keep the cmake files out of the source directory.
After this, the compile automatically holds the correct command.
Archive: melpa
(use-package cmake-project
:defer 2
;; :hook ((c++-mode . cmake-project-mode )
;; (c-mode . cmake-project-mode))
)Archive: elpa, melpa
(if jmn-connected-extras
(use-package yasnippet
:defer 1
:config
(yas-global-mode 1))
(use-package yasnippet-snippets
:after yas-minor-mode)) ;; load basic snippets from melpaC-, flyspell-goto-next-error
C-. flyspell-auto-correct-word
;; free up C-; for evil-nerd-commenter
(with-eval-after-load 'flyspell
(define-key flyspell-mode-map (kbd "C-;") nil))
;; (progn
;; (define-key flyspell-mode-map (kbd "C-;") nil)
;; (define-key flyspell-mode-map (kbd "M-;") flyspell-auto-correct-previous-word)))Archive: melpa
(use-package evil-nerd-commenter
:bind ("C-;". evilnc-comment-or-uncomment-lines))Archive: melpa
(use-package tree-sitter-langs
:hook ((sh-mode . tree-sitter-hl-mode)
(python-mode . tree-sitter-hl-mode)
(c-mode . tree-sitter-hl-mode)
(c++-mode . tree-sitter-hl-mode)))Archive: melpa
(use-package ripgrep
:defer 2
:ensure-system-package
((rg . "sudo dnf install -y ripgrep")))Archive: melpa
(use-package yaml-mode
:defer t)(use-package toml-mode
:defer t)Archive: melpa
(use-package dockerfile-mode
:defer t)Note: not used or tangled
(defadvice compile (before ad-compile-smart activate)
"Advises `compile' so it sets the argument COMINT to t."
(ad-set-arg 1 t))
(add-hook 'shell-mode-hook 'compilation-shell-minor-mode)To install documentation, use M-x evdocs-install
(use-package devdocs
:defer 2
:bind ("C-h D" . 'devdocs-lookup))(defun jmn-smerge-accept-all-lower()
"Accept all lower changes below the cursor point"
(interactive)
(while (not (smerge-next))
(smerge-keep-lower)))
(defun jmn-smerge-accept-all-upper()
"Accept all upper changes below the cursor point"
(interactive)
(while (not (smerge-next))
(smerge-keep-upper)))
(with-eval-after-load 'smerge
(define-key smerge-mode-map (kbd "C-c ^ L") 'jmn-smerge-accept-all-lower)
(define-key smerge-mode-map (kbd "C-c ^ U") 'jmn-smerge-accept-all-upper))Gives of tab completion in:
- [X] python-mode
- [X] emacs-lisp-mode
- [X] shell-script mode (bash)
With this setup, TAB - which is usually bound to indent-for-tab-command - first tries to adjust the indentation according to the mode’s settings, but if the indentation is already correct, completion is triggered. This is usually the desired behavior, and IMHO works better than third-party plugins like smart-tab. reference
I believe this is replacing what company-mode does for us.
(defun jmn-tab-complete-mode ()
"My tab complete config"
(setq tab-always-indent 'complete) ;;complete if indented
(add-to-list 'completion-styles 'initials t))
;; turning it on everywhere and only turning company mode on for prog-mode
;;;; if this stayes it will just be moved up to under the 'General Emacs'
(jmn-tab-complete-mode)As of 28.1 there is tab-first-completion. Could add a setup for it above which depends on Emacs version.
(if jmn-pure
(global-set-key (kbd "C-c g") (lambda () (interactive)
(vc-dir (file-name-directory (buffer-file-name))))))
(defun jmn-vc-commit ()
"My command to show the vc-diff along with the commit input"
(interactive)
(vc-next-action (buffer-file-name))
(previous-multiframe-window)
(vc-diff)
(previous-multiframe-window)
(switch-to-buffer"*vc-log*")
;; (set-window-text-height (selected-window) 4)
;; (kill-buffer "*log-edit-files*")
)
(with-eval-after-load 'vc-dir
(define-key vc-dir-mode-map (kbd "C-o") 'other-window)
(define-key vc-dir-mode-map (kbd "C-M-o") 'vc-dir-display-file)
(define-key vc-dir-mode-map (kbd "c") 'jmn-vc-commit))Use C-c ' to view elisp babel blocks in their own file to get completion in company-mode.
- added flycheck-mode-hook in it’s use-package config.
(add-hook 'emacs-lisp-mode-hook 'display-line-numbers-mode)
(add-hook 'emacs-lisp-mode-hook 'visual-line-mode)- debuggers are available
(defun my-sh-mode-hook-fn()
(setq sh-basic-offset 2
sh-indentation 2)) ;; defaults is 4
(add-hook 'sh-mode-hook #'my-sh-mode-hook-fn)
(use-package sh-script
:defer t
:config
(setq sh-basic-offset 2
sh-indentation 2)) ;; defaults are 4See https://amitp.blogspot.com/2023/10/emacs-and-shellcheck.html
Archive: melpa
(use-package pyvenv
:ensure t
:defer t
:diminish
:config
(setenv "WORKON_HOME" "/home/ape/.conda/envs")
; Show python venv name in modeline
(setq pyvenv-mode-line-indicator
'(pyvenv-virtual-env-name ("[venv:" pyvenv-virtual-env-name "] ")))
(pyvenv-mode t))After package installation, you should have M-x pyvenv-workon command with a list of your virtual environments.
The only lack of this is that you need to restart LSP workspace at least once when you change venv by pyvenv-workon command.
So the flow should be like this:
M-x pyvenv-workon <your-venv> # or conda environment?
M-x lsp-restart-workspace # eglot’s corresponding command?
After changing venv all installed packages from venv should be visible for LSP server.
For lsp, have pyright installed pip install pyright
(with-eval-after-load 'python
;; if emacs is not run from a terminal, we need to add the PYTHONPATH set in .bashrc
(unless (getenv "PYTHONPATH")
(setenv "PYTHONPATH" (shell-command-to-string "$SHELL --login -c 'echo -n $PYTHONPATH'")))
;; allow completion
(setq python-shell-completion-native-enable 1)
;; keybindings
(define-key python-mode-map (kbd "C-RET") 'python-shell-send-statement)
;; use ipython for interpreter if it exists
(if (executable-find "ipython")
(progn (setq python-shell-interpreter "ipython")
(setq python-shell-interpreter-args "-i --simple-prompt"))))(defun my-python-mode-hook-fn ()
(with-eval-after-load 'devdocs
(setq-local devdocs-current-docs '("python~3.12"))))
(add-hook 'python-mode-hook #'my-python-mode-hook-fn)(setq compilation-scroll-output t) ;;*Compilation* buffer scroll with the output.The following keeps the compilation buffer if there are warnings or errors, and buries it otherwise (after 1 second). source
(defun bury-compile-buffer-if-successful (buffer string)
"Bury a compilation buffer if succeeded without warnings "
(when (and
(buffer-live-p buffer)
(string-match "compilation" (buffer-name buffer))
(string-match "finished" string)
(not
(with-current-buffer buffer
(goto-char (point-min))
(search-forward "warning" nil t))))
(run-with-timer 1 nil
(lambda (buf)
(bury-buffer buf)
(switch-to-prev-buffer (get-buffer-window buf) 'kill))
buffer)))
(add-hook 'compilation-finish-functions 'bury-compile-buffer-if-successful)Currently lsp-mode works with clangd backend without any initial setup.
company-clang needs clang installed on the system.
;;settings
(setq-default c-basic-offset 2)
;; gdb
(with-eval-after-load 'gdb-mi
(setq gdb-many-windows t
gdb-show-main t))
(advice-add 'gdb :after (lambda (&rest r) (tool-bar-mode 1)))
;; mode
(defun my-c++-mode-hook-fn ()
(with-eval-after-load 'devdocs
(setq-local devdocs-current-docs '("cpp"))))
(defun my-c-mode-hook-fn ()
(with-eval-after-load 'devdocs
(setq-local devdocs-current-docs '("c"))))
(add-hook #'c-mode-hook #'my-c-mode-hook-fn)
(add-hook #'c++-mode-hook #'my-c++-mode-hook-fn)(add-to-list 'auto-mode-alist '("\\.m$" . octave-mode))Use markdown-preview-mode to view in browser.
(use-package markdown-mode
:defer t
:hook ((markdown-mode-hook . flyspell-mode)
(markdown-mode-hook . visual-line-mode)))
(use-package markdown-preview-mode
:defer t)1) Install GHCup
Installs the following:
- ghcup - The Haskell toolchain installer
- ghc - The Glasgow Haskell Compiler
- cabal - The Cabal build tool for managing Haskell software
- stack - A cross-platform program for developing Haskell projects (similar to cabal)
- hls - (optional) A language server for developers to integrate with their editor/IDE
(use-package haskell-mode
:hook (haskell-mode . interactive-haskell-mode) ;; For GHCi integration
)
;; (use-package lsp-haskell)
;; Enable haskell-mode and lsp-mode automatically for Haskell files
(add-hook 'haskell-mode-hook #'eglot-ensure)
(add-hook 'haskell-mode-hook #'interactive-haskell-mode) ; For GHCi integration
(use-package flymake-hlint)Notes on completion: use C-c C-l to insert a path link and get completion.
- alternatively company-mode will complete in the buffer, but will get in the way in the org-blocks.
(defun jmn/org-mode-setup ()
(unless (or jmn-term (version<= emacs-version "26.1"))
(org-indent-mode))
(variable-pitch-mode 1)
(visual-line-mode 1)
;; fix issue where it matches > with partentheses -- may break blocks with <>
(modify-syntax-entry ?< ".")
(modify-syntax-entry ?> ".")
)(defun jmn/org-font-setup ()
(unless jmn-term ;; Replace list hyphen with dot
(font-lock-add-keywords
'org-mode '(("^ *\\([-]\\) "
(0 (prog1 () (compose-region (match-beginning 1)
(match-end 1) "•")))))))
;; Set faces for heading levels
(let ((jmn-org-hfont-alist '((gnu/linux . "Cantarell")
(windows-nt . unspecified))))
(dolist (face '((org-level-1 . 1.2)
(org-level-2 . 1.1)
(org-level-3 . 1.1)
(org-level-4 . 1.1)
(org-level-5 . 1.1)
(org-level-6 . 1.1)
(org-level-7 . 1.1)
(org-level-8 . 1.1)
))
(set-face-attribute (car face) nil
:font (alist-get system-type jmn-org-hfont-alist)
:weight 'regular :height (cdr face))))
;; Ensure that anything that should be fixed-pitch in Org files appears that way
;; (set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch) ;;warning
(set-face-attribute 'org-block nil :foreground 'unspecified' :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil
:inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil
:inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch))(add-hook 'org-mode-hook 'jmn/org-mode-setup)
(with-eval-after-load 'org
(jmn/org-font-setup)
(unless (or jmn-term jmn-pure)
(progn (setq org-ellipsis " ▾")
(set-face-underline 'org-ellipsis nil)))
(setq org-hide-emphasis-markers t
org-src-fontify-natively t
org-fontify-quote-and-verse-blocks t
org-src-tab-acts-natively t
org-edit-src-content-indentation 2 ;; I undo this somewhere 4tangling
org-hide-block-startup nil
org-src-preserve-indentation nil
org-startup-folded 'content
org-cycle-separator-lines 2
org-capture-bookmark nil
org-list-indent-offset 1
org-image-actual-width nil ;; fix to allow picture resizing
org-return-follows-link t
org-use-speed-commands t
org-use-property-inheritance t ;; preperties to affect nested sections
org-export-babel-evaluate nil ;; don't run src blocks on export
org-agenda-tags-column (alist-get
(system-name) '(("xps" . -85)
("dsk" . -90))
'auto nil 'string=)))Archive: melpa
(unless (or jmn-term (not jmn-connected-extras))
(use-package org-bullets
:hook (org-mode . org-bullets-mode)
:custom
(org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●"))))Archive: melpa
(defun jmn/org-mode-visual-fill ()
(setq visual-fill-column-width 120
visual-fill-column-center-text t)
(visual-fill-column-mode 1))
(use-package visual-fill-column
:hook (org-mode . jmn/org-mode-visual-fill))Either start a source block with <[template] or C-c C-, to select from org-select.
Notes: Use # -*- org-src-preserve-indentation: t; -*- when doing tangle/detangle with python
(with-eval-after-load 'org
(org-babel-do-load-languages 'org-babel-load-languages
(append org-babel-load-languages
'((shell . t)
(python . t)
(makefile . t)
(latex . t)
(C . t)))))
(setq org-confirm-babel-evaluate nil)
(with-eval-after-load 'org
(if (version<= "27" emacs-version)
(progn
(require 'org-tempo) ;; needed for <sh to complete on new systems -- works without on v 26.1
(add-to-list 'org-structure-template-alist '("la" . "src latex"))
(add-to-list 'org-structure-template-alist '("m" . "src makefile"))
(add-to-list 'org-structure-template-alist '("js" . "src js"))
(add-to-list 'org-structure-template-alist '("sh" . "src shell"))
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python :results output"))
(add-to-list 'org-structure-template-alist '("pyim" . "src python :results file :var f=strNameWithDoubleQuotes
import matplotlib.pyplot as plt
plt.savefig(f)
f"))
(add-to-list 'org-structure-template-alist '("cpp" . "src C++ :includes <iostream>"))
(add-to-list 'org-structure-template-alist '("cppnm" . "src C++ :main no")))
(progn
(add-to-list 'org-structure-template-alist '("m" "#+BEGIN_SRC makefile
?
#+END_SRC"))
(add-to-list 'org-structure-template-alist '("js" "#+BEGIN_SRC js
?
#+END_SRC"))
(add-to-list 'org-structure-template-alist '("sh" "#+BEGIN_SRC shell
?
#+END_SRC"))
(add-to-list 'org-structure-template-alist '("el" "#+BEGIN_SRC emacs-lisp
?
#+END_SRC"))
(add-to-list 'org-structure-template-alist '("py" "#+BEGIN_SRC python
?
#+END_SRC"))
(add-to-list 'org-structure-template-alist '("cpp" "#+BEGIN_SRC C++ :includes <iostream>
?
#+END_SRC"))
(add-to-list 'org-structure-template-alist '("cppnm" "#+BEGIN_SRC C++ :main no
?
#+END_SRC")))))Note: I had to install texlive dependencies for latex framents to work. I found what needed to be installed by running pdflatex on the generated tex file in /tmp/ created by org.
sudo dnf install texlive-scheme-full- texlive-ulem
(with-eval-after-load 'org
(defconst jmn-latex-scale 1.1 "scaling factor for latex fragments")
(setq org-format-latex-options (plist-put org-format-latex-options :scale jmn-latex-scale)))Create a function to align the size of displayed latex framents with overall org-mode font size.
(defun update-org-latex-fragments ()
(org-latex-preview '(64))
(plist-put org-format-latex-options :scale
(+ jmn-latex-scale (* 0.3 text-scale-mode-amount)))
(org-latex-preview '(16)))
(add-hook 'text-scale-mode-hook 'update-org-latex-fragments)Automatically toggle between displaying and editing LaTeX depending on the cursor’s position.
(unless jmn-pure
(use-package org-fragtog
:hook
(org-mode . org-fragtog-mode)))(global-set-key (kbd "C-c x") #'org-html-export-to-html)
(global-set-key (kbd "C-c s") #'org-store-link)
(global-set-key (kbd "C-c i") #'org-insert-link)
(global-set-key (kbd "C-c c") #'org-capture)For syntax highlighting in export html, we want htmlize version > 1.34
(use-package htmlize
:ensure t
:defer t)This org file converts to html on save, via the file’s local variables. See the end of the file.
- Here we designate the auto convert to html on save as safe so we are not prompted to designate it safe on startup the first time.
;; initialize if not already (if (not (bound-and-true-p jmn-org-files-to-html-on-save)) (setq jmn-org-files-to-html-on-save nil)) (defun jmn-org-export-html-on-save-list() (when (member (buffer-file-name) jmn-org-files-to-html-on-save) (org-html-export-to-html))) (add-hook 'after-save-hook #'jmn-org-export-html-on-save-list) (defun jmn-export-to-html-on-save() (interactive) (add-to-list 'jmn-org-files-to-html-on-save (buffer-file-name))) (add-to-list 'safe-local-variable-values '(eval jmn-export-to-html-on-save))
(add-to-list 'safe-local-variable-values `(eval add-hook 'after-save-hook #'org-html-export-to-html))Make the setup file safe for non-pure machines.
(if (and (version<= "29" emacs-version) (not jmn-pure))
(with-eval-after-load 'org
(add-to-list 'org-safe-remote-resources "\\`https://fniessen\\.github\\.io/org-html-themes/org/html-theme-readtheorg\\.setup\\'")))Following the tutorial here.
;; Org Agenda
(setq org-agenda-window-setup 'other-window) ;; other good option: reorganize-frame
;; Exited with ‘q’ or ‘x’ and the old state is restored.
(setq org-agenda-restore-windows-after-quit 1)
(setq org-agenda-span 'day)
;; SOMEDAY itmes are ommitted from GTD interface on purpose
(setq org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "HOLD(h)" "|"
"DONE(d)" "IGNORE(i)")))
(require 'find-lisp) ;; may not be needed"\\.\\(org\\|org_archived\\)$"
; use "\.org$" or "\\.\\(org\\|org_archived\\)$" exclude or include archives
(setq org-agenda-files (find-lisp-find-files jmn-gtd-directory
".*\\.\\(org\\|org_archive\\)$")) ;; "\\.\\(org\\|org_archive\\)$"))
;; level/maxlevel = order in hierarchy
(setq org-refile-targets
'(("projects.org" :maxlevel . 2)
("someday.org" :maxlevel . 1)
("whip.org" :level . 1)
("next.org" :level . 0)))
;; https://github.com/syl20bnr/spacemacs/issues/3094
(setq org-refile-use-outline-path 'file org-outline-path-complete-in-steps nil)
(setq org-refile-allow-creating-parent-nodes 'confirm)
(setq org-agenda-prefix-format '((agenda . " %i %-10:c%t [%e]% s ")
(todo . " %i %-10:c [%-4e] ")
(tags . " %i %-12:c")))
(setq org-deadline-warning-days 30)
(setq org-agenda-start-with-log-mode t) ;; allows us to see closed in calendar
(setq org-log-done 'time) ;; creates CLOSED time tag
(setq org-log-into-drawer t) ;; creates a LOGBOOK drawer for notes
(setq org-agenda-use-time-grid nil) ;; no grid at top of agenda
(setq org-agenda-custom-commands
'(("d" "Dashboard"
((agenda ""
((org-deadline-warning-days 30)))
(todo "NEXT"
((org-agenda-overriding-header "Next Un-Scheduled Tasks")))
(todo "TODO"
((org-agenda-overriding-header "Active Un-Scheduled Tasks")))))
(" " "Agenda"
((agenda ""
((org-agenda-span 'day)
(org-deadline-warning-days 7)))
(todo "TODO"
((org-agenda-overriding-header "To Refile")
(org-agenda-files (list (concat jmn-gtd-directory "inbox.org")))))
(todo "NEXT"
((org-agenda-overriding-header "In Progress")
(org-agenda-files (list (concat jmn-gtd-directory "projects.org")
(concat jmn-gtd-directory "next.org")
(concat jmn-gtd-directory "inbox.org")))))
(todo "TODO"
((org-agenda-overriding-header "Projects")
(org-agenda-files (list (concat jmn-gtd-directory "projects.org")))))
(todo "TODO"
((org-agenda-overriding-header "One-off Tasks")
(org-agenda-files (list (concat jmn-gtd-directory "next.org"))))
(org-agenda-skip-function '(org-agenda-skip-entry-if
'deadline 'scheduled)))
(todo "HOLD"
((org-agenda-overriding-header "HOLD")
(org-agenda-files (list (concat jmn-gtd-directory "projects.org")
(concat jmn-gtd-directory "next.org")
(concat jmn-gtd-directory "inbox.org")))))
))))
(defun jmn-someday() "Quick access to someday.org (no links in agenda)"
(interactive)
(find-file (concat jmn-gtd-directory "someday.org")))
(setq org-agenda-todo-ignore-scheduled 'all) ;; cant get it to work for deadlines(add-hook 'org-agenda-mode-hook 'hl-line-mode)File holding habits must be added to org-agenda-files above
- habits must have the
:STYLE: habitproperty
;; org habit;;
(with-eval-after-load 'org
(add-to-list 'org-modules 'org-habit))
;;(require 'org-habit)
(with-eval-after-load 'org-habit
(setq org-habit-graph-column
(alist-get (system-name) '(("xps" . 56)
("dsk" . 52))
50 nil 'string=))) ;; default is 40Capture templates (The Org Manual)
C-c c i: add an entry to the inboxC-c c w: add an entry to the whip- Creates a time stamp for now, need to add time for when I’d like to be reminded,
C-c . C-c C-c: adds tags to a heading
- Creates a time stamp for now, need to add time for when I’d like to be reminded,
(setq org-capture-templates
`(("t" "Todo [inbox]" entry
(file ,(concat jmn-gtd-directory "inbox.org"))
"* TODO %i%?" :empty-lines 1)
("T" "Todo Today [inbox]" entry
(file ,(concat jmn-gtd-directory "inbox.org"))
"* TODO %?\nDEADLINE: %t" :empty-lines 1)
("l" "Linked Todo [inbox]" entry
(file ,(concat jmn-gtd-directory "inbox.org"))
"* TODO %i%? \n %a" :empty-lines 1)
("s" "Schedule" entry
(file+headline ,(concat jmn-gtd-directory "whip.org") "Whip")
"* %i%? \n %U %^t" :empty-lines 1)
("j" "Journal" entry
(file+datetree ,(concat jmn-gtd-directory "journal.org"))
"* %?\nEntered on %U\n %i\n %a" :empty-lines 1)))(defun org-archive-done-tasks-tree ()
"Archive all DONE tasks in the current org tree"
(interactive)
(org-map-entries
(lambda ()
(org-archive-subtree)
(setq org-map-continue-from (org-element-property :begin (org-element-at-point))))
"/DONE" 'tree))
(defun org-archive-done-tasks-file ()
"Archive all DONE tasks in the current org file"
(interactive)
(org-map-entries
(lambda ()
(org-archive-subtree)
(setq org-map-continue-from (org-element-property :begin (org-element-at-point))))
"/DONE" 'file))https://github.com/jethrokuan/.emacs.d/blob/master/init.el
;; could set in the inbox header instead (where tags are set)
(customize-set-variable 'org-global-properties
'(("Effort_ALL" . "0:05 0:15 0:30 1:00 2:00 4:00")))
(defun jmn/org-agenda-process-inbox-item ()
"Process a single item in the org-agenda."
(interactive)
(org-with-wide-buffer ; what does this do?
;; (org-agenda-set-tags) ; may want in the future
(org-agenda-priority)
(org-agenda-set-effort)
(org-agenda-refile nil nil t)))
(global-set-key (kbd "C-c p") 'jmn/org-agenda-process-inbox-item)(defmacro func-ignore (fnc)
"Return function that ignores its arguments and invokes FNC."
`(lambda (&rest _rest)
(funcall ,fnc)))
(advice-add 'org-archive-done-tasks-tree
:after (func-ignore #'org-save-all-org-buffers))
(advice-add 'org-archive-done-tasks-file
:after (func-ignore #'org-save-all-org-buffers))
(advice-add 'org-refile
:after (func-ignore #'org-save-all-org-buffers))
(advice-add 'org-deadline
:after (func-ignore #'org-save-all-org-buffers))
(advice-add 'org-schedule
:after (func-ignore #'org-save-all-org-buffers))
(advice-add 'org-store-log-note
:after (func-ignore #'org-save-all-org-buffers))
(advice-add 'org-todo
:after (func-ignore #'org-save-all-org-buffers))
;; if agenda is already open, update it with new capture;; work?
(advice-add 'org-capture-finalize
:after (func-ignore #'org-agenda-redo-all))
;; ;; (advice-add 'org-capture-finalize
;; ;; :after (func-ignore #'org-agenda-redo-all))C-c C-s: scheduled timestampC-c C-d: deadline timestampC-c C-w: refile actionable/project items from inbox to appropriate area.C-x C-s: org-save-all-org-buffersC-c C-x e: org-set-efforto: open agenda item in other window –after my change+,-,,: increase, decrease, and set priorityShift-right: advance the todo stateS-<down>: org-agenda-priority-downS-<left>: org-agenda-do-date-earlierS-<right>: org-agenda-do-date-laterS-<up>: org-agenda-priority-up
(defun jmn-agenda (&optional arg) (interactive "P") (org-agenda arg " "))
(global-set-key (kbd "C-c a") 'jmn-agenda)
(with-eval-after-load 'org-agenda
(define-key org-agenda-keymap (kbd "o") 'org-agenda-goto)) ;; more like dired- Slower than vterm at printing large amounts of information.
- For more than one terminal, you must M-x rename-uniquely the terminal.
- C-c prefix for term commands
Line-mode vs char-mode selection shows on the modeline: C-c C-k -> char-mode C-c C-j -> line-mode
Just some changes to make it feel more like the other modes.
- I don’t really use the
M-pnor theM-n, but they could be nice.
(with-eval-after-load 'term
(define-key term-raw-map (kbd "C-o") 'other-window)
(define-key term-raw-map (kbd "M-o") 'previous-multiframe-window)
;; access prev commandsin line mode, though line and char-mode rings are separate
(define-key term-raw-map (kbd "M-p") 'term-send-up)
(define-key term-raw-map (kbd "M-n") 'term-send-down)
;; add "C-x" as escape character and use it for keybindings
(let (term-escape-char)
(term-set-escape-char ?\C-x)) ; set "C-x" as an escape character
(define-key term-raw-map (kbd "C-x C-k") 'kill-current-buffer)
(define-key term-raw-map (kbd "C-c C-k") 'nil)) ; no only used to change from char to line modeArchive: melpa
(use-package eterm-256color
:hook (term-mode . eterm-256color-mode))(if (version<= emacs-version "29" )
(setq explicit-shell-file-name "/bin/bash"))Faster terminal due to being compiled. Default is a better mode than term-mode; it’s like a Char-mode but with ability to access function list with M-x. vterm Documentation
- For more than one terminal, you must M-x rename-uniquely the terminal.
- C-c prefix for term commands
- C-c C-c = send C-c to the terminal (kill running command)
Extra installs needed: For some reason :ensure-system-package did not work here so it is done explicitly in the :init Need to install: cmake, libtool
(use-package vterm
:ensure t
:ensure-system-package ((cmake . "sudo dnf install -y cmake")
(libtool . "sudo dnf install -y libtool" )) ;; compilation
:defer t
:bind (("C-`". vterm) ;; gets overwriteent by vterm-toggle
(:map vterm-mode-map ("C-o" . other-window)))
:config
(jmn-remove-M-1-9-from-mode-map vterm-mode-map)
(defun vterm-send-escape ()
"Sends `ESC` to the libvterm."
(interactive)
(vterm-send-key "<escape>")
)
(setq vterm-max-scrollback 10000)
:init (let ((package "cmake"))
(unless (executable-find package)
(async-shell-command (concat "sudo dnf install -y " package))))
(let ((package "libtool"))
(unless (executable-find package)
(async-shell-command (concat "sudo dnf install -y " package)))))
(use-package vterm-toggle
:after vterm
:config
(setq vterm-toggle-fullscreen-p nil)
(global-set-key (kbd "C-`") 'vterm-toggle)
(add-to-list 'display-buffer-alist
'((lambda(bufname _) (with-current-buffer
bufname (equal major-mode 'vterm-mode)))
(display-buffer-reuse-window display-buffer-at-bottom)
;;(display-buffer-reuse-window display-buffer-in-direction)
;;display-buffer-in-direction/direction/dedicated is added in emacs27
;;(direction . bottom)
;;(dedicated . t) ;dedicated is supported in emacs27
(reusable-frames . visible)
(window-height . 0.3))))To modify a theme it is helpful to use:
list-faces-displayto show the fonts used showing an example of how they lookdescribe-faceto show the font under the cursor
(setq custom-safe-themes t) ;; don't ask if theme is safe
(add-to-list 'custom-theme-load-path "~/.emacs.d/themes/")
(defun jmn-disable-all-themes()
(interactive)
(while custom-enabled-themes
(disable-theme (car custom-enabled-themes))))(use-package gruvbox-theme)(deftheme jmn-gruvbox-general-org
"Altering all the gruvbox themes-- load after loading the gruvbox theme")
;; changes which will be permanent
(with-eval-after-load 'org
(setq org-todo-keyword-faces
`(("NEXT" . ,(face-foreground font-lock-function-name-face))
("HOLD" . ,(face-foreground font-lock-builtin-face)))))
;; changes which will be undone when disabling the theme
(custom-theme-set-faces
'jmn-gruvbox-general-org
`(org-priority ((t (:foreground ,(face-foreground 'font-lock-constant-face)))))
`(org-block-begin-line ((t (:inherit font-lock-comment-face
:background ,(face-background 'default)))))
`(org-block-end-line ((t (:inherit font-lock-comment-face
:background ,(face-background 'default))))))
(provide-theme 'jmn-gruvbox-general-org)(deftheme jmn-gruvbox-dark-hard
"Altering the gruvbox-dark-hard theme-- load after loading the gruvbox theme")
(let ((done-color "gray35"))
;; changes which will be permanent
(with-eval-after-load 'org
(setq org-todo-keyword-faces
`(("NEXT" . ,(face-foreground font-lock-function-name-face))
("HOLD" . ,(face-foreground font-lock-builtin-face))
("DONE" . done-color)
("IGNORE" . done-color))))
;; changes which will be undone when disabling the theme
(custom-theme-set-faces
'jmn-gruvbox-dark-hard
;; Basics
`(mode-line-inactive ((t (:background "gray22" :extend t))))
`(mode-line-active ((t (:background "gray35" :extend t))))
`(line-number ((t :background ,(face-attribute 'default :background))))
`(fringe ((t :background ,(face-attribute 'default :background))))
;; org
`(org-agenda-done ((t (:foreground ,done-color))))
`(org-headline-done ((t (:foreground ,done-color))))
`(org-done ((t (:foreground ,done-color))))
`(org-block ((t (:background "gray8" :extend t))))))
(provide-theme 'jmn-gruvbox-dark-hard)(deftheme jmn-gruvbox-dark-hardest
"Altering the gruvbox-dark-hard theme-- load after loading the gruvbox theme")
(let ((done-color "gray35"))
;; changes which will be permanent
(with-eval-after-load 'org
(setq org-todo-keyword-faces
`(("NEXT" . ,(face-foreground font-lock-function-name-face))
("HOLD" . ,(face-foreground font-lock-builtin-face))
("DONE" . done-color)
("IGNORE" . done-color))))
;; changes which will be undone when disabling the theme
(custom-theme-set-faces
'jmn-gruvbox-dark-hardest
;; Basics
`(default ((t (:background "gray11" :extend t))))
`(link ((t (:foreground "#83a598" :extend t)))) ;;'tree-sitter-hl-face inherits it
`(line-number ((t :background "gray11" :extend t )))
`(fringe ((t :background "gray11" :extend t )))
;; treesitter
`(tree-sitter-hl-face:variable ((t :foreground "#FFA500" :extend t)))
`(tree-sitter-hl-face:variable.parameter ((t :foreground ,(face-attribute 'default :foreground))))
`(tree-sitter-hl-face:label ((t :foreground "#d65d0e" :extend t)))
;; org
`(org-agenda-done ((t (:foreground ,done-color))))
`(org-headline-done ((t (:foreground ,done-color))))
`(org-done ((t (:foreground ,done-color))))
`(org-block ((t (:background "gray7" :extend t))))))
(provide-theme 'jmn-gruvbox-dark-hardest)(deftheme jmn-gruvbox-dark-medium
"Altering the gruvbox-dark-medium theme-- load after loading the gruvbox theme")
(let ((done-color "gray35"))
;; changes which will be permanent
(with-eval-after-load 'org
(setq org-todo-keyword-faces
`(("NEXT" . ,(face-foreground font-lock-function-name-face))
("HOLD" . ,(face-foreground font-lock-builtin-face))
("DONE" . done-color)
("IGNORE" . done-color))))
;; changes which will be undone when disabling the theme
(custom-theme-set-faces
'jmn-gruvbox-dark-medium
;; Basics
;; `(default ((t (:foreground "moccasin" :extend t))))
`(line-number ((t :background ,(face-attribute 'default :background))))
`(font-lock-comment-face ((t (:foreground "#98be65" :extend t))))
;; org
`(org-agenda-done ((t (:foreground ,done-color))))
`(org-headline-done ((t (:foreground ,done-color))))
`(org-done ((t (:foreground ,done-color))))))
(provide-theme 'jmn-gruvbox-dark-medium)(deftheme jmn-gruvbox-light-hard
"Altering the gruvbox-light-hard theme-- load after loading the gruvbox theme")
(let ((done-color "Navajowhite3"))
;; changes which will be permanent
(with-eval-after-load 'org
(setq org-todo-keyword-faces
`(("NEXT" . ,(face-foreground font-lock-function-name-face))
("HOLD" . ,(face-foreground font-lock-builtin-face))
("DONE" . done-color)
("IGNORE" . done-color))))
;; changes which will be undone when disabling the theme
(custom-theme-set-faces
'jmn-gruvbox-light-hard
;; org
`(org-agenda-done ((t (:foreground ,done-color))))
`(org-headline-done ((t (:foreground ,done-color))))
`(org-done ((t (:foreground ,done-color))))
`(org-block ((t (:background "#fbf1c7" :extend t))))))
(provide-theme 'jmn-gruvbox-light-hard)(deftheme jmn-gruvbox-light-medium
"Altering the gruvbox-light-medium theme-- load after loading the gruvbox theme")
(let ((done-color "Navajowhite3"))
;; changes which will be permanent
(with-eval-after-load 'org
(setq org-todo-keyword-faces
`(("NEXT" . ,(face-foreground font-lock-function-name-face))
("HOLD" . ,(face-foreground font-lock-builtin-face))
("DONE" . done-color)
("IGNORE" . done-color))))
;; changes which will be undone when disabling the theme
(custom-theme-set-faces
'jmn-gruvbox-light-medium
;; org
`(org-agenda-done ((t (:foreground ,done-color))))
`(org-headline-done ((t (:foreground ,done-color))))
`(org-done ((t (:foreground ,done-color))))))
(provide-theme 'jmn-gruvbox-light-medium)(deftheme jmn-gruvbox-light-soft
"Altering the gruvbox-light-soft theme-- load after loading the gruvbox theme")
(let ((done-color "Navajowhite3"))
;; changes which will be permanent
(with-eval-after-load 'org
(setq org-todo-keyword-faces
`(("NEXT" . ,(face-foreground font-lock-function-name-face))
("HOLD" . ,(face-foreground font-lock-builtin-face))
("DONE" . done-color)
("IGNORE" . done-color))))
;; changes which will be undone when disabling the theme
(custom-theme-set-faces
'jmn-gruvbox-light-soft
;; org
`(org-agenda-done ((t (:foreground ,done-color))))
`(org-headline-done ((t (:foreground ,done-color))))
`(org-done ((t (:foreground ,done-color))))
`(org-block ((t (:background "#ebdbb2" :extend t))))))
(provide-theme 'jmn-gruvbox-light-soft)
(defun jmn-load-gruvbox-dark-medium ()
"Theme for a medium dark time"
(interactive)
(jmn-disable-all-themes)
(load-theme 'gruvbox-dark-medium )
(load-theme 'jmn-gruvbox-general-org)
(load-theme 'jmn-gruvbox-dark-medium))
(defun jmn-load-gruvbox-dark-hard ()
"Theme for dark time"
(interactive)
(jmn-disable-all-themes)
(load-theme 'gruvbox-dark-hard )
(load-theme 'jmn-gruvbox-general-org)
(load-theme 'jmn-gruvbox-dark-hard))
(defun jmn-load-gruvbox-dark-hardest()
"Theme for very darkest of times"
(interactive)
(jmn-disable-all-themes)
(load-theme 'gruvbox-dark-hard )
(load-theme 'jmn-gruvbox-general-org)
(load-theme 'jmn-gruvbox-dark-hardest))
(defun jmn-load-gruvbox-light-medium()
"Theme for light time"
(interactive)
(jmn-disable-all-themes)
(load-theme 'gruvbox-light-medium )
(load-theme 'jmn-gruvbox-general-org)
(load-theme 'jmn-gruvbox-light-medium))
(defun jmn-load-gruvbox-light-hard()
"Theme for very light time"
(interactive)
(jmn-disable-all-themes)
(load-theme 'gruvbox-light-hard )
(load-theme 'jmn-gruvbox-general-org)
(load-theme 'jmn-gruvbox-light-hard))
(defun jmn-load-gruvbox-light-soft()
"Theme for very light time"
(interactive)
(jmn-disable-all-themes)
(load-theme 'gruvbox-light-soft )
(load-theme 'jmn-gruvbox-general-org)
(load-theme 'jmn-gruvbox-light-soft))(deftheme jmn-light
"Altering the default theme-- load after loading the default theme")
;; variables which will be permanent
(with-eval-after-load 'org
(setq org-todo-keyword-faces
`(("TODO" . "Red1")
("NEXT" . "orange")
("HOLD" . "Black")
("IGNORE" . "gray60"))))
(custom-theme-set-faces
'jmn-light
;; Org-mode
`(org-block ((t (:background "gray93" :extend t))))
;; Tab bar
'(tab-bar ((t (:inherit org-default :extend t))))
`(tab-bar-tab ((t (:background "darkseagreen2"))))
'(tab-bar-tab-inactive ((t (:inherit org-default :extend t)))))
(provide-theme 'jmn-light)(deftheme jmn-wombat
"Altering the wombat theme-- load after loading the wombat theme")
;; variables which will be permanent
(with-eval-after-load 'org
(setq org-todo-keyword-faces
`(("TODO" . "Pink")
("NEXT" . "gold2")
("HOLD" . "orange3")
("IGNORE" . "#99968b"))))
(custom-theme-set-faces
'jmn-wombat
;; Basics
`(mode-line ((t (:background "gray44" :extend t))))
;; Org-mode
`(org-block ((t (:background "gray10" :extend t))))
`(org-level-7 ((t (:background "MediumPurple1" :extend t))))
;; Tab bar
'(tab-bar ((t (:inherit org-default :extend t))))
'(tab-bar-tab ((t (:inherit mode-line :weight bold :box nil :extend t))))
'(tab-bar-tab-inactive ((t (:inherit org-default :extend t)))))
(provide-theme 'jmn-wombat)(defun jmn-load-pure-light-theme()
(interactive)
(jmn-disable-all-themes)
(load-theme 'jmn-light))
(defun jmn-load-pure-dark-theme()
(interactive)
(jmn-disable-all-themes)
(load-theme 'wombat)
(load-theme 'jmn-wombat))(if jmn-dark-mode
(if (eq system-type 'gnu/linux) ;; dark theme looks bad on windows
(if jmn-pure
(jmn-load-pure-dark-theme) ;; dark, linux, pure
(jmn-load-gruvbox-dark-hardest))
(load-theme 'jmn-light)) ;; dark on windows (show light)
(load-theme 'jmn-light)) ;; non-dark(if (window-system)
(set-frame-height (selected-frame) 53))This allows aliases set in .bashrc can then be used when running shells
It also does not causes a print of errors which stops the use of getenv
(if (eq system-type 'gnu/linux)
(setq shell-command-switch "-ic")) ;; add -i so it loads .bashrc (aliases!)Major changes for windows. Small changes also exist in the rest of the config.
(cond
((eq system-type 'windows-nt)
;;set font
(when (member "Consolas" (font-family-list))
(set-frame-font "Consolas" t t))
(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on) ;; needed?
(add-hook 'term-mode-hook 'ansi-color-for-comint-mode-on) ;; needed?
;; (setq explicit-shell-file-name "c:/Program Files/Git/bin/bash.exe") ;; gitbash
(setq explicit-shell-file-name "c:/Program Files/Emacs/libexec/emacs/27.2/x86_64-w64-mingw32/cmdproxy.exe") ;; Emacs recommended
(setq shell-file-name explicit-shell-file-name)
;; give emacs access to gnu coreutils, though should already be in =path=
(add-to-list 'exec-path "c:/Program Files/Git/") ;; git-bash, git-cmd
(add-to-list 'exec-path "c:/Program Files/Git/bin") ;; bash
(add-to-list 'exec-path "c:/Program Files/Git/usr/bin") ;; coreutils (diff, ls, etc.)
(add-to-list 'exec-path "c:/Program Files/Python312") ;; python-- not working
;; likey no octave, so read only matlab files
(add-hook 'octave-mode-hook 'read-only-mode)
;; external ls for directories first support (dired) -- may not be needed with above
(setq ls-lisp-use-insert-directory-program t) ;; use external ls
(setq inserft-directory-program "c:/Program Files/Git/user/bin/ls.exe") ;; ls loc
))(setq image-types '(svg png gif tiff jpeg xpm xbm pbm))Was needed at one point– keeping just in case it is need in the future.
(if (version<= "29" emacs-version)
(progn
(defun toggle-full-screen-with-transparency ()
"Toggle full screen and adjust frame transparency."
(interactive)
(let ((current-alpha (frame-parameter nil 'alpha-background)))
(transparency 100)
(toggle-frame-fullscreen)
(sit-for 0.7)
(transparency current-alpha)
))
;; (global-unset-key (kbd "<f11>"))
;; (global-set-key (kbd "<f11>") 'toggle-full-screen-with-transparency)
))source: syl20bnr/spacemacs#7262
(defun jmn-set-background-unspecified ()
"Set background of buffer and line numbers to unspecified"
(interactive)
(set-face-background 'default "unspecified-bg" (selected-frame))
(set-face-background 'line-number "unspecified-bg"))
(if jmn-term
(add-hook 'window-setup-hook 'jmn-set-background-unspecified))For unknown reasons I must change ("dvipng -D %D -T tight -o %O %f") to ("dvipng -D %D -T tight -o %O %F") to preview LaTeX in org-mode. All of the code below is used only to make this one small change.
(setq org-preview-latex-process-alist
'((dvipng :programs
("latex" "dvipng")
:description "dvi > png" :message "you need to install the programs: latex and dvipng." :image-input-type "dvi" :image-output-type "png" :image-size-adjust
(1.0 . 1.0)
:latex-compiler
("latex -interaction nonstopmode -output-directory %o %f")
:image-converter
("dvipng -D %D -T tight -o %O %F")
:transparent-image-converter
("dvipng -D %D -T tight -bg Transparent -o %O %f"))
(dvisvgm :programs
("latex" "dvisvgm")
:description "dvi > svg" :message "you need to install the programs: latex and dvisvgm." :image-input-type "dvi" :image-output-type "svg" :image-size-adjust
(1.7 . 1.5)
:latex-compiler
("latex -interaction nonstopmode -output-directory %o %f")
:image-converter
("dvisvgm %f --no-fonts --exact-bbox --scale=%S --output=%O"))
(imagemagick :programs
("latex" "convert")
:description "pdf > png" :message "you need to install the programs: latex and imagemagick." :image-input-type "pdf" :image-output-type "png" :image-size-adjust
(1.0 . 1.0)
:latex-compiler
("pdflatex -interaction nonstopmode -output-directory %o %f")
:image-converter
("convert -density %D -trim -antialias %f -quality 100 %O"))))- Won’t work with
#+ATTR_ORG :width 600 - This will set it globally for the time being
(setq org-image-actual-width 600)(defun jmn-set-files-read-only ()
"Set buffers to read only if have one of the extensions hard coded in the function"
(dolist (extension'("dat" "out"))
(if (string-match extension (car (last (split-string (buffer-name) "\\."))))
(read-only-mode 1))))
(add-hook 'find-file-hook 'jmn-set-files-read-only)(defun jmn-set-files-display-line-numbers ()
"Set buffers to read only if have one of the extensions hard coded in the function"
(dolist (extension'("txt"))
(if (string-match extension (car (last (split-string (buffer-name) "\\."))))
(display-line-numbers-mode 1))))
(add-hook 'find-file-hook 'jmn-set-files-display-line-numbers)Recentf is needed for recent files on the dashboard.
(recentf-mode 1) ;; needed for recent files in dashboard
(setq recentf-max-menu-items 25) ;; max number of entries
;; (run-at-time nil (* 5 60) 'recentf-save-list) ;; save recent files periodically
;; Exclude the following files from the recents list
(add-to-list 'recentf-exclude "~/.emacs.d/recentf")
(add-to-list 'recentf-exclude (concat jmn-gtd-directory "inbox.org"))
(add-to-list 'recentf-exclude (concat jmn-gtd-directory "next.org"))
(add-to-list 'recentf-exclude (concat jmn-gtd-directory "whip.org"))
(add-to-list 'recentf-exclude (concat jmn-gtd-directory "someday.org"))
(add-to-list 'recentf-exclude (concat jmn-gtd-directory "journal.org"))
(add-to-list 'recentf-exclude (concat jmn-gtd-directory "habits.org"))
(add-to-list 'recentf-exclude
(concat (file-name-directory jmn-config-location) "emacs.html"))
(if (or jmn-pure (not jmn-connected-extras))
(progn
;; display recent files on startup
;; (add-hook 'after-init-hook (lambda () (recentf-open-files)))
;; display projects.org on startup
(add-hook 'after-init-hook
(lambda () (find-file
(concat jmn-gtd-directory "projects.org"))))
;; make display recent files the dashboard command
(global-set-key (kbd "C-c d") 'recentf-open-files)))(if (version<= "27" emacs-version)
(progn
(setq tab-bar-close-button-show nil ; remove close button
tab-bar-show 1 ; only show tab bar if #tabs>1
tab-bar-select-tab-modifiers '(meta) ; Alt-i switch to the tab numbered i
tab-bar-tab-hints t) ; show a number on each tabs
(tab-bar-mode 1)
(tab-bar-close-other-tabs) ; ensures (tab-bar-mode 1) works on older systems
(defun jmn-create-my-tabs()
"Create my default tabs"
(interactive)
(tab-close-other)
(delete-other-windows)
;; TAB 1
(tab-bar-rename-tab "gtd")
(find-file (concat jmn-gtd-directory "projects.org"))
(jmn-agenda)
;; TAB 2
(tab-bar-new-tab)
(tab-bar-rename-tab "workspace")
(dired "/home/ape/Programming/projects/radar/radar-signal-processing")
(unless jmn-pure
(magit-status))
;; ;; TAB
;; (tab-bar-new-tab)
;; (if jmn-pure
;; (progn
;; (term "/bin/bash")
;; (tab-bar-rename-tab "term"))
;; (progn
;; (vterm)
;; (tab-bar-rename-tab "vterm")))
;; (delete-other-windows)
;; TAB N
(tab-bar-new-tab)
(tab-bar-rename-tab "config")
(find-file jmn-config-location)
(unless jmn-pure
(magit-status))
(tab-bar-select-tab 2))))Dash board for initial startup of emacs. github link
- For the icons to display correctly, I needed to execute
all-of-the-icons-install-fonts.
(if jmn-connected-extras
(progn
(defun my-dashboard-hook()
"Needed to define these after hook for some reason"
(define-key dashboard-mode-map (kbd "n") 'dashboard-next-line)
(define-key dashboard-mode-map (kbd "p") 'dashboard-previous-line))
(use-package dashboard
:ensure t
:init (dashboard-setup-startup-hook)
:bind ("C-c d" . dashboard-open)
:hook ((dashboard-mode . hl-line-mode)
(dashboard-mode . my-dashboard-hook))
:config
(setq dashboard-banner-logo-title "Habits, not goals.")
(setq dashboard-startup-banner 2) ;; (nil . no-banner) ([1-5] . plain-text banners)
(setq dashboard-center-content 1)
(setq dashboard-show-shortcuts 1) ;; show the single-character shortcuts
(setq dashboard-items '((recents . 5)
(bookmarks . 5)
(projects . 5)
(agenda . 5)
(registers . 5)))
(setcdr (assoc 'projects dashboard-item-shortcuts) "j")
(setq dashboard-set-heading-icons t)
(setq dashboard-set-file-icons t)
(setq dashboard-projects-backend 'project-el)
(dashboard-modify-heading-icons '((recents . "file-text")))
(setq dashboard-set-footer nil)
(setq dashboard-startupify-list
'(dashboard-insert-banner
dashboard-insert-newline
dashboard-insert-banner-title
dashboard-insert-newline
dashboard-insert-init-info
dashboard-insert-items
dashboard-insert-newline
;;dashboard-insert-footer
)))))(unless jmn-pure
(use-package hnreader))To highlight the LLM response, use gptel-highlight-mode
- requires transient – shipped in emacs in 29.1
;; Helper function to read from authinfo.gpg
(defun my-get-api-key (host)
(let ((entry (car (auth-source-search :host host))))
(when entry
(funcall (plist-get entry :secret)))))
;; Configure gptel to use the keys
(use-package gptel
:defer t
:ensure t
:config
(global-set-key(kbd "C-c RET") 'gptel-send)
(setq gptel-default-mode 'org-mode)
(gptel-make-gemini "Gemini" :key (my-get-api-key "generativelanguage.googleapis.com") :stream t)
(setq
gptel-model 'gemini-2.5-pro
gptel-backend (gptel-make-gemini "Gemini"
:key (my-get-api-key "generativelanguage.googleapis.com")
:stream t))
)