Abstract | A Notebook system based on Emacs borrowing from existing config files. This system works from a single org file as an attempt to be as easy as possible for non-emacs users. It handles analyses in any language supported by org and through any server with a ssh interface. Since, its contents (an org file) are automatically rendered in Github or similar, it is trivial to share analyses results with reviewers and auditors, thus providing a way for transparent review/auditing of statistical analyses. This configuration provides a more complete set of functionality than jupyter, with less hassle.
This project is heavily inspired by existing configs:
- Emacs Bedrock https://codeberg.org/ashton314/emacs-bedrock and;
- Emacs notebook-mode https://github.com/rougier/notebook-mode.
It was created in order to simplify Emacs use as a server-ready Notebook.
- In order to run this you need
emacs -q -f org-babel-load-file
and select this README.org. - Although most packages will be installed in the first run, pay attention to the warnings and manually install them with
Ctrl-Shift-P package-install
. - The first run will take some time to compile packages.
- Vim mode is available, but not enabled. In order to enable it, go to the vim mode section and set :eval yes.
- All you can ever need is listed in
Ctrl-Shift-P package-install
. - Once done with analyses provide the link to your repo in your paper
# load package and data
options(scipen=999) # turn-off scientific notation like 1e+48
library(ggplot2)
theme_set(theme_bw()) # pre-set the bw theme.
data("midwest", package = "ggplot2")
# Scatterplot
gg <- ggplot(midwest, aes(x=area, y=poptotal)) +
geom_point(aes(col=state, size=popdensity)) +
geom_smooth(method="loess", se=F) +
xlim(c(0, 0.1)) +
ylim(c(0, 500000)) +
labs(subtitle="Area Vs Population",
y="Population",
x="Area",
title="Scatterplot",
caption = "Source: midwest")
plot(gg)
library(tableone)
## Load Mayo Clinic Primary Biliary Cirrhosis Data
library(survival)
data(pbc)
## Make categorical variables factors
varsToFactor <- c("status","trt","ascites","hepato","spiders","edema","stage")
pbc[varsToFactor] <- lapply(pbc[varsToFactor], factor)
## Create a variable list
dput(names(pbc))
vars <- c("time","status","age","sex","ascites","hepato",
"spiders","edema","bili","chol","albumin",
"copper","alk.phos","ast","trig","platelet",
"protime","stage")
## Create Table 1 stratified by trt
tableOne <- CreateTableOne(vars = vars, strata = c("trt"), data = pbc)
## Just typing the object name will invoke the print.TableOne method
print(tableOne)
158 | 154 | |
2015.62 (1094.12) | 1996.86 (1155.93) | 0.883 |
0.894 | ||
83 (52.5) | 85 (55.2) | |
10 ( 6.3) | 9 ( 5.8) | |
65 (41.1) | 60 (39.0) | |
51.42 (11.01) | 48.58 (9.96) | 0.018 |
137 (86.7) | 139 (90.3) | 0.421 |
14 ( 8.9) | 10 ( 6.5) | 0.567 |
73 (46.2) | 87 (56.5) | 0.088 |
45 (28.5) | 45 (29.2) | 0.985 |
0.877 | ||
132 (83.5) | 131 (85.1) | |
16 (10.1) | 13 ( 8.4) | |
10 ( 6.3) | 10 ( 6.5) | |
2.87 (3.63) | 3.65 (5.28) | 0.131 |
365.01 (209.54) | 373.88 (252.48) | 0.748 |
3.52 (0.44) | 3.52 (0.40) | 0.874 |
97.64 (90.59) | 97.65 (80.49) | 0.999 |
2021.30 (2183.44) | 1943.01 (2101.69) | 0.747 |
120.21 (54.52) | 124.97 (58.93) | 0.46 |
124.14 (71.54) | 125.25 (58.52) | 0.886 |
258.75 (100.32) | 265.20 (90.73) | 0.555 |
10.65 (0.85) | 10.80 (1.14) | 0.197 |
0.201 | ||
12 ( 7.6) | 4 ( 2.6) | |
35 (22.2) | 32 (20.8) | |
56 (35.4) | 64 (41.6) | |
55 (34.8) | 54 (35.1) |
one | 1 | 2 | 3 | 4 | 5 |
two | 6 | 7 | 8 | 9 | 10 |
print(tab)
Just use M-x notebook-export-html
, this functionality was slightly modified using code from notebook model.
Although knowing to work in Emacs is not required (since which-key is active, and doing anything is really a matter of hitting Ctrl-Shift-P
), Emacs bindings are too complex. I am still thinking on how to make keybindings more accessible.
- [X] Figure out why eglot is not starting with ess
- [ ] Simplify keybindings.
- [ ] Magit workflow to easily share notebooks within the interface
- [X] Figure out why svg-tag-mode does not load in the first try completely
- [X] Figure out why :toc: is not autopopulating
;;; Guardrail
(when (< emacs-major-version 29)
(error (format "Emacs Bedrock only works with Emacs 29 and newer; you have version ~a" emacs-major-version)))
;; This initializes the packages for when one is reading the org file directly
(package-initialize)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Basic settings
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Package initialization
;;
;; We'll stick to the built-in GNU and non-GNU ELPAs (Emacs Lisp Package
;; Archive) for the base install, but there are some other ELPAs you could look
;; at if you want more packages. MELPA in particular is very popular. See
;; instructions at:
;;
;; https://melpa.org/#/getting-started
;;
;; You can simply uncomment the following if you'd like to get started with
;; MELPA packages quickly:
;;
(with-eval-after-load 'package
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t))
;; If you want to turn off the welcome screen, uncomment this
(setopt inhibit-splash-screen t)
(setopt initial-major-mode 'fundamental-mode) ; default mode for the *scratch* buffer
(setopt display-time-default-load-average nil) ; this information is useless for most
;; Automatically reread from disk if the underlying file changes
(setopt auto-revert-avoid-polling t)
;; Some systems don't do file notifications well; see
;; https://todo.sr.ht/~ashton314/emacs-bedrock/11
(setopt auto-revert-interval 5)
(setopt auto-revert-check-vc-info t)
(global-auto-revert-mode)
;; Save history of minibuffer
(savehist-mode)
;; Move through windows with Ctrl-<arrow keys>
(windmove-default-keybindings 'control) ; You can use other modifiers here
;; Fix archaic defaults
(setopt sentence-end-double-space nil)
;; Make right-click do something sensible
(when (display-graphic-p)
(context-menu-mode))
; Disable the bell
(setq ring-bell-function 'ignore)
;; Don't litter file system with *~ backup files; put them all inside
;; ~/.emacs.d/backup or wherever
(defun bedrock--backup-file-name (fpath)
"Return a new file path of a given file path.
If the new path's directories does not exist, create them."
(let* ((backupRootDir (concat user-emacs-directory "emacs-backup/"))
(filePath (replace-regexp-in-string "[A-Za-z]:" "" fpath )) ; remove Windows driver letter in path
(backupFilePath (replace-regexp-in-string "//" "/" (concat backupRootDir filePath "~") )))
(make-directory (file-name-directory backupFilePath) (file-name-directory backupFilePath))
backupFilePath))
(setopt make-backup-file-name-function 'bedrock--backup-file-name)
(set-face-attribute 'default nil :height 150) ; set font size
(setq undo-outer-limit 72000000)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Discovery aids
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Show the help buffer after startup
;;(add-hook 'after-init-hook 'help-quick)
;;(setq inhibit-startup-screen t
;; initial-buffer-choice nil)
;; which-key: shows a popup of available keybindings when typing a long key
;; sequence (e.g. C-x ...)
(use-package which-key
:ensure t
:config
(which-key-mode))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Minibuffer/completion settings
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; For help, see: https://www.masteringemacs.org/article/understanding-minibuffer-completion
(setopt enable-recursive-minibuffers t) ; Use the minibuffer whilst in the minibuffer
(setopt completion-cycle-threshold 1) ; TAB cycles candidates
(setopt completions-detailed t) ; Show annotations
(setopt tab-always-indent 'complete) ; When I hit TAB, try to complete, otherwise, indent
(setopt completion-styles '(basic initials substring)) ; Different styles to match input to candidates
(setopt completion-auto-help 'always) ; Open completion always; `lazy' another option
(setopt completions-max-height 20) ; This is arbitrary
(setopt completions-detailed t)
(setopt completions-format 'one-column)
(setopt completions-group t)
(setopt completion-auto-select 'second-tab) ; Much more eager
;(setopt completion-auto-select t) ; See `C-h v completion-auto-select' for more possible values
(keymap-set minibuffer-mode-map "TAB" 'minibuffer-complete) ; TAB acts more like how it does in the shell
;; some global key bindings
(global-set-key (kbd "C-S-p") 'execute-extended-command)
(global-set-key (kbd "C-f") 'isearch-forward)
(global-set-key (kbd "C-S-f") 'isearch-backward)
(global-set-key (kbd "C-s") 'save-buffer)
(global-set-key (kbd "C-s") 'save-buffer)
(define-key minibuffer-local-map (kbd "C-S-p") 'keyboard-escape-quit)
;; For a fancier built-in completion option, try ido-mode,
;; icomplete-vertical, or fido-mode. See also the file extras/base.el
;(icomplete-vertical-mode)
;(fido-vertical-mode)
;(setopt icomplete-delay-completions-threshold 4000)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Interface enhancements/defaults
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Mode line information
(setopt line-number-mode t) ; Show current line in modeline
(setopt column-number-mode t) ; Show column as well
(setopt x-underline-at-descent-line nil) ; Prettier underlines
(setopt switch-to-buffer-obey-display-actions t) ; Make switching buffers more consistent
(setopt show-trailing-whitespace nil) ; By default, don't underline trailing spaces
(setopt indicate-buffer-boundaries 'left) ; Show buffer top and bottom in the margin
;; Enable horizontal scrolling
(setopt mouse-wheel-tilt-scroll t)
(setopt mouse-wheel-flip-direction t)
;; We won't set these, but they're good to know about
;;
;; (setopt indent-tabs-mode nil)
;; (setopt tab-width 4)
;; Misc. UI tweaks
(blink-cursor-mode -1) ; Steady cursor
(pixel-scroll-precision-mode) ; Smooth scrolling
;; Use common keystrokes by default
(cua-mode)
;; Display line numbers in programming mode
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(setopt display-line-numbers-width 3) ; Set a minimum width
;; Nice line wrapping when working with text
(add-hook 'text-mode-hook 'visual-line-mode)
;; Modes to highlight the current line with
(let ((hl-line-hooks '(text-mode-hook prog-mode-hook)))
(mapc (lambda (hook) (add-hook hook 'hl-line-mode)) hl-line-hooks))
;; remove scroll-bar
;;(scroll-bar-mode -1)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Tab-bar configuration
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Show the tab-bar as soon as tab-bar functions are invoked
(setopt tab-bar-show 1)
;; Add the time to the tab-bar, if visible
(add-to-list 'tab-bar-format 'tab-bar-format-align-right 'append)
(add-to-list 'tab-bar-format 'tab-bar-format-global 'append)
(setopt display-time-format "%a %F %T")
(setopt display-time-interval 1)
(display-time-mode)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Theme
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package emacs
:config
(load-theme 'modus-operandi)) ; for light theme, use modus-operandi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Built-in customization framework
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(custom-enabled-themes '(modus-operandi))
'(package-selected-packages '(org-roam citar ess evil which-key)))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Motion aids
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package avy
:ensure t
:demand t
:bind (("C-c j" . avy-goto-line)
("S-j" . avy-goto-char-timer)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Power-ups: Embark and Consult
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Consult: Misc. enhanced commands
(use-package consult
:ensure t
:bind (
;; Drop-in replacements
("C-x b" . consult-buffer) ; orig. switch-to-buffer
("M-y" . consult-yank-pop) ; orig. yank-pop
;; Searching
("M-s r" . consult-ripgrep)
("M-s l" . consult-line) ; Alternative: rebind C-s to use
("M-s s" . consult-line) ; consult-line instead of isearch, bind
("M-s L" . consult-line-multi) ; isearch to M-s s
("M-s o" . consult-outline)
;; Isearch integration
:map isearch-mode-map
("M-e" . consult-isearch-history) ; orig. isearch-edit-string
("M-s e" . consult-isearch-history) ; orig. isearch-edit-string
("M-s l" . consult-line) ; needed by consult-line to detect isearch
("M-s L" . consult-line-multi) ; needed by consult-line to detect isearch
)
:config
;; Narrowing lets you restrict results to certain groups of candidates
(setq consult-narrow-key "<"))
(use-package embark-consult
:ensure t
:after embark
:after consult
)
(use-package embark
:ensure t
:demand t
:after avy
:bind (("C-c a" . embark-act)) ; bind this to an easy key to hit
:init
;; Add the option to run embark when using avy
(defun bedrock/avy-action-embark (pt)
(unwind-protect
(save-excursion
(goto-char pt)
(embark-act))
(select-window
(cdr (ring-ref avy-ring 0))))
t)
;; After invoking avy-goto-char-timer, hit "." to run embark at the next
;; candidate you select
(setf (alist-get ?. avy-dispatch-alist) 'bedrock/avy-action-embark))
(use-package embark-consult
:ensure t)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Minibuffer and completion
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Vertico: better vertical completion for minibuffer commands
(use-package vertico
:ensure t
:init
;; You'll want to make sure that e.g. fido-mode isn't enabled
(vertico-mode))
(use-package vertico-directory
:ensure nil
:after vertico
:bind (:map vertico-map
("M-DEL" . vertico-directory-delete-word)))
;; Marginalia: annotations for minibuffer
(use-package marginalia
:ensure t
:config
(marginalia-mode))
;; Popup completion-at-point
(use-package corfu
:ensure t
:init
(global-corfu-mode)
:custom
(corfu-auto t) ;; Enable auto completion
(corfu-preview-current nil) ;; Disable current candidate preview
:bind
(:map corfu-map
("SPC" . corfu-insert-separator)
("C-n" . corfu-next)
("C-p" . corfu-previous)))
;; Part of corfu
(use-package corfu-popupinfo
:after corfu
:ensure nil
:hook (corfu-mode . corfu-popupinfo-mode)
:custom
(corfu-popupinfo-delay '(0.25 . 0.1))
(corfu-popupinfo-hide nil)
:config
(corfu-popupinfo-mode))
;; Make corfu popup come up in terminal overlay
(use-package corfu-terminal
:if (not (display-graphic-p))
:ensure t
:config
(corfu-terminal-mode))
(use-package corfu-doc
:hook (corfu-mode-hook . corfu-doc-mode))
;; Fancy completion-at-point functions; there's too much in the cape package to
;; configure here; dive in when you're comfortable!
(use-package cape
:ensure t
:init
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(add-to-list 'completion-at-point-functions #'cape-file))
;; Pretty icons for corfu
(use-package kind-icon
:if (display-graphic-p)
:ensure t
:after corfu
:config
(add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))
(use-package eshell
:init
(defun bedrock/setup-eshell ()
;; Something funny is going on with how Eshell sets up its keymaps; this is
;; a work-around to make C-r bound in the keymap
(keymap-set eshell-mode-map "C-r" 'consult-history))
:hook ((eshell-mode . bedrock/setup-eshell)))
;; Orderless: powerful completion style
(use-package orderless
:ensure t
:config
(setq completion-styles '(orderless)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Misc. editing enhancements
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Modify search results en masse
(use-package wgrep
:ensure t
:config
(setq wgrep-auto-save-buffer t))
(which-key-show-top-level)
(use-package tramp
:ensure t
:config
(eval-after-load 'tramp '(setenv "NCPUS" "23")) ;; set env variables
(eval-after-load 'tramp '(setenv "OMP_NUM_THREADS" "23")) ;; set env variables
(add-to-list 'tramp-methods
;; this is an internal method for interactive scripting, change to what your server uses
'("qsub"
(tramp-login-program "qsub")
(tramp-login-args (("-I -l ncpus=23"))) ; options here?
;; the local $SHELL may contain conflicting configuration
;; this should be good for most cases
(tramp-login-env (("SHELL") ("/bin/sh")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-connection-timeout 10)))
)
;;; This will try to use tree-sitter modes for many languages. Please run
;;;
;;; M-x treesit-install-language-grammar
;;;
;;; Before trying to use a treesit mode.
;;; Contents:
;;;
;;; - Built-in config for developers
;;; - Version Control
;;; - Common file types
;;; - Eglot, the built-in LSP client for Emacs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Built-in config for developers
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(setq treesit-language-source-alist
'((r . ("https://github.com/r-lib/tree-sitter-r" "main" "src"))))
(use-package emacs
:config
;; Treesitter config
;; Tell Emacs to prefer the treesitter mode
;; You'll want to run the command `M-x treesit-install-language-grammar' before editing.
(setq major-mode-remap-alist
'((yaml-mode . yaml-ts-mode)
(bash-mode . bash-ts-mode)
(js2-mode . js-ts-mode)
(typescript-mode . typescript-ts-mode)
(json-mode . json-ts-mode)
(css-mode . css-ts-mode)
(python-mode . python-ts-mode)))
:hook
;; Auto parenthesis matching
(prog-mode . electric-pair-mode))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Version Control
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Magit: best Git client to ever exist
(use-package magit
:ensure t
:bind (("C-x g" . magit-status)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Common file types
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package markdown-mode
:hook ((markdown-mode . visual-line-mode)))
(use-package yaml-mode
:ensure t)
(use-package json-mode
:ensure t)
;; Emacs ships with a lot of popular programming language modes. If it's not
;; built in, you're almost certain to find a mode for the language you're
;; looking for with a quick Internet search.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Eglot, the built-in LSP client for Emacs
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Helpful resources:
;;
;; - https://www.masteringemacs.org/article/seamlessly-merge-multiple-documentation-sources-eldoc
(use-package eglot
;; no :ensure t here because it's built-in
:defer t
;; Configure hooks to automatically turn-on eglot for selected modes
:custom
(eglot-send-changes-idle-time 0.1)
(eglot-extend-to-xref t) ; activate Eglot in referenced non-project files
:config
(fset #'jsonrpc--log-event #'ignore) ; massive perf boost---don't log every event
;; Sometimes you need to tell Eglot where to find the language server
; (add-to-list 'eglot-server-programs
; '(haskell-mode . ("haskell-language-server-wrapper" "--lsp")))
(setq eglot-stay-out-of '(company))
(defun company-R-objects--prefix ()
(unless (ess-inside-string-or-comment-p)
(let ((start (ess-symbol-start)))
(when start
(buffer-substring-no-properties start (point))))))
(defun company-R-objects--candidates (arg)
(let ((proc (ess-get-next-available-process)))
(when proc
(with-current-buffer (process-buffer proc)
(all-completions arg (ess--get-cached-completions arg))))))
(defun company-capf-with-R-objects--check-prefix (prefix)
(cl-search "$" prefix))
(defun company-capf-with-R-objects (command &optional arg &rest ignored)
(interactive (list 'interactive))
(cl-case command
(interactive (company-begin-backend 'company-R-objects))
(prefix (company-R-objects--prefix))
(candidates (if (company-capf-with-R-objects--check-prefix arg)
(company-R-objects--candidates arg)
(company-capf command arg)))
(annotation (if (company-capf-with-R-objects--check-prefix arg)
"R-object"
(company-capf command arg)))
(kind (if (company-capf-with-R-objects--check-prefix arg)
'field
(company-capf command arg)))
(doc-buffer (company-capf command arg))))
)
(use-package citar
:ensure t
:bind (("C-c b" . citar-insert-citation)
:map minibuffer-local-map
("M-b" . citar-insert-preset))
:custom
;; Allows you to customize what citar-open does
(citar-file-open-functions '(("html" . citar-file-open-external)
;; ("pdf" . citar-file-open-external)
(t . find-file))))
;; Optional: if you have the embark package installed, enable the ability to act
;; on citations with Citar by invoking `embark-act'.
(use-package citar-embark
:ensure t
:after citar embark
:diminish ""
:no-require
:config (citar-embark-mode))
(use-package citar-org-roam
:diminish ""
;; To get this to work both Citar *and* Org-roam have to have been used
:after citar org-roam
:no-require
:config
(citar-org-roam-mode)
(setq citar-org-roam-note-title-template "${author} - ${title}\n#+filetags: ${tags}"))
;; Evil: vi emulation
(use-package evil
:ensure t
:init
(setq evil-respect-visual-line-mode t)
(setq evil-undo-system 'undo-redo)
;; Enable this if you want C-u to scroll up, more like pure Vim
;(setq evil-want-C-u-scroll t)
:config
(evil-mode)
;; Configuring initial major mode for some modes
(evil-set-initial-state 'vterm-mode 'emacs))
(use-package org
:ensure t
:hook ((org-mode . visual-line-mode) ; wrap lines at word breaks
(org-mode . flyspell-mode) ; spell checking!
(org-mode . notebook-mode)
(org-mode . toc-org-mode)) ; notebook mode
:bind (:map global-map
("C-c l s" . org-store-link) ; Mnemonic: link → store
("C-c l i" . org-insert-link-global)) ; Mnemonic: link → insert
:init
(setq org-startup-with-inline-images 'inlineimages)
(setq org-image-actual-width `( ,(truncate (* (frame-pixel-width) 0.85))))
(setq org-confirm-babel-evaluate nil)
;(setq org-format-latex-options (plist-put org-format-latex-options :scale 2))
(setq org-format-latex-options (plist-put nil :scale 1.0))
:custom
(org-display-remote-inline-images 'download)
:config
(require 'oc-csl) ; citation support
(add-to-list 'org-export-backends 'md)
;; Make org-open-at-point follow file links in the same window
(setf (cdr (assoc 'file org-link-frame-setup)) 'find-file)
;; Make exporting quotes better
(setq org-export-with-smart-quotes t)
;; Verbatim in slides
(require 'ox-latex)
(add-to-list 'org-latex-packages-alist '("" "minted"))
(setq org-latex-listings 'minted)
;; toggle blocks
(defvar org-blocks-hidden nil)
(defun org-toggle-blocks ()
(interactive)
(if org-blocks-hidden
(org-show-block-all)
(org-hide-block-all))
(setq-local org-blocks-hidden (not org-blocks-hidden)))
(define-key org-mode-map (kbd "C-c b t") 'org-toggle-blocks)
;; (define-key org-mode-map (kbd "C-c b t") 'org-babel-switch-to-session-with-code)
(add-hook 'org-mode-hook 'org-toggle-blocks)
(org-babel-do-load-languages
'org-babel-load-languages
'((python . t)
(R . t)
(julia . t)
(latex . t)
(C . t)
(emacs-lisp . t)))
(defun ek/babel-ansi ()
(when-let ((beg (org-babel-where-is-src-block-result nil nil)))
(save-excursion
(goto-char beg)
(when (looking-at org-babel-result-regexp)
(let ((end (org-babel-result-end))
(ansi-color-context-region nil))
(ansi-color-apply-on-region beg end))))))
(add-hook 'org-babel-after-execute-hook 'ek/babel-ansi)
(define-key org-mode-map (kbd "$")
(lambda ()
(interactive)
(insert "$")
(save-excursion
(backward-char 1)
(if (org-inside-LaTeX-fragment-p)
(progn
(forward-char 2)
(org-preview-latex-fragment))))))
)
;; THIS SECTION IS FOR THE HTML EMBEDDED EXPORT
(require 'org)
(require 'ox-html)
(require 'base64)
(defcustom org-html-image-base64-max-size #x40000
"Export embedded base64 encoded images up to this size."
:type 'number
:group 'org-export-html)
(defun file-to-base64-string (file &optional image prefix postfix)
"Transform binary file FILE into a base64-string prepending PREFIX and appending POSTFIX.
Puts \"data:image/%s;base64,\" with %s replaced by the image type before the actual image data if IMAGE is non-nil."
(concat prefix
(with-temp-buffer
(set-buffer-multibyte nil)
(insert-file-contents file nil nil nil t)
(base64-encode-region (point-min) (point-max) 'no-line-break)
(when image
(goto-char (point-min))
(insert (format "data:image/%s;base64," (image-type-from-file-name file))))
(buffer-string))
postfix))
(defun orgTZA-html-base64-encode-p (file)
"Check whether FILE should be exported base64-encoded.
The return value is actually FILE with \"file://\" removed if it is a prefix of FILE."
(when (and (stringp file)
(string-match "\\`file:" file))
(if (string-match "\\`file://ssh" file)
(setq file (replace-regexp-in-string "\\`file://ssh" "/ssh" file))
(setq file (substring file (match-end 0)))))
(and
(file-readable-p file)
(let ((size (nth 7 (file-attributes file))))
(<= size org-html-image-base64-max-size))
file))
(defun orgTZA-html--format-image (source attributes info)
"Return \"img\" tag with given SOURCE and ATTRIBUTES.
SOURCE is a string specifying the location of the image.
ATTRIBUTES is a plist, as returned by
`org-export-read-attribute'. INFO is a plist used as
a communication channel."
(if (string= "svg" (file-name-extension source))
(org-html--svg-image source attributes info)
(let* ((file (orgTZA-html-base64-encode-p source))
(data (if file (file-to-base64-string file t)
source)))
(org-html-close-tag
"img"
(org-html--make-attribute-string
(org-combine-plists
(list :src data
:alt (if (string-match-p "^ltxpng/" source)
(org-html-encode-plain-text
(org-find-text-property-in-string 'org-latex-src source))
(file-name-nondirectory source)))
attributes))
info))))
(advice-add 'org-html--format-image :override #'orgTZA-html--format-image)
;; END THIS SECTION IS FOR THE HTML EMBEDDED EXPORT
(use-package toc-org
:ensure t
:after org
:hook (org-mode-hook . toc-org-mode)
)
This is set up last as I could not find a way to auto-install svg-tag-mode, if it is loaded last it is a lessen problem. In any case run M-x install package
and then install svg-tag-mode
.
(use-package svg-tag-mode
:ensure t
)
(require 'org)
(require 'svg-tag-mode)
(defgroup notebook nil
"Customization options for `notebook-mode'."
:group 'org)
(defcustom notebook-babel-python-command
"/opt/anaconda3/bin/python"
"Python interpreter's path."
:group 'notebook)
(defcustom notebook-cite-csl-styles-dir
"."
"CSL styles citations' directory."
:group 'notebook)
(defcustom notebook-tags
'(
;; Inline code
;; --------------------------------------------------------------------
("^#\\+call:" . ((lambda (tag) (svg-tag-make "CALL"
:face 'org-meta-line))
(lambda () (interactive) (notebook-call-at-point)) "Call function"))
("call_" . ((lambda (tag) (svg-tag-make "CALL"
:face 'default
:margin 1
:alignment 0))
(lambda () (interactive) (notebook-call-at-point)) "Call function"))
("src_" . ((lambda (tag) (svg-tag-make "CALL"
:face 'default
:margin 1
:alignment 0))
(lambda () (interactive) (notebook-call-at-point)) "Execute code"))
;; Code blocks
;; --------------------------------------------------------------------
("^#\\+begin_src\\( [a-zA-Z\-]+\\)" . ((lambda (tag)
(svg-tag-make (upcase tag)
:face 'org-meta-line
:crop-left t))))
("^#\\+begin_src" . ((lambda (tag) (svg-tag-make "RUN"
:face 'org-meta-line
:inverse t
:crop-right t))
(lambda () (interactive) (notebook-run-at-point)) "Run code block"))
("^#\\+end_src" . ((lambda (tag) (svg-tag-make "END"
:face 'org-meta-line))))
(":session" . ((lambda (tag) (svg-tag-make "ZOOM-IN"
:face 'org-meta-line
:inverse t
:crop-right t))
(lambda () (interactive) (mb/org-babel-zoom-in)) "Zoom-in"))
;; Export blocks
;; --------------------------------------------------------------------
("^#\\+begin_export" . ((lambda (tag) (svg-tag-make "EXPORT"
:face 'org-meta-line
:inverse t
:alignment 0
:crop-right t))))
("^#\\+begin_export\\( [a-zA-Z\-]+\\)" . ((lambda (tag)
(svg-tag-make (upcase tag)
:face 'org-meta-line
:crop-left t))))
("^#\\+end_export" . ((lambda (tag) (svg-tag-make "END"
:face 'org-meta-line))))
;; :noexport: tag
;; --------------------------------------------------------------------
("\\(:no\\)export:" . ((lambda (tag) (svg-tag-make "NO"
:face 'org-meta-line
:inverse t
:crop-right t))))
(":no\\(export:\\)" . ((lambda (tag) (svg-tag-make "EXPORT"
:face 'org-meta-line
:crop-left t))))
;; Miscellaneous keywords
;; --------------------------------------------------------------------
("|RUN|" . ((lambda (tag) (svg-tag-make "RUN"
:face 'org-meta-line
:inverse t))))
("|RUN ALL|" . ((lambda (tag) (svg-tag-make "RUN ALL"
:face 'org-meta-line))
(lambda () (interactive) (notebook-run)) "Run all notebook code blocks"))
("|SETUP|" . ((lambda (tag) (svg-tag-make "SETUP"
:face 'org-meta-line))
(lambda () (interactive) (notebook-setup)) "Setup notebook environment"))
("|ZOOM-IN-CODE|" . ((lambda (tag) (svg-tag-make "ZOOM-IN"
:face 'org-meta-line))
(lambda () (interactive) (mb/org-babel-zoom-in)) "Zoom-in"))
("|EXPORT|" . ((lambda (tag) (svg-tag-make "EXPORT"
:face 'org-meta-line))
(lambda () (interactive) (notebook-export-html)) "Export the notebook to HTML"))
("|CALL|" . ((lambda (tag) (svg-tag-make "CALL"
:face 'org-meta-line))))
;; References
;; --------------------------------------------------------------------
("\\(\\[cite:@[A-Za-z]+:\\)" .
((lambda (tag) (svg-tag-make (upcase tag)
; :face 'nano-default
:inverse t
:beg 7 :end -1
:crop-right t))))
("\\[cite:@[A-Za-z]+:\\([0-9a-z]+\\]\\)" .
((lambda (tag) (svg-tag-make (upcase tag)
; :face 'nano-default
:end -1
:crop-left t))))
;; Miscellaneous properties
;; --------------------------------------------------------------------
("^#\\+caption:" . ((lambda (tag) (svg-tag-make "CAPTION"
:face 'org-meta-line))))
("^#\\+latex:" . ((lambda (tag) (svg-tag-make "LATEX"
:face 'org-meta-line))))
("^#\\+html:" . ((lambda (tag) (svg-tag-make "HTML"
:face 'org-meta-line))))
("^#\\+name:" . ((lambda (tag) (svg-tag-make "NAME"
:face 'org-meta-line))))
("^#\\+header:" . ((lambda (tag) (svg-tag-make "HEADER"
:face 'org-meta-line))))
("^#\\+label:" . ((lambda (tag) (svg-tag-make "LABEL"
:face 'org-meta-line))))
("^#\\+results:" . ((lambda (tag) (svg-tag-make "RESULTS"
:face 'org-meta-line)))))
"The `notebook-mode' tags alist.
This alist is the `notebook-mode' specific tags list. It follows the
same definition pattern as the `svg-tag-tags' alist (to which
`notebook-tags' is added)."
:group 'notebook)
(defcustom notebook-font-lock-case-insensitive t
"Make the keywords fontification case insensitive if non-nil."
:group 'notebook)
(defcustom notebook-indent t
"Default document indentation.
If non-nil, `org-indent' is called when the mode is turned on."
:group 'notebook)
(defcustom notebook-hide-blocks t
"Default visibility of org blocks in `notebook-mode'.
If non-nil, the org blocks are hidden when the mode is turned on."
:group 'notebook)
(defun notebook-run-at-point ()
"Update notebook rendering at point."
(interactive)
(org-ctrl-c-ctrl-c)
(org-redisplay-inline-images))
(defalias 'notebook-call-at-point 'org-ctrl-c-ctrl-c)
(defun notebook-setup ()
"Notebook mode setup function."
(interactive)
(setq org-cite-csl-styles-dir notebook-cite-csl-styles-dir)
(setq org-babel-python-command notebook-babel-python-command)
(require 'ob-python)
(require 'oc-csl))
(defalias 'notebook-run 'org-babel-execute-buffer)
(defalias 'notebook-export-html 'org-html-export-to-html)
(defun notebook-mode-on ()
"Activate notebook mode."
(add-to-list 'font-lock-extra-managed-props 'display)
(setq font-lock-keywords-case-fold-search notebook-font-lock-case-insensitive)
(setq org-image-actual-width `( ,(truncate (* (frame-pixel-width) 0.85))))
(setq org-startup-with-inline-images t)
(mapc #'(lambda (tag) (add-to-list 'svg-tag-tags tag)) notebook-tags)
(org-redisplay-inline-images)
(if notebook-indent (org-indent-mode))
(if notebook-hide-blocks (org-hide-block-all))
(add-hook 'org-babel-after-execute-hook 'org-redisplay-inline-images)
(svg-tag-mode 1)
(message "notebook mode on"))
(defun notebook-mode-off ()
"Deactivate notebook mode."
(svg-tag-mode -1)
(if notebook-indent (org-indent-mode -1))
(if notebook-hide-blocks (org-hide-block-all))
(remove-hook 'org-babel-after-execute-hook 'org-redisplay-inline-images))
;;; autoload
(define-minor-mode notebook-mode
"Minor mode for graphical tag as rounded box."
:group 'notebook
(if notebook-mode
(notebook-mode-on)
(notebook-mode-off)))
(define-globalized-minor-mode
global-notebook-mode notebook-mode notebook-mode-on)
(use-package notebook
:after org-mode
:config
(svg-tag-mode 1)
)
;; accept completion from copilot and fallback to company
(use-package copilot
:ensure t
:hook (prog-mode . copilot-mode)
:bind (:map copilot-completion-map
("<tab>" . 'copilot-accept-completion)
("TAB" . 'copilot-accept-completion)
("C-TAB" . 'copilot-accept-completion-by-word)
("C-<tab>" . 'copilot-accept-completion-by-word)))
(defun my-ess-mode-hook () (ess-switch-to-inferior-or-script-buffer t) ; Switch to ESS process buffer
(ess-rdired)) ; Open ESS Dired
(use-package ess
:ensure t
:defer t
:init
(add-hook 'ess-mode-hook
(lambda()
(make-local-variable 'company-backends)
(setq company-backends '(company-files company-capf-with-R-objects))))
(add-hook 'ess-mode-hook 'my-ess-mode-hook)
(add-hook 'ess-mode-hook 'eglot-mode)
(add-hook 'ess-r-mode-hook 'eglot-mode)
;;(setq ess-use-flymake nil)
(setq ess-use-company 'scriptonly)
:config
(setq ess-history-directory "~/.cache")
(setq ess-R-font-lock-keywords
'((ess-R-fl-keyword:keywords . t)
(ess-R-fl-keyword:constants . t)
(ess-R-fl-keyword:modifiers . t)
(ess-R-fl-keyword:fun-defs . t)
(ess-R-fl-keyword:assign-ops . t)
(ess-R-fl-keyword:%op% . t)
(ess-fl-keyword:fun-calls . t)
(ess-fl-keyword:numbers . t)
(ess-fl-keyword:operators)
(ess-fl-keyword:delimiters)
(ess-fl-keyword:=)
(ess-R-fl-keyword:F&T . t)))
(setq ess-help-own-frame 'one) ; avoid destroying existing frame
(setq ess-help-reuse-window t) ; same above
(setq comint-scroll-to-bottom-on-input t)
(setq comint-scroll-to-bottom-on-output t)
(setq comint-move-point-for-output t)
(setq comint-scroll-show-maximum-output t)
(setq ess-ask-for-ess-directory nil)
(setq ess-startup-directory 'default-directory)
;; Trying to speed up ess on orgmode
(setq ess-eval-visibly-p 'nowait)
(setq display-buffer-alist
'(("^\\*R[:\\*]" . (display-buffer-in-side-window
(side . bottom)
(slot . -1)
))
("^\\*R dired\\*" . (display-buffer-in-side-window
(side . right)
(slot . -1)
(window-width . 0.25)))
("^\\*help\\[R\\]" . (display-buffer-in-side-window
(side . right)
(slot . 1)
(window-width . 0.33)))))
(define-key comint-mode-map (kbd "<up>") 'comint-previous-matching-input-from-input)
(define-key comint-mode-map (kbd "<down>") 'comint-next-matching-input-from-input)
)
(setenv "PATH" (concat (getenv "PATH") ":~/.nimble/bin"))
(setq exec-path (append exec-path '("~/.nimble/bin")))
;; The `nimsuggest-path' will be set to the value of
;; (executable-find "nimsuggest"), automatically.
(setq nimsuggest-path "~/.nimble/bin/nimsuggest")
(defun my--init-nim-mode ()
"Local init function for `nim-mode'."
;; Just an example, by default these functions are
;; already mapped to "C-c <" and "C-c >".
(local-set-key (kbd "M->") 'nim-indent-shift-right)
(local-set-key (kbd "M-<") 'nim-indent-shift-left)
;; Make files in the nimble folder read only by default.
;; This can prevent to edit them by accident.
(when (string-match "/\.nimble/" (or (buffer-file-name) "")) (read-only-mode 1))
;; If you want to experiment, you can enable the following modes by
;; uncommenting their line.
(nimsuggest-mode 1)
;; Remember: Only enable either `flycheck-mode' or `flymake-mode' at the same time.
(flycheck-mode 1)
;; (flymake-mode 1)
;; The following modes are disabled for Nim files just for the case
;; that they are enabled globally.
;; Anything that is based on smie can cause problems.
(auto-fill-mode 0)
(electric-indent-local-mode 0)
)
(add-hook 'nim-mode-hook 'my--init-nim-mode)