Initialization files setup in Emacs

https://alhassy.com/emacs.d/

https://alhassy.com/AlBasmala

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:

  1. Installation/Updating of packages is perfomed in separate file install-packages.el (abbreviation for install or upgrage packages) which is intended to be executed every now and then, while Emacs initialization is done in init.el.
  2. I’m not going to use use-package since I still don’t get it well. What is more, according to this post use-package is just a fancier way of doing things that can be done in vanilla Emacs.
  3. The style of init.el presented on this page is something that seems to look nice and I’m going to implement this approach.
  4. 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.
  5. 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 and init.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 load ox 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 evaluating init.el. I have no idea whether there are any relevant differences between both approaches.

Sources worth further reading

  1. 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:

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).

  1. Solution

    1. Install MikTeX with installer
    2. Install Perl distribution (Strawberry Perl).

The things that need to be adjusted in init.el

  1. Adjust org-cite-csl-styles-dir to point to appropriate directory

    (setq org-cite-csl-styles-dir "~/Zotero/styles")

  2. DEPRECATED Python paths

    python3 path was an artifact from some old debian distribution. In newer Debian releases python stands for python3, so I corrected two occurances of python3 in init.el.

    1. DEPRECATED Solution

      You need to amend paths to python executable in two places: 1.7.9.8 1.7.7.3

  3. Liberation mono font

    That part of code is in init.el only for 1.7.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:

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.8). 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
  ;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.

  1. 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")
    
  2. Package package initialization

    In 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)
    
  3. Quelpa and quelpa-use-package

    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 of quelpa-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.

  1. Self-descriptive oneliners

    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:

    From two possible alternatives at the time: nlinum-mode and display-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=
    
  2. 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.

  3. Emacs shell history from previous sessions

    Emacs wiki page

    (savehist-mode 1)          ; Save history for future sessions
    
  4. 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

  5. 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 
    
  6. 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…)

  7. Prevent from deselecting text after M-w copying

    Link

    ;; 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
    
  8. 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.7.20.

  9. 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.7.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)
    ;;
    
  10. Time and calendar

    1. 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

      Link 1

      Link 3

      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
      
    2. 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 hitting RET.

      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, if calendar-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
  11. 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
    
    1. 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
      
  12. 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 
    
  13. 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 modes text-mode and special-mode. Unfortunately, these modes do not contain all required modes (DocOnce-mode or org-mode are absent on the list of modes). (The list of modes inherited after prog-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.7.7 section of this document

  14. 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)
    
  15. Ibuffer - an advanced replacement for BufferMenu

    Description of the package is here.

      ;; Advanced buffer mode
    (global-set-key (kbd "C-x C-b") 'ibuffer)
    
  16. 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.

    1. emacs-sessions

      The simplest solution and it works as I would like it to work.

      1. 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
        
      2. Initialization

        ;; emacs-sessions
        (add-to-list 'load-path "~/.emacs.d/manual-download/emacs-sessions/")
        (require 'sessions)
        
    2. ABANDONED persp-mode

      The fork of perspective-el named persp-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…

    3. 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)
      
    4. DEPRECATED Approach no 1: perspective-el and tab-bar-mode

      https://github.com/nex3/perspective-el

      To ease the problem we may enable tab-bar-mode and use perspestive-el package (loaded with the command (persp-mode 1)). We also need to rebind C-x C-b to invoke persp wrapper of ibuffer 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:

    5. DEPRECATED tabspaces package

      https://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 my init.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.

  17. Other solution

    There are also solutions based on frame approach:

  18. Setting font size for all buffers

    https://stackoverflow.com/questions/24705984/increase-decrease-font-size-in-an-emacs-frame-not-just-buffer

    ;; 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

  1. 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!)

    1. 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 with x.

    2. Ibuffer interactive way

      In 1.7.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):

      1. Open ibuffer

        C-x C-b
        

        or

        M-x ibuffer
        
      2. Select all the buffer of the mode

        * M
        
      3. Search for all dired or sunrise mode buffers and kill them:

        * D
        
    3. Simple dired way

      You can use dired-find-alternate-file function which is bounded to key a in dired-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).

  2. 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 delete
    • x to delete all D marked ones
    • r to rename
    • s to save changes

    You can always achieve the same functionality without bookmarks feature like here.

Completing

