greek statue on emacs

For nearly a year now, I’ve had a side project in mind: creating a minimal version of Emacs with org-mode. This idea stemmed from my experience with Spacemacs, which, while intuitive, was plagued by sluggish performance. Finally, thanks to the assistance of ChatGPT, I was able to iterate and complete approximately 150 lines of Emacs configuration code, resulting in a lean and user-friendly org-mode client that suits my needs.

It had to include:

  • Some Spacemacs shorcuts (for buffer/window navigation).
  • Simpler Orgmode shorcuts using CTRL+O as base.
  • CTRL+TAB for toggling between last tab and current.
  • Full restore if emacs exits.
  • My custom CTRL+SHIFT+UP/DOWN/LEFT/RIGHT Orgmode headers navigation.
  • Dark theme, with a similar Orgmode look like Spacemacs dark theme has.
  • Lean. It has to be extremely lean.

tl;dr here’s the source code:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
(require 'package)

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

(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))

;; Install use-package if it's not already installed
(unless (package-installed-p 'use-package)
  (package-install 'use-package))

(require 'use-package)

;; Install and configure evil mode
(use-package evil
  :ensure nil
  :init
  (setq evil-want-integration t)
  (setq evil-want-keybinding nil)
  :config
  (evil-mode 1)
  (evil-define-key 'normal org-mode-map (kbd "TAB") 'org-cycle))  ; Set the TAB key to open/close org-mode subheaders in org-mode

;; Prevent start-up screen
(setq inhibit-startup-screen t)

;; Install and configure general.el
(use-package general
  :ensure nil
  :config
  (general-create-definer my-leader-def
    :prefix "SPC"))

;; Org mode configuration
(use-package org
  :ensure nil
  :config
  ;; Enable Org mode related features
  (add-hook 'org-mode-hook 'turn-on-auto-fill)
  (add-hook 'org-mode-hook 'org-indent-mode)  ; Enable org-indent-mode
  (setq org-log-done t)
  (setq org-agenda-files '("~/emacs"))
  (setq org-hide-emphasis-markers t)
  (setq org-hide-leading-stars t)
  (setq org-priority-default 67)
  (setq org-priority-lowest 69)
  )  ; Hide leading stars

;; General keybindings
(my-leader-def
  :states '(normal visual emacs)
  :keymaps 'override
  "b d" 'kill-buffer       ; Kill a buffer
  "w d" 'delete-window     ; Kill a window
  "f f" 'find-file)  ; Open a file

; Buffer cycling keybindings
(global-set-key (kbd "<C-tab>") 'mode-line-other-buffer) ; Switch to last buffer

;; Toggle window switch with ALT+1
(global-set-key (kbd "M-1") 'other-window) ; Switch to last window

;; Set CTRL+UP and CTRL+DOWN for scrolling
(general-define-key
 :states '(normal visual insert emacs)
 :keymaps 'override
 "C-<up>" 'evil-scroll-line-up
 "C-<down>" 'evil-scroll-line-down)

;; Additional keybindings for org-mode
(general-define-key
 :states '(normal visual insert emacs)
 :keymaps 'org-mode-map
 "C-S-<up>" 'org-backward-heading-same-level
 "C-S-<down>" 'org-forward-heading-same-level
 "C-S-<left>" 'outline-up-heading
 "C-S-<right>" 'outline-next-visible-heading
 "C-o t" 'org-agenda-todo
 "C-o '" 'org-edit-special
 "C-o a" 'org-agenda
 "C-o c" 'org-capture)

;; Configure desktop mode to save and restore open files
(setq desktop-path '("~/.emacs.d/"))
(setq desktop-dirname "~/.emacs.d/")
(setq desktop-base-file-name "emacs-desktop")
(setq desktop-load-locked-desktop t)

(desktop-save-mode 1)
(add-hook 'emacs-startup-hook
          (lambda ()
            (if (file-exists-p (concat desktop-dirname "/" desktop-base-file-name))
                (desktop-read)
              (desktop-create-buffer))))

;; Theme

(defun set-lean-dark-theme ()
  "Set a lean dark theme for Emacs, including Org mode colors, font sizes, and bullets."
  (interactive)
  (setq foreground-color "#f8f8f2") ; Light gray
  (setq background-color "#282a36") ; Dark gray
  (setq comment-color "#6272a4")    ; Comment color
  (setq string-color "#50fa7b")      ; String color
  (setq keyword-color "#8be9fd")     ; Keyword color
  (setq function-color "#ffb86c")    ; Function color
  (setq org-level-1-color "#4f97d7")  ; Org mode level 1 heading color
  (setq org-level-2-color "#2d9574")  ; Org mode level 2 heading color
  (setq org-level-3-color "#67b11d")
  (setq org-level-4-color "#b1951d")
  (setq org-level-5-color "#4f97d7")
  (setq timestamp-link-color "#7590db") ; Timestamp and link color
  (setq todo-color "#ff4500")           ; TODO color (orange)
  (setq done-color "#50fa7b")           ; DONE color (green)

  ;; Set the theme colors
  (custom-set-faces
   `(default ((t (:foreground ,foreground-color :background ,background-color))))
   `(font-lock-comment-face ((t (:foreground ,comment-color))))
   `(font-lock-string-face ((t (:foreground ,string-color))))
   `(font-lock-keyword-face ((t (:foreground ,keyword-color))))
   `(font-lock-function-name-face ((t (:foreground ,function-color))))
   `(org-level-1 ((t (:foreground ,org-level-1-color :weight bold :height 1.2))))
   `(org-level-2 ((t (:foreground ,org-level-2-color :weight bold :height 1.1))))
   `(org-level-3 ((t (:foreground ,org-level-3-color :weight bold :height 1.1))))
   `(org-level-4 ((t (:foreground ,org-level-4-color :weight bold :height 1.1))))
   `(org-level-5 ((t (:foreground ,org-level-5-color :weight bold :height 1.1))))
   `(org-link ((t (:foreground ,timestamp-link-color :underline t))))
   `(org-todo ((t (:foreground ,todo-color :weight bold))))
   `(org-done ((t (:foreground ,done-color :weight bold))))
   `(org-date ((t (:foreground ,timestamp-link-color))))
   `(org-verbatim ((t (:foreground ,timestamp-link-color))))
   `(org-property-value ((t (:foreground ,timestamp-link-color))))
   `(org-special-keyword ((t (:foreground ,timestamp-link-color)))))

  ;; Customize Org bullets
  (use-package org-bullets
    :ensure nil
    :config
    (setq org-bullets-bullet-list '("◉" "○" "✸" "✿" "✜" "►" "◆"))
    (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))

  ;; Disable the fringe
  (fringe-mode 0))

;; Call the function to set the lean dark theme
(set-lean-dark-theme)
(custom-set-variables
 ;; custom-set-variables was added by Custom.
 '(package-selected-packages '(org-bullets general evil use-package))
 '(tool-bar-mode nil))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 '(default ((t (:foreground "#f8f8f2" :background "#282a36"))))
 '(font-lock-comment-face ((t (:foreground "#6272a4"))))
 '(font-lock-function-name-face ((t (:foreground "#ffb86c"))))
 '(font-lock-keyword-face ((t (:foreground "#8be9fd"))))
 '(font-lock-string-face ((t (:foreground "#50fa7b"))))
 '(org-date ((t (:foreground "#7590db"))))
 '(org-done ((t (:foreground "#50fa7b" :weight bold))))
 '(org-level-1 ((t (:foreground "#4f97d7" :weight bold :height 1.2))))
 '(org-level-2 ((t (:foreground "#2d9574" :weight bold :height 1.1))))
 '(org-level-3 ((t (:foreground "#67b11d" :weight bold :height 1.1))))
 '(org-level-4 ((t (:foreground "#b1951d" :weight bold :height 1.1))))
 '(org-level-5 ((t (:foreground "#4f97d7" :weight bold :height 1.1))))
 '(org-link ((t (:foreground "#7590db" :underline t))))
 '(org-property-value ((t (:foreground "#7590db"))) t)
 '(org-special-keyword ((t (:foreground "#7590db"))))
 '(org-todo ((t (:foreground "#ff4500" :weight bold))))
 '(org-verbatim ((t (:foreground "#7590db")))))

To kickstart the development of my lean org-mode client, I began by leveraging the power of Emacs and its extensive customization capabilities. With the help of ChatGPT, I was able to refine my approach and optimize the configuration code to achieve a faster and more streamlined experience. By carefully selecting essential packages and fine-tuning keybindings, I ensured that the client remained lightweight while retaining crucial functionality.

One of the core focuses of my work was improving the performance and responsiveness of the org-mode client. With ChatGPT’s guidance, I implemented techniques to reduce startup times, minimize unnecessary overhead, and enhance buffer management. These optimizations resulted in a significant boost in overall speed, allowing for smooth navigation, editing, and organization of org files.

In addition to performance enhancements, ChatGPT helped me tailor the visual appearance of the org-mode client to enhance readability and aesthetics. By selecting a dark theme and carefully configuring font sizes and colors, I created a visually appealing environment that reduces eye strain and promotes focus during long coding sessions. Furthermore, I incorporated custom bullet styles for org headers, inspired by Spacemacs, to maintain a consistent and visually pleasing structure within org files.

ChatGPT played a pivotal role in troubleshooting and refining the org-mode client. By providing insights and suggestions, it helped me overcome challenges, such as resolving conflicts between keybindings and fine-tuning org-mode configurations. With each iteration, the client became more polished and aligned with my personal workflow, ensuring a seamless and enjoyable org-mode experience.

By combining my expertise with Emacs, the power of ChatGPT, and a relentless pursuit of efficiency, I successfully built a lean org-mode client tailored to my needs. The journey of creating this customized Emacs configuration not only honed my programming skills but also exemplified the collaborative potential of human-AI partnerships in software development.

As an added note, I have even taken the liberty to comment out lines 3 to 13, Thereby disabling auto-update. Emacs has caused me many woes in the past due to package upgrades, so I have decided to ensure it doesn’t happen again.