Notes on My Recent Exploration of Emacs

I briefly tried to use Emacs Doom, but I quickly realized that configuring it properly would take up quite a while, and would involve deleting quite a lot. So I ultimately went back to modifying my own init file to suit my writing workflow.

I saw that Doom divided up the config files by functionality, and I decided to give that a try. And so now my setup looks the way described below. Also, it has a lot more functionality than it did in my earlier basic config.

The visual and writing experience within Emacs is beautiful enough for me to now want to go to Obsidian to write. Previously, I was using Obsidian to write up my blogs. But this one is being written in Emacs. I had to open it up initially using Obsidian (I have not ported over the template), but the writing itself is occurring inside Emacs. I still will return to Obsidian to put the final touches. (The code blocks still look bad in Emacs, and sometimes using the trackpad/mouse just makes things much easier.) . . . Indeed, I ended using both to write.

Configuration Files

Inside /.emacs.d/ I have early-init.el and init.el.

early-init.el:

(setq gc-cons-threshold most-positive-fixnum)
(setq gc-cons-percentage 0.6)

(setq inhibit-startup-message t)

(setq package-enable-at-startup nil)

(add-to-list 'default-frame-alist '(fullscreen . maximized))

(setq custom-file
      (expand-file-name "custom.el" user-emacs-directory))

init.el:

(add-to-list 'load-path
             (expand-file-name "lisp" user-emacs-directory))