ido/smex vs ivy/counsel/swiper vs helm

  1. 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 with C-x C-f emacs will automatically concatenate necessary modifier in order to have it open…

  2. 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
    
  3. TODO Ivy (for testing)

    Furthermore, according to some other users “Ivy is simpler (and faster) than Helm but more powerful than Ido”.

  4. 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 trigger abbrev-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 and company 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
    
    1. 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)
  1. 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
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1. Emacs-Lisp mode

    Be sure to set emacs-lisp-mode maps/hooks etc, not just lisp-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)  
    )
    
  2. 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, because octve-mode command is available. The only thing to do is to add octave-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 (run C-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')" ))
         )
    )
    
    1. 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 by octave (or matlab) 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 to src_matlab

        (or vice versa)

      • and only then run the code (or export the file) to the format of your choice.
  3. 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") ))
    
  4. 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 get exporting menu and in the third line you can see Async export option that can be enabled by pressin C-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 by C-c C-e). When calling org-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.7.7.4.1).

    1. Setting org-export-async-init-file to avoid failure while exporting to Beamer

      Org-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)

    2. TODO async for odt documents still not working

  5. 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)
    
  6. 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
     ))
    
  7. 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

  1. 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

  2. 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 in init.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 (provided apa.csl is inside ~/Zotero/styles)

Org customization: org-mode, org-babel …

  1. Modyfing TODO-DONE sequence in org-mode

    https://emacs.stackexchange.com/questions/31466/all-todos-how-to-set-different-colors-for-different-categories

    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).

  2. 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)
    
  3. Toggle between TODO-DONE keywords for all subnodes of the current node

    Based on: https://emacs.stackexchange.com/questions/52492/change-todo-keywords-of-all-nodes-in-an-orgmode-subtree-in-elisp

    (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)
      )
    
  4. Org-special-block-extras

    Author’s page

    ;; **** org-special-block-extras -> 
    (add-hook #'org-mode-hook #'org-special-block-extras-mode)
    ;; <- **** org-special-block-extras 
    
  5. Org-babel asynchronous source block execution

    1. session-async

    2. DEPRECATED emacs-async

      https://github.com/jwiegley/emacs-async#async-usage It’s built into the newest emacs versions…

    3. 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…

  6. 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)
    
    1. Tangling the specific/named block of code and other useful functions to work with source blocks

      1. Tangle the specific (pointed) block of code

        (defun mb/org-babel-tangle-block()
          (interactive)
          (let ((current-prefix-arg '(4)))
             (call-interactively 'org-babel-tangle)
        ))
        
      2. 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)) 
        )
        
      3. Tangle all (and only those) source code blocks that belong to a specific target file

        https://emacs.stackexchange.com/questions/80174/how-to-tangle-only-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)))))
        
      4. 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)))))
        
      5. 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)
          )
        
    2. plantuml

      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)
      
  7. 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:

    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.el

    In the end I just downloaded the file and the inclusion of this package is done in section 1.7.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 on altmany’s export_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 without export_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
    
    1. 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

    2. Wrong formatting of matlab output’s in org-babel

      https://www.reddit.com/r/emacs/comments/fy98bs/orgbabels_matlab_session_output_is_malformed/

    3. 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 ;
      
  8. 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 not python

    ;; 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.

  9. 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
    
  10. Miscellaneous oneliners

    ;; alphabetical ordered lists
    (setq org-list-allow-alphabetical t)
    
  11. TODO Asynchronous babel sessions

    ob-comint.el

  12. 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.

  13. 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 in install-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 and org-latex-engraved-options

    Please do note that engraved includes fvextra package and tcolorbox package with options breakable and xparse. This should be taken into account when using org-special-blocks-package since it also depends on tcolorbox 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 for tcolorbox 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.7.14.2.2 placed inside #+begin_ai #+end_ai we need to define ai environement in latex. Concatenation of variable org-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
    
    1. 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

    2. TODO PROBLEM: bash output aligned to center with engraved

  14. How to properly deal with picture/figure size attributes when picture is produced by org-babel block

    1. 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"))
      
    2. TODO Problems with passing “Local variables:” to asynchronous exporter

  15. CDLatex installed in order to ease working with LaTeX in org-mode

    The special mode org-cdlatex-mode is included in org package. In order to have it working properly we need to install cdlatex itself. This can be done in 1.6.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 {
    
  16. org-ref for references

    Enabling 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)
    
  17. Reftex for managing references

    Use org-cite for citations and bibliography. And org-ref for references.

    1. OLDER COMMENTS

      Reftex is preinstalled since Emacs 20.2, however in order to have it working you need to install auctex 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 with reftex and LaTeX tags.

  18. 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…

  1. Alternative solutions:

    https://github.com/samrawal/emacs-secondmate/tree/main

  2. 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 my init.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 use user-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.

    1. 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, see org-ai.el to view other keybindings…)

    2. ChatGPT session blocks export with engraved

      In order to flawlessly export ChatGPT sessions placed inside #+begin_ai #+end_ai we need to define ai environement in latex for engraved exports (see 1.7.9.13) That is why we need to update org-latex-engraved-preamble introduction in section 1.7.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.7.9.13, where I repeated default setting of org-latex-engraved-preamble with necessary lines added at the end of the string.

    3. Updating org-structure-template-alist to include org-ai environment … and to add newlines in appropriate items

      Based on https://emacs.stackexchange.com/questions/52441/how-to-modify-org-structure-template-alist-after-org-mode-9-2

      (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")))
      
  3. gptel

    I also tried with gptel. Unfortunately I wasn’t able to succeed in installing it.

  4. 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)

  5. 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/57919/preview-images-and-pdfs-inside-a-ssh-terminal-session-or-inside-emacsclient-ses

->

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))
  1. '’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)
    
  2. 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.

  3. Useful fast line-copying shortcut

    Another ideas can be found here: https://emacs.stackexchange.com/questions/15134/how-to-get-contents-of-current-line

    1. 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 and C-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 invoking mb-map,

      but at some point I realized that it overwrittens default keybinding for previous-line.

    2. 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)  
      
    3. 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)
      
    4. ABANDONED Solution 3 (NOT WORKING)

      https://www.emacswiki.org/emacs/CopyWithoutSelection

  4. 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 for shell-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).

  5. 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.7.17.2.

  1. 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
    
  2. 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))
  1. DEPRECATED OLD Approaches

    As a temporary workaround I decided to try 1.7.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.
    1. Links that can be useful:

    2. 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.

  1. Install package emacs-everywhere from melpa (1.6.2)
  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)

  3. 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 the init.el.

  4. 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 press C-c C-c or C-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.

  5. 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:

    1. https://www.google.com/search?q=emacs+default+font+emacs+daemon
    2. https://emacs.stackexchange.com/questions/52063/emacsclient-gui-has-small-fonts
    3. https://github.com/doomemacs/doomemacs/issues/1223
    4. https://www.reddit.com/r/emacs/comments/pc189c/fonts_in_emacs_daemon_mode/
    5. 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

information in emacs manual

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.

  1. 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

  2. TODO Sending emails with calendar events

    To be done in some free time.

  3. Links that I found useful setting up this package:

    https://emacs.stackexchange.com/questions/3035/how-to-know-if-emacs-is-running-as-a-daemon

Load Emacs theme of your preference

  1. 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 and modus-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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1. 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)
    
  2. 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 be org-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).

  3. DEPRECATED Integrating calendar, agenda and diary (partially)

    REMARK: -> I moved to 1.7.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.

  4. calfw package a way to integrate agenda entries to calendar

    https://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 =====")
  1. Sunrise - Norton Commander-like file browser

    There are few packages to emulate Norton Commander experience in Emacs. I tested mc.el, nc.el and sunrise.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

    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 to sunrise-kill-pane-buffer command which, at least to me, works only for commander-like frame layout, which is triggered after invoking M-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)))
    
  2. 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)
    
  3. ob-octave-fix.el

    The discussion on this is thread can be found in section 1.7.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)
    
  4. My own packages and settings

    1. 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)
      
  5. ox-extra for :ignore: tag

    ignore tag functionality is very useful. It is implemented in ox-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))
    
  6. 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.

  7. 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")
    
    1. Similar packages

      Reddit discussion on this issue

  8. 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

  1. 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))
        ))
    
  2. 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))
       ))
    
  3. Blogging with easy-hugo

    1. 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

  1. 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 your init.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 or C-c z C-c

    • To open an existing work group:

    M-x wg-open-workgroup or C-c z C-v

    • To delete an existing work group:

    M-x wg-kill-workgroup or C-c z C-k

    There is one problem with workgroups2 packages. It does not like with desktop-save-mode. When workgroups2 is enabled desktop-save-mode does not restore the windows layout from the previous Emacs session, which sucks. I decided to stick to workgroups2 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
       )
    )
    
  2. Last lines

  3. 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 of init.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)
    
  4. 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 using recentf 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 found find-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:

Tests

Emacs and Zotero integration - zotxt-emacs

https://github.com/egh/zotxt-emacs

  1. Install zotxt

    https://github.com/egh/zotxt

    1. Visit https://github.com/egh/zotxt/releases
    2. Download the latest .xpi file. If you are using Firefox, you will need to right-click and “Save as”
    3. Start Zotero standalone.
    4. In Zotero, select Tools -> Add-ons -> Gear (upper right) -> Install Add-On from file, and install the downloaded xpi file.
    5. RESTART Zotero!!!
  2. Install zotxt-emacs package

  3. 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)

  4. 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.

  5. 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 from zotxt-emacs I created similiar function that enables opening zotero link in okular. (Interesting observation: variable paths used in function is not a list. It is a vector! That is why to get its element we need to use aref 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:

    1. Link does not work when exported to other formats (e.g. pdf).
    2. 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.
  6. TODO TODO

    1. Add zotxt-emacs to install-packages.el script.
    2. Move this section to proper section in this documents after tests.

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