Initialization files setup in Emacs
TODO Todo List:
- move to
use-package
configuration ofinit.el
- since Emacs 29 it’s bundled with Emacs! https://www.masteringemacs.org/article/spotlight-use-package-a-declarative-configuration-tool
Links to files generated by this file
- <file:///home/mb/.emacs.d/install-packages.el>
- <file:///home/mb/.emacs.d/init.el>
Links, blog pages really worth reading:
init.el
configuration:
- portable emacs and some early-init optimizations
https://www.reddit.com/r/emacs/comments/tt08di/my_portable_emacs_setup/
https://tfree87.github.io/.emacs.d/
https://tfree87.github.io/.emacs.d/early-init.html
TL;DR
An org source of this post can be found
here. This org-file can be used to generate (tangle in Emacs nomenclature)
to scripts:
install-packages.el
and
init.el
.
Place them in your ./emacs.d
and hope ;) they will run without
problems on your machine.
Problem description
The aim of this post is to finally have clean and tidy Emacs initialization file. After some time of battling with Emacs with the use of find-and-copy-snippets-from-internet I decided I had achieved sufficient level of experience to rewrite init.el from the scratch. In the post I’m going to implement the following rules:
- Installation/Updating of packages is perfomed in separate file
install-packages.el
(abbreviation forinstall or upgrage packages
) which is intended to be executed every now and then, while Emacs initialization is done ininit.el
. - I’m not going to use
use-package
since I still don’t get it well. What is more, according to this postuse-package
is just a fancier way of doing things that can be done in vanilla Emacs. - The style of init.el presented on this page is something that seems to look nice and I’m going to implement this approach.
- I’m not going to use multi-init-files approach presented … somewhere I saw some time ago and I’m unable to locate it now… As for now I think all-setup-in-one-file approach means less clutter.
-
I want to do things in emacsian way. So most of the comments are going to be included in this org file.
install-packages.el
andinit.el
will be tangled from it:C-c C-v t
. If this shortcut does not work (for plain emacs 27.1 installation tangling didn’t work out of the box so I needed to loadox
package: ->M-x eval-expression
->(require 'ox)
)There is an optional way of approaching this point presented here. It comes down to extracting
emacs-lisp
source snippets directly from an .org file when evaluatinginit.el
. I have no idea whether there are any relevant differences between both approaches.
Sources worth further reading
-
https://ruzkuku.com/emacs.d.html#org804158b - with a list of other useful pages with configurations
-
https://docs.freebsd.org/en/books/developers-handbook/tools/#emacs
- https://karthinks.com/software/batteries-included-with-emacs/
-
https://karthinks.com/software/more-batteries-included-with-emacs/
- https://stackoverflow.com/questions/5500035/set-custom-keybinding-for-specific-emacs-mode
- https://tuhdo.github.io/emacs-tutor3.html
- https://karthinks.com
-
Latex (not interesting after getting used to org?)
https://karthinks.com/software/latex-input-for-impatient-scholars/
Emacs on Windows
Deploying this system on Windows comes down to:
migrating ~/.emacs.d
The proper place for .emacs.d
in the newest Windows (11)
is C:\Users\<UserName>\AppData\Roaming\
.
Don’t forget about ~/.mysecrets
if you want to have ChaptGPT sessions running.
Before copying it is wise to zip .emacs.d to save some time.
zip -r ~/emacs.zip ~/.emacs.d
installing/configuring LaTeX distribution
I used to use existing MiKTeX standalone distribution, however this solution is troublesome. You need to:
- update windows
PATH
environment to point to tex bin directory -
probably also add:
(setenv “PATH” (concat “D:\Programs\Latex\miktex-portable\texmfs\install\miktex\bin\x64” (getenv “PATH”))) (add-to-list ‘exec-path “D:\Programs\Latex\miktex-portable\texmfs\install\miktex\bin\x64”)
somewhere in init.el
.
In the end I kept getting error when exporting to latex, and export
process complained something about
lack of perl for Windows when exporting via latexmk
.
(New MikTeX is supposedly distributed without perl).
-
Solution
- Install MikTeX with installer
- Install Perl distribution (Strawberry Perl).
The things that need to be adjusted in init.el
-
Adjust
org-cite-csl-styles-dir
to point to appropriate directory(setq org-cite-csl-styles-dir "~/Zotero/styles")
-
DEPRECATED Python paths
python3 path was an artifact from some old debian distribution. In newer Debian releases
python
stands forpython3
, so I corrected two occurances of python3 ininit.el
. -
Liberation mono font
That part of code is in
init.el
only for 1.8.20, so if one does not use it, they won’t miss it.
Installation/upgrade script
This script is meant to (re-)install/prepare/upgrade Emacs packages in order to have fully working Emacs environment.
This is an installation (or upgrade) script to keep installation commands outside init.el, in order to have everything clean and tidy (for details and discussion check this). Each time this script is run, the packages are not only installed but also upgraded. Thus, it might happen that a new version of some package breaks your installation. In order to prevent this troublesome situation it’s better to keep whole .emacs.d directory as a git repository and make a commit before executing this script. Then, in case any problems you can go back to restore properly working emacs installation.
Before running this script you should have git repository initialized in emacs directory. The repository should contain the following content:
- init.el
- install-packages.el
- elpa/
- .gitignore
- …
Synchronization of the local repository with the remote one is not performed in this script. It should be performed explicitely by the user in a convenient time.
Preparation
First, there is a configuration line. The user needs to set the directory where Emacs initialization files are located (I know in new Emacs there exist some variable for this but a bit of redundancy won’t do much harm).
Each time this script is run, the packages are not only installed but also upgraded. Thus, it might happen that a new version of some package breaks your installation. In order to prevent this troublesome situation it’s better to keep whole .emacs.d directory as a git repository and make a commit before executing this script. Then, in case any problems you can go back to restore properly working emacs installation. Before running this script you should have a git repository initialized in emacs directory and git itself installed in the system (see Sec. 1.9). Synchronization of the local repository with the remote one is not performed in this script. It should be performed explicitely by the user in a convenient time.
In order to make a git commit from within elisp script I followed this post. x
;; Make a git commit of your repository.
;;
(let ((default-directory my-emacs-dir)) ; run command `git add -u` in the context of my-emacs-dir
(shell-command "git add -u"))
(let ((default-directory my-emacs-dir)) ; run command `git commmit` in the context of my-emacs-dir
(shell-command
"git commit -m 'Precautionary commit before running install-packages.el'"))
Perform package initialization, only for Emacs < 27.1, since in Emacs 27.1
package-initialize
is executed automatically, before
loading the init file (see here).
(when (< emacs-major-version 27)
(package-initialize)) ; set up the load-paths and autoloads for installed packages
(setq package-check-signature nil)
then declare repositories where emacs packages can be found. There used to be more
addresses here, something like:
(setq package-archives
'(("gnu" . "http://elpa.gnu.org/packages/") ;; default value of package-archives in Emacs 27.1
; ("marmalade" . "http://marmalade-repo.org/packages/")
("melpa-stable" . "http://stable.melpa.org/packages/")
("melpa" . "https://melpa.org/packages/")
; ("org" . "https://orgmode.org/elpa/") ;;; removed as a way of dealing with https://emacs.stackexchange.com/questions/70081/how-to-deal-with-this-message-important-please-install-org-from-gnu-elpa-as-o
))
but, at the time of writing this (Jan, 2023), the biggest, the freshest etc.
repository is melpa
and it is advised to work with it. Marmalade
is
outdated, and I also needed to get rid of orgmode
as a remedy for
some problem (BTW).
What is more, at some point I stumbled upon the troubles with refreshing melpa
repository. Even after explicit running (package-refresh-contents)
I couldn’t
see melpa packages in packages-list
.
There is quite a long thread on this problem.
What helped me was replacing
("melpa" . "https://melpa.org/packages/")
to
("melpa" . "http://melpa.org/packages/")
and restarting emacs. Restarting is
important part of the procedure!
(Aside note: A way to go might also be this post that recommends adding
(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")
in your init.el
. This should allow to use https
adresses as package archives.
I haven’t check this approach but I should try this if anything goes
wrong in the future.)
NOTE (2023.08.30): In order to install org-contrib
package
(mediawiki
needs it as a dependency) I also needed to add
("nongnu" . "https://elpa.nongnu.org/nongnu/")
repository.
NOTE (2023.12.06): In order to be sure that emacs downloads the freshest
version of the package I changed the order of the
melpa
and melpa-stable
archives. I read somewhere that if
two packages of the same name are provided from two different
repositories, Emacs takes the first one to install. So, from now on,
let melpa
be before melpa-stable
.
Now my list of repositories looks as follows:
;;first, declare repositories
(setq package-archives
'(("gnu" . "http://elpa.gnu.org/packages/") ;; default value of package-archives in Emacs 27.1
("melpa" . "http://melpa.org/packages/")
("melpa-stable" . "http://stable.melpa.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
))
Now, synchronize your data: download descriptions of ELPA packages and update the cache with current versions of packages kept in remote repositories:
;; Refresh the repositories to have the newest versions of the packages
(package-refresh-contents)
In Emacs 27.1 it shouldn’t be necessary to use
(require 'packagename)
, so I can leave out the following code:
;; ;; Comment out if you've already loaded this package...
;; (require 'cl-lib) ;; built-in in 27.1
;; (require 'package) ;; built-in in 27.1
The main part of the installation script - list of the packages
I used to have (defvar my-packages ...
instead of (setq my-packages ...
below but… Do not use defvar
for declaring a list of packages to be installed!
If the variable is already defined
defvar
does nothing with it so it does
not refresh a list after editing it and thus it prevents from the
expected way of reevaluating of the package-install.el
.
The main point of the file. Set the list of packages to be installed
(setq my-packages
'(
auctex ; in order to have reftex working
bash-completion
calfw ; calendar and...
calfw-cal ; agenda ...
calfw-org ; integration
; counsel ; for ivy
cdlatex
company
chatgpt-shell
dall-e-shell
;; ob-chatgpt-shell
;; ob-dall-e-shell
dockerfile-mode
emacs-everywhere
engrave-faces
expand-region
fill-column-indicator
;flycheck
;flycheck-pos-tip
flyspell
;; gptel ;; not working
;; google-this
ido
; ivy
; jedi
magit
markdown-mode
matlab-mode ;
modus-themes ; theme by Protesilaos Stavrou
;moe-theme ; https://github.com/kuanyui/moe-theme.el
;mh
;ob-async
org ; ver. 9.3 built-in in Emacs 27.1; this install version 9.6 from melpa
org-ac
org-ai
;org-download
; org-plus-contrib
;org-mime
org-ref ; for handling org-mode references https://emacs.stackexchange.com/questions/9767/can-reftex-be-used-with-org-label
org-special-block-extras
;ox-gfm
;ox-pandoc
; ox-ipynb -> manual-download
;pandoc-mode
pdf-tools
popup ; for yasnippet
;projectile
;pyenv-mode
;Pylint ; zeby dzialal interpreter python'a po: C-c C-c
quelpa
quelpa-use-package
;rebox2
;recentf
session-async
;shell-pop
smex
ssh
; tramp ; ver. 2.4.2 built-in in Emacs 27.1
;tao-theme ; https://github.com/11111000000/tao-theme-emacs
texfrag
;treemacs
;use-package
websocket
workgroups2
;w3m
yasnippet
)
;; "A list of packages to be installed at Emacs launch."
)
And finally, perform the installation/upgrade of packages and print an information message.
(defun my-packages-installed-p ()
(cl-loop for p in my-packages
when (not (package-installed-p p)) do (cl-return nil)
finally (cl-return t)))
(unless (my-packages-installed-p)
;; check for new packages (package versions)
(package-refresh-contents)
;; install the missing packages
(dolist (p my-packages)
(when (not (package-installed-p p))
(package-install p))))
;; ; (jedi:install-server)
(message "All done in install-packages.")
Problems/errors during installation of packages
No problems so far…
My init.el
There’s something like early-init.el
in modern versions of Emacs that is intended
to speed up the launching process, however I’m not going to use this approach as
for now. An interesting discussion about this can be found here.
A note:
When Emacs init.el
does not load at startup.
-
DEPRECATED Setting an auxiliary variable
This section is deprecated in favour of
workgroups2 package
.;; This file is designed to be re-evaled; use the variable first-time ;; to avoid any problems with this. (defvar first-time t "Flag signifying this is the first time that .emacs has been evaled")
-
Package
package
initializationIn theory, in new Emacs two following lines shouldn’t be required to have everything working fine. However, it seems that some packages (
modus-themes
,workgroups2
?) cannot run without it when emacs commands are to be executed from command line without invoking Emacs window (Post with demonstration makefile should be published soon).(require 'package) (package-initialize)
-
https://github.com/quelpa/quelpa Quelpa lets you build and install your Emacs Lisp packages on-the-fly and directly from source (i.e. github repositories) in a comfortable way. Both packages are added to
install-packages.el
list of packages.Simple invoking
(require 'quelpa-use-package)
resulted in an error message (use-package: Unrecognized keyword: :quelpa
) while trying to install anything with the use ofquelpa-use-package
. So I decided to use a fix from this link and then succeeded with installation from github:(require 'quelpa-use-package) (setq package-archives '(("melpa" . "https://melpa.org/packages/")) use-package-always-ensure t) (package-initialize) (require 'use-package-ensure) (use-package quelpa :ensure) (use-package quelpa-use-package :demand :config (quelpa-use-package-activate-advice))
Setting separate file for emacs custom entries
If you don’t set the separate for custom entries, Emacs appends its code
directly into init.el
. To prevent this we need to define other file.
Remember to create custom-file.el
file by hand! Emacs won’t create it
for you.
(setq custom-file "~/.emacs.d/custom-file.el")
Assuming that the code in custom-file is execute before the code ahead of this line is not a safe assumption. So load this file proactively.
(load-file custom-file)
Global emacs customization
Here are global Emacs customization. If necessary some useful infomation or link is added to the customization.
-
Remarks: At around May 2023 I stopped using
global-linum-mode
because of the annoying lags while typing in a buffer that occured quite frequently, Links:- https://github.com/jrblevin/markdown-mode/issues/181
- https://www.reddit.com/r/orgmode/comments/e7pq7k/linummode_very_slow_for_large_org_files/
- https://emacs.stackexchange.com/questions/49032/line-numbering-stick-with-linum-or-nlinum
From two possible alternatives at the time:
nlinum-mode
anddisplay-line-numbers-mode
I decided on the latter because it was built-in Emacs.(auto-revert-mode 1) ; Automatically reload file from a disk after change (global-auto-revert-mode 1) (delete-selection-mode 1) ; Replace selected text (show-paren-mode 1) ; Highlight matching parenthesis ; Enable line numbering ;; DEPRECATED, CAUSES LAGS WHEN TYPING: (global-linum-mode 1) (global-display-line-numbers-mode 1) (scroll-bar-mode 1) ; Enable scrollbar (menu-bar-mode 1) ; Enable menubar (tool-bar-mode -1) ; Disable toolbar since it's rather useless (setq line-number-mode t) ; Show line number (setq column-number-mode t); Show column number (define-key global-map (kbd "RET") 'newline-and-indent) ; Auto-indent new lines (if (not (daemonp)) ; if this is not a --daemon session -> see: [[emacs-everywhere]] section (desktop-save-mode 1) ; Save buffers on closing and restore them at startup ) (setq desktop-load-locked-desktop t) ; and don't ask for confirmation when ; opening locked desktop (setq desktop-save t) (save-place-mode t) ; When re-entering a file, return to the place, ; where I was when I left it the last time. (setq list-command-history-max 500) ; no of available commands in =command-history=
-
Problems with
julia
and~/.bashrc
According to https://stackoverflow.com/a/42036157
emacs loads your personal
~/.bashrc
after setting:(setq shell-command-switch "-ic")
however this in turn gives an error:
cannot set terminal process group
.And furthermore because of that I cannot run julia in org-babel source codes. What worked for me is:
(setq shell-command-switch "-c")
based on https://emacs.stackexchange.com/questions/3447/cannot-set-terminal-process-group-error-when-running-bash-script and https://stackoverflow.com/questions/9471341/emacs-shell-command-outputting-cannot-set-terminal-process-group-and-no-job-c.
-
Emacs shell history from previous sessions
(savehist-mode 1) ; Save history for future sessions
-
Easily restore previous/next window layout
-
undo = previous window view
C-c left
-
redo (undo undo)
C-c right
(winner-mode 1) ; Toggle between previous window layouts
-
-
Line truncation
There are some other ways of truncating:
(setq-default truncate-lines t) ; ugly way of truncating
or
; fancier way of truncating (word truncating) THIS DOES NOT WORK!!! (setq-default global-visual-line-mode t)
however I didn’t find them pretty and finally this command is useful:
(global-visual-line-mode t) ; Truncate lines
-
Preserving indentation
While working with python code in org-babel the default may be cumbersome since emacs converts 8 spaces gap into tab sign during the code tangling which in turn results in errors when python interprets the code.
https://emacs.stackexchange.com/questions/24283/org-mode-converting-spaces-to-tabs-when-evaluating-source https://emacs.stackexchange.com/questions/37299/org-mode-setting-to-preserve-spacing-in-src-code-with-verbatim-latex-output-to https://emacs.stackexchange.com/questions/54526/python-src-block-sets-tabs
https://www.reddit.com/r/orgmode/comments/mj6rg2/python_indentation_in_source_block/
In order to fix it we need to set the following:
; fix for python indentation problems after tangling of org-babel blocks (setq org-src-preserve-indentation t org-edit-src-content-indentation 0)
org-edit-src-content-indentation
is by default set to 2, which preserves nice-looking two-space gap in org-babel blocks of code. So by setting it to 0 we lose the feature of nice-looking indentation, and each source block in python should be left aligned (in other languages however you may add some extra whitespaces if you don’t mind this gap in source files…) -
Prevent from deselecting text after M-w copying
;; Do not deselect after M-w copying -> (defadvice kill-ring-save (after keep-transient-mark-active ()) "Override the deactivation of the mark." (setq deactivate-mark nil)) (ad-activate 'kill-ring-save) ;; <- Do not deselect after M-w copying
-
Setting default font
To get the list of available fonts: Type the following in the scratch buffer, and press
C-j
at the end of it:(font-family-list)
You may need to expand the result to see all of them, by hitting enter on the...
at the end. (Source).The font of my choice is:
;; now this setting is done much lower in the code due to ;; problems with fonts in emacsclient/daemonp instances -> see [[emacs-everywhere]] ;; (set-frame-font "liberation mono 11" nil t) ; Set default font
Due to due to the problems with fonts in
emacsclient/daemonp
instances font is set now in the section 1.8.20. -
Highlight on an active window/buffer
Although the active window can be recognized by the cursor which blinking in it, sometimes it is hard to find in on the screen (especially if you use a colourful theme like 1.8.23.1.
I found a post adressing this issue. Although the accepted answer is using
auto-dim-other-buffers.el
I prefer this solution which does not rely on external package;;Highlight an active window/buffer or dim all other windows (defun highlight-selected-window () "Highlight selected window with a different background color." (walk-windows (lambda (w) (unless (eq w (selected-window)) (with-current-buffer (window-buffer w) (buffer-face-set '(:background "#111")))))) (buffer-face-set 'default)) (add-hook 'buffer-list-update-hook 'highlight-selected-window) ;;
-
Time and calendar
-
DONE Locale for names of days of the week in org-mode
Setting names of the days of the week and months to arbitrarily language: Link 1, Link 2
The best method I found working for my purposes is:
(setq system-time-locale "C") ; Force Emacs to use English timestamps
It makes Emacs use English language and not the system localization language when inserting weekdays abreviations in org-mode timestamps and in org-agenda.
(setq calendar-week-start-day 1) ; set Monday as the starting day of the week
-
DONE Calendar
Inserting the date from the calendar. Here’s the way how one can insert date in org-mode by hitting
C-c .
choosing the day and hittingRET
.The above shortcuts are listed in
Scroll
menu item which is visible in menu bar, when you’re in Calendar buffer.;; Calendar -> (defun calendar-insert-date () "Capture the date at point, exit the Calendar, insert the date." (interactive) (seq-let (month day year) (save-match-data (calendar-cursor-to-date)) (calendar-exit) (insert (format "%d-%02d-%02d" year month day))))
Warning! Here, instead of using:
(define-key calendar-mode-map (kbd "RET") 'calendar-insert-date)
it’s better to define the action as
(eval-after-load "calendar" `(progn (define-key calendar-mode-map (kbd "RET") 'calendar-insert-date))) ;; <- Calendar
Otherwise, you may get
calendar-mode-map is void
error, ifcalendar-mode-map
it’s not loaded at the moment of executing the command (Link).Moving in calendar buffer is like follows:
Move by Backward Forward a day S-<left> S-<right> a week S-<up> S-<down> a month > < 3 months M-v C-v a year 4 M-v 4 C-v
-
-
Easy moving between windows
It is managed by WindMove package that is built-in in Emacs. The default keybindings of this package is
Shift arrow
, which sometimes may be inconvenient (there are conflicts for example in org-mode, other packages that conflict with org are listed here). That is why it’s better to remap those keybindings to other combination (Super-Key-<arrow>
in the code below).;; windmove -> ;; Easy moving between windows ;; setting windmove-default-keybindings to super-<arrow> in order ;; to avoid org-mode conflicts (global-set-key (kbd "s-<left>") 'windmove-left) (global-set-key (kbd "s-<right>") 'windmove-right) (global-set-key (kbd "s-<up>") 'windmove-up) (global-set-key (kbd "s-<down>") 'windmove-down) ;; <- windmove
-
DEPRECATED Useful For Emacs < 27.1
(This section is deprecated. In Emacs 27.1 the package works ok without the need of application of
ignore-error-wrapper
function.)According to package’s wikipage there exist some problem with the package, namely: “When you run for instance windmove-left and there is no window on the left, windmove will throw exception (and if you have debug-on-error enabled) you will see Debugger complaining.”
Proposed workaround requires
cl
package, which unfortunately is deprecated in Emacs 27.1 (The workaround worked in Emacs < 27). With the use of this post and this part of emacs manual I sort of solved the problem and with the following code Emacs does not throw warnings or errors.;; windmove -> ;; Easy moving between windows (when (fboundp 'windmove-default-keybindings) (windmove-default-keybindings)) (eval-when-compile (require 'cl)) (setq lexical-binding t) (defun ignore-error-wrapper (fn) "Funtion return new function that ignore errors. The function wraps a function with `ignore-errors' macro." (lexical-let ((fn fn)) (lambda () (interactive) (ignore-errors (funcall fn))))) ;; setting windmove-default-keybindings to super-<arrow> in order ;; to avoid org-mode conflicts (global-set-key (kbd "M-s-<left>") (ignore-error-wrapper 'windmove-left)) (global-set-key (kbd "M-s-<right>") (ignore-error-wrapper 'windmove-right)) (global-set-key (kbd "M-s-<up>") (ignore-error-wrapper 'windmove-up)) (global-set-key (kbd "M-s-<down>") (ignore-error-wrapper 'windmove-down)) ;; <- windmove
-
-
Easy windows resize
;; Easy windows resize -> (define-key global-map (kbd "C-s-<left>") 'shrink-window-horizontally) (global-set-key (kbd "C-s-<right>") 'enlarge-window-horizontally) (global-set-key (kbd "C-s-<down>") 'shrink-window) (global-set-key (kbd "C-s-<up>") 'enlarge-window) ;; <- Easy windows resize
-
Column marker
In Emacs 27.1 in only needs to add the following lines in your
init.el
to have properly working fill-column indicator in all buffers. (https://www.gnu.org/software/emacs/manual/html_node/emacs/Displaying-Boundaries.html);; Fill column indicator -> (global-display-fill-column-indicator-mode) ;; <- Fill column indicator
This behaviour, however, may not be wanted in some buffers (for example ipython command line bufffer or octave command line buffer). In order to have fill-column-indicator only for buffers of some type (code files, text files (org, doconce etc.) we could add a hook for
prog-mode
and two relative modestext-mode
andspecial-mode
. Unfortunately, these modes do not contain all required modes (DocOnce-mode
ororg-mode
are absent on the list of modes). (The list of modes inherited afterprog-mode
and two other modes can be viewed with the use of the following function:(defun list-prog-modes () "List all programming modes known to this Emacs." (interactive) (with-help-window "*Programming Major Modes*" (mapatoms (lambda (f) (when (provided-mode-derived-p f 'prog-mode) ;; prog-mode or text-mode or special-mode (princ f) (princ "\n"))))))
Anyway, I decided on the following approach based on this page:
-
enable display-fill-column mode, which can be done by settings variable
;; Fill column indicator -> (setq display-fill-column-indicator-column 81)
-
write general function that can be hooked into mode
(defun my-default-text-buffer-settings-mode-hook() (display-fill-column-indicator-mode 1) ) ;; <- Fill column indicator
-
and add this hook per each required mode (this is done in 1.8.7 section of this document
-
-
Turning on/off beeping
Completely out of the blue my emacs started beeping. I guess it had to be some keybinding I accidentally pressed but have no idea what I did. Anyway, to disable it we must do the following:
;; Setting alarms in Emacs -> (setq-default visible-bell t) (setq ring-bell-function 'ignore)
-
Ibuffer - an advanced replacement for BufferMenu
Description of the package is here.
;; Advanced buffer mode (global-set-key (kbd "C-x C-b") 'ibuffer)
-
Sessions for buffers, tabs etc.
Interesting discussion on the topic: https://www.reddit.com/r/emacs/comments/j5bm4x/best_way_to_have_multiple_work_environments_in/ https://www.emacswiki.org/emacs/SessionManagement
Too many opened buffers ultimately end up in a mess that is inconvenient for managing.
-
emacs-sessions
The simplest solution and it works as I would like it to work.
-
Installation
Sessions are stored in
~/.emacs.d/sesssions/
directory.cd ~/.emacs.d/ cd manual-download git clone git@github.com:przemarbor/emacs-sessions.git cd .. mkdir sessions
-
Initialization
;; emacs-sessions (add-to-list 'load-path "~/.emacs.d/manual-download/emacs-sessions/") (require 'sessions)
-
-
ABANDONED
persp-mode
The fork of
perspective-el
namedpersp-mode
(https://github.com/Bad-ptr/persp-mode.el) seems to have the features I’d like to have (i.e.:- saving/restoring workspaces
- renaming workspace
- displaying only buffers from the given workspace
- … )
However, at first glance it seems to be quite complicated. Maybe I should give it a try in the future…
-
Oldschool way of installation (according to github README:
Place the persp-mode.el file somewhere in the emacs’ load-path and add (require ‘persp-mode) (persp-mode 1) to your configuration file.
Download the file
mkdir ~/.emacs.d/manual-download/persp-mode cd ~/.emacs.d/manual-download/persp-mode curl https://raw.githubusercontent.com/Bad-ptr/persp-mode.el/master/persp-mode.el > persp-mode.el
and
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; persp-mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (add-to-list 'load-path "~/.emacs.d/manual-download/persp-mode/") (require 'persp-mode) (persp-mode 1)
-
DEPRECATED Approach no 1:
perspective-el
andtab-bar-mode
https://github.com/nex3/perspective-el
To ease the problem we may enable
tab-bar-mode
and useperspestive-el
package (loaded with the command(persp-mode 1)
). We also need to rebindC-x C-b
to invoke persp wrapper ofibuffer
to have buffer displayed per session. More about it can be found here.(Using old
M-x ibuffer
is an old previously used buffer view…;; :tangle (concat (org-entry-get nil "PRJ-DIR" t) "init.el") ;; tabs, sessions for buffers (tab-bar-mode 1) (customize-set-variable 'persp-mode-prefix-key (kbd "C-c M-p")) (persp-mode 1) (global-set-key (kbd "C-x C-b") 'persp-ibuffer)
In order to have auto-reloaded session we need to define additional variable and hook, however the code below does not work flawlessly (There are some problems when re-/starting Emacs. What is more, in
perspecitve-el
package I cannot find a way to name tab bar with the name of the perspetive name (the name of the tab bar changes with the name of the file).;; :tangle (concat (org-entry-get nil "PRJ-DIR" t) "init.el") ;; tabs, sessions for buffers (tab-bar-mode 1) (setq persp-state-default-file "~/.emacs.d/myarch/perspective-state-save-sessions") (customize-set-variable 'persp-mode-prefix-key (kbd "C-c M-p")) (persp-mode 1) (persp-state-load persp-state-default-file) (global-set-key (kbd "C-x C-b") 'persp-ibuffer) (add-hook 'kill-emacs-hook #'persp-state-save)
That’s why I switched to:
-
DEPRECATED
tabspaces
packagehttps://www.reddit.com/r/emacs/comments/10tulyc/multi_project_management_perspective_perspmode/
https://github.com/mclear-tools/tabspaces
Set auto-restoring of the sessions.
;; :tangle (concat (org-entry-get nil "PRJ-DIR" t) "init.el") ;; tabs, sessions for buffers (setq tabspaces-session t) (setq tabspaces-session-auto-restore t)
Enable
tabspaces-mode
and redefine (only to have it explicitely written in myinit.el
) keymap. You can invoke particular command, for example buffer list of the current tabspace by pressing:C-c TAB b
;; :tangle (concat (org-entry-get nil "PRJ-DIR" t) "init.el") (tabspaces-mode) (defvar tabspaces-command-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C") 'tabspaces-clear-buffers) (define-key map (kbd "b") 'tabspaces-switch-to-buffer) (define-key map (kbd "d") 'tabspaces-close-workspace) (define-key map (kbd "k") 'tabspaces-kill-buffers-close-workspace) (define-key map (kbd "o") 'tabspaces-open-or-create-project-and-workspace) (define-key map (kbd "r") 'tabspaces-remove-current-buffer) (define-key map (kbd "R") 'tabspaces-remove-selected-buffer) (define-key map (kbd "s") 'tabspaces-switch-or-create-workspace) (define-key map (kbd "t") 'tabspaces-switch-buffer-and-tab) map) "Keymap for tabspace/workspace commands after `tabspaces-keymap-prefix'.")
The problem with tabspace is that I couldn’t find a way to save buffers belonging to a certain tab (workspace) to file.
-
-
Other solution
There are also solutions based on frame approach:
-
Setting font size for all buffers
;; Resize the whole frame, and not only a window ;; Adapted from https://stackoverflow.com/a/24714383/5103881 (defun acg/zoom-frame (&optional amt frame) "Increaze FRAME font size by amount AMT. Defaults to selected frame if FRAME is nil, and to 1 if AMT is nil." (interactive "p") (let* ((frame (or frame (selected-frame))) (font (face-attribute 'default :font frame)) (size (font-get font :size)) (amt (or amt 1)) (new-size (+ size amt))) (set-frame-font (font-spec :size new-size) t `(,frame)) (message "Frame's font new size: %d" new-size))) (defun acg/zoom-frame-out (&optional amt frame) "Call `acg/zoom-frame' with negative argument." (interactive "p") (acg/zoom-frame (- (or amt 1)) frame)) (global-set-key (kbd "C-x C-=") 'acg/zoom-frame) (global-set-key (kbd "C-x C--") 'acg/zoom-frame-out) (global-set-key (kbd "<C-down-mouse-4>") 'acg/zoom-frame) (global-set-key (kbd "<C-down-mouse-5>") 'acg/zoom-frame-out)
Useful tools
-
Dired
https://www.emacswiki.org/emacs/DiredBookmarks
The default behaviour of Dired when walking across directory structure is to open each directory in a new buffer. In this way you end up with a lot of (probably unnecessary) buffers. How to circumvent this behaviour. (Beware! There are some reasons you might want to keep it!)
-
Straightforward solution
The most straighforward way is to kill them by going to buffer menu
C-x C-b
and selecting the ones you want to kill with
d
and delete them all at once withx
. -
Ibuffer interactive way
In 1.8.3.15 there a nice shortcut to do this. You can select all the files of the given mode with:
* M
(note the capital
M
!* m
is for selecting modified buffers). and then kill them with (again capital!)D
.Summary (providing you have Ibuffer, which is built-in in Emacs 27.1):
-
Open ibuffer
C-x C-b
or
M-x ibuffer
-
Select all the buffer of the mode
* M
-
Search for all
dired
orsunrise
mode buffers and kill them:* D
-
-
Simple dired way
You can use
dired-find-alternate-file
function which is bounded to keya
indired-mode
for going down the directory structure. For going up you need to do some more tweaks and the simplest way is given by Xah Lee (original source, stackoverflow).
-
-
Dired and bookmarks
When going up and down the directory structure you can mark/add the favourite places into bookmarks which comes down to:
C-x r m
Then, you can go to your bookmarks menu by:
C-x r b
Select the directory you want to open and go there in dired/sunrise mode.
To delete, rename a bookmark:
M-x list-bookmarks
d
to mark to deletex
to delete all D marked onesr
to renames
to save changes
You can always achieve the same functionality without bookmarks feature like here.
-
texfrag
package for rendering latex fragmentstexfrag is a package that might be useful when browsing web pages in
eww
. It lets one render all the latex fragments to look nice. In order to do that you might need to:- force
texfrag-mode
(ortexfrag-global-mode
) - press
C-c C-p C-p
in order to convert the latex code into rendered images on a webpage opened viaeww
- force
Completing
ido/smex vs ivy/counsel/swiper vs helm
-
ido-mode
They say that
ido
is a powerful package and you should have it enabled… I’m not going to argue with that, yet I haven’t studied much its capabilities.;; ido-mode -> (ido-mode 1) (setq ido-enable-flex-matching t) (setq ido-everywhere t) ; ido-mode for file searching ;; <- ido-mode
For conenient opening files with
sudo
privilages we’ll add an auxiliary command (https://stackoverflow.com/a/29255604/4649238):(defadvice ido-find-file (after find-file-sudo activate) "Find file as root if necessary." (unless (and buffer-file-name (file-writable-p buffer-file-name)) (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
Now, after trying to open
sudo
file withC-x C-f
emacs will automatically concatenate necessary modifier in order to have it open… -
smex
This package is installed because I was inspired by some post. Just for tests. https://github.com/nonsequitur/smex/
;; smex -> (global-set-key (kbd "M-x") 'smex) (global-set-key (kbd "M-X") 'smex-major-mode-commands) ;; This is your old M-x. (global-set-key (kbd "C-c C-c M-x") 'execute-extended-command) ;; <- smex
-
Furthermore, according to some other users “Ivy is simpler (and faster) than Helm but more powerful than Ido”.
-
TODO (TEMPORARILY COMMENTED OUT) Abbreviations (abbrev-mode)
- NOTE: This part of my init.el is temporarily commented out.
abbrev-mode
can be useful, however it brings some trouble when working with more than one language. I would like to come back here after having prepared a piece of code that would recognize the language of the current document and based on this, change the autocorrection dictionary. Until then it’s better to manually triggerabbrev-mode
per a document (in English), when you really need it.I’ve just discovered this mode and wanted to use it. I’m not sure whether
abbrev-mode
,yasnippet
andcompany
aren’t substitute modes. Well, in fact they partly are.Emacs abbreviations are
;; ;; abbrev-mode -> ;; (setq-default abbrev-mode t) ;; ; (read-abbrev-file "~/.emacs.d/abbrev_defs") ;; (read-abbrev-file "~/.emacs.d/abbrev_defs_autocorrectionEN") ;; (read-abbrev-file "~/.emacs.d/abbrev_defs_autocorrectionPL") ;; (read-abbrev-file "~/.emacs.d/abbrev_defs_cis") ;; (setq save-abbrevs t) ;; ;; <- abbrev-mode
-
Useful commands
- C-x a - inverse-add-global-abbrev
- C-x a i l - inverse-add-global-abbrev
- C-x a i g - inverse-add-mode-abbrev
- unexpand-abbrev
- edit-abbrevs
- list-abbrevs
- kill-all-abbrevs
Autocomplete
auto-complete
vs company
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; *** Auto-completing
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(add-hook 'after-init-hook 'global-company-mode)
-
Recently opened files
;; Recently opened files -> (recentf-mode 1) (setq recentf-max-menu-items 200) (setq recentf-max-saved-items 200) ;; in original emacs this binding is for "Find file read-only" (global-set-key "\C-x\ \C-r" 'recentf-open-files) ;; <- Recently opened files
Settings for modes
It’s good to have keybindings for the commands often used, and it’s good to have them enabled per specific mode.
How to define keybindings and key sequences: Link 1, Link 2.
How to define shortcuts for major modes: Link 1, Link 2.
The problem that can be encountered in this point is that we choose wrong (restricted) keybinding. In that case Emacs will print an error message like:
Key sequence M-x g starts with non-prefix key M-x
We can check the bindings that are restricted for the specific mode:
In the buffer with the mode enabled press C-h m
. New window with
information on the modes enabled for the buffer appears. You can
find the bindings tagged as Prefix Command
. If you’d really like to use
other shortcut
you need to rebind it (1, 2, 3).
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; *** Minor mode settings and keybindings
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
Emacs-Lisp mode
Be sure to set
emacs-lisp-mode
maps/hooks etc, not justlisp-mode-...
otherwise the shortcuts won’t work.;; Emacs-Lisp mode... (defun my-emacs-lisp-mode-hook () (define-key emacs-lisp-mode-map (kbd "C-e b") 'eval-buffer) (define-key emacs-lisp-mode-map (kbd "C-e e") 'eval-expression) (define-key emacs-lisp-mode-map (kbd "C-e r") 'eval-region) )
-
Octave/Matlab mode
Based on https://wiki.octave.org/Emacs.
Three files mentioned in the link must be already installed somewhere within my
Emacs 26.1
, becauseoctve-mode
command is available. The only thing to do is to addoctave-mode-hook
:;; Octave mode... (defun my-octave-mode-hook() (define-key octave-mode-map (kbd "C-c C-s") 'octave-send-buffer) (define-key octave-mode-map (kbd "<f8>") 'octave-send-buffer) (lambda () (abbrev-mode 1) (auto-fill-mode 1) (if (eq window-system 'x) (font-lock-mode 1))))
This code is compiled however it throws an error while writing the code and expecting function syntax hints working:
=eldoc error: ( error Selecting deleted buffer)
Now
C-c TAB a
should invoke octave and run a buffer in it (runC-h m
or visit https://wiki.octave.org/Emacs to see the keybindings)Define your own custom shortcuts to run specific script in matlab shell.
; Matlab mode... (defun my-matlab-mode-hook() (define-key matlab-mode-map (kbd "<f8>") '(lambda () (interactive) (matlab-shell-send-command "emacsrun('/home/mb/projects/TSdistributed/srcMTLB/main')" )) ) )
-
Change all matlab source blocks to octave (or vice versa) in the current buffer
If you want to have consistent way of working with matlab/octave source blocks you need to tend to use named sessions.
(defun replace-string-in-buffer (string1 string2) (save-excursion (goto-char (point-min)) (while (search-forward string1 nil t) (replace-match string2)))) ;; (replace-string-in-buffer "string2" "string2") (defun mb/matlab-octave-org-babel-source-conversion() (interactive) (replace-string-in-buffer "#+begin_src octave" "#+begin_src oct2mat") (replace-string-in-buffer "#+begin_src matlab" "#+begin_src mat2oct") (replace-string-in-buffer "src_octave" "src_oct2mat") (replace-string-in-buffer "src_matlab" "src_mat2oct") (replace-string-in-buffer "#+begin_src oct2mat" "#+begin_src matlab" ) (replace-string-in-buffer "#+begin_src mat2oct" "#+begin_src octave") (replace-string-in-buffer "src_oct2mat" "src_matlab") (replace-string-in-buffer "src_mat2oct" "src_octave") (kill-buffer "*MatOct*") ) (defun mb/matoct-conversion() ;; auxiliary shortcut for an original function (interactive) (mb/matlab-octave-org-babel-source-conversion) )
Remember not to give the same name to the matlab and octave session and place it simultaneously in the same org file! It won’t work (which is obvious if you give it a think for a second).
Provided you have opened session named
*MatOct*
that is managed byoctave
(ormatlab
) and you want to run the code in the other language be sure to:- kill currently running
*MatOct*
session, -
change all the occurances of:
#+begin_src octave
to#+begin_src matlab
, and- for inline code blocks:
src_octave
tosrc_matlab
(or vice versa)
- and only then run the code (or export the file) to the format of your choice.
- kill currently running
-
-
Python mode
The below code does not work as expected. Probably it’d be better to apply the configuration given here.
The old versions have explicitely pointed to python3 binary like this
;; Python mode... (defun my-python-mode-hook() (lambda () (setq python-shell-interpreter "python3") ))
but it’s outdated now and now it’s enough to have:
;; Python mode... (defun my-python-mode-hook() (lambda () (setq python-shell-interpreter "python") ))
-
Org mode
By default emacs waits until all exporting processes finish. It may take quite a while in some situations (for example when exporting long document to LaTeX). In order to make emacs work in asyncronous mode you need to toggle this (link 1, link 2).
One way is to do it each time when exporting: after pressing
C-c C-e
you getexporting menu
and in the third line you can seeAsync export
option that can be enabled by pressinC-a
. It is rather cumbersome.To have this option toggled after launching emacs put the line below in your init file.
;; Org mode... (setq org-export-in-background t)
This setting has impact only when exporting via
org exporting menu
(triggered byC-c C-e
). When callingorg-latex-export-to-pdf
this setting is not taken into account. Fortunately, this function has optional parameter that can be set to obtain async behaviour. All in all, the (almost) working solution can be written as a custom hook like this:(defun my-org-mode-hook() (define-key org-mode-map (kbd "<f9>") '(lambda () (interactive) (org-latex-export-to-pdf :async t) (org-beamer-export-to-pdf :async t) (org-odt-export-to-odt :async t) (org-odt-export-as-pdf :async t) ) ) )
Why “almost”? Because this solution still won’t work when exporting files to Beamer. In order one needs to create appropriate init file with settings for async export and set
org-export-async-init-file
variable as path to this file (see 1.8.7.4.1).-
Setting
org-export-async-init-file
to avoid failure while exporting to BeamerOrg-beamer async exporter may fail because of lacking
org-export-async-init-file
(as it is stated here and here).In order to avoid this problem we can create a file with the following content (note setting
org-export-allow-bind-keywords
variable):(require 'package) (setq package-enable-at-startup nil) (package-initialize) (require 'org) (require 'ox) (require 'cl) (require 'ox-beamer) (setq org-export-async-debug nil) ;; no impact here. Do it in main init.el (setq org-export-allow-bind-keywords t) ;; Important! In order to have #+BIND command working.
and set the variable
org-export-async-init-file
.(setq org-export-async-init-file (expand-file-name "~/.emacs.d/myarch/async_init.el")) (setq org-export-async-debug nil) ;; when set to 't' it stores all "*Org Export Process*" buffers, when set to 'nil' it leaves only the last one in the buffer list, but already killed
The important line is
(require 'ox-beamer)
!!! (link) -
TODO async for odt documents still not working
-
-
Updating all of the hooks to make them aware of your mode settings
Now we need to update the hooks to
;; Add all of the hooks... ;(add-hook 'c++-mode-hook 'my-c++-mode-hook) ;(add-hook 'c-mode-hook 'my-c-mode-hook) (add-hook 'emacs-lisp-mode-hook 'my-emacs-lisp-mode-hook) (add-hook 'octave-mode-hook 'my-octave-mode-hook) (add-hook 'matlab-mode-hook 'my-matlab-mode-hook) (add-hook 'python-mode-hook 'my-python-mode-hook) (add-hook 'org-mode-hook 'my-org-mode-hook) ; (add-hook 'lisp-mode-hook 'my-lisp-mode-hook) ;(add-hook 'perl-mode-hook 'my-perl-mode-hook)
-
Adding a hook to more than a one mode at once
https://emacs.stackexchange.com/questions/501/how-do-i-group-hooks https://stackoverflow.com/questions/7398216/how-can-i-apply-a-hook-to-multiple-emacs-modes-at-once
In order to add a hook to more than one modes we need to use a function (taken from here.
;; Add a hook to the list of modes (defun my-add-to-multiple-hooks (function hooks) (mapc (lambda (hook) (add-hook hook function)) hooks)) (defun my-turn-on-auto-fill () my-default-text-buffer-settings-mode-hook ) (my-add-to-multiple-hooks 'my-default-text-buffer-settings-mode-hook ;; my-turn-on-auto-fill '(DocOnce-hook emacs-lisp-mode-hook matlab-mode-hook octave-mode-hook org-mode-hook python-mode-hook ))
-
Change font color for specific mode (eww)
Based on this.
;; Change font color for eww (defun my-eww-mode-faces () (face-remap-add-relative 'default '(:foreground "#BD8700"))) (add-hook 'eww-mode-hook 'my-eww-mode-faces)
Bibliography - citations
-
Useful links for Emacs 29
https://orgmode.org/manual/Citations.html https://www.reddit.com/r/orgmode/comments/vchefn/guide_to_citations_in_orgmode/ https://kristofferbalintona.me/posts/202206141852/ https://blog.tecosaur.com/tmio/2021-07-31-citations.html#more-exporting
-
In Emacs 29 the only thing you need to have citations working is to:
- add
#+BIBLIOGRAPHY: path/to/your/bib/file.bib
at the beginning of the org file (or you could do it here ininit.el
) - add
#+PRINT_BIBLIOGRAPHY:
at the place where you want to have references to be included - do something about the style of the references and citations:
- set the directory with csl styles for the easy use of them in Emacs
;; BIBLIOGRAPHY (setq org-cite-csl-styles-dir “~/Zotero/styles”)
- add
#+CITE_EXPORT: csl apa.csl
at the beginning of the file (providedapa.csl
is inside~/Zotero/styles
)
- add
Org customization: org-mode, org-babel …
-
Modyfing TODO-DONE sequence in org-mode
https://orgmode.org/manual/TODO-Extensions.html
;; customized todo-done sequence (setq org-todo-keywords '( (sequence "TODO" "????" "POSTPONED" "|" "DONE") (sequence "TODO" "ABANDONED" "|" "DEPRECATED" "DONE") (sequence "TODO" "????" "ABANDONED" "POSTPONED" "|" "DEPRECATED" "DONE") )) (setq org-todo-keyword-faces '( ("????" . (:foreground "red" :weight bold)) ("POSTPONED" . (:foreground "orange" :weight bold)) ("DONE" . (:foreground "purple" :weight bold)) ("ABANDONED" . (:foreground "blue" :weight bold)) ("DEPRECATED" . (:foreground "blue" :weight bold)) ("[OPTIONALLY]" . (:foreground "violet" :weight bold)) ("[OPCJONALNIE]" . (:foreground "violet" :weight bold)) ) )
WARNING! When changing this variables in the middle of the emacs session you need to restart org-mode (
M-x org-mode-restart
) to to have them enabled (source)!Furthermore, it may be more convenient to have this tags set for individual file (
#+TODO:
) (link). -
Customizing font style for TODO-DONE keywords in latex export
https://stackoverflow.com/questions/36197545/org-mode-latex-export-making-todos-red
ATTENTION!!! WATCH OUT!!! The code below contained a piece of text that was not parsed well by jekyll/github pages leading to irritating error while deploying on github pages. (see https://stackoverflow.com/questions/17720167/how-do-i-include-in-markdown-file-when-using-jekyll to see post that is probably related to the problem)
Namely, the critical part are the charactes
{
and%
. If they are written without a space between them, this brings troubles. In the code below there is no problem to rewrite the text as\\textsc{ %s
since in Latex this space would be ommitted anyway (wouldn’t it???).;; customized todo-done keywords in latex documents (defun org-latex-format-headline-colored-keywords-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 %s} " todo)) (cond ((string= todo "TODO")(and todo (format "{\\color{red}\\bfseries\\sffamily %s} " todo))) ((string= todo "????")(and todo (format "{\\color{red}\\bfseries\\sffamily %s} " todo))) ((string= todo "POSTPONED")(and todo (format "{\\color{blue}\\bfseries\\sffamily %s} " todo))) ((string= todo "DEPRECATED")(and todo (format "{\\color{blue}\\bfseries\\sffamily %s} " todo))) ((string= todo "DONE")(and todo (format "{\\color{green}\\bfseries\\sffamily %s} " 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 'org-latex-format-headline-colored-keywords-function)
-
Toggle between TODO-DONE keywords for all subnodes of the current node
(defun mb/org-toggle-org-keywords-right () "Toggle between todo-done keywords for all subnodes of the current node." (interactive) (org-map-entries (lambda () (org-shiftright)) nil 'tree) ) (defun mb/org-toggle-org-keywords-left () "Toggle between todo-done keywords for all subnodes of the current node." (interactive) (org-map-entries (lambda () (org-shiftleft)) nil 'tree) )
-
Org-special-block-extras
;; **** org-special-block-extras -> (add-hook #'org-mode-hook #'org-special-block-extras-mode) ;; <- **** org-special-block-extras
-
Org-babel asynchronous source block execution
-
session-async
-
DEPRECATED
emacs-async
https://github.com/jwiegley/emacs-async#async-usage It’s built into the newest emacs versions…
-
DEPRECATED
ob-async
ob-async package enables asynchronous execution of org-babel src blocks.
;; enabling asynchronous org-babel source block execution (require 'ob-async)
There might be some problems with some languages (see the link above for
ipython
and jupyter-like environments…
-
-
Org-babel and tangling
To have org-babel enabled (execution of portions of code):
;; enabling org-babel (org-babel-do-load-languages 'org-babel-load-languages '( (C . t) ; enable processing C, C++, and D source blocks (julia . t) (matlab . t) (js . t) ;;(perl . t) (octave . t) (org . t) (python . t) (plantuml . t) (shell . t) )) ;; no question about confirmation of evaluating babel code block (setq org-confirm-babel-evaluate nil)
-
Tangling the specific/named block of code and other useful functions to work with source blocks
-
Tangle the specific (pointed) block of code
(defun mb/org-babel-tangle-block() (interactive) (let ((current-prefix-arg '(4))) (call-interactively 'org-babel-tangle) ))
-
Tangle the block of code given by the name
(defun mb/org-babel-tangle-named-block(block-name) (interactive) (save-excursion (org-babel-goto-named-src-block block-name) (mb/org-babel-tangle-block)) )
-
Tangle all (and only those) source code blocks that belong to a specific target file
Auxiliary function:
(defun mb/tangle-file (tangle-file) (interactive "P") (run-hooks 'org-babel-pre-tangle-hook) ;; Possibly Restrict the buffer to the current code block (save-restriction (save-excursion (let ((block-counter 0) (org-babel-default-header-args org-babel-default-header-args) path-collector) (mapc ;; map over file-names (lambda (by-fn) (let ((file-name (car by-fn))) (when file-name (let ((lspecs (cdr by-fn)) (fnd (file-name-directory file-name)) modes make-dir she-banged lang) ;; drop source-blocks to file ;; We avoid append-to-file as it does not work with tramp. (with-temp-buffer (mapc (lambda (lspec) (let* ((block-lang (car lspec)) (spec (cdr lspec)) (get-spec (lambda (name) (cdr (assq name (nth 4 spec))))) (she-bang (let ((sheb (funcall get-spec :shebang))) (when (> (length sheb) 0) sheb))) (tangle-mode (funcall get-spec :tangle-mode))) (unless (string-equal block-lang lang) (setq lang block-lang) (let ((lang-f (org-src-get-lang-mode lang))) (when (fboundp lang-f) (ignore-errors (funcall lang-f))))) ;; if file contains she-bangs, then make it executable (when she-bang (unless tangle-mode (setq tangle-mode #o755))) (when tangle-mode (add-to-list 'modes (org-babel-interpret-file-mode tangle-mode))) ;; Possibly create the parent directories for file. (let ((m (funcall get-spec :mkdirp))) (and m fnd (not (string= m "no")) (setq make-dir t))) ;; Handle :padlines unless first line in file (unless (or (string= "no" (funcall get-spec :padline)) (= (point) (point-min))) (insert "\n")) (when (and she-bang (not she-banged)) (insert (concat she-bang "\n")) (setq she-banged t)) (org-babel-spec-to-string spec) (setq block-counter (+ 1 block-counter)))) lspecs) (when make-dir (make-directory fnd 'parents)) (unless (and (file-exists-p file-name) (let ((tangle-buf (current-buffer))) (with-temp-buffer (insert-file-contents file-name) (and (equal (buffer-size) (buffer-size tangle-buf)) (= 0 (let (case-fold-search) (compare-buffer-substrings nil nil nil tangle-buf nil nil))))))) ;; erase previous file (when (file-exists-p file-name) (delete-file file-name)) (write-region nil nil file-name) (mapc (lambda (mode) (set-file-modes file-name mode)) modes)) (push file-name path-collector)))))) (org-babel-tangle-collect-blocks nil tangle-file)) (message "Tangled %d code block%s from %s" block-counter (if (= block-counter 1) "" "s") (file-name-nondirectory (buffer-file-name (or (buffer-base-buffer) (current-buffer) (and (org-src-edit-buffer-p) (org-src-source-buffer)))))) ;; run `org-babel-post-tangle-hook' in all tangled files (when org-babel-post-tangle-hook (mapc (lambda (file) (org-babel-with-temp-filebuffer file (run-hooks 'org-babel-post-tangle-hook))) path-collector)) (run-hooks 'org-babel-tangle-finished-hook) path-collector)))) (defun mb/org-babel-tangle-to-target-file-from-the-file (file target-file) (interactive "fFile to tangle: \nP") (let* ((visited (find-buffer-visiting file)) (buffer (or visited (find-file-noselect file)))) (prog1 (with-current-buffer buffer (org-with-wide-buffer (mapcar #'expand-file-name (mb/tangle-file target-file)))) (unless visited (kill-buffer buffer)))))
-
Export given org-file to pdf (latex)
(defun mb/org-babel-export-org-file-to-latex (filename) (interactive "fFile to export: \nP") (let* ((visited (find-buffer-visiting filename)) (buffer (or visited (find-file-noselect filename)))) (prog1 (with-current-buffer buffer (org-latex-export-to-pdf nil) ) (unless visited (kill-buffer buffer)))))
-
Tangle AND export org-file to pdf
(defun mb/org-babel-tangle-and-export (file target-file) (interactive) (mb/org-babel-tangle-to-target-file-from-the-file file target-file) (sleep-for 0.5) (mb/org-babel-export-org-file-to-latex target-file) )
-
-
plantuml
- https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-plantuml.html
- https://medium.com/@shibucite/emacs-and-plantuml-for-uml-diagrams-academic-tools-6c34bc07fd2
- https://plantuml.com/activity-diagram-beta
In order to work with
plantuml
you need to install it (there’s another way which is documented in the link above, but I won’t use it). On debian machine I’ll just execute:sudo apt install plantuml
and add the following line to tell emacs to use system installed plantuml:
;; enabling plantuml (setq plantuml-executable-path "plantuml") (setq org-plantuml-exec-mode 'plantuml)
-
-
Fix for Octave/Matlab org-babel - problems with matlab in org-babel
http://gewhere.github.io/blog/2017/12/19/setup-matlab-in-emacs-and-babel-orgmode/
;; setup matlab in babel (setq org-babel-default-header-args:matlab '((:results . "output") (:session . "*MATLAB*")))
In the current version of matlab org-babel there is a problem of including input lines in the output of org-babel block. The way to circumvent it is to use the approach suggested by the user named
karthink
(karthinks
?). I traced it starting from the pages:- https://www.reddit.com/r/emacs/comments/pufgce/matlab_mode/
- https://www.reddit.com/r/emacs/comments/fy98bs/orgbabels_matlab_session_output_is_malformed/
In the last link user
nakkaya
refers to his/her solution of the problem, however his/her link does not seem to include this solution.I searched web for
karthink
,matlab
,emacs
appearances and found the fix here: https://github.com/karthink/.emacs.d/blob/master/plugins/ob-octave-fix.elIn the end I just downloaded the file and the inclusion of this package is done in section 1.8.25.3.
Remark: There exist at least two versions of the fix (I renamed the one I already had to
ob-octave-fixOLDER.el
). Previous version of the file didn’t seem to resolve the problem.Remark 2: In case of matlab code-block newer version of
ob-octave-fix.el
depends onaltmany
’sexport_fig
function! I have been using it for a while so I don’t care anyway but in one may obtain errors when using this library withoutexport_fig
!Now, results show only the first line without semicolon and … all the lines below it! (even if they end with semicolon!).
x = 2 ; a = x+1 ; y = x + 1 ; z = 3 ; t = 2 t = 2
-
Export plots to png
https://lists.gnu.org/archive/html/emacs-orgmode/2017-08/msg00376.html
https://emacs.stackexchange.com/questions/54695/no-graphic-output-for-matlab-src-block-in-org-mode
-
Wrong formatting of matlab output’s in org-babel
https://www.reddit.com/r/emacs/comments/fy98bs/orgbabels_matlab_session_output_is_malformed/
-
TODO Erroneous behaviour when plotting
When exporting graphic file from matlab code-block, the resulting image does not appear when followed by automatically generated keyword
#+RESULTS:
. When this keyword is deleted the image appears in generated pdf.plot([1 2],[1 2]) print -dpng ./images/plot.png ;
-
Set path to Python executable to work in org-babel code block
Pythonic org-babel code blocks like the one below:
print("Hello world")
don’t work out-of-the-box. The similar problem for
R
can be found here.In order to fix the problem you need to explicitely set the path to your Python interpreter.
; :tangle (concat (org-entry-get nil "PRJ-DIR" t) "init.el") ;; Python in org-babel (setq org-babel-python-command "python")
The old versions have explicitely pointed to python3 binary like this
;; Python in org-babel (setq org-babel-python-command "/bin/python3")
but it’s outdated in newer versions of Debian…
Unfortunately, it seems that you need this
python3
notpython
…;; Python in org-babel (setq org-babel-python-command "python3")
Two observations:
python script.py
executed in command line works ok- there is no
python
comannd in/bin/
directory.
An interesting discussion on python/python2/python3 related issues can be found here.
Another interesting remark about python in org-babel is available here. The following code block
#+begin_src python ,print("Hello world") #+end_src
won’t work as expected. You need to add
results output
to get string printed by python in results block in org. -
Tailoring org-mode to markdown export
When exporting to markdown I want to add some keywords in a special format to the preamble of .md file. How to do that is described here.
;; **** org-to-markdown exporter customization -> (defun org-export-md-format-front-matter () (let* ((kv-alist (org-element-map (org-element-parse-buffer 'greater-element) 'keyword (lambda (keyword) (cons (intern (downcase (org-element-property :key keyword))) (org-element-property :value keyword))))) (lines (mapcar (lambda (kw) (let ((val (alist-get kw kv-alist))) (format (pcase kw ('author "%s: %s") ((or 'tags 'title) "%s: '%s'") (_ "%s: %s")) (downcase (symbol-name kw)) (pcase kw ('date (substring val 1 -1)) (_ val))))) '(author date tags title)))) (concat "---\n" (concat (mapconcat #'identity lines "\n")) "\n---"))) (defun my/org-export-markdown-hook-function (backend) (if (eq backend 'md) (insert (org-export-md-format-front-matter) "\n")))
In the beginning the line below where hook is added was uncommented because of my unawareness of how Emacs works. Now I add the hook below per each org-file and this line is the cause of unwanted behaviour that the required information (title, tags, etc.) is added twice in exported
md
file. So I comment out the line below, however in the free time I should supplement all the older posts with this line. (TODO!);; This hook should be added per file in my org posts. Unfortunately, so far I don't know ;; how to do this. ;; (add-hook 'org-export-before-processing-hook #'my/org-export-markdown-hook-function)
Besides, in order to have markdown exporter options in menu appearing after
C-c C-e
you need to add (Link 1, Link 2):(require 'ox-md nil t) ;; <- **** org-to-markdown exporter customization
-
Miscellaneous oneliners
;; alphabetical ordered lists (setq org-list-allow-alphabetical t)
-
TODO Asynchronous babel sessions
ob-comint.el
-
LaTeX fragments in org-mode source code
To have nice-coloured latex syntax in Emacseditor while writing in org-mode you need to embrace it with
#+begin_export latex
and#+end_export
keywords (source).Another hints can be found here.
-
Engraved - the better (?) way of having nice source code formatting
Following some internet posts about
Engraved
package I decided to give it a try. We’ll if it works better than minted (which has obvious flaws, such as dependency on external code or slowing down overall compilation process)The installation process is easier than with minted. All you need to do is to install package
engrave-faces
(it’s done ininstall-packages.el
) and then set;; org-to-latex exporter to have nice code formatting (setq org-latex-src-block-backend 'engraved) ;; ;; (setq org-latex-packages-alist '((""))) ; there's no need to add minted package anymore here, we're using engraved, special options for engraved are passed in org-latex-engraved-preamble
The customization of the styles can be performed by editing two variables:
org-latex-engraved-preamble
andorg-latex-engraved-options
Please do note that
engraved
includesfvextra
package andtcolorbox
package with optionsbreakable
andxparse
. This should be taken into account when usingorg-special-blocks-package
since it also depends ontcolorbox
package. This potentially may lead to package clash! And there may be a need to come back here to configure the usage of tcolorbox once again. (Note the options fortcolorbox
mentioned in package manual (Sec. 1.3 Libraries, page 10, ->/tcb/library/most
vs/tcb/library/all
vs/tcb/library/minted
).Their default values are written below (taken from documentation):
(setq org-latex-engraved-preamble "\\usepackage{fvextra} [FVEXTRA-SETUP] % Make line numbers smaller and grey. \\renewcommand\\theFancyVerbLine{\\footnotesize\\color{black!40!white}\\arabic{FancyVerbLine}} \\usepackage{xcolor} % In case engrave-faces-latex-gen-preamble has not been run. \\providecolor{EfD}{HTML}{f7f7f7} \\providecolor{EFD}{HTML}{28292e} % Define a Code environment to prettily wrap the fontified code. \\usepackage[breakable,xparse]{tcolorbox} \\DeclareTColorBox[]{Code}{o}% {colback=EfD!98!EFD, colframe=EfD!95!EFD, fontupper=\\footnotesize\\setlength{\\fboxsep}{0pt}, colupper=EFD, IfNoValueTF={#1}% {boxsep=2pt, arc=2.5pt, outer arc=2.5pt, boxrule=0.5pt, left=2pt}% {boxsep=2.5pt, arc=0pt, outer arc=0pt, boxrule=0pt, leftrule=1.5pt, left=0.5pt}, right=2pt, top=1pt, bottom=0.5pt, breakable} [LISTINGS-SETUP]" )
In order to flawlessly export ChatGPT sessions 1.8.14.2.2 placed inside
#+begin_ai #+end_ai
we need to defineai
environement in latex. Concatenation of variableorg-latex-engraved-preamble
and new lines has no effect, so I decided to set explicitely here:Furthermore, I added:
\\IfPackageLoadedTF{tcolorbox}{}{\\usepackage[breakable,xparse]{tcolorbox}}
line in order to bypass latex error which stops compilation when a package is loaded for the second time. (Beware! I needed to follow this post and use\IfPackageLoadedTF
, not\IfPackageLoadedTF
since the latter one procuded an error:"! You can't use '\spacefactor' in vertical mode."
).(setq org-latex-engraved-preamble "\\usepackage{fvextra} [FVEXTRA-SETUP] % Make line numbers smaller and grey. \\renewcommand\\theFancyVerbLine{\\footnotesize\\color{black!40!white}\\arabic{FancyVerbLine}} \\usepackage{xcolor} % In case engrave-faces-latex-gen-preamble has not been run. \\providecolor{EfD}{HTML}{f7f7f7} \\providecolor{EFD}{HTML}{28292e} % Define a Code environment to prettily wrap the fontified code. \\IfPackageLoadedTF{tcolorbox}{}{\\usepackage[breakable,xparse]{tcolorbox}} \\DeclareTColorBox[]{Code}{o}% {colback=EfD!98!EFD, colframe=EfD!95!EFD, fontupper=\\footnotesize\\setlength{\\fboxsep}{0pt}, colupper=EFD, IfNoValueTF={#1}% {boxsep=2pt, arc=2.5pt, outer arc=2.5pt, boxrule=0.5pt, left=2pt}% {boxsep=2.5pt, arc=0pt, outer arc=0pt, boxrule=0pt, leftrule=1.5pt, left=0.5pt}, right=2pt, top=1pt, bottom=0.5pt, breakable} [LISTINGS-SETUP] \\newenvironment{ai} { \\begin{Code} } { \\end{Code} }" )
The default value of
org-latex-engraved-options
is:; :tangle (concat (org-entry-get nil "PRJ-DIR" t) "init.el") (setq org-latex-engraved-options '( ("commandchars" . "\\\\\\{\\}") ("highlightcolor" . "white!95!black!80!blue") ("breaklines" . "true") ("breaksymbol" . "\\color{white!60!black}\\tiny\\ensuremath{\\hookrightarrow}") ))
Other example of usage taken from help of
org-latex-engraved-options
variable.(setq org-latex-engraved-options '( ("commandchars" . "\\\\\\{\\}") ("highlightcolor" . "white!95!black!80!blue") ("breaklines" . "true") ("breaksymbol" . "\\color{white!60!black}\\tiny\\ensuremath{\\hookrightarrow}") ("highlightcolor" . "lightgray") ("frame" . "single") ("numbers" . "left") ) )
Engraved options can also be set per block. If you need block-specific options, you may use the following syntax:
#+ATTR_LATEX: :options key1=value1,key2=value2 #+BEGIN_SRC <LANG> ... #+END_SRC
Here’s a simple org file that shows some of the capabilities of
engraved
:#+title: Engraving source blocks #+latex_engraved_theme: modus-operandi #+begin_src python :results output :exports both print("look ma, some text") #+end_src #+RESULTS: : look ma, some text #+ATTR_LATEX: :options highlightlines=2 #+begin_src python :results output :exports both print("look, another text") #+end_src #+RESULTS: : look ma, some text #+attr_latex: :engraved-theme modus-vivendi #+begin_src sh echo "This is shell code" #+end_src #+ATTR_LATEX: :options highlightcolor=green,frame=lines,highlightlines=2,numbers=left #+begin_src sh :exports both echo "First" echo "This is shell code" #+end_src #+RESULTS: : This is shell code #+ATTR_LATEX: :options highlightcolor=green,frame=lines,highlightlines=2,numbers=left #+begin_src elisp :exports both (message "AAA elisp") #+end_src #+RESULTS: : AAA elisp #+ATTR_LATEX: :options highlightcolor=green,frame=lines,highlightlines=2,numbers=left #+begin_src elisp :exports both (message "AAA elisp") #+end_src #+RESULTS: : AAA elisp #+ATTR_LATEX: :options highlightcolor=green,frame=single,highlightlines=2,numbers=left #+begin_src elisp :exports both (message "AAA elisp") #+end_src #+ATTR_LATEX: :options highlightcolor=green,frame=lines,highlightlines=2,numbers=left #+begin_src elisp :exports both (message "AAA elisp") #+end_src
-
Where to find the options that can be passed to engraved blocks of code?
In
fvextra
documentation (-> Section 3 General options) https://sunsite.icm.edu.pl/pub/CTAN/macros/latex/contrib/fvextra/fvextra.pdf -
TODO PROBLEM: bash output aligned to center with
engraved
-
-
How to properly deal with picture/figure size attributes when picture is produced by org-babel block
-
Making asynchronous exporter deals easily with
minted
source code colorization;; org-to-latex exporter to have nice code formatting (setq org-latex-listings 'minted org-export-with-sub-superscripts 'nil org-latex-minted-options '(("bgcolor=lightgray") ("frame" "lines")) org-latex-packages-alist '(("" "minted")) org-latex-pdf-process '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f" "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f" "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
-
TODO Problems with passing “Local variables:” to asynchronous exporter
-
-
CDLatex installed in order to ease working with LaTeX in org-mode
The special mode
org-cdlatex-mode
is included inorg
package. In order to have it working properly we need to installcdlatex
itself. This can be done in 1.7.2.Link to
org-cdlatex-mode
description: http://doc.endlessparentheses.com/Fun/org-cdlatex-mode.html.After launching
org-cdlatex-mode
you can insert latex environments by typing:C-c {
-
org-ref
for referencesEnabling
org-ref
in all modes.TODO: do it only for org-mode and latex mode…
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; *** Reftex default bibliography - though it's easier to use org-cite ;; This is left in case org-ref doesn't work at all without it.... ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require 'org-ref)
-
Reftex for managing references
Use
org-cite
for citations and bibliography. Andorg-ref
for references.-
OLDER COMMENTS
Reftex
is preinstalled since Emacs 20.2, however in order to have it working you need to installauctex
package!Then you can turn on
reftex
per a buffer via:reftex-mode
.At the beginning type:
C-c = (reftex-toc)
and choose
r
to generate a list of all labels, references in the document.From now on, every time you type
C-c =
reftex
menu appears on the top of the current buffer prompting the actions you can take.The problem with
reftex
is that it does not recognize org-mode references added by#+NAME:
#+LABEL:
etc.org-ref
is said to handle this, so maybe in the future I will return to this package. As for now I’m going to work withreftex
and LaTeX tags.
-
-
Listing name tags of environments
Based on this page.
;; Managing org-mode #+NAME properties like in reftex-mode (defun my/get-name (e) (org-element-property :name e)) (defun my/latex-environment-names () (org-element-map (org-element-parse-buffer) 'latex-environment #'my/get-name)) (defun my/report-latex-environment-names () (interactive) (message (format "%S" (my/latex-environment-names)))) (define-key org-mode-map (kbd "C-z z") #'my/report-latex-environment-names)
TODO Flyspell (TODO: dive deeper into the package and its capabilities)
https://ruzkuku.com/emacs.d.html#org804158b https://www.emacswiki.org/emacs/FlySpell
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; *** Flyspell
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Flymake/Flycheck
https://www.masteringemacs.org/article/spotlight-flycheck-a-flymake-replacement
In Emacs 27.1 flymake
is said to be competitive with flycheck
again.
It is built-in in Emacs. As for now, I’m gonna use flymake
.
Bash completions :notForWindows:
Bash has usually very good command completion facilities, which aren’t accessible by default from Emacs (except by running M-x term
). This package integrates them into regular commands such as shell-command
and shell
.
PDF-Tools
Original repo: https://github.com/politza/pdf-tools. Maintened fork: https://github.com/vedang/pdf-tools
http://alberto.am/2020-04-11-pdf-tools-as-default-pdf-viewer.html
After installation you need to activate the package by running:
M-x pdf-tools-install
.
Something important is that this library doesn’t play well with Emacs
linum-mode
. The following lines of code will deactivate this mode
when rendering the .pdf:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Add this hook in order to run pdf-tools without a warning message.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(add-hook 'pdf-view-mode-hook (lambda() (linum-mode -1)))
ChatGPT
In order to get some help from AI I decided to give it a try inside Emacs. There are tons of pages about it. Here you have a list of Emacs libraries that handle this issue.
The problem with OpenAI API keys is that they expire after some time and you need to buy a credit to have the possibility of using it again…
-
Alternative solutions:
-
org-ai
At first, I decided on org-ai. It looks promising, mature, and seems to have a quite a lot of features. To use it, you also need to have
websocket
package.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; AI - ChatGPT, Dall-E, Stable Diffusion and ... ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; (require 'org-ai) (add-hook 'org-mode-hook #'org-ai-mode) (org-ai-global-mode) ;; (setq org-ai-default-chat-model "gpt-4") ; if you are on the gpt-4 beta: ;; (org-ai-install-yasnippets) ; if you are using yasnippet and want `ai` snippets
Now, in order to keep my secrets off my
init.el
instead of storing api key directly in myinit.el
, I’ll load it here from another file, which is located outside this repository. In order to have this file properly loaded when running emacs daemon we need to explicitely useuser-emacs-directory
variable when refering to the file. The content of the file looks like:(load-file (concat user-emacs-directory "../.mysecrets/openaiapi.el"))
where the content of the
openaiapi.el
looks like:(setq org-ai-openai-api-token "<ENTER YOUR API TOKEN HERE>")
In case you have more openai accounts/keys you may replicate the above line inserting another API keys.
-
Useful commands/shortcuts:
org-ai-mark-block-contents
- marks the contents of the current block between#+begin_ai
and#+end_ai
. Useful for clearing the buffer after the session is finished and you don’t want to store its results.C-c Backspace
- kills the ai region where the cursor is located (C-c DEL
does not work in my case, seeorg-ai.el
to view other keybindings…) -
ChatGPT session blocks export with
engraved
In order to flawlessly export ChatGPT sessions placed inside
#+begin_ai #+end_ai
we need to defineai
environement in latex for engraved exports (see 1.8.9.13) That is why we need to updateorg-latex-engraved-preamble
introduction in section 1.8.9.13.In fact, updating this variable (as in the code commented out above) has no effect on the variable, so I decided to move this piece of code to 1.8.9.13, where I repeated default setting of
org-latex-engraved-preamble
with necessary lines added at the end of the string. -
Updating
org-structure-template-alist
to include org-ai environment … and to add newlines in appropriate items(setq org-structure-template-alist '(("a" . "export ascii\n") ("A" . "ai\n") ("c" . "center\n") ("C" . "comment\n") ("e" . "example\n") ("E" . "export") ("h" . "export html\n") ("l" . "export latex\n") ("q" . "quote\n") ("s" . "src") ("v" . "verse\n")))
-
-
gptel
I also tried with
gptel
. Unfortunately I wasn’t able to succeed in installing it. -
chatgpt-shell
Also tried with this: https://github.com/xenodium/chatgpt-shell (But I’ve got too old version of curl (7.76 while I have 7.74 on Debian)
-
Interesting/funny links:
Whisper.el for voice recognition
Whisper is OpenAI’s model for voice recognition (https://openai.com/index/whisper/).
For using it in Emacs we can use this project: https://github.com/natrys/whisper.el
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; AI - Whisper for voice recording
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(setq whisper-install-directory "/tmp/"
whisper-model "base"
whisper-language "en"
whisper-translate nil
whisper-use-threads (/ (num-processors) 2))
(add-to-list 'load-path "~/.emacs.d/manual-download/whisper.el/")
;; doconce (M-x DocOnce) may be needed to activate it ->
(load-file "~/.emacs.d/manual-download/whisper.el/whisper.el")
(global-set-key [f12] 'whisper-run)
The first evaluation of whisper-run
completes downloading
and compiling
whisper-run
TRAMP
->
https://emacs.stackexchange.com/questions/42252/run-local-command-on-remote-file-with-tramp
Something is wrong with this part of code and init.el
is not
loading properly.
General global shortcuts not restricted to specific package/mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Useful global shortcuts (text operations)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(global-set-key (kbd "C-d") 'delete-forward-char) ; Backspace/Insert remapping
(global-set-key (kbd "C-S-d") 'delete-backward-char)
; (global-set-key (kbd "M-S-d") 'backward-kill-word)
(global-set-key (kbd "C-c C-e s") 'mark-end-of-sentence)
(global-set-key (kbd "C-C C-e C-w C-w") 'eww-list-bookmarks) ; Open eww bookmarks
(defun mynet () (interactive) (eww-list-bookmarks))
-
'’Compile and run’’ the current temporary project
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Useful global shortcuts (system-wide operations) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun mb/F5-run-project() (interactive) (shell-command "cd ~/projects/dolfinx-tutorials && docker run --rm --name temp --net=host -e DISPLAY -v ${HOME}/.Xauthority:/home/user/.Xauthority -v \"$(pwd)/src/dolfx/unda1/:/tmp\" dolfinx-mb-bash -c \"python3 main.py\"")) ; (define-key global-map (kbd "f5") 'mb/F5-run-project) (global-set-key [f5] 'mb/F5-run-project)
-
Defining own prefix key to ease finding free keybindings
https://stackoverflow.com/a/1025257/4649238
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; my own prefix keymap ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-prefix-command 'mb-map) (global-set-key (kbd "C-z") 'mb-map) ; (define-key mb-map (kbd "C-k") "\C-a\C- \C-e\M-w\M-;\C-e\C-m\C-y") ; (define-key mb-map (kbd "C-l") "\M-w\M-;\C-e\C-m\C-y")
Now you can create your own shortcut with the command
(define-key mb-map (kbd "C-k") "\C-a\C- \C-e\M-w\M-;\C-e\C-m\C-y")
which will be triggered by
C-z C-k
. -
Useful fast line-copying shortcut
Another ideas can be found here: https://emacs.stackexchange.com/questions/15134/how-to-get-contents-of-current-line
-
Solution
Based on idea presented here. Smart but not recommended approach! However it works for me. You only need to remember that it may break down at any momement, if you encounter a mode that rebinds one of the default keybindings used in the sequence.
;; fast copy-line-comment-it-and-paste-below ;(global-set-key "\C-c\C-k" "\C-a\C- \C-e\M-w\M-;\C-e\C-m\C-y") (define-key mb-map (kbd "C-k") "\C-a\C- \C-e\M-w\M-;\C-e\C-m\C-y")
The code below is not fully doing what it is meant to do. I don’t have a time now to correct it.
;; copy-selection-comment-it-and-paste-below (works ok provided selection is ;; performed from left to right.... ; (global-set-key "\C-c\C-l" "\M-w\M-;\C-e\C-m\C-y") (define-key mb-map (kbd "C-l") "\M-w\M-;\C-e\C-m\C-y")
Aside notes:
- I used to use
C-c C-k
andC-c C-l
keybindings, respectively, for
the above commands. However, they are overwriten when working in org-mode. That’s why I needed to change them
- Then I used
C-p
shortcut for invokingmb-map
,
but at some point I realized that it overwrittens default keybinding for
previous-line
. - I used to use
-
ABANDONED OLD: Solution 1 (NOT FULLY WORKING)
https://www.emacswiki.org/emacs/CopyingWholeLines
This solution only copies active line and moves the pointer to the next line
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; fast copy-line shortcut (defun copy-line (arg) "Copy lines (as many as prefix argument) in the kill ring. Ease of use features: - Move to start of next line. - Appends the copy on sequential calls. - Use newline as last char even on the last line of the buffer. - If region is active, copy its lines." (interactive "p") (let ((beg (line-beginning-position)) (end (line-end-position arg))) (when mark-active (if (> (point) (mark)) (setq beg (save-excursion (goto-char (mark)) (line-beginning-position))) (setq end (save-excursion (goto-char (mark)) (line-end-position))))) (if (eq last-command 'copy-line) (kill-append (buffer-substring beg end) (< end beg)) (kill-ring-save beg end))) (kill-append "\n" nil) (beginning-of-line (or (and arg (1+ arg)) 2)) (if (and arg (not (= 1 arg))) (message "%d lines copied" arg))) (global-set-key "\C-c\C-k" 'copy-line)
-
ABANDONED OLD: Solution 2 (NOT FULLY WORKING)
And even better solution because it also comments out the line and yanks (pastes) copied text the line below. Based on the post.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; fast copy-line-comment-and-paste-below (defun copy-and-comment-region (beg end &optional arg) "Duplicate the region and comment-out the copied text. See `comment-region' for behavior of a prefix arg." (interactive "r\nP") (copy-region-as-kill beg end) (goto-char end) (yank) (comment-region beg end arg)) (global-set-key "\C-c\C-v\C-k" 'copy-and-comment-region)
-
ABANDONED Solution 3 (NOT WORKING)
-
-
Open the directory of the current file/buffer in the external file manager
Based on this link: https://www.reddit.com/r/emacs/comments/4zmly1/how_to_open_the_directory_of_a_file/ in KDE with
dolphin
installed we can do like below.So we need to use =call-process”. However in order to pass a parameter to it you need
Warning 1: The original solution uses
shell-command
which is not asynchronous operation and it blocks emacs until I close the external window. https://emacs.stackexchange.com/questions/65090/how-to-start-a-persistent-asynchronous-process-trough-emacs;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Useful global shortcuts (system-wide operations) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun mb/browse-file-directory() (interactive) (shell-command "dolphin .")) (define-key global-map (kbd "<s-f12>") 'mb/browse-file-directory)
So, in order to ‘‘spawn’’ a new process we need to use
call-process
function. However, in this case, calling the function with parameter is a bit more complicated than forshell-command
(https://stackoverflow.com/questions/4858975/in-emacs-lisp-what-is-the-correct-way-to-use-call-process-on-an-ls-command);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Useful global shortcuts (system-wide operations) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun mb/browse-file-directory() (interactive) (call-process "dolphin" nil 0 nil ".")) (define-key global-map (kbd "<s-f12>") 'mb/browse-file-directory)
Warning: NickD’s solution contains:
#'ndk/desktop-open-link-at-point
. I had to delete#
from it to have properly working keybinding!Similar solution is given here (actually, I did not test it).
-
Smart selecting blocks of text
(require 'expand-region) (global-set-key (kbd "C-=") 'er/expand-region)
Custom, useful text operations
Keybindings are defined with the use of 1.8.17.2.
-
Select current line
(defun mb/select-current-line () "Select the entire current line." (interactive) (beginning-of-line) (set-mark-command nil) (end-of-line)) ;; (global-set-key (kbd "C-c M-^") 'mb/select-current-line) (define-key mb-map (kbd "l") 'mb/select-current-line) ; -> C-z l
-
Wrap region with specific tags
(defun mb/wrap-region-with-tags (begin end) "Wrap the selected region with specific tags given in the body of the function." (interactive "r") (save-excursion (goto-char end) (insert "\n\\end{equation}") (insert "\n#+end_export") (goto-char begin) (insert "\n#+begin_export latex") (insert "\n\\begin{equation}\n") ) ) ;; (global-set-key (kbd "C-c M-%") 'mb/wrap-region-with-tags) (define-key mb-map (kbd "w") 'mb/wrap-region-with-tags) ; -> C-z w
Emailing in Emacs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Email configuration >>>>>>>>>>>>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
https://www.gnu.org/software/emacs/manual/html_mono/smtpmail.html
Snippet for sending email from inside emacs:
(progn
(mail)
(mail-to) (insert "address@sth.com")
(mail-subject) (insert "Subject ")
(mail-text) (insert "body of mail")
(mail-send))
-
DEPRECATED OLD Approaches
As a temporary workaround I decided to try 1.8.20.
Basing on this post I decided to perform configuration of email service within Emacs in three steps. Each of them takes care of one of the following problems
- fetching emails
- sending emails
- viewing emails.
-
Links that can be useful:
- https://www.reddit.com/r/emacs/comments/4rl0a9/email_in_emacs_i_want_to_but_wow_its_overwhelming/
- https://www.emacswiki.org/emacs/GettingMail
- https://www.jonatkinson.co.uk/posts/syncing-gmail-with-mbsync/
- https://isync.sourceforge.io
- https://brian-thompson.medium.com/setting-up-isync-mbsync-on-linux-e9fe10c692c0
- https://wiki.archlinux.org/title/isync
- https://www.maketecheasier.com/use-email-within-emacs/
-
ABANDONED Another approach: External Editor Revived – a Thunderbird extension
External Editor Revived is a Thunderbird extension that allows using external editor (vim/emacs/…) to edit your mails.
I had problems with installing necessary binary (https://github.com/Frederick888/external-editor-revived/releases/download/v0.6.0/ubuntu-latest-gnu-native-messaging-host-v0.6.0.zip) due to lacking dependencies:
./external-editor-revived: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by ./external-editor-revived) ./external-editor-revived: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./external-editor-revived) ./external-editor-revived: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./external-editor-revived)
so I abandoned this idea at this stage.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; <<<<<<<<<<<<<< Email configuration ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Emacs-everywhere
Repository of the package and some basic information can be found here.
- Install package
emacs-everywhere
from melpa (1.7.2) -
Add system-wide shortcut for the command
#!/bin/bash # https://github.com/tecosaur/emacs-everywhere/ emacsclient --eval "(emacs-everywhere)"
(I added
Ctrl+Alt+E
in custom shortcuts of KDE) -
Run emacs daemon in the system (for example after hitting
Alt+F2
) with:emacs --daemon
Warning!: In order not to restore files from previous session (and avoid being asked for confirmation of loading some commands when files are restored) additional if statement is added to embrace
(desktop-save-mode 1)
at the beginning of theinit.el
. -
Now you can invoke Emacs anywhere in the system with
Ctrl+Alt+E
. (If a piece of code is highlighted, it will be copied into Emacs buffer). After editing Emacs buffer pressC-c C-c
orC-x 5 0
to go back to the original programme. If you do not wish to paste the buffer content into the original window,C-c C-k
still copies the content to the clipboard, but never pastes. -
The buffer opened within Emacs deamon instance has small fonts despite the fact that font is set somewhere at the beginning of the
init.el
. It is well-known problem:- https://www.google.com/search?q=emacs+default+font+emacs+daemon
- https://emacs.stackexchange.com/questions/52063/emacsclient-gui-has-small-fonts
- https://github.com/doomemacs/doomemacs/issues/1223
- https://www.reddit.com/r/emacs/comments/pc189c/fonts_in_emacs_daemon_mode/
- https://www.reddit.com/r/emacs/comments/dwy299/how_to_set_fonts_in_daemon_mode_windows/
I used the solution based on the one presented in the last link above, however the one presented in the second link seems to be simpler…
;; setting up configuration for emacs-everywhere: ;; 1. font size ;(if (daemonp) ;( (defun my-after-frame (frame) (if (display-graphic-p frame) (progn (set-frame-font "liberation mono 11" nil t) ))) (mapc 'my-after-frame (frame-list)) (add-hook 'after-make-frame-functions 'my-after-frame) ;) ;)
Restart emacs from within emacs
Found here: https://emacs.stackexchange.com/questions/5428/restart-emacs-from-within-emacs According to the above source there may be some problems with running it in TTY.
(defun launch-separate-emacs-in-terminal ()
(suspend-emacs "fg ; emacs -nw"))
(defun launch-separate-emacs-under-x ()
(call-process "sh" nil nil nil "-c" "emacs &"))
(defun restart-emacs ()
(interactive)
;; We need the new emacs to be spawned after all kill-emacs-hooks
;; have been processed and there is nothing interesting left
(let ((kill-emacs-hook (append kill-emacs-hook (list (if (display-graphic-p)
#'launch-separate-emacs-under-x
#'launch-separate-emacs-in-terminal)))))
(save-buffers-kill-emacs)))
Diary
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Diary
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
By default, emacs expects diary file to be located in ~/.emacs.d/diary
but I’m gonna keep it in:
(setq diary-file "~/org/diary/diary")
Tutorial by Protesilaos Stavrou.
-
Changing date format to iso and some other configurations
Some variables need to be set in order to have calendar/diary looking working fancy. You can see those settings in Stavrou’s init.el in the movie linked above.
; 'american’ - month/day/year ; ‘european’ - day/month/year ; ‘iso’ - year/month/day (setq calendar-date-style "iso") (setq diary-date-forms diary-iso-date-forms) (setq diary-comment-start ";;") (setq diary-comment-end "") (setq diary-nonmarking-symbol "!") ; (setq diary-show-holidays-flag t)
In order to include diary entries in calendar you need to set:
(setq calendar-mark-diary-entries-flag t)
Stavrou mentions that he does not use org-agenda’s features (and org-mode syntax) with calendar/diary, as he does not need to makes things so complex. And that’s the way how I’m gonna use it for a moment.
A nice thing to have in the future is
-
TODO Sending emails with calendar events
To be done in some free time.
-
Links that I found useful setting up this package:
- https://wikemacs.org/wiki/Command-line_startup_options
- https://ftp.gnu.org/old-gnu/Manuals/emacs-20.7/html_chapter/emacs_37.html
https://emacs.stackexchange.com/questions/3035/how-to-know-if-emacs-is-running-as-a-daemon
Load Emacs theme of your preference
-
Modus themes by Protesilaos Stavrou
noconfirm
flag needs to be added for two reasons. First, without it we cannot run Emacs in batch mode from command line (emacs -batch -load ~/.emacs.d/init.el ...
). Second,… (I forgot the second reason).;; (setq modus-themes-headings ; this is an alist: read the manual or its doc string ;; '((1 . (overline background variable-pitch 1.3)) ;; (2 . (rainbow overline 1.1)) ;; (t . (semibold))) ) ;; Add all your customizations prior to loading the themes (setq modus-themes-italic-constructs t modus-themes-bold-constructs nil modus-themes-region '(bg-only no-extend)) ;; Load the theme of your choice: ; (load-theme 'modus-operandi) ;; bright ; (load-theme 'modus-vivendi) ;; dark (setq modus-themes-headings ; this is an alist: read the manual or its doc string '((1 . (rainbow overline background 1.4)) (2 . (rainbow background 1.3)) (3 . (rainbow bold 1.2)) (t . (semilight 1.1)))) (setq modus-themes-scale-headings t) (setq modus-themes-org-blocks 'tinted-background)
There are two types of modus themes:
modus-operandi
which is bright andmodus-vivendi
which is dark one. In order to ease switching between them it is convenient to define custom keybinding (details).;; Auxiliary function to toggle betwen bright and dark theme (defun toggle-theme () (interactive) (if (eq (car custom-enabled-themes) 'modus-vivendi) (disable-theme 'modus-vivendi) (load-theme 'modus-vivendi :noconfirm))) (global-set-key [f6] 'toggle-theme)
Load theme after defining all necessary definitions (otherwise different font sizes won’t work after running
init.el
at the startup and you’ll need to eval it once again or manually invoke the following command):;; load theme after defining (load-theme 'modus-vivendi :noconfirm)
Org-agenda
CAUTION!
org-agenda-files
is somehow overwritten by
(load-theme 'modus-vivendi :noconfirm)
so I decided to put this section after loading the theme.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Agenda
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
Org-agenda activation
https://orgmode.org/manual/Activation.html#Activation
;; org-agenda activation (global-set-key (kbd "C-c l") #'org-store-link) (global-set-key (kbd "C-c a") #'org-agenda) (global-set-key (kbd "C-c c") #'org-capture)
-
Configuration
https://cachestocaches.com/2016/9/my-workflow-org-agenda/
By default emacs set my agenda file to be
~/.notes
. I didn’t mind it at first but in order to have it working I needed to add# -*- mode: org -*-
as the first line of this file. Org-mode needs agenda files to beorg-mode
files. Since~/.notes
does not have proper extension adding# -*- mode: org -*-
was necessary.;; Set your agenda files/directories (as a list of paths) (setq org-agenda-files '("~/org/agenda/" "~/.notes") ) ;; ;; Set default column view headings: Task Total-Time Time-Stamp ;; (setq org-columns-default-format "%50ITEM(Task) %10CLOCKSUM %16TIMESTAMP_IA") (setq org-columns-default-format "%25ITEM %TODO %3PRIORITY %TAGS") ;; Define the custom capture templates (setq org-capture-templates '(("t" "todo" entry (file org-default-notes-file) "* TODO %?\n%u\n%a\n" :clock-in t :clock-resume t) ("m" "Meeting" entry (file org-default-notes-file) "* MEETING with %? :MEETING:\n%t" :clock-in t :clock-resume t) ("d" "Diary" entry (file+datetree "~/org/diary.org") "* %?\n%U\n" :clock-in t :clock-resume t) ("i" "Idea" entry (file org-default-notes-file) "* %? :IDEA: \n%t" :clock-in t :clock-resume t) ("n" "Next Task" entry (file+headline org-default-notes-file "Tasks") "** NEXT %? \nDEADLINE: %t") )) (setq org-refile-targets (quote ((nil :maxlevel . 9) (org-agenda-files :maxlevel . 9))))
Now running
C-c c
will trigger the menu to capture an agenda entry.Now running
C-c a
will trigger the menu with some agenda actions and commands.C-c C-x C-a
removes an entry from agenda view (refiles the entry to~/.notes_archive
and adds :ARCHIVE: tag to it). -
DEPRECATED Integrating calendar, agenda and diary (partially)
REMARK: -> I moved to 1.8.24.4 package to obtain this feature…
https://emacs.stackexchange.com/questions/29632/org-mode-calendar-integration
(setq org-agenda-include-diary t)
Now my past and future diary entries can be seen in calendar and in agenda.
-
calfw package
a way to integrate agenda entries to calendarhttps://github.com/kiwanami/emacs-calfw?tab=readme-ov-file
After installing
calfw
,calfw-cal
,calfw-org
.I need to:
(require 'calfw) (require 'calfw-cal) (require 'calfw-org)
Now, define my special function for integrating agenda and diary entries into
calfw
view and launch it.(defun cfw:open-mbx-calendar () (interactive) (cfw:open-calendar-buffer :contents-sources (list (cfw:org-create-source "Green") ; orgmode source ; (cfw:howm-create-source "Blue") ; howm source (cfw:cal-create-source "Orange") ; diary source ; (cfw:ical-create-source "Moon" "~/moon.ics" "Gray") ; ICS source1 ; (cfw:ical-create-source "gcal" "https://..../basic.ics" "IndianRed") ; google calendar ICS ))) (cfw:open-mbx-calendar)
in this way calendar and org-agenda entries should be visible in calfw calendar.
Now, after
cfw:open-calendar-buffer
calfw calendar opens in a new Emacs buffer.
Manually downloaded packages
;; Set location for external packages.
(add-to-list 'load-path "~/.emacs.d/manual-download/")
;; doconce (M-x DocOnce) may be needed to activate it ->
(load-file "~/.emacs.d/manual-download/.doconce-mode.el")
;; activating org-mode for doconce pub files:
;; https://github.com/doconce/publish/blob/master/doc/manual/publish-user-manual.pdf
(setq auto-mode-alist
(append '(("\\.org$" . org-mode))
'(("\\.pub$" . org-mode))
auto-mode-alist))
;; <- doconce
Adding custom useful keybindings for doconce. As for now, this is added as a global shortcut…
(global-set-key "\C-c\C-j" "\C-k =====")
-
Sunrise - Norton Commander-like file browser
There are few packages to emulate Norton Commander experience in Emacs. I tested
mc.el
,nc.el
andsunrise.el
. From these three only the last one turned out to be useful (or to run without errors).https://www.emacswiki.org/emacs/Sunrise_Commander_Tips#h5o-1
https://pragmaticemacs.wordpress.com/2015/10/29/double-dired-with-sunrise-commander/
https://enzuru.medium.com/sunrise-commander-an-orthodox-file-manager-for-emacs-2f92fd08ac9e
-
buttons extension for sunrise
https://pragmaticemacs.wordpress.com/2015/10/29/double-dired-with-sunrise-commander/
;; sunrise (add-to-list 'load-path "~/.emacs.d/manual-download/sunrise") (require 'sunrise) (require 'sunrise-buttons) (require 'sunrise-modeline) (add-to-list 'auto-mode-alist '("\\.srvm\\'" . sr-virtual-mode))
The thing that may be annoying in sunrise/dired mode is that is redefines
C-x k
keybinding which does not kill buffer anymore, but it is bounded tosunrise-kill-pane-buffer
command which, at least to me, works only forcommander-like
frame layout, which is triggered after invokingM-x sunrise
.In order to have
C-x k
working as usual we can apply the following rebinding:(add-hook 'sunrise-mode-hook '(lambda () (local-set-key (kbd "C-x k") 'kill-buffer) (local-set-key (kbd "C-x j") 'sunrise-kill-pane-buffer)))
-
-
Buffer-move - swapping buffers easily
https://www.emacswiki.org/emacs/buffer-move.el
;; buffer-move - swap buffers easily (require 'buffer-move)
Now you can use commands:
buf-move-up
buf-move-down
buf-move-left
buf-move-right
or you can define keybindings as package documentation recommends (I guess it’ll be used too seldom to waste keybinding for that):
;; (global-set-key (kbd "<C-S-up>") 'buf-move-up) ;; (global-set-key (kbd "<C-S-down>") 'buf-move-down) ;; (global-set-key (kbd "<C-S-left>") 'buf-move-left) ;; (global-set-key (kbd "<C-S-right>") 'buf-move-right)
-
ob-octave-fix.el
The discussion on this is thread can be found in section 1.8.9.7 so I here I just include the solution, namely I load fixed library.
;; octave/matlab-fix ;;;; (require 'ob-octave-fix nil t) ; This is for older approach (require 'ob-octave-fix)
-
My own packages and settings
-
Custom org-special-block-extras definitions used globally in org-mode files
;; custom org-special-block-extras blocks (add-to-list 'load-path "~/.emacs.d/myarch") (require 'MB-org-special-block-extras)
-
-
ox-extra for
:ignore:
tagignore
tag functionality is very useful. It is implemented inox-extra.el
library. Unfortunately I couldn’t find a way how to install it via emacs repositories…So, in order to have them enabled emacs-wide I have downloaded it and here it is loaded.
;; sunrise (add-to-list 'load-path "~/.emacs.d/manual-download/ox-extra") (require 'ox-extra) (ox-extras-activate '(ignore-headlines))
-
DEPRECATED Matlab-mode (2024.04.18)
symbols value as variable is void: font-lock-reference-face
In the newest version of the package in melpa repository there is a patch that fixes this error.
-
Keepass integration
https://github.com/tangxinfa/counsel-keepassxc
Download the package from git to the proper directory
cd ~/.emacs.d/manual-download git clone https://github.com/tangxinfa/counsel-keepassxc.git ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Keepass ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (add-to-list 'load-path "~/.emacs.d/manual-download/counsel-keepassxc") (require 'counsel-keepassxc) (setq counsel-keepassxc-database-file "~/.kipa/mb.kdbx")
-
Similar packages
- https://gitlab.com/tay-dev/keepass.el
- https://github.com/ifosch/keepass-mode (needs some dependencies - cask)
- https://github.com/fuyu0425/keepass-cli-rs (needs more dependencies)
-
-
Other packages
;; org to ipython exporter ;;(use-package ox-ipynb ; :load-path "~/.emacs.d/manual-download/ox-ipynb")
Auxiliary functions for emacs packages management
This pieces of code are inserted in install-packages.el
however it does happen every now and then that we want
to refresh our package list. So now we’ve got packed as
an elisp function:
Blogging
-
Blog stencil
Auxiliary function that generates predefined stencil for blog posts
(defun cissic-blog-stencil (title ) "Create and open a file with the given stencil." (interactive "sEnter the title: ") (let* ((date (format-time-string "%Y-%m-%d")) (dateDay (format-time-string "%Y-%m-%d %a")) (titleUnspaced (replace-regexp-in-string " " "-" title)) (file-name (concat date "-" (downcase titleUnspaced) ".org")) (file-path (concat "~/projects/cissic.github.io/mysource/public-notes-org/" file-name)) (stencil (concat "#+TITLE: " title "\n" "#+DESCRIPTION: \n" "#+AUTHOR: cissic \n" "#+DATE: <" dateDay ">\n" "#+TAGS: \n" "#+OPTIONS: -:nil\n" "\n" "* TODO " title "\n" ":PROPERTIES:\n" ":PRJ-DIR: ./" date "-" (car (split-string titleUnspaced)) "/\n" ":END:\n" "\n" "** Problem description\n" "#+begin_src org :tangle (concat (org-entry-get nil \"PRJ-DIR\" t) \"script.org\") :mkdirp yes :exports none :results none\n" "\n" "#+end_src\n" ))) (with-temp-file file-path (insert stencil)) (find-file file-path) (goto-char (point-max)) ))
-
org entries
(defun mb/org-entry-stencil (title ) "Create and open a file with the given stencil." (interactive "sEnter the title: ") (let* ((date (format-time-string "%Y.%m.%d")) (dateDay (format-time-string "%Y-%m-%d %a")) (titleUnspaced (replace-regexp-in-string " " "-" title)) (file-name (concat date "-" (downcase titleUnspaced) ".org")) (file-path (concat "~/org/" file-name)) (stencil (concat "#+TITLE: " title "\n" "#+DESCRIPTION: \n" "#+AUTHOR: \n" "#+DATE: <" dateDay ">\n" "#+TAGS: \n" "#+OPTIONS: -:nil\n" "\n" ))) (with-temp-file file-path (insert stencil)) (find-file file-path) (goto-char (point-max)) )) (defun mb/orgpriv-entry-stencil (title ) "Create and open a file with the given stencil." (interactive "sEnter the title: ") (let* ((date (format-time-string "%Y.%m.%d")) (dateDay (format-time-string "%Y-%m-%d %a")) (titleUnspaced (replace-regexp-in-string " " "-" title)) (file-name (concat date "-" (downcase titleUnspaced) ".org")) (file-path (concat "~/orgpriv/" file-name)) (stencil (concat "#+TITLE: " title "\n" "#+DESCRIPTION: \n" "#+AUTHOR: \n" "#+DATE: <" dateDay ">\n" "#+TAGS: \n" "#+OPTIONS: -:nil\n" "\n" ))) (with-temp-file file-path (insert stencil)) (find-file file-path) (goto-char (point-max)) )) (defun mb/rditit-entry-stencil (title ) "Create and open a file with the given stencil." (interactive "sEnter the title: ") (let* ((date (format-time-string "%Y.%m.%d")) (dateDay (format-time-string "%Y-%m-%d %a")) (titleUnspaced (replace-regexp-in-string " " "-" title)) (file-name (concat date "-" (downcase titleUnspaced) ".org")) (file-path (concat "~/org/RDITiT/pisma,maile-org/" file-name)) (stencil (concat "#+TITLE: " title "\n" "#+DESCRIPTION: \n" "#+AUTHOR: \n" "#+DATE: <" dateDay ">\n" "#+TAGS: \n" "#+OPTIONS: -:nil\n" "\n" ))) (with-temp-file file-path (insert stencil)) (find-file file-path) (goto-char (point-max)) ))
-
Blogging with easy-hugo
-
Install hugo
First, install
hugo
sudo apt install hugo -y
Then, you need to configure it a bit:
(setq easy-hugo-basedir "~/projects/easy-hugo-blog/quickstart/") (setq easy-hugo-url "http://marbor.strony.prz.edu.pl/hugo") (setq easy-hugo-sshdomain "blogdomain") (setq easy-hugo-root "/usr/bin/") (setq easy-hugo-previewtime "300") ;; (define-key global-map (kbd "C-c C-e") 'easy-hugo)
-
TODO The end
-
Workgroups (should be executed at the end of init.el)
https://tuhdo.github.io/emacs-tutor3.html
workgroups2
is a fine package for managing session. To enable it and set the filepath for keeping sessions (default is/.emacs_workgroups
) put this in yourinit.el
:(workgroups-mode 1) ; session manager for emacs (setq wg-session-file "~/.emacs.d/.emacs_workgroups") ;
And then you can use the following commands to manage sessions:
- To save window&buffer layout as a work group:
M-x wg-create-workgroup
orC-c z C-c
- To open an existing work group:
M-x wg-open-workgroup
orC-c z C-v
- To delete an existing work group:
M-x wg-kill-workgroup
orC-c z C-k
There is one problem with
workgroups2
packages. It does not like withdesktop-save-mode
. Whenworkgroups2
is enableddesktop-save-mode
does not restore the windows layout from the previous Emacs session, which sucks. I decided to stick toworkgroups2
and supply the needed functionality with the use of only this package. I did it by adding hooks:(add-hook 'kill-emacs-hook ( lambda () (wg-create-workgroup "currentsession" ))) (setq inhibit-startup-message t) (add-hook 'window-setup-hook ( lambda () (wg-open-workgroup "currentsession")))
The line
(setq inhibit-startup-message t)
is added in order to prevent Emacs splash screen to appear in one of the restored"currentsession"
frames.There is one problem with the code above. When running Emacs in batch mode like this:
emacs -batch -Q -load ~/.emacs.d/init.el
(I have such a line of code in the makefile of this blog) it asks in the command line about saving the “currentsession”. It sucks. As a workaround we can put those hooks inside if statement, which checks whether Emacs was run in batch mode or not. How to write an if statements is here. In the code below I also use
noninteractive
variable which is true if emacs is run in batch mode.The code below somehow worked for a while. Then, out of a sudden it stopped.
(if (not noninteractive) ( ; if Emacs is started in graphical environment (add-hook 'kill-emacs-hook ( lambda () (wg-create-workgroup "currentsession"))) (setq inhibit-startup-message t) (add-hook 'window-setup-hook ( lambda () (wg-open-workgroup "currentsession"))) ) ( ; if Emacs is run in batch mode - do not care about workgroups ) )
The problem was the lack of a special keyword
progn
as I found here (Part of the manual about it). All in all, now everything seems to be ok with the following lines:(if (not noninteractive) ( ; if Emacs is started in graphical environment progn (add-hook 'kill-emacs-hook ( lambda () (wg-create-workgroup "currentsession"))) (setq inhibit-startup-message t) (add-hook 'window-setup-hook ( lambda () (wg-open-workgroup "currentsession"))) ) ( ; if Emacs is run in batch mode - do not care about workgroups ) )
-
Last lines
-
DEPRECATED Restoring previous session
This section is deprecated in favour of
workgroups2 package
.This way of restoring session throws some warnings and needs additional confirmations so I give it up. Simple
(desktop-save-mode 1)
which is included in the beginning ofinit.el
works ok.;; Restore the "desktop" - do this as late as possible (if first-time (progn ;(desktop-load-default) ; this is for Emacs 20-21 (desktop-read))) ;; Indicate that this file has been read at least once (setq first-time nil)
-
DEPRECATED Open some useful files in the background
I don’t use this part of
init.el
anymore. I can get the similar functionality by usingrecentf
package or prepare a session with required files opened in it.;;; Always have several files opened at startup ;; hint: https://stackoverflow.com/a/19284395/4649238 (find-file "~/.emacs.d/init.el") (find-file "~/.emacs.d/install-packages.el") (find-file "~/.emacs.d/useful-shortcuts.org")
What’s more, the commands above cause an unwanted behaviour when evaluating
init.el
. The last file in the list is opened in an active buffer. I’d like to have those files opened “in background”. I foundfind-file-noselect
function have this functionality, but first: it is not recommended way of doing this thing; second: it is not present in Emacs 27.1 anyway.;; All done (message "All done in init.el.")
Dependencies of the presented Emacs configuration :
The list of external applications that this script is dependent on:
- git
-
LaTeX distribution (for org to latex exporters)
- xclip (1.8.20)
- xdotool (1.8.20)
- xprop (1.8.20) - this is not a package but executable
- xwininfo (1.8.20) - this is not a package but executable
Tests
Emacs and Zotero integration - zotxt-emacs
https://github.com/egh/zotxt-emacs
-
Install zotxt
- Visit https://github.com/egh/zotxt/releases
- Download the latest .xpi file. If you are using Firefox, you will need to right-click and “Save as”
- Start Zotero standalone.
- In Zotero, select Tools -> Add-ons -> Gear (upper right) -> Install Add-On from file, and install the downloaded xpi file.
- RESTART Zotero!!!
-
Install zotxt-emacs package
-
Org mode integration
To insert a link to a reference into a org-mode document, first enable the org-zotxt minor mode:
M-x org-zotxt-mode
Then you can use:C-c " i
(org-zotxt-insert-reference-link
) to insert an item.To update the current link text at point to reflect changed metadata from Zotero, use
C-c " u
(org-zotxt-update-reference-link-at-point
).To open an attachment of the link at point, use
C-c " a
(org-zotxt-open-attachment
) -
Tests
Below I include the link inserted with
org-zotxt-insert-reference-link
command. Since it breaks export to markdown I comment it out. In order to check if it works you need to uncomment and mouse click it. -
More tests - redefinition of
org-zotxt-open-attachment
The function
org-zotxt-open-attachment
opens the link provided by zotero inside emacs pdf viewer. It would be lovely to be able to open it inside zotero pdf viewer, unfortunately I couldn’t find a way of doing that.As a last resort I decided to implement opening in my default pdf viewer. Basing on
org-zotxt-open-attachment
fromzotxt-emacs
I created similiar function that enables opening zotero link inokular
. (Interesting observation: variablepaths
used in function is not a list. It is a vector! That is why to get its element we need to usearef
function.)(defun mb/org-zotxt-open-attachment (&optional arg) "Open attachment of Zotero items linked at point. Opens with `org-open-file', see for more information about ARG." (interactive "P") (let ((item-id (org-zotxt-extract-link-id-at-point)) (arg arg)) (deferred:$ (zotxt--request-deferred (format "%s/items" zotxt-url-base) :params `(("key" . ,item-id) ("format" . "paths")) :parser 'json-read) (deferred:nextc it (lambda (response) (let ((paths (cdr (assq 'paths (elt (request-response-data response) 0))))) ;;; (org-open-file (org-zotxt-choose-path paths) arg) ; (print (type-of paths)) ; (print (aref paths 0)) ; (print (concat "okular " (aref paths 0) ) ) ; (print (concat "okular " "'" (aref paths 0) "'" ) ) (shell-command (concat "okular " "\"" (aref paths 0) "\"" ) ) ))) (deferred:error it #'zotxt--deferred-handle-error) (if zotxt--debug-sync (deferred:sync! it)))))
Basing on this thread we can come up with a code that triggers
mb/org-zotxt-open-attachment
when clicking on it inside emacs.(defun org-zotero-open (path) (browse-url (format "zotero:%s" path))) (with-eval-after-load 'org (org-link-set-parameters "zotero" :follow #'mb/org-zotxt-open-attachment))
There are two drawbacks of this solution:
- Link does not work when exported to other formats (e.g. pdf).
- When clicking on the link it is opened in dolphin however
the error message appears in minibuffer:
Qt: Session management error: None of the authentication protocols specified are supported
.
-
TODO TODO
- Add zotxt-emacs to
install-packages.el
script. - Move this section to proper section in this documents after tests.
- Add zotxt-emacs to
Some useful information and links:
What to do when Emacs is slow and laggy:
https://emacs.stackexchange.com/questions/5359/how-can-i-troubleshoot-a-very-slow-emacs
emacs packages