Kostya's Emacs Configuration
Table of Contents
- Setup
- Defaults
- Visuals
- File browsing
- Interaction
- Org mode
- General settings
- Styling
- BibTeX integration
- Polymode and ESS for reading and exporting .rmd files
- LaTeX export options
- Handling PDFs
- TOC in Org files
- Agenda
- Google calendar integration
- Org-clock
- Org-capture templates
- Org-Roam
- org-roam-bibtex and org-noter integration
- Org-related extensions
- Website with Org
- LLM
- LaTeX
- Emacs Mail
- Python
- Snippets
Setup
init.el
Code
I use org-babel-tangle
and this document, written in Org mode.
The code below extracts the elisp configuration code and creates/overwrites the
~/.emacs.d/init.el
configuration file when the .org
-file is saved.
Therefore, changes are only done in the .org
-file, where writing longer
comments about how things work and why things are added is easier,
hence the resulting init.el
-file remains clean and without excessive comments.
This is what the init.el
file should look like, prompting it to tangle the init.org
file and replace itself with that code.
;; We need org in order to make use of the tangling functionality (require 'org) ;; Open the org-mode configuration (find-file (concat user-emacs-directory "init.org")) ;; Tangle the file (org-babel-tangle) ;; Load the tangled file (load-file (concat user-emacs-directory "init.el")) ;; Byte-compile it (byte-compile-file (concat user-emacs-directory "init.el"))
Git tracking & practicalities
We also don't need to track the generated init.el
file on Git, since it is directly derived from init.org
.
This code makes Git ignore changes to init.el
:
git update-index --assume-unchanged init.el
If you do want to start tracking the file again, you can use:
git update-index --no-assume-unchanged init.el
Lexical scoping
First, I want lexical scoping for the init
-file, so I will add that to the top of the file.
;;; -*- lexical-binding: t -*-
Tangling
The init.el
should (after the first run) mirror the source blocks in
the init.org
. We can use C-c C-v t
to run org-babel-tangle
,
which extracts the code blocks from the current file into
a source-specific file (in this case a .el
-file).
To avoid doing this each time we can add a function to the
after-save-hook
ensuring that .org
-document always tangles and byte-compiles after changes.
(defun tangle-init () "If the current buffer is init.org, the code-blocks are tangled, and the tangled file is compiled." (when (equal (buffer-file-name) (expand-file-name (concat user-emacs-directory "init.org"))) ;; Avoid running hooks when tangling. (let ((prog-mode-hook nil)) (org-babel-tangle) (byte-compile-file (concat user-emacs-directory "init.el"))))) (add-hook 'after-save-hook 'tangle-init)
Start-up
The line below is only for the KUT-lab that uses proxy!
(setq url-proxy-services '(("no_proxy" . "^\\(localhost\\|172.16.2.30\\)") ("http" . "proxy.noc.kochi-tech.ac.jp:3128") ("https" . "proxy.noc.kochi-tech.ac.jp:3128")))
Below are some tweaks to improve startup performance. First common tweak is to disable the garbage collector during initialization, and then resetting it afterwards.
(setq gc-cons-threshold (* 50 1000 1000)) ;; Set and reset threshold (let ((old-gc-treshold gc-cons-threshold)) (setq gc-cons-threshold most-positive-fixnum) (add-hook 'after-init-hook (lambda () (setq gc-cons-threshold old-gc-treshold)))) (setq inhibit-startup-screen t) ;; disable startup screen
Fix IO bugs.
(setq process-adaptive-read-buffering nil) (setq read-process-output-max (* 4 1024 1024))
Set Emacs user directory explicitly:
(setq user-emacs-directory "~/.emacs.d/") (setq default-directory "~/")
Set UFT-8 as preferred coding system.
(set-language-environment "UTF-8")
Packages
To manage downloaded packages, Emacs comes with package.el
installed. In
addition, I want to use use-package
, so let's make sure we have those loaded.
(require 'package) (require 'use-package) ;; (setq use-package-always-ensure t)
Next, I'll set up my package sources. These are very common and well-maintained mirrors.
(setq package-archives '(("GNU ELPA" . "https://elpa.gnu.org/packages/") ("MELPA" . "https://melpa.org/packages/") ("ORG" . "https://orgmode.org/elpa/") ("MELPA Stable" . "https://stable.melpa.org/packages/") ("nongnu" . "https://elpa.nongnu.org/nongnu/")) package-archive-priorities '(("GNU ELPA" . 20) ("MELPA" . 15) ("ORG" . 10) ("MELPA Stable" . 5) ("nongnu" . 0))) (package-initialize)
Defaults
General settings
(setq default-directory "~/" ;; Set default directory scroll-margin 0 ;; Space between top/bottom auto-revert-interval 1 ;; Refresh buffers fast echo-keystrokes 0.1 ;; Show keystrokes fast frame-inhibit-implied-resize 1 ;; Don't resize frame implicitly sentence-end-double-space nil ;; No double spaces recentf-max-saved-items 1000 ;; Show more recent files save-interprogram-paste-before-kill t ;; Save copies between programs auto-fill-function 'do-auto-fill ;; Auto-fill-mode everywhere warning-minimum-level :emergency ;; Suppress startup warnings ; auto-fill-mode -1 ;; visual fill fill-column 99999 debug-on-error t split-width-threshold 0 ;; default vertical split for new buffers split-height-threshold nil )
Short answers
I want to only provide short answers to Emacs' prompts. E.g., I want to type "y" or "n" instead of out "yes" or "no".
(setq use-short-answers t)
Shortcuts for source-blocks
(require 'org-tempo) (add-to-list 'org-structure-template-alist '("sh" . "src shell")) (add-to-list 'org-structure-template-alist '("la" . "src latex")) (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) (add-to-list 'org-structure-template-alist '("py" . "src python")) (add-to-list 'org-structure-template-alist '("ipy" . "src ipython")) (add-to-list 'org-structure-template-alist '("ju" . "src jupyter-ipython")) (add-to-list 'org-structure-template-alist '("r" . "src R")) (add-to-list 'org-structure-template-alist '("ai" . "src ai")) (add-to-list 'org-structure-template-alist '("pl" . "src plantuml")) (add-to-list 'org-structure-template-alist '("gpt" . "src chatgpt-shell"))
Auto-saved directory
To avoid clutter, let's put all the auto-saved files into one and the same directory.
(defvar emacs-autosave-directory (concat user-emacs-directory "auto-save-list/") "This variable dictates where to put auto saves. It is set to a directory called autosaves located wherever your .emacs.d/ is located.") ;; Sets all files to be backed up and auto saved in a single directory. (setq backup-directory-alist `((".*" . ,emacs-autosave-directory)) auto-save-file-name-transforms `((".*" ,emacs-autosave-directory t)))
Keys' directory
(setq auth-sources '("~/.emacs.d/secrets/.authinfo.gpg"))
(use-package exec-path-from-shell :ensure t) (when (memq window-system '(mac ns x)) (exec-path-from-shell-initialize)) (exec-path-from-shell-copy-env "OPENAI_API_KEY")
Editor configuration
I want to use the EditorConfig plugin, which helps maintain consistent coding styles across editors when collaborating.
(use-package editorconfig :ensure t :config (editorconfig-mode 1))
Smoother scrolling
I want scrolling to be a lot slower than it is by default.
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; 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 scroll-step 1) ;; keyboard scroll one line at a time (setq use-dialog-box nil) ;; Disable dialog
Visuals
Optimizing the look
(dolist (mode '(tool-bar-mode ;; Remove toolbar blink-cursor-mode)) ;; Solid cursor, not blinking (funcall mode 0))
Frame settings
Emacs maximized and full-screen on a startup.
(set-frame-parameter (selected-frame) 'fullscreen 'maximized) (add-to-list 'default-frame-alist '(fullscreen . maximized))
Automatically resize frames your are working in
(use-package golden-ratio :defer t )
Delimiters, brackets, cursor
Bar cursor instead of a block cursor.
(setq-default cursor-type 'bar)
When coding, I want my delimiters (parentheses, brackets, etc.) to be colorized in pairs: rainbow-delimiters does exactly that.
(use-package rainbow-delimiters :ensure t :hook (prog-mode . rainbow-delimiters-mode)) ;; Highlight-parentheses (require 'highlight-parentheses) (global-highlight-parentheses-mode t)
Smart parentheses
(use-package smartparens :ensure smartparens ;; install the package :hook (prog-mode text-mode markdown-mode) ;; add `smartparens-mode` to these hooks :config (require 'smartparens-config)) ;; (add-hook 'LaTeX-mode-hook 'smartparens-mode) ;; (smartparens-global-mode t) ;; (sp-pair "\\[" "\\]") ;; (sp-pair "'" "") ;; (sp-pair "`" "") ;; (sp-pair "``" "''") ;; (show-smartparens-global-mode t)
Enable line numbers globally
;; (global-display-line-numbers-mode 1)
Font
(set-face-attribute 'default nil :font "DejaVu Sans Mono 15")
Theme
;; (use-package ef-themes ;; :config ;; (load-theme 'ef-tritanopia-dark t)) ;; (use-package kaolin-themes ;; :config ;; (load-theme 'kaolin-galaxy t)) (use-package doom-themes :ensure t :config ;; Global settings (defaults) (setq doom-themes-enable-bold t ; if nil, bold is universally disabled doom-themes-enable-italic t) ; if nil, italics is universally disabled (load-theme 'doom-monokai-pro t) ;; Enable flashing mode-line on errors (doom-themes-visual-bell-config) ;; Enable custom neotree theme (all-the-icons must be installed!) (doom-themes-neotree-config) ;; or for treemacs users (setq doom-themes-treemacs-theme "doom-colors") ; use "doom-colors" for less minimal icon theme (doom-themes-treemacs-config) ;; Corrects (and improves) org-mode's native fontification. (doom-themes-org-config))
Customize the color of the text selected by cursor
(set-face-attribute 'region nil :background "#d897f0" :foreground "#0b0309")
Add transparency
(add-to-list 'default-frame-alist '(alpha-background . 90))
Mode line
Configuration takes from here
;; Disables showing system load in modeline, useless anyway (setq display-time-default-load-average nil) (line-number-mode) (column-number-mode) (display-time-mode -1) (size-indication-mode 0) (use-package hide-mode-line :commands (hide-mode-line-mode)) (use-package doom-modeline :ensure t :init (doom-modeline-mode 1) :config (setq doom-modeline-buffer-file-name-style 'truncate-upto-project doom-modeline-enable-word-count nil doom-modeline-buffer-encoding nil doom-modeline-icon t ;; Enable/disable all icons doom-modeline-modal-icon t ;; Icon for Evil mode doom-modeline-time t doom-modeline-major-mode-icon t doom-modeline-major-mode-color-icon t doom-modeline-buffer-modification-icon t doom-modeline-buffer-state-icon t doom-modeline-bar-width 3 doom-modeline-text-height 140 doom-modeline-height 30))
Adaptive wrap
Use adaptive-wrap to visually wrap lines.
(use-package adaptive-wrap :defer t :hook (visual-line-mode . adaptive-wrap-prefix-mode))
Minor modes for efficient writing
;; Text centering (use-package olivetti :defer t :config (setq-default olivetti-body-width (+ fill-column 4))) ;; Dimming surrounding text (use-package focus :defer t)
File browsing
Neotree
(use-package neotree :ensure t :config (global-set-key (kbd "C-c n e") 'neotree-toggle) (setq neo-window-fixed-size nil) (setq neo-theme (if (display-graphic-p) 'icons 'arrow)))
Switching between windows
(use-package ace-window :config (global-set-key (kbd "M-p") 'ace-window))
Dired
(use-package all-the-icons-dired :config (add-hook 'dired-mode-hook 'all-the-icons-dired-mode))
Dashboard
(use-package dashboard :config (dashboard-setup-startup-hook) :custom (dashboard-startup-banner 'logo) (dashboard-banner-logo-title nil) (dashboard-center-content t) (dashboard-icon-type 'all-the-icons) (dashboard-set-heading-icons t) (dashboard-set-file-icons t) (dashboard-set-navigator t) (dashboard-set-init-info t) (dashboard-page-separator "\n\n\n") (dashboard-projects-backend 'project-el) (dashboard-display-icons-p t) (dashboard-items '( (recents . 5) (agenda . 5) (projects . 5) (bookmarks . 5) )))
Interaction
Tweaking default behavior
(dolist (mode '(column-number-mode ;; Show current column number in mode line delete-selection-mode ;; Replace selected text when yanking dirtrack-mode ;; Directory tracking in shell ;; global-so-long-mode ;; Mitigate performance for long lines global-visual-line-mode ;; Break lines instead of truncating them global-auto-revert-mode ;; Revert buffers automatically when they change recentf-mode ;; Remember recently opened files savehist-mode ;; Remember minibuffer prompt history save-place-mode ;; Remember last cursor location in file show-paren-mode)) ;; Highlight matching parentheses (funcall mode 1)) (setq history-length 25) ;; Only save the last 25 minibuffer prompts (setq global-auto-revert-non-file-buffers t) ;; Revert Dired and other buffers
Terminal emulator
Make vterm not to double check before killing an instance of the terminal.
One function is for toggling the vterm
buffer with the other open buffer, and another binds a
separate vterm
instance to each M-n
keystroke.
The configuration is taken from here.
(use-package vterm :defer t :preface (let ((last-vterm "")) (defun toggle-vterm () (interactive) (cond ((string-match-p "^\\vterm<[1-9][0-9]*>$" (buffer-name)) (goto-non-vterm-buffer)) ((get-buffer last-vterm) (switch-to-buffer last-vterm)) (t (vterm (setq last-vterm "vterm<1>"))))) (defun goto-non-vterm-buffer () (let* ((r "^\\vterm<[1-9][0-9]*>$") (vterm-buffer-p (lambda (b) (string-match-p r (buffer-name b)))) (non-vterms (cl-remove-if vterm-buffer-p (buffer-list)))) (when non-vterms (switch-to-buffer (car non-vterms))))) (defun switch-vterm (n) (let ((buffer-name (format "vterm<%d>" n))) (setq last-vterm buffer-name) (cond ((get-buffer buffer-name) (switch-to-buffer buffer-name)) (t (vterm buffer-name) (rename-buffer buffer-name)))))) :config ;; key to stop terminal process (define-key vterm-mode-map (kbd "C-c C-c") 'vterm--self-insert) ;; ;; Don't query about killing vterm buffers, just kill it (defadvice vterm (after kill-with-no-query nil activate) (set-process-query-on-exit-flag (get-buffer-process ad-return-value) nil)))
Spelling
See the instruction on setting up personal dictionary here.
;; find aspell and hunspell automatically (cond ;; try hunspell at first ;; if hunspell does NOT exist, use aspell ((executable-find "hunspell") (setq ispell-program-name "hunspell") (setq ispell-local-dictionary "en_US") (setq ispell-local-dictionary-alist ;; Please note the list `("-d" "en_US")` contains ACTUAL parameters passed to hunspell ;; You could use `("-d" "en_US,en_US-med")` to check with multiple dictionaries '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_US") nil utf-8))) ;; new variable `ispell-hunspell-dictionary-alist' is defined in Emacs ;; If it's nil, Emacs tries to automatically set up the dictionaries. (when (boundp 'ispell-hunspell-dictionary-alist) (setq ispell-hunspell-dictionary-alist ispell-local-dictionary-alist))) ((executable-find "aspell") (setq ispell-program-name "aspell") ;; Please note ispell-extra-args contains ACTUAL parameters passed to aspell (setq ispell-extra-args '("--sug-mode=ultra" "--lang=en_US")))) (setq ispell-personal-dictionary "~/MEGA/Job/Kochi/Emacs/Emacs_dictionary/.aspell.en.pws") (add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:")) ;; do not check code blocks (add-to-list 'ispell-skip-region-alist '("#\\+begin_src" . "#\\+end_src")) (add-hook 'text-mode-hook 'flyspell-mode) (add-hook 'LaTeX-mode-hook 'flyspell-mode) (add-hook 'prog-mode-hook 'flyspell-prog-mode) (flyspell-mode 1)
harper
(from here)
(use-package eglot :defer :hook (python-mode . eglot-ensure) ;; (markdown-mode . eglot-ensure) ;; (prog-mode . eglot-ensure) ;; (LaTeX-mode . eglot-ensure) ;; (org-mode . eglot-ensure) :bind (:map eglot-mode-map ("C-c e r" . eglot-rename) ("C-c e a" . eglot-code-actions) ("C-c e o" . eglot-code-action-organize-imports) ("C-c e d" . eldoc) ("C-c e f" . eglot-format) ("C-c e =" . eglot-format)) ;; :config ;; (add-to-list 'eglot-server-programs ;; '(markdown-mode . ("harper-ls" "--stdio")) ;; '(prog-mode . ("harper-ls" "--stdio")) ;; '(LaTeX-mode . ("harper-ls" "--stdio")) ;; '(org-mode . ("harper-ls" "--stdio")) ;; ) :custom (eglot-autoshutdown t) ;; default is to leave servers runing when last buffer exits (eglot-extend-to-xref nil)) ;; cover files found through xref (M-.)
(use-package highlight-indent-guides :ensure t :hook (prog-mode . highlight-indent-guides-mode) ;; (ess-mode . highlight-indent-guides-mode) :config (setq highlight-indent-guides-method 'character) )
Some flyspell enhancements
(use-package consult-flyspell :config ;; default settings (setq consult-flyspell-select-function nil consult-flyspell-set-point-after-word t consult-flyspell-always-check-buffer nil))
Auto-complete mode
(use-package corfu :custom (corfu-cycle t) ;; Enable cycling for `corfu-next/previous' (corfu-auto t) ;; Enable auto completion (corfu-auto-delay 0) ;; No delay (corfu-auto-prefix 2) ;; Start when this many characters have been typed (corfu-popupinfo-delay 0.5) ;; Short delay ;; (corfu-separator ?\s) ;; Orderless field separator ;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary ;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match ;; (corfu-preview-current nil) ;; Disable current candidate preview (corfu-preselect 'prompt) ;; Preselect the prompt ;; (corfu-on-exact-match nil) ;; Configure handling of exact matches :init (global-corfu-mode)) (use-package emacs :init ;; TAB cycle if there are only few candidates (setq completion-cycle-threshold 3) ;; Hide commands in M-x which do not apply to the current mode. ;; Corfu commands are hidden, since they are not supposed to be used via M-x. (setq read-extended-command-predicate #'command-completion-default-include-p) ;; Enable indentation+completion using the TAB key. ;; `completion-at-point' is often bound to M-TAB. (setq tab-always-indent 'complete))
(use-package cape ;; Bind dedicated completion commands ;; Alternative prefix keys: C-c p, M-p, M-+, ... :bind (("C-c p p" . completion-at-point) ;; capf ("C-c p t" . complete-tag) ;; etags ("C-c p d" . cape-dabbrev) ;; or dabbrev-completion ("C-c p h" . cape-history) ("C-c p f" . cape-file) ("C-c p k" . cape-keyword) ("C-c p s" . cape-symbol) ("C-c p a" . cape-abbrev) ("C-c p l" . cape-line) ("C-c p w" . cape-dict) ("C-c p \\" . cape-tex) ("C-c p _" . cape-tex) ("C-c p ^" . cape-tex) ("C-c p &" . cape-sgml) ("C-c p r" . cape-rfc1345)) :init ;; Add `completion-at-point-functions', used by `completion-at-point'. ;; NOTE: The order matters! (add-to-list 'completion-at-point-functions #'cape-dabbrev) (add-to-list 'completion-at-point-functions #'cape-file) (add-to-list 'completion-at-point-functions #'cape-elisp-block) (add-to-list 'completion-at-point-functions #'cape-history) (add-to-list 'completion-at-point-functions #'cape-keyword) (add-to-list 'completion-at-point-functions #'cape-tex) ;;(add-to-list 'completion-at-point-functions #'cape-sgml) ;;(add-to-list 'completion-at-point-functions #'cape-rfc1345) ;;(add-to-list 'completion-at-point-functions #'cape-abbrev) (add-to-list 'completion-at-point-functions #'cape-dict) ;;(add-to-list 'completion-at-point-functions #'cape-symbol) ;;(add-to-list 'completion-at-point-functions #'cape-line) )
(use-package orderless :ensure t :config (setq completion-styles '(orderless basic partial-completion) completion-category-overrides '((file (styles basic partial-completion))) orderless-component-separator "[ |]"))
Which-key
This package enables display of key bindings
(use-package which-key :init (which-key-mode) :diminish which-key-mode :config (setq which-key-idle-delay 0.3))
Ivy mode
This package provides enhanced explanations to the functions. Configuration is taken from here.
- While in an Ivy minibuffer, you can search within the current results by using S-Space.
- To quickly jump to an item in the minibuffer, use C-' to get Avy line jump keys.
- To see actions for the selected minibuffer item, use M-o and then press the action's key.
- Super useful: Use
C-c C-o
to open ivy-occur to open the search results in a separate buffer. From there you can click any item to perform the ivy action.
(use-package ivy :diminish :bind (("C-s" . swiper) :map ivy-minibuffer-map ("TAB" . ivy-alt-done) ("C-f" . ivy-alt-done) ("C-l" . ivy-alt-done) ("C-j" . ivy-next-line) ("C-k" . ivy-previous-line) :map ivy-switch-buffer-map ("C-k" . ivy-previous-line) ("C-l" . ivy-done) ("C-d" . ivy-switch-buffer-kill) :map ivy-reverse-i-search-map ("C-k" . ivy-previous-line) ("C-d" . ivy-reverse-i-search-kill)) :init (ivy-mode 1) :config (setq ivy-use-virtual-buffers t) (setq ivy-wrap t) (setq ivy-count-format "(%d/%d) ") (setq enable-recursive-minibuffers t) ;; Use different regex strategies per completion command (push '(completion-at-point . ivy--regex-fuzzy) ivy-re-builders-alist) ;; This doesn't seem to work... (push '(swiper . ivy--regex-ignore-order) ivy-re-builders-alist) (push '(counsel-M-x . ivy--regex-ignore-order) ivy-re-builders-alist) ;; Set minibuffer height for different commands (setf (alist-get 'counsel-projectile-ag ivy-height-alist) 15) (setf (alist-get 'counsel-projectile-rg ivy-height-alist) 15) (setf (alist-get 'swiper ivy-height-alist) 15) (setf (alist-get 'counsel-switch-buffer ivy-height-alist) 7))
(use-package ivy-hydra :defer t :after hydra)
(use-package ivy-rich :ensure t :init (ivy-rich-mode 1) :config (setq ivy-format-function #'ivy-format-function-line) (setq ivy-rich-display-transformers-list (plist-put ivy-rich-display-transformers-list 'ivy-switch-buffer '(:columns ((ivy-rich-candidate (:width 40)) (ivy-rich-switch-buffer-indicators (:width 4 :face error :align right)); return the buffer indicators (ivy-rich-switch-buffer-major-mode (:width 12 :face warning)) ; return the major mode info (ivy-rich-switch-buffer-project (:width 15 :face success)) ; return project name using `projectile' (ivy-rich-switch-buffer-path (:width (lambda (x) (ivy-rich-switch-buffer-shorten-path x (ivy-rich-minibuffer-width 0.3)))))) ; return file path relative to project root or `default-directory' if project is nil :predicate (lambda (cand) (if-let ((buffer (get-buffer cand))) ;; Don't mess with EXWM buffers (with-current-buffer buffer (not (derived-mode-p 'exwm-mode))))))))) (use-package all-the-icons-ivy-rich :ensure t :init (all-the-icons-ivy-rich-mode 1))
(use-package ivy-posframe :ensure t :init (ivy-posframe-mode 1) :config (setq ivy-posframe-display-functions-alist '((swiper . ivy-display-function-fallback) (complete-symbol . ivy-posframe-display-at-point) (counsel-M-x . ivy-posframe-display-at-frame-center) (t . ivy-posframe-display))) )
Change the color of the searched text in the mini-buffer (taken from here)
(progn (set-face-attribute 'ivy-current-match nil :foreground "white" :background "purple") (set-face-attribute 'ivy-minibuffer-match-face-2 nil :foreground "white" :background "red") (set-face-attribute 'ivy-minibuffer-match-face-3 nil :foreground "white" :background "darkgreen") (set-face-attribute 'ivy-minibuffer-match-face-4 nil :foreground "white" :background "blue") ;; (set-face-attribute 'swiper-match-face-2 nil :foreground "white" :background "red") (set-face-attribute 'swiper-match-face-3 nil :foreground "white" :background "darkgreen") (set-face-attribute 'swiper-match-face-4 nil :foreground "white" :background "blue"))
Counsel
(use-package counsel :after ivy :demand t :bind (("M-x" . counsel-M-x) ("C-x b" . counsel-ibuffer) ("C-x C-f" . counsel-find-file) ("C-M-j" . counsel-switch-buffer) ("C-M-m" . counsel-imenu) :map minibuffer-local-map ("C-r" . 'counsel-minibuffer-history)) :custom (counsel-linux-app-format-function #'counsel-linux-app-format-function-name-only) :config (setq ivy-initial-inputs-alist nil)) ;; Don't start searches with ^ (use-package all-the-icons-ibuffer :ensure t :hook (ibuffer-mode . all-the-icons-ibuffer-mode)) (global-set-key (kbd "C-x C-b") 'ibuffer)
Helpful
Remap the help
functions by referring to helpful package
(use-package helpful :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))
Vertico
as alternative completion system
(use-package vertico :ensure t :init (vertico-mode 1) :config (setq vertico-count 25 ; Show more candidates read-extended-command-predicate 'command-completion-default-include-p read-file-name-completion-ignore-case t ; Ignore case of file names read-buffer-completion-ignore-case t ; Ignore case in buffer completion completion-ignore-case t ; Ignore case in completion ))
Marginalia
Annotations in mini-buffer.
Marginalia
can be considered as ivy-rich replacement
(use-package marginalia :after vertico :ensure t :custom (marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil)) :init (marginalia-mode))
Auto-save
Auto-save buffers except init.org
(use-package auto-save-buffers-enhanced :ensure t :config (auto-save-buffers-enhanced t) (setq auto-save-buffers-enhanced-exclude-regexps '("init.org")))
Version control
Magit is a Git client specifically for Emacs, and it's super powerful.
Let's first make sure we're highlighting uncommitted changes.
(use-package diff-hl :config (global-diff-hl-mode))
Then configure Magit.
(use-package magit :config (add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh) (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh))
Project management
Projectile provides a convenient project interaction interface. I keep most of my projects in a specific folder, so I'll set Projectile to check that path specifically.
(use-package projectile ; :bind (:map custom-bindings-map ("C-c p" . projectile-command-map)) :config (setq projectile-project-search-path '("~/MEGA/Emacs-projects/")))
Org mode
General settings
Change the default programs that org uses for opening files
(add-to-list 'org-file-apps '("\\.html" . "brave-browser %s"))
Specify languages to be recognized by Org-mode
(org-babel-do-load-languages 'org-babel-load-languages '((R . t) (latex . t) (shell . t) (python . t) (ipython . t) ;; (jupyter . t) (emacs-lisp . t) (plantuml . t) )) (setq org-babel-python-command "/home/kostya/.local/bin/ipython3 --no-banner --classic --no-confirm-exit")
Specify the path to plantunl
as instructed here
(setq org-plantuml-jar-path (expand-file-name "/usr/share/java/plantuml.jar"))
Taken from here:
(dolist (face '((org-level-1 . 1.2) (org-level-2 . 1.1) (org-level-3 . 1.05) (org-level-4 . 1.0) (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 "Cantarell" :weight 'regular :height (cdr face))) ;; Make sure org-indent face is available ;; (require 'org-indent) ;; 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) (set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch)) (set-face-attribute 'org-indent nil :inherit '(org-hide 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 some setting to improve Org-mode's look
;; (add-hook 'org-mode-hook 'org-indent-mode) ;; (add-hook 'org-mode-hook 'turn-on-auto-fill) (add-hook 'org-mode-hook 'variable-pitch-mode) (use-package org-bullets :ensure org-bullets :config :hook org-mode)
Styling
The part below is taken from here
(setq org-ellipsis " ▼") ;; ⤵ ▼ ⬎ ⮷ (setq org-src-fontify-natively t) ;; Syntax highlighting in org src blocks (setq org-highlight-latex-and-related '(native)) ;; Highlight inline LaTeX (setq org-startup-folded 'showeverything) (setq org-image-actual-width 300) (setq org-fontify-whole-heading-line t) (setq org-pretty-entities t)
Colorize quote-blocks (taken from here)
(setq org-fontify-quote-and-verse-blocks t)
Colorize source-blocks (taken from here)
(custom-set-faces '(org-block-begin-line ((t (:underline "#A7A6AA" :foreground "#008ED1" :extend t)))) '(org-block ((t (:background "#312c2c")))) '(org-block-end-line ((t (:underline "#A7A6AA" :foreground "#008ED1" :extend t)))) '(org-quote ((t (:background "#312c2c")))) )
Org-download lets us easily put copied screenshots into my org-documents.
(use-package org-download :after org :bind (:map org-mode-map (("s-t" . org-download-screenshot) ("s-y" . org-download-clipboard))))
Inline display of images, especially convenient for R
(add-hook 'org-babel-after-execute-hook 'org-display-inline-images 'append) (add-hook 'org-mode-hook 'org-display-inline-images) (setq org-confirm-babel-evaluate nil) ;don't prompt me to confirm everytime I want to evaluate a block
Org-modern
;; taken from [[https://github.com/jdtsmith/org-modern-indent][here]] (use-package org-modern :ensure t :custom (org-modern-hide-stars nil) ; adds extra indentation (org-modern-table nil) (org-modern-list '(;; (?- . "-") (?* . "•") (?+ . "‣"))) (org-modern-block-name '("" . "")) ; or other chars; so top bracket is drawn promptly :hook (org-mode . org-modern-mode) (org-agenda-finalize . org-modern-agenda)) ;; Add frame borders and window dividers (modify-all-frames-parameters '( (bottom-divider-width . 0) (internal-border-width . 30))) (dolist (face '(window-divider window-divider-first-pixel window-divider-last-pixel)) (face-spec-reset-face face) (set-face-foreground face (face-attribute 'default :background))) (set-face-background 'fringe (face-attribute 'default :background)) (setq ;; Edit settings org-auto-align-tags nil org-tags-column 0 org-catch-invisible-edits 'show-and-error org-special-ctrl-a/e t org-insert-heading-respect-content t ;; Org styling, hide markup etc. org-hide-emphasis-markers t org-pretty-entities t ;; Agenda styling org-agenda-tags-column 0 org-agenda-block-separator ?─ org-agenda-time-grid '((daily today require-timed) (800 1000 1200 1400 1600 1800 2000) " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄") org-agenda-current-time-string "◀── now ─────────────────────────────────────────────────") ;; Ellipsis styling (setq org-ellipsis "…") (set-face-attribute 'org-ellipsis nil :inherit 'default :box nil) (global-org-modern-mode)
Visual tweaks taken from here
(defun my/prettify-symbols-setup () ; Greek symbols ;; (push '("lambda" . ?λ) prettify-symbols-alist) ;; (push '("delta" . ?Δ) prettify-symbols-alist) ;; (push '("gamma" . ?Γ) prettify-symbols-alist) ;; (push '("phi" . ?φ) prettify-symbols-alist) ;; (push '("psi" . ?ψ) prettify-symbols-alist) ;; ;; org-abel (push '("#+BEGIN_SRC" . ?≫) prettify-symbols-alist) (push '("#+END_SRC" . ?≫) prettify-symbols-alist) (push '("#+begin_src" . ?≫) prettify-symbols-alist) (push '("#+end_src" . ?≫) prettify-symbols-alist) (push '("#+BEGIN_QUOTE" . ?❝) prettify-symbols-alist) (push '("#+END_QUOTE" . ?❞) prettify-symbols-alist) (prettify-symbols-mode)) (add-hook 'org-mode-hook #'my/prettify-symbols-setup) (add-hook 'org-agenda-mode-hook #'my/prettify-symbols-setup)
BibTeX integration
(defun org-mode-reftex-setup () (load-library "reftex") (and (buffer-file-name)(file-exists-p (buffer-file-name)) (reftex-parse-all)) (define-key org-mode-map (kbd "C-c [") 'reftex-citation)) (add-hook 'org-mode-hook 'org-mode-reftex-setup)
(use-package citar :custom (citar-bibliography '("~/MEGA/Emacs-projects/RoamNotes/references/Library.bib")) (org-cite-global-bibliography '("~/MEGA/Emacs-projects/RoamNotes/references/Library.bib")) (org-cite-insert-processor 'citar) (org-cite-follow-processor 'citar) (org-cite-activate-processor 'citar) (citar-bibliography org-cite-global-bibliography) :hook (org-mode . citar-capf-setup) (markdown-mode . citar-capf-setup) :bind (:map org-mode-map :package org ("C-c b" . #'org-cite-insert))) (use-package citar-embark :after citar embark :no-require :config (citar-embark-mode)) (setq citar-at-point-function 'embark-act) (defvar citar-indicator-notes-icons (citar-indicator-create :symbol (all-the-icons-material "speaker_notes" :face 'all-the-icons-blue :v-adjust -0.3) :function #'citar-has-notes :padding " " :tag "has:notes"))
Polymode and ESS for reading and exporting .rmd files
(use-package poly-R :ensure t) (use-package ess :ensure t) (require 'ess-r-flymake) (require 'ess-r-insert-obj) (require 'ess-view-data) (setq tab-always-indent t)
Apply the familiar (RStudio or similar) design to R with ESS (taken from here)
(add-hook 'ess-mode-hook (lambda () (ess-set-style 'C++ 'quiet) (add-hook 'local-write-file-hooks (lambda () (ess-nuke-trailing-whitespace))))) (setq ess-nuke-trailing-whitespace-p 'ask)
Tweak the polymode exporter to avoid errors (taken from here and here) :
(defcustom polymode-exporter-output-file-format "%s" "Format of the exported files. %s is substituted with the current file name sans extension." :group 'polymode-export :type 'string) ;; associate the new polymode to Rmd files: (add-to-list 'auto-mode-alist '("\\.[rR]md\\'" . poly-gfm+r-mode)) ;; uses braces around code block language strings: (setq markdown-code-block-braces t)
LaTeX export options
Specify the way orgmode exports LaTeX to PDF via the org-latex-pdf-process
General export way suggested here is the one that works correctly for me.
This one also works, plus thanks to the XeLaTeX, it correctly renders Japanese symbols and exports to LaTeX format C-c C-e l l
smoothly.
;; (setq org-latex-pdf-process '("texi2dvi -p -b -V %f")) (setq org-latex-pdf-process '("xelatex -interaction=nonstopmode -output-directory %o %f" "xelatex -interaction=nonstopmode -output-directory %o %f" "xelatex -interaction=nonstopmode -output-directory %o %f"))
Automatically process PDF on save (taken from here)
(defun org-export-as-pdf () (interactive) (save-buffer) (org-latex-export-to-pdf)) (add-hook 'org-mode-hook (lambda() (define-key org-mode-map (kbd "s-e") 'org-export-as-pdf)))
Instant preview of LaTeX components
(use-package org-fragtog :hook (org-mode . org-fragtog-mode) :config (setq org-latex-create-formula-image-program 'dvisvgm) ;; sharper (plist-put org-format-latex-options :scale 2)) ;; bigger
(require 'ox-latex) (unless (boundp 'org-latex-classes) (setq org-latex-classes nil))
LaTeX templates for org-mode
(with-eval-after-load 'ox-latex (add-to-list 'org-latex-classes '("kochi-article" "\\documentclass[12pt,a4paper]{article} \\usepackage{amsmath} \\usepackage[mathlines]{lineno} \\usepackage[margin=.9in]{geometry} \\usepackage[english]{babel} \\usepackage[T1]{fontenc} \\usepackage{adjustbox} \\usepackage{amsfonts} \\usepackage{amssymb} \\usepackage{amstext} \\usepackage{array} \\usepackage{arydshln} \\usepackage{booktabs} \\usepackage{boxedminipage} \\usepackage{caption} \\usepackage{colortbl} \\usepackage{csquotes} \\usepackage{dcolumn} \\usepackage{endfloat} \\usepackage{enumerate} \\usepackage{epsfig} \\usepackage{epstopdf} \\usepackage{etoolbox} \\usepackage{gensymb} \\usepackage{graphicx} \\usepackage{hyperref} \\usepackage{indentfirst} \\usepackage{latexsym} \\usepackage{multirow} \\usepackage{oldgerm} \\usepackage{rotating} \\usepackage{setspace} \\usepackage{siunitx} \\usepackage{subcaption} \\usepackage[noabbrev]{cleveref} \\usepackage[comma]{natbib} \\usepackage[normalem]{ulem} \\pagestyle{empty} [NO-DEFAULT-PACKAGES] [NO-PACKAGES]" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))
Handling PDFs
Use pdf-tools
instead of a doc-view
for PDFs=
(pdf-tools-install) (add-hook 'pdf-tools-enabled-hook 'pdf-view-midnight-minor-mode) ;; dark theme by default for PDFs
org-noter
for annotating PDFs
(setq org-noter-property-doc-file "NOTER_DOCUMENT" org-noter-property-note-location "NOTER_PAGE")
Enable linking of PDFs with org-mode (taken from here)
(use-package org-noter :init (setq org-noter-enable-org-roam-integration t) :config ;; Your org-noter config ........ (require 'org-noter-pdftools) (setq org-noter-pdftools-markup-pointer-color "orange")) (use-package org-pdftools :hook (org-mode . org-pdftools-setup-link)) (use-package org-noter-pdftools :after org-noter :config ;; Add a function to ensure precise note is inserted (defun org-noter-pdftools-insert-precise-note (&optional toggle-no-questions) (interactive "P") (org-noter--with-valid-session (let ((org-noter-insert-note-no-questions (if toggle-no-questions (not org-noter-insert-note-no-questions) org-noter-insert-note-no-questions)) (org-pdftools-use-isearch-link t) (org-pdftools-use-freepointer-annot t)) (org-noter-insert-note (org-noter--get-precise-info)))))) ;; fix https://github.com/weirdNox/org-noter/pull/93/commits/f8349ae7575e599f375de1be6be2d0d5de4e6cbf (defun org-noter-set-start-location (&optional arg) "When opening a session with this document, go to the current location. With a prefix ARG, remove start location." (interactive "P") (org-noter--with-valid-session (let ((inhibit-read-only t) (ast (org-noter--parse-root)) (location (org-noter--doc-approx-location (when (called-interactively-p 'any) 'interactive)))) (with-current-buffer (org-noter--session-notes-buffer session) (org-with-wide-buffer (goto-char (org-element-property :begin ast)) (if arg (org-entry-delete nil org-noter-property-note-location) (org-entry-put nil org-noter-property-note-location (org-noter--pretty-print-location location)))))))) (with-eval-after-load 'pdf-annot (add-hook 'pdf-annot-activate-handler-functions #'org-noter-pdftools-jump-to-note))
Patch to select more than one line in PDF for inserting a note (taken from here)
;; Added patch function (defun org-noter--check-and-convert-location (location) "If the location is an org-noter-pdftools-location, it transforms it into a (page . height) cons, otherwise it keeps the cons unaltered" (if (org-noter-pdftools--location-p location) (cons (org-noter-pdftools--location-page location) (org-noter-pdftools--location-height location)) location))
Customize TODO formatting in org PDF output (taken from here)
(defun my-org-latex-format-headline-function (todo todo-type priority text tags _info) "Default format function for a headline. See `org-latex-format-headline-function' for details." (concat (and todo (format "{\\bfseries\\sffamily\\color{%s} %s} " (pcase todo-type ('todo "orange") ('done "green")) todo)) (and priority (format "\\framebox{\\#%c} " priority)) text (and tags (format "\\hfill{}\\textsc{%s}" (mapconcat #'org-latex--protect-text tags ":"))))) (setq org-latex-format-headline-function 'my-org-latex-format-headline-function)
TOC in Org files
toc-org creates nice, Markdown compatible tables of content for your Org files.
(use-package toc-org :config (add-hook 'org-mode-hook 'toc-org-mode) ;; enable in markdown, too (add-hook 'markdown-mode-hook 'toc-org-mode))
Agenda
(setq org-directory "~/MEGA/Emacs-projects/OrgFiles") ;; If you only want to see the agenda for today ;; (setq org-agenda-span 'day) (setq org-agenda-start-with-log-mode t) (setq org-log-done t) (setq org-log-done 'time) (setq org-log-into-drawer t) (setq org-clock-continuously t) (setq org-icalendar-include-todo t) (add-to-list 'auto-mode-alist '("\\.org$" . org-mode)) (global-set-key (kbd "C-c s l") #'org-store-link)
Custom TODO states and Agendas (taken from here)
(setq org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)") (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANC(k@)")))
Large part regarding org-agenda
(below) is taken from here and here
;; Configure custom agenda views (setq org-agenda-custom-commands '(("d" "Dashboard" ((agenda "" ((org-deadline-warning-days 7))) (todo "NEXT" ((org-agenda-overriding-header "Next Tasks"))) (tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects"))))) ("A" "Daily agenda and top priority tasks" ((tags-todo "*" ((org-agenda-skip-function '(org-agenda-skip-if nil '(timestamp))) (org-agenda-skip-function `(org-agenda-skip-entry-if 'notregexp ,(format "\\[#%s\\]" (char-to-string org-priority-highest)))) (org-agenda-block-separator nil) (org-agenda-overriding-header "Important tasks without a date\n"))) (agenda "" ((org-agenda-span 1) (org-deadline-warning-days 0) (org-agenda-block-separator nil) (org-scheduled-past-days 0) ;; We don't need the `org-agenda-date-today' ;; highlight because that only has a practical ;; utility in multi-day views. (org-agenda-day-face-function (lambda (date) 'org-agenda-date)) (org-agenda-format-date "%A %-e %B %Y") (org-agenda-overriding-header "\nToday's agenda\n"))) (agenda "" ((org-agenda-start-on-weekday nil) (org-agenda-start-day "+1d") (org-agenda-span 3) (org-deadline-warning-days 0) (org-agenda-block-separator nil) (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) (org-agenda-overriding-header "\nNext three days\n"))) (agenda "" ((org-agenda-time-grid nil) (org-agenda-start-on-weekday nil) ;; We don't want to replicate the previous section's ;; three days, so we start counting from the day after. (org-agenda-start-day "+4d") (org-agenda-span 14) (org-agenda-show-all-dates nil) (org-deadline-warning-days 0) (org-agenda-block-separator nil) (org-agenda-entry-types '(:deadline)) (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) (org-agenda-overriding-header "\nUpcoming deadlines (+14d)\n"))))) ("n" "Next Tasks" ((todo "NEXT" ((org-agenda-overriding-header "Next Tasks"))))) ("W" "Work Tasks" tags-todo "+work") ;; Low-effort next actions ("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0" ((org-agenda-overriding-header "Low Effort Tasks") (org-agenda-max-todos 20) (org-agenda-files org-agenda-files))) ("w" "Workflow Status" ((todo "WAIT" ((org-agenda-overriding-header "Waiting on External") (org-agenda-files org-agenda-files))) (todo "REVIEW" ((org-agenda-overriding-header "In Review") (org-agenda-files org-agenda-files))) (todo "PLAN" ((org-agenda-overriding-header "In Planning") (org-agenda-todo-list-sublevels nil) (org-agenda-files org-agenda-files))) (todo "BACKLOG" ((org-agenda-overriding-header "Project Backlog") (org-agenda-todo-list-sublevels nil) (org-agenda-files org-agenda-files))) (todo "READY" ((org-agenda-overriding-header "Ready for Work") (org-agenda-files org-agenda-files))) (todo "ACTIVE" ((org-agenda-overriding-header "Active Projects") (org-agenda-files org-agenda-files))) (todo "COMPLETED" ((org-agenda-overriding-header "Completed Projects") (org-agenda-files org-agenda-files))) (todo "CANC" ((org-agenda-overriding-header "Cancelled Projects") (org-agenda-files org-agenda-files))))))) (global-set-key (kbd "C-c a") #'org-agenda)
Google calendar integration
Based on this
(setq plstore-cache-passphrase-for-symmetric-encryption t)
(use-package org-gcal :ensure t :config (setq org-gcal-client-id "" org-gcal-client-secret "" org-gcal-file-alist '(("" . "~/MEGA/Emacs-projects/OrgFiles/GoogleSchedule.org"))))
Org-clock
Taken from here
(use-package org-clock :after org :custom ;; Save clock history accross emacs sessions (read var for required info) (org-clock-persist t) ;; If idle for more than 15 mins, resolve by asking what to do with clock (org-clock-idle-time 15) ;; Don't show current clocked in task (org-clock-clocked-in-display nil) ;; Show more clocking history (org-clock-history-length 10) ;; Include running time in clock reports (org-clock-report-include-clocking-task t) ;; Put all clocking info int the "CLOCKING" drawer (org-clock-into-drawer "CLOCKING") ;; Setup default clocktable summary (org-clock-clocktable-default-properties '(:maxlevel 2 :scope file :formula % ;; :properties ("Effort" "Points") :sort (5 . ?t) :compact t :block today)) :bind (:map global-map ("C-c j" . (lambda () (interactive) (org-clock-jump-to-current-clock))) :map org-mode-map ("C-c C-x r" . (lambda () (interactive) (org-clock-report)))))
Org-capture templates
Integrate org-journal
, as specified here
(use-package org-journal :ensure t :defer t :init ;; Change default prefix key; needs to be set before loading org-journal (setq org-journal-prefix-key "C-c o") :config (setq org-journal-dir "~/MEGA/Emacs-projects/OrgFiles/Journal/" org-journal-date-format "%A, %d %B %Y"))
(defun org-journal-find-location () ;; Open today's journal, but specify a non-nil prefix argument in order to ;; inhibit inserting the heading; org-capture will insert the heading. (org-journal-new-entry t) (unless (eq org-journal-file-type 'daily) (org-narrow-to-subtree)) (goto-char (point-max)))
Include the org-capture
, which works together with the browser extension.
The custom function below is for capturing ArXiv entries
(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)) ) ;; Kill the frame if one was created for the capture (defvar kk/delete-frame-after-capture 0 "Whether to delete the last frame after the current capture") (defun kk/delete-frame-if-neccessary (&rest r) (cond ((= kk/delete-frame-after-capture 0) nil) ((> kk/delete-frame-after-capture 1) (setq kk/delete-frame-after-capture (- kk/delete-frame-after-capture 1))) (t (setq kk/delete-frame-after-capture 0) (delete-frame)))) (advice-add 'org-capture-finalize :after 'kk/delete-frame-if-neccessary) (advice-add 'org-capture-kill :after 'kk/delete-frame-if-neccessary) (advice-add 'org-capture-refile :after 'kk/delete-frame-if-neccessary)
Set up org-protocol
required by org-capture
(server-start) (add-to-list 'load-path "~/.local/share/applications/org-protocol.desktop") (require 'org-protocol)
Based on this example
(setq org-capture-templates '(("t" "Tasks / Projects") ("tt" "Task" entry (file+olp "~/MEGA/Emacs-projects/OrgFiles/Tasks.org" "Inbox") "* TODO %?\n %U\n %a\n %i" :empty-lines 1) ("ts" "Clocked Entry Subtask" entry (clock) "* TODO %?\n %U\n %a\n %i" :empty-lines 1) ("a" "Appointment" entry (file "~/MEGA/Emacs-projects/OrgFiles/GoogleSchedule.org") "* %?\n:PROPERTIES:\n:calendar-id:\tk.ovsiannikov@gmail.com\n:END:\n:org-gcal:\n%^T--%^T\n:END:\n\n" :jump-to-captured t :empty-lines 1) ("j" "Journal Entries") ("jj" "Journal" entry (file+olp+datetree "~/MEGA/Emacs-projects/OrgFiles/journal.org") "\n* %<%I:%M %p> - Journal :journal:\n\n%?\n\n" :clock-in :clock-resume :empty-lines 1) ("jo" "Org-Journal" plain (function org-journal-find-location) "** %(format-time-string org-journal-time-format)%^{Title}\n%i%?" :jump-to-captured t :immediate-finish t) ("jm" "Meeting" entry (file+olp+datetree "~/MEGA/Emacs-projects/OrgFiles/journal.org") "* %<%I:%M %p> - %a :meetings:\n\n%?\n\n" :clock-in :clock-resume :empty-lines 1) ("jl" "Liya" entry (file+datetree "~/MEGA/Liya/Liya-Milestones.org") "\n* %?\n %U\n %i\n" :emty-lines 1) ("p" "Web quote" entry (file+headline "~/MEGA/Emacs-projects/OrgFiles/notes.org" "Web") ;; (file+headline (expand-file-name "notes.org" org-directory) "Web") "* [[%:link][%:description]] \nCaptured On: %U\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n%?") ("L" "Web link" entry (file+headline "~/MEGA/Emacs-projects/OrgFiles/notes.org" "Web") ;; (file+headline (expand-file-name "notes.org" org-directory) "Web") "* %? [[%:link][%(transform-square-brackets-to-round-ones \"%:description\")]] %(progn (setq kk/delete-frame-after-capture 2) \"\")\nCaptured On: %U" :emty-lines 1) )) (global-set-key (kbd "C-c c") #'org-capture)
(with-eval-after-load 'org (add-hook 'org-mode-hook 'org-ref-prettify-mode))
Org-Roam
(use-package org-roam :ensure t :init (setq org-roam-v2-ack t) :custom (org-roam-directory "~/MEGA/Emacs-projects/RoamNotes/") (org-roam-completion-everywhere t) (org-roam-dailies-capture-templates '( ("d" "default" entry "* %<%I:%M %p>: %?" :if-new (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n")))) (org-roam-capture-templates '( ("m" "main" plain "%?" :if-new (file+head "main/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n") :unnarrowed t) ("b" "bibliography notes" plain (file "~/MEGA/Emacs-projects/RoamNotes/Templates/BibNoteTemplate.org") :target (file+head "references/notes/${citekey}.org" "#+title: ${title}\n#+date: %U\n#+filetags: BibNote\n#+options: author:nil, date:nil, toc:nil, num:5, H:5, html-postamble:nil\n") :emty-lines 1) ("l" "programming language" plain "* Characteristics\n\n- Family: %?\n- Inspired by: \n\n* Reference:\n\n" :if-new (file+head "main/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("n" "book notes" plain (file "~/MEGA/Emacs-projects/RoamNotes/Templates/BookNoteTemplate.org") :if-new (file+head "main/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("p" "project" plain "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n" :if-new (file+head "main/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+category: ${title}\n#+filetags: Project") :unnarrowed t) ) ) :bind (("C-c n l" . org-roam-buffer-toggle) ("C-c n f" . org-roam-node-find) ("C-c n i" . org-roam-node-insert) ("C-c n g" . org-roam-graph) :map org-roam-dailies-map ("Y" . org-roam-dailies-capture-yesterday) ("T" . org-roam-dailies-capture-tomorrow)) :bind-keymap ("C-c n d" . org-roam-dailies-map) :config (setq org-roam-capture-ref-templates ;; based on: https://org-roam.discourse.group/t/passing-protocol-capture-text-with-quotations-inside/1970 '( ("r" "ref" entry "* Quote\n#+BEGIN_QUOTE\n%(replace-regexp-in-string \"^\" \" \" \"${body}\")\n#+END_QUOTE\n%?" :if-new (file+head "webrefs/%<%Y%m%d%H%M%S>-webref.org" "#+title: ${title}\n#+category: ${title}\n#+date: %U\n#+filetags: web-capture\n") :unnarrowed t :empty-lines 1) ) ) (setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag))) ;; for a more informative completion interface (org-roam-db-autosync-mode) (require 'org-roam-dailies) ;; Ensure the keymap is available (require 'org-roam-protocol) ;; If using org-roam-protocol )
Custom functions from System Crafters
Fast node insertion
;; Bind this to C-c n I (defun org-roam-node-insert-immediate (arg &rest args) (interactive "P") (let ((args (cons arg args)) (org-roam-capture-templates (list (append (car org-roam-capture-templates) '(:immediate-finish t))))) (apply #'org-roam-node-insert args)))
Build Org-agenda with Org-roam notes
(defun my/org-roam-filter-by-tag (tag-name) (lambda (node) (member tag-name (org-roam-node-tags node)))) (defun my/org-roam-list-notes-by-tag (tag-name) (require 'org-roam-node) ;; this was missing from the source and has to be added! (mapcar #'org-roam-node-file (seq-filter (my/org-roam-filter-by-tag tag-name) (org-roam-node-list)))) (defun my/org-roam-refresh-agenda-list () (interactive) (require 'org-roam-node) (setq org-agenda-files (my/org-roam-list-notes-by-tag "Project"))) ;; Build the agenda list the first time for the session (my/org-roam-refresh-agenda-list)
Selecting from a list of notes with a specific tag
(defun my/org-roam-project-finalize-hook () "Adds the captured project file to `org-agenda-files' if the capture was not aborted." ;; Remove the hook since it was added temporarily (remove-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook) ;; Add project file to the agenda list if the capture was confirmed (unless org-note-abort (with-current-buffer (org-capture-get :buffer) (add-to-list 'org-agenda-files (buffer-file-name))))) (defun my/org-roam-find-project () (interactive) ;; Add the project file to the agenda after capture is finished (add-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook) ;; Select a project file to open, creating it if necessary (org-roam-node-find nil nil (my/org-roam-filter-by-tag "Project") nil ;; added this based on the comment under the video - it's essential for the function to work! :templates '( ("p" "project" plain "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n" :if-new (file+head "main/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+category: ${title}\n#+filetags: Project") :unnarrowed t) ))) (global-set-key (kbd "C-c n p") #'my/org-roam-find-project)
Streamlined custom capture for tasks and notes
(defun my/org-roam-capture-inbox () (interactive) (org-roam-capture- :node (org-roam-node-create) :templates '(("i" "inbox" plain "* %?" :if-new (file+head "Inbox.org" "#+title: Inbox\n"))))) (global-set-key (kbd "C-c n b") #'my/org-roam-capture-inbox)
Capture a task directly into a specific project
(defun my/org-roam-capture-task () (interactive) ;; Add the project file to the agenda after capture is finished (add-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook) ;; Capture the new task, creating the project file if necessary (org-roam-capture- :node (org-roam-node-read nil (my/org-roam-filter-by-tag "Project")) :templates '(("p" "project" plain "** TODO %?" :if-new (file+head+olp "main/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+category: ${title}\n#+filetags: Project" ("Tasks")))))) (global-set-key (kbd "C-c n t") #'my/org-roam-capture-task)
Automatically copy (or move) completed tasks to dailies
(defun my/org-roam-copy-todo-to-today () (interactive) (let ((org-refile-keep t) ;; Set this to nil to delete the original! (org-roam-dailies-capture-templates '(("t" "tasks" entry "%?" :if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n" ("Tasks"))))) (org-after-refile-insert-hook #'save-buffer) today-file pos) (save-window-excursion (org-roam-dailies--capture (current-time) t) (setq today-file (buffer-file-name)) (setq pos (point))) ;; Only refile if the target file is different than the current file (unless (equal (file-truename today-file) (file-truename (buffer-file-name))) (org-refile nil nil (list "Tasks" today-file nil pos))))) (add-to-list 'org-after-todo-state-change-hook (lambda () (when (equal org-state "DONE") (my/org-roam-copy-todo-to-today))))
Creating the property "type" for the notes (taken from here)
(cl-defmethod org-roam-node-type ((node org-roam-node)) "Return the TYPE of NODE." (condition-case nil (file-name-nondirectory (directory-file-name (file-name-directory (file-relative-name (org-roam-node-file node) org-roam-directory)))) (error "")))
Modifying the display template to show the node “type”
(setq org-roam-node-display-template (concat "${type:15} ${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
org-roam-bibtex and org-noter integration
Taken from here
helm-bibtex
;; IMP: Ensure 'latexmk' installed as a system package! ;; see also: http://www.jonathanleroux.org/bibtex-mode.html (use-package helm-bibtex :config (setq bibtex-completion-bibliography '("~/MEGA/Emacs-projects/RoamNotes/references/Library.bib")) ; location of .bib file containing bibliography entries (setq bibtex-completion-find-additional-pdfs t) ; support for multiple pdfs for one %citekey (setq bibtex-completion-pdf-field "File") ; in bib entry, file = {/path/to/file.pdf} could be set to locate the accompanying file ;; for multiple files use, file = {:/path/to/file0.pdf:PDF;:/path/to/file1.pdf:PDF} (setq bibtex-completion-library-path '("~/MEGA/Emacs-projects/RoamNotes/references/documents/")) ; in this dir, %citekey-name(s).pdf would automatically attach pdf(s) to %citekey ;; if only !exist "file" field in bib entry (setq bibtex-completion-notes-path "~/MEGA/Emacs-projects/RoamNotes/references/") ; dir to keep notes for the pdfs ;; BEGIN: Change insert citation (<f3>) behaviour of helm-bibtex for org-mode (defun custom/bibtex-completion-format-citation-org (keys) "Custom cite definition for org-mode" (s-join ", " (--map (format "cite:&%s" it) keys))) (setq bibtex-completion-format-citation-functions '((org-mode . custom/bibtex-completion-format-citation-org) (latex-mode . bibtex-completion-format-citation-cite) (markdown-mode . bibtex-completion-format-citation-pandoc-citeproc) (python-mode . bibtex-completion-format-citation-sphinxcontrib-bibtex) (rst-mode . bibtex-completion-format-citation-sphinxcontrib-bibtex) (default . bibtex-completion-format-citation-default)) ) ;; END: Change insert citation (<f3>) behaviour of helm-bibtex for org-mode (setq bibtex-autokey-year-length 4 ; customisations for 'bibtex-generate-autokey' bibtex-autokey-name-year-separator "-" ; press C-c C-c (bibtex-clean-entry) on a bib entry w/o %citekey bibtex-autokey-year-title-separator "-" ; to automatically insert a %citekey based on meta data bibtex-autokey-titleword-separator "-" ; use M-x crossref-add-bibtex-entry <ret>: to add an entry from bibtex-autokey-titlewords 2 ; https://www.crossref.org/ bibtex-autokey-titlewords-stretch 1 bibtex-autokey-titleword-length 5 bibtex-completion-pdf-symbol "⌘" bibtex-completion-notes-symbol "✎"))
org-roam-bibtex
(use-package org-roam-bibtex :after org-roam :config ;(setq bibtex-completion-edit-notes-function 'bibtex-completion-edit-notes-default) ; default to org-ref for notes (setq bibtex-completion-edit-notes-function 'orb-bibtex-completion-edit-note) ; use org-roam-capture-templates for notes (setq orb-preformat-keywords '("citekey" "title" "url" "author-or-editor" "keywords" "file") ; customisation for notes, org-noter integration orb-process-file-keyword t orb-attached-file-extensions '("pdf")) (require 'org-ref)) ; optional: if using Org-ref v2 or v3 citation links
org-noter
integration
(setq org-noter-notes-search-path '("/home/kostya/MEGA/Emacs-projects/RoamNotes/references/notes/")) ; V IMPORTANT: SET FULL PATH!
Global key-binding
(global-set-key (kbd "C-c f r") 'helm-bibtex)
Org-related extensions
org-reveal
(use-package ox-reveal :ensure t :config (setq org-reveal-root "file:///home/kostya/bin/reveal.js/"))
ox-report
(use-package ox-report :custom (ox-report-logo "/home/kostya/MEGA/Pictures/") )
Website with Org
(use-package simple-httpd :ensure t)
LLM
(use-package gptel :config ;; (setq ;; gptel-model 'gemma3:latest ;; gptel-backend (gptel-make-ollama "Ollama" ;; :host "localhost:11434" ;; :stream t ;; :models '(gemma3:latest))) (setq gptel-api-key "") (setq gptel-model 'gpt-5-mini) (setq gptel-default-mode 'org-mode) (setq gptel-use-curl nil) (setq gptel-log-level "info"))
LaTeX
Auctex setup
(require 'auctex-latexmk) (auctex-latexmk-setup) (setq-default TeX-master nil) (setq TeX-view-program-selection '((output-pdf "Evince"))) (setq TeX-save-query nil) (setq TeX-PDF-mode t) (setq TeX-parse-self t) (setq TeX-auto-save t) (setq TeX-source-correlate-method 'synctex) (setq TeX-source-correlate-start-server t) (setq auctex-latexmk-inherit-TeX-PDF-mode t) (add-hook 'LaTeX-mode-hook 'TeX-toggle-debug-bad-boxes) (add-hook 'LaTeX-mode-hook 'TeX-toggle-debug-warnings) (add-hook 'LaTeX-mode-hook 'flyspell-mode) (add-hook 'LaTeX-mode-hook 'prettify-symbols-mode) (add-hook 'LaTeX-mode-hook 'LaTeX-math-mode) (add-hook 'LaTeX-mode-hook 'TeX-source-correlate-mode) (add-hook 'LaTeX-mode-hook 'TeX-interactive-mode) (add-hook 'LaTeX-mode-hook #'TeX-fold-mode) (add-hook 'LaTeX-mode-hook 'simpleclip-mode) (add-hook 'LaTeX-mode-hook 'display-line-numbers-mode) (add-hook 'prog-mode-hook 'display-line-numbers-mode)
Indentation
(defun LaTeX-indent-item () "Provide proper indentation for LaTeX \"itemize\",\"enumerate\", and \"description\" environments. \"\\item\" is indented `LaTeX-indent-level' spaces relative to the the beginning of the environment. Continuation lines are indented either twice `LaTeX-indent-level', or `LaTeX-indent-level-item-continuation' if the latter is bound." (save-match-data (let* ((offset LaTeX-indent-level) (contin (or (and (boundp 'LaTeX-indent-level-item-continuation) LaTeX-indent-level-item-continuation) (* 1 LaTeX-indent-level))) (re-beg "\\\\begin{") (re-end "\\\\end{") (re-env "\\(itemize\\|\\enumerate\\|description\\)") (indent (save-excursion (when (looking-at (concat re-beg re-env "}")) (end-of-line)) (LaTeX-find-matching-begin) (current-column)))) (cond ((looking-at (concat re-beg re-env "}")) (or (save-excursion (beginning-of-line) (ignore-errors (LaTeX-find-matching-begin) (+ (current-column) (if (looking-at (concat re-beg re-env "}")) contin offset)))) indent)) ((looking-at (concat re-end re-env "}")) indent) ((looking-at "\\\\item") (+ offset indent)) (t (+ contin indent)))))) (defcustom LaTeX-indent-level-item-continuation 1 "*Indentation of continuation lines for items in itemize-like environments." :group 'LaTeX-indentation :type 'integer) (eval-after-load "latex" '(setq LaTeX-indent-environment-list (nconc '(("itemize" LaTeX-indent-item) ("enumerate" LaTeX-indent-item) ("description" LaTeX-indent-item)) LaTeX-indent-environment-list))) (setq LaTeX-item-indent 0 LaTeX-indent-level 2) (setq LaTeX-indent-level-item-continuation 2)
RefTeX
(setq reftex-plug-into-AUCTeX t) (setq reftex-format-ref-function `reftex-format-cref) (add-hook 'LaTeX-mode-hook 'turn-on-reftex) (add-hook 'latex-mode-hook 'turn-on-reftex) (add-hook 'text-mode-hook 'turn-on-reftex) (add-hook 'text-mode-hook 'turn-on-prettify-symbols-mode) (eval-after-load "latex" '(TeX-add-style-hook "cleveref" (lambda () (if (boundp 'reftex-ref-style-alist) (add-to-list 'reftex-ref-style-alist '("Cleveref" "cleveref" (("\\cref" ?c) ("\\Cref" ?C) ("\\cpageref" ?d) ("\\Cpageref" ?D))))) (reftex-ref-style-activate "Cleveref") (TeX-add-symbols '("cref" TeX-arg-ref) '("Cref" TeX-arg-ref) '("cpageref" TeX-arg-ref) '("Cpageref" TeX-arg-ref))))) (add-hook 'LaTeX-mode-hook (lambda () (LaTeX-add-environments '("A" LaTeX-env-label) '("C" LaTeX-env-label) '("D" LaTeX-env-label) '("Ex" LaTeX-env-label) '("Prop" LaTeX-env-label) '("Q" LaTeX-env-label) '("R" LaTeX-env-label) '("T" LaTeX-env-label)) (font-lock-add-keywords nil '(("\\(\\\\cref\\)\\>" 1 font-lock-warning-face t))) (font-lock-add-keywords nil '(("\\(\\\\Cref\\)\\>" 1 font-lock-warning-face t))) (font-lock-add-keywords nil '(("\\(\\\\glsxtrshort\\)\\>" 1 font-lock-warning-face t))) (font-lock-add-keywords nil '(("\\(\\\\glsxtrlong\\)\\>" 1 font-lock-warning-face t))) (font-lock-add-keywords nil '(("\\(\\\\glsxtrfull\\)\\>" 1 font-lock-warning-face t))) (add-to-list 'LaTeX-label-alist '("A" . "%f:a")) (add-to-list 'LaTeX-label-alist '("C" . "%f:c")) (add-to-list 'LaTeX-label-alist '("D" . "%f:d")) (add-to-list 'LaTeX-label-alist '("Ex" . "%f:x")) (add-to-list 'LaTeX-label-alist '("Prop" . "%f:p")) (add-to-list 'LaTeX-label-alist '("Q" . "%f:q")) (add-to-list 'LaTeX-label-alist '("R" . "%f:r")) (add-to-list 'LaTeX-label-alist '("T" . "%f:h")))) (setq reftex-label-alist '(("A" ?a "%f:a" "~\\ref{%s}" nil ("A" "a.")) ("C" ?c "%f:c" "~\\ref{%s}" nil ("C" "c.")) ("D" ?d "%f:d" "~\\ref{%s}" nil ("D" "d.")) ("equation" ?e "%f:e" "~\\ref{%s}" nil ("equation" "e.")) ("Ex" ?x "%f:x" "~\\ref{%s}" nil ("Ex" "x.")) ("figure" ?f "%f:f" "~\\ref{%s}" nil ("figure" "f.")) ("Prop" ?p "%f:p" "~\\ref{%s}" nil ("Prop" "p.")) ("Q" ?q "%f:q" "~\\ref{%s}" nil ("Q" "q.")) ("R" ?r "%f:r" "~\\ref{%s}" nil ("R" "r.")) ("section" ?s "%f:s" "~\\ref{%s}" nil ("section" "s.")) ("T" ?h "%f:h" "~\\ref{%s}" nil ("T" "h.") ) ("table" ?t "%f:t" "~\\ref{%s}" nil ("table" "t.")))) (setq reftex-insert-label-flags '("sft" "sft")) ; table of contents (setq reftex-toc-split-windows-horizontally t reftex-toc-split-windows-fraction 0.2)
Nomenclature
(eval-after-load "tex" '(add-to-list 'TeX-command-list '("Nomenclature" "makeindex %s.nlo -s nomencl.ist -o %s.nls" TeX-run-command nil t :help "Create nomenclature file")))
Others
Instant preview
(add-hook 'latex-mode-hook #'xenops-mode) (add-hook 'LaTeX-mode-hook #'xenops-mode)
Emacs Mail
Basic config
(use-package mu4e :ensure nil ;; :load-path "/usr/share/emacs/site-lisp/mu4e/" :defer 20 ; Wait until 20 seconds after startup :config ;; This is set to 't' to avoid mail syncing issues when using mbsync (setq mu4e-change-filenames-when-moving t) ;; Refresh mail using isync every 10 minutes (setq mu4e-update-interval (* 10 60)) (setq mu4e-get-mail-command "mbsync -a") (setq mu4e-maildir "~/Mail") (setq mu4e-drafts-folder "/[Gmail]/Drafts") (setq mu4e-sent-folder "/[Gmail]/Sent Mail") (setq mu4e-refile-folder "/[Gmail]/All Mail") (setq mu4e-trash-folder "/[Gmail]/Trash") (setq mu4e-maildir-shortcuts '((:maildir "/Inbox" :key ?i) (:maildir "/[Gmail]/Sent Mail" :key ?s) (:maildir "/[Gmail]/Trash" :key ?t) (:maildir "/[Gmail]/Drafts" :key ?d) (:maildir "/[Gmail]/All Mail" :key ?a))))
Sending email
;; Now I set a list of (defvar my-mu4e-account-alist '(("Gmail" (user-mail-address "...@gmail.com") (smtpmail-smtp-user "...") (smtpmail-local-domain "gmail.com") (smtpmail-default-smtp-server "smtp.gmail.com") (smtpmail-smtp-server "smtp.gmail.com") (smtpmail-smtp-service 587) ) ;; Include any other accounts here ... )) (defun my-mu4e-set-account () "Set the account for composing a message. This function is taken from: https://www.djcbsoftware.nl/code/mu/mu4e/Multiple-accounts.html" (let* ((account (if mu4e-compose-parent-message (let ((maildir (mu4e-message-field mu4e-compose-parent-message :maildir))) (string-match "/\\(.*?\\)/" maildir) (match-string 1 maildir)) (completing-read (format "Compose with account: (%s) " (mapconcat #'(lambda (var) (car var)) my-mu4e-account-alist "/")) (mapcar #'(lambda (var) (car var)) my-mu4e-account-alist) nil t nil nil (caar my-mu4e-account-alist)))) (account-vars (cdr (assoc account my-mu4e-account-alist)))) (if account-vars (mapc #'(lambda (var) (set (car var) (cadr var))) account-vars) (error "No email account found")))) (add-hook 'mu4e-compose-pre-hook 'my-mu4e-set-account)
Python
(use-package lsp-mode :config (setq lsp-idle-delay 0.5 lsp-enable-symbol-highlighting t lsp-enable-snippet nil ;; Not supported by company capf, which is the recommended company backend lsp-pyls-plugins-flake8-enabled t) (lsp-register-custom-settings '(("pyls.plugins.pyls_mypy.enabled" t t) ("pyls.plugins.pyls_mypy.live_mode" nil t) ("pyls.plugins.pyls_black.enabled" t t) ("pyls.plugins.pyls_isort.enabled" t t) ;; Disable these as they're duplicated by flake8 ("pyls.plugins.pycodestyle.enabled" nil t) ("pyls.plugins.mccabe.enabled" nil t) ("pyls.plugins.pyflakes.enabled" nil t))) :hook ((python-mode . lsp) (lsp-mode . lsp-enable-which-key-integration)) )
(use-package lsp-ui :config (setq lsp-ui-sideline-show-hover t lsp-ui-sideline-delay 0.5 lsp-ui-doc-delay 5 lsp-ui-sideline-ignore-duplicates t lsp-ui-doc-position 'bottom lsp-ui-doc-alignment 'frame lsp-ui-doc-header nil lsp-ui-doc-include-signature t lsp-ui-doc-use-childframe t) )
(use-package elpy :init (elpy-enable) :config (setq python-shell-interpreter "ipython" ;; python-shell-interpreter-args "--profile=default" python-shell-prompt-regexp "In \\[[0-9]+\\]: " python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: " python-shell-completion-setup-code "from IPython.core.completerlib import module_completion" python-shell-completion-module-string-code "';'.join(module_completion('''%s'''))\n" python-shell-completion-string-code "';'.join(get_ipython().Completer.all_completions('''%s'''))\n" ;; python-shell-interpreter-args ;; "--colors=Linux --profile=default" elpy-rpc-virtualenv-path 'current)) ;; modify ob-ipython.el as follows: https://github.com/gregsexton/ob-ipython/issues/135#issuecomment-397463174
Taken from here:
(use-package pyvenv :ensure t :config (pyvenv-mode t) (pyvenv-tracking-mode 1) ; Automatically use pyvenv-workon via dir-locals ;; Set correct Python interpreter (setq pyvenv-post-activate-hooks (list (lambda () (setq python-shell-interpreter (concat pyvenv-virtual-env "bin/python3"))))) (setq pyvenv-post-deactivate-hooks (list (lambda () (setq python-shell-interpreter "python3")))) )
(require 'virtualenvwrapper) (venv-initialize-interactive-shells) ;; if you want interactive shell support (venv-initialize-eshell) ;; if you want eshell support (setq venv-location "~/.virtualenvs/")
(use-package flycheck :ensure t :config (when (require 'flycheck nil t) (setq elpy-modules (delq 'elpy-module-flymake elpy-modules)) (add-hook 'elpy-mode-hook 'flycheck-mode)) )
(use-package flyover :ensure t :hook (flycheck-mode-hook . flyover-mode) :config (setq flyover-levels '(error warning info) flyover-wrap-messages t flyover-max-line-length 80 flyover-use-theme-colors t flymake-show-diagnostics-at-end-of-line 'fancy flyover-virtual-line-type 'curved-dotted-arrow flyover-show-at-eol t flyover-hide-when-cursor-is-on-same-line t flyover-show-virtual-line t flyover-virtual-line-icon "╰──" flyover-info-icon "🛈" flyover-warning-icon "⚠" flyover-error-icon "✘"))
(use-package blacken :ensure t )
(use-package jupyter :ensure t :config (setq jupyter-use-zmq nil) :commands (jupyter-run-server-repl jupyter-run-repl jupyter-server-list-kernels))
To fix the jupyter 404 error, taken from here:
(defun gm/jupyter-api-request-xsrf-cookie-error-advice (func &rest args) (condition-case nil (apply func args) (jupyter-api-http-error nil))) (advice-add 'jupyter-api-request-xsrf-cookie :around #'gm/jupyter-api-request-xsrf-cookie-error-advice)
Convert jupyter-notebooks to org-files (taken from here):
(setq code-cells-convert-ipynb-style '( ("pandoc" "--to" "ipynb" "--from" "org") ("pandoc" "--to" "org" "--from" "ipynb") org-mode))
Snippets
(use-package yasnippet :diminish yas-minor-mode :defer 5 :config (setq yas-snippet-dirs '("~/.emacs.d/snippets/")) (yas-global-mode 1)) ;; or M-x yas-reload-all if you've started YASnippet already. ;; Silences the warning when running a snippet with backticks (runs a command in the snippet) (require 'warnings) (add-to-list 'warning-suppress-types '(yasnippet backquote-change))
(use-package yasnippet-snippets :ensure t)