;; These files are located inside .emacs.d/lisp folder.
(require 'my-core)
(require 'my-ui)
(require 'my-completion)
(require 'my-programming)
(require 'my-org)
(require 'my-functions)

(load custom-file t)

The init.el calls a number of files located within the /.emacs.d/lisp/ folder. These files are as follows.

my-core.el:

(require 'package)

(setq package-archives
      '(("gnu" . "https://elpa.gnu.org/packages/")
        ("nongnu" . "https://elpa.nongnu.org/nongnu/")
        ("melpa" . "https://melpa.org/packages/")))

(package-initialize)

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(require 'use-package)
(setq use-package-always-ensure t)

(menu-bar-mode 0)
(tool-bar-mode 0)
(tooltip-mode 0)

(recentf-mode 1)
(setq recentf-max-saved-items 200)
(setq recentf-max-menu-items 25)
(setq recentf-auto-cleanup 'never)

(use-package olivetti)
(use-package centered-cursor-mode)

(add-hook 'text-mode-hook
          (lambda ()
            (olivetti-mode 1)
            (centered-cursor-mode 1)))

(add-hook 'prog-mode-hook
          (lambda ()
            (olivetti-mode 1)
	        (display-line-numbers-mode 1)
            (centered-cursor-mode 1)))

(add-hook 'vterm-mode-hook
          (lambda ()
	        (olivetti-mode -1)
            (centered-cursor-mode -1)))

(setq initial-major-mode 'org-mode)
(setq initial-scratch-message
      "#+title: Scratch\n\n")

(add-hook 'emacs-startup-hook
        (lambda ()
          (setq gc-cons-threshold (* 64 1024 1024)
                gc-cons-percentage 0.1)))
  
(provide 'my-core)  

my-ui.el:

;;THEMES
(use-package doom-themes)
(mapc #'disable-theme custom-enabled-themes)

(defvar my/dark-theme 'doom-acario-dark)
(defvar my/light-theme 'doom-acario-light)
(defvar my/current-theme my/dark-theme)

(load-theme my/current-theme t)

;;TRANSPARENCY 
(set-frame-parameter nil 'alpha-background 90)
(add-to-list 'default-frame-alist '(alpha-background . 90))

;;FONTS
(set-face-attribute 'default nil
                    :family "JetBrainsMono Nerd Font Mono"
                    :height 120)

;;MODELINE
(use-package telephone-line
  :config
  (setq telephone-line-primary-left-separator 'telephone-line-cubed-left
        telephone-line-secondary-left-separator 'telephone-line-cubed-hollow-left
        telephone-line-primary-right-separator 'telephone-line-cubed-right
        telephone-line-secondary-right-separator 'telephone-line-cubed-hollow-right)
  (telephone-line-mode 1))

(provide 'my-ui)

my-completion.el:

(use-package vertico
  :init
  (vertico-mode 1)
  :bind
  (:map vertico-map
        ("C-j" . vertico-next)
        ("C-k" . vertico-previous)))

(use-package orderless
  :custom
  (completion-styles '(orderless basic))
  (completion-category-defaults nil)
  (completion-category-overrides
   '((file (styles basic partial-completion)))))
   
(use-package marginalia
  :init
  (marginalia-mode 1))
  
(use-package which-key
  :init
  (which-key-mode 1)
  :custom
  (which-key-idle-delay 0.2))

(use-package consult
  :defer t)

(use-package embark
  :bind
  (("C-." . embark-act)
   ("C-;" . embark-dwim)
   ("C-h B" . embark-bindings)))

(use-package corfu
  :init
  (global-corfu-mode 1)
  :custom
  (corfu-auto t)
  (corfu-auto-delay 0.1)
  (corfu-auto-prefix 2)
  (corfu-cycle t))

(use-package evil
  :init
  (setq evil-want-keybinding nil)
  (setq evil-want-C-u-scroll t)
  (setq evil-want-C-i-jump nil)
  :config
  (evil-mode 1))

(use-package evil-collection
  :after evil
  :config
  (evil-collection-init))

(use-package general
  :demand t
  :config
  (general-evil-setup t)

  (general-create-definer my/leader
    :states '(normal visual motion)
    :keymaps 'override
    :prefix "SPC"
    :global-prefix "C-SPC")

  (my/leader
    "f f" '(find-file :which-key "find file")
    "f s" '(save-buffer :which-key "save file")
    "f r" '(consult-recent-file :which-key "recent file")

    "b b" '(consult-buffer :which-key "switch buffer")
    "b d" '(kill-current-buffer :which-key "kill buffer")
    "g g" '(magit-status :which-key "Magit status")
    
    "w 2" '(evil-window-vsplit :which-key "split window vertically")
    "w 1" '(delete-other-windows :which-key "delete other windows")
    "w e" '(enlarge-window-horizontally :which-key "grow window")

    "n" '(other-window :which-key "other window")
    "s" '(consult-line :which-key "search in file")
    "S" '(consult-ripgrep :which-key "search in project")
    ";" '(comment-region :which-key "comment region")
    "/" '(uncomment-region :which-key "uncomment region")
    "w w" '(emacs-init-time :which-key "init time")
    
    "o t" '(my/open-vterm :which-key "open terminal") 

    "t t" '(my/toggle-theme :which-key "toggle theme") 

    "q r" '(restart-emacs :which-key "restart Emacs")  
    "q q" '(kill-emacs :which-key "quit Emacs")))

(provide 'my-completion)

my-programming.el:

(use-package magit
  :commands (magit-status)
  :bind ("C-x g" . magit-status))
 
(setq treesit-language-source-alist
      '((python "https://github.com/tree-sitter/tree-sitter-python")
        (julia  "https://github.com/tree-sitter/tree-sitter-julia")))

(setq major-mode-remap-alist
      '((python-mode . python-ts-mode)))

(use-package python
  :ensure nil
  :mode ("\\.py\\'" . python-ts-mode))

(use-package julia-mode
  :ensure t
  :mode ("\\.jl\\'" . julia-mode))

(use-package ess
  :mode ("\\.R\\'" . R-mode))

(use-package markdown-mode
  :mode ("\\.md\\'" . markdown-mode)
  :init
  (setq markdown-command "pandoc"))

(use-package adaptive-wrap
  :hook (visual-line-mode . adaptive-wrap-prefix-mode))

(show-paren-mode 1)
(electric-pair-mode 1)
(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

(provide 'my-programming)

my-org.el:

(with-eval-after-load 'org
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((python . t)
     (julia  . t)
     (R      . t))))

(setq org-confirm-babel-evaluate nil)

(setq org-src-fontify-natively t)
(setq org-src-tab-acts-natively t)
(setq org-edit-src-content-indentation 0)
(setq org-src-preserve-indentation t)

(provide 'my-org)

my-functions.el:

(defun reload-init-file ()
  "Reload the Emacs init file."
  (interactive)
  (load-file user-init-file)
  (message "Reloaded %s" user-init-file))

(global-set-key (kbd "<f5>") #'reload-init-file)

(defun my/open-vterm ()
  "Open vterm in a bottom window using the current buffer's directory."
  (interactive)
  (let ((default-directory
          (if buffer-file-name
              (file-name-directory buffer-file-name)
            default-directory)))
    (split-window-below 25)
    (other-window 1)
    (if (get-buffer "*vterm*")
        (switch-to-buffer "*vterm*")
      (vterm))
    (vterm-send-string (concat "cd " default-directory))
    (vterm-send-return)))

(defun my/toggle-theme ()
  (interactive)
  (mapc #'disable-theme custom-enabled-themes)
  (setq my/current-theme
        (if (eq my/current-theme my/dark-theme)
            my/light-theme
          my/dark-theme))
  (load-theme my/current-theme t))
  
(provide 'my-functions)  

My setup might still not be involved enough to justify splitting the init file into so many files, but I suspect each of these files will gain bulk over time.

  1. A Minimal Emacs Config.