From 8c0110d8844ca85b06fdf9800ae2bc1ae4571b3c Mon Sep 17 00:00:00 2001 From: Eduardo Cueto-Mendoza Date: Tue, 9 Apr 2024 17:18:11 +0100 Subject: [PATCH] Initial commit of my basic configuration --- .gitignore | 6 + Emacs.org | 1460 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1466 insertions(+) create mode 100644 .gitignore create mode 100755 Emacs.org diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2849a33 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +var/ +elpa/ +etc/ +*~ +.last-package-update-day +init.el \ No newline at end of file diff --git a/Emacs.org b/Emacs.org new file mode 100755 index 0000000..308eedc --- /dev/null +++ b/Emacs.org @@ -0,0 +1,1460 @@ +#+title: Emacs From Scratch Configuration +#+PROPERTY: header-args:emacs-lisp :tangle ./init.el :mkdirp yes + +* Welcome! + +The following variables are used to tweak some of the configuration pieces for use in the live streams so you might need to adjust them for your local machine if you try to use this configuration directly. + +#+begin_src emacs-lisp + + ;; NOTE: init.el is now generated from Emacs.org. Please edit that file + ;; in Emacs and init.el will be generated automatically! + + ;; You will most likely need to adjust this font size for your system! + (defvar efs/default-font-size 100) + (defvar efs/default-variable-font-size 100) + + ;; Make frame transparency overridable + (defvar efs/frame-transparency '(90 . 90)) + + ;; Electric pair mode + (electric-pair-mode 1) + + ;; Use gnu-ls for the BSD's + (cond ((eq system-type 'berkeley-unix) + (setq insert-directory-program "/usr/local/bin/gls"))) + +#+end_src + + +* Tips for Use + +In this document I've added links in many places that lead you to documentation for the various packages we use. If you're looking at this file in Emacs, you can put your cursor on a link and press =C-c C-o= or run =M-x org-open-at-point= to open the link in your web browser. + +* Startup Performance + +#+begin_src emacs-lisp + + ;; The default is 800 kilobytes. Measured in bytes. + (setq gc-cons-threshold (* 50 1000 1000)) + + (defun efs/display-startup-time () + (message "Emacs loaded in %s with %d garbage collections." + (format "%.2f seconds" + (float-time + (time-subtract after-init-time before-init-time))) + gcs-done)) + + (add-hook 'emacs-startup-hook #'efs/display-startup-time) + +#+end_src + + +* Package System Setup + +Emacs has a built in package manager but it doesn't make it easy to automatically install packages on a new system the first time you pull down your configuration. [[https://github.com/jwiegley/use-package][use-package]] is a really helpful package used in this configuration to make it a lot easier to automate the installation and configuration of everything else we use. + +#+begin_src emacs-lisp + + ;; Initialize package sources + (require 'package) + + (setq package-archives '(("melpa" . "https://melpa.org/packages/") + ("org" . "https://orgmode.org/elpa/") + ("elpa" . "https://elpa.gnu.org/packages/") + ("nongnu" . "https://elpa.nongnu.org/nongnu/"))) + + (package-initialize) + (unless package-archive-contents + (package-refresh-contents)) + + ;; Initialize use-package on non-Linux platforms + (unless (package-installed-p 'use-package) + (package-install 'use-package)) + + ;; Initialize exec-path-from-shell on non-Linux platforms + (unless (package-installed-p 'use-package) + (package-install 'exec-path-from-shell)) + + (require 'use-package) + (setq use-package-always-ensure t) + (require 'exec-path-from-shell) + + ;; load Linux PATH + (when (memq window-system '(mac ns x)) + (exec-path-from-shell-initialize)) + ;; if loaded as daemon + (when (daemonp) + (exec-path-from-shell-initialize)) + +#+end_src + + +** Automatic Package Updates + +The auto-package-update package helps us keep our Emacs packages up to date! It will prompt you after a certain number of days either at startup or at a specific time of day to remind you to update your packages. + +You can also use =M-x auto-package-update-now= to update right now! + +#+begin_src emacs-lisp + +; (use-package auto-package-update +; :custom +; (auto-package-update-interval 7) +; (auto-package-update-prompt-before-update t) +; (auto-package-update-hide-results t) +; :config +; (auto-package-update-maybe) +; (auto-package-update-at-time "09:00")) + +#+end_src + + +* Keep Folders Clean + +We use the [[https://github.com/emacscollective/no-littering/blob/master/no-littering.el][no-littering]] package to keep folders where we edit files and the Emacs configuration folder clean! It knows about a wide variety of variables for built in Emacs features as well as those from community packages so it can be much easier than finding and setting these variables yourself. + +#+begin_src emacs-lisp + + ;; NOTE: If you want to move everything out of the ~/.emacs.d folder + ;; reliably, set `user-emacs-directory` before loading no-littering! + ;(setq user-emacs-directory "~/.cache/emacs") + + (use-package no-littering) + + ;; no-littering doesn't set this by default so we must place + ;; auto save files in the same path as it uses for sessions + (setq auto-save-file-name-transforms + `((".*" ,(no-littering-expand-var-file-name "auto-save/") t))) + +#+end_src + + +* Wayland clipboard support + +#+begin_src emacs-lisp + ;;;; credit: yorickvP on Github + ;;(setq wl-copy-process nil) + ;;(defun wl-copy (text) + ;; (setq wl-copy-process (make-process :name "wl-copy" + ;; :buffer nil + ;; :command '("wl-copy" "-f" "-n") + ;; :connection-type 'pipe)) + ;; (process-send-string wl-copy-process text) + ;; (process-send-eof wl-copy-process)) + ;;(defun wl-paste () + ;; (if (and wl-copy-process (process-live-p wl-copy-process)) + ;; nil ; should return nil if we're the current paste owner + ;; (shell-command-to-string "wl-paste -n | tr -d \r"))) + ;;(setq interprogram-cut-function 'wl-copy) + ;;(setq interprogram-paste-function 'wl-paste) +#+end_src + +* Basic UI Configuration + +This section configures basic UI settings that remove unneeded elements to make Emacs look a lot more minimal and modern. If you're just getting started in Emacs, the menu bar might be helpful so you can remove the =(menu-bar-mode -1)= line if you'd like to still see that. + +#+begin_src emacs-lisp + + (setq inhibit-startup-message t) + ;;(setq default-directory "~/.emacs.d") + + (scroll-bar-mode -1) ; Disable visible scrollbar + (tool-bar-mode -1) ; Disable the toolbar + (tooltip-mode -1) ; Disable tooltips + (set-fringe-mode 10) ; Give some breathing room + + (menu-bar-mode -1) ; Disable the menu bar + + ;; Set up the visible bell + (setq visible-bell t) + + (column-number-mode) + (global-display-line-numbers-mode t) + + ;; Set frame transparency + (set-frame-parameter (selected-frame) 'alpha efs/frame-transparency) + (add-to-list 'default-frame-alist `(alpha . ,efs/frame-transparency)) + (set-frame-parameter (selected-frame) 'fullscreen 'maximized) + (add-to-list 'default-frame-alist '(fullscreen . maximized)) + + ;; Disable line numbers for some modes + (dolist (mode '(org-mode-hook + term-mode-hook + shell-mode-hook + treemacs-mode-hook + eshell-mode-hook)) + (add-hook mode (lambda () (display-line-numbers-mode 0)))) + + (global-set-key (kbd "C-x l") 'load-file) + +#+end_src + + +** Font Configuration + +I am using the [[https://github.com/tonsky/FiraCode][Fira Code]] and [[https://fonts.google.com/specimen/Cantarell][Cantarell]] fonts for this configuration which will more than likely need to be installed on your machine. Both can usually be found in the various Linux distro package managers or downloaded from the links above. + +#+begin_src emacs-lisp + + (set-face-attribute 'default nil :font "Comic Code" :height efs/default-font-size) + + ;; Set the fixed pitch face + (set-face-attribute 'fixed-pitch nil :font "Comic Code" :height efs/default-font-size) + + ;; Set the variable pitch face + (set-face-attribute 'variable-pitch nil :font "Comic Code" :height efs/default-variable-font-size :weight 'regular) + +#+end_src + +* Keybinding Configuration + +This configuration uses [[https://evil.readthedocs.io/en/latest/index.html][evil-mode]] for a Vi-like modal editing experience. [[https://github.com/noctuid/general.el][general.el]] is used for easy keybinding configuration that integrates well with which-key. [[https://github.com/emacs-evil/evil-collection][evil-collection]] is used to automatically configure various Emacs modes with Vi-like keybindings for evil-mode. + +#+begin_src emacs-lisp + + ;; Make ESC quit prompts + (global-set-key (kbd "") 'keyboard-escape-quit) + + (use-package general + :after evil + :config + (general-create-definer efs/leader-keys + :keymaps '(normal insert visual emacs) + :prefix "SPC" + :global-prefix "C-SPC") + + (efs/leader-keys + "t" '(:ignore t :which-key "toggles") + "tt" '(counsel-load-theme :which-key "choose theme") + "fde" '(lambda () (interactive) (find-file (expand-file-name "~/.emacs.d/Emacs.org"))))) + + (use-package evil + :init + (setq evil-want-integration t) + (setq evil-want-keybinding nil) + (setq evil-want-C-u-scroll t) + (setq evil-want-C-i-jump nil) + :config + (evil-mode 1) + (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state) + (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join) + + ;; Use visual line motions even outside of visual-line-mode buffers + (evil-global-set-key 'motion "j" 'evil-next-visual-line) + (evil-global-set-key 'motion "k" 'evil-previous-visual-line) + + (evil-set-initial-state 'messages-buffer-mode 'normal) + (evil-set-initial-state 'dashboard-mode 'normal)) + + (use-package evil-collection + :after evil + :config + (evil-collection-init)) + +#+end_src + +* UI Configuration + +** Command Log Mode + +[[https://github.com/lewang/command-log-mode][command-log-mode]] is useful for displaying a panel showing each key binding you use in a panel on the right side of the frame. Great for live streams and screencasts! + +#+begin_src emacs-lisp + + (use-package command-log-mode + :commands command-log-mode) + +#+end_src + +** Color Theme + +[[https://github.com/hlissner/emacs-doom-themes][doom-themes]] is a great set of themes with a lot of variety and support for many different Emacs modes. Taking a look at the [[https://github.com/hlissner/emacs-doom-themes/tree/screenshots][screenshots]] might help you decide which one you like best. You can also run =M-x counsel-load-theme= to choose between them easily. + +#+begin_src emacs-lisp + +(use-package doom-themes + :init (load-theme 'doom-palenight t)) + +#+end_src + +** Better Modeline + +[[https://github.com/seagle0128/doom-modeline][doom-modeline]] is a very attractive and rich (yet still minimal) mode line configuration for Emacs. The default configuration is quite good but you can check out the [[https://github.com/seagle0128/doom-modeline#customize][configuration options]] for more things you can enable or disable. + +*NOTE:* The first time you load your configuration on a new machine, you'll need to run `M-x all-the-icons-install-fonts` so that mode line icons display correctly. + +#+begin_src emacs-lisp + +(use-package all-the-icons) + +(use-package doom-modeline + :init (doom-modeline-mode 1) + :custom ((doom-modeline-height 15))) + +#+end_src + +** Which Key + +[[https://github.com/justbur/emacs-which-key][which-key]] is a useful UI panel that appears when you start pressing any key binding in Emacs to offer you all possible completions for the prefix. For example, if you press =C-c= (hold control and press the letter =c=), a panel will appear at the bottom of the frame displaying all of the bindings under that prefix and which command they run. This is very useful for learning the possible key bindings in the mode of your current buffer. + +#+begin_src emacs-lisp + + (use-package which-key + :defer 0 + :diminish which-key-mode + :config + (which-key-mode) + (setq which-key-idle-delay 1)) + +#+end_src + +** Auto-Minor-mode + +#+begin_src emacs-lisp + + (use-package auto-minor-mode) + +#+end_src + +** Ivy and Counsel + +[[https://oremacs.com/swiper/][Ivy]] is an excellent completion framework for Emacs. It provides a minimal yet powerful selection menu that appears when you open files, switch buffers, and for many other tasks in Emacs. Counsel is a customized set of commands to replace `find-file` with `counsel-find-file`, etc which provide useful commands for each of the default completion commands. + +[[https://github.com/Yevgnen/ivy-rich][ivy-rich]] adds extra columns to a few of the Counsel commands to provide more information about each item. + +#+begin_src emacs-lisp + + (use-package ivy + :diminish + :bind (("C-s" . swiper) + :map ivy-minibuffer-map + ("TAB" . ivy-alt-done) + ("C-l" . ivy-alt-done) + ("C-j" . ivy-next-line) + ("C-k" . ivy-previous-line) + :map ivy-switch-buffer-map + ("C-k" . ivy-previous-line) + ("C-l" . ivy-done) + ("C-d" . ivy-switch-buffer-kill) + :map ivy-reverse-i-search-map + ("C-k" . ivy-previous-line) + ("C-d" . ivy-reverse-i-search-kill)) + :config + (ivy-mode 1)) + + (use-package ivy-rich + :after ivy + :init + (ivy-rich-mode 1)) + + (use-package counsel + :bind (("C-M-j" . 'counsel-switch-buffer) + :map minibuffer-local-map + ("C-r" . 'counsel-minibuffer-history)) + :custom + (counsel-linux-app-format-function #'counsel-linux-app-format-function-name-only) + :config + (counsel-mode 1)) + +#+end_src + +*** Improved Candidate Sorting with prescient.el + +prescient.el provides some helpful behavior for sorting Ivy completion candidates based on how recently or frequently you select them. This can be especially helpful when using =M-x= to run commands that you don't have bound to a key but still need to access occasionally. + +This Prescient configuration is optimized for use in System Crafters videos and streams, check out the [[https://youtu.be/T9kygXveEz0][video on prescient.el]] for more details on how to configure it! + +#+begin_src emacs-lisp + + (use-package ivy-prescient + :after counsel + :custom + (ivy-prescient-enable-filtering nil) + :config + ;; Uncomment the following line to have sorting remembered across sessions! + ;(prescient-persist-mode 1) + (ivy-prescient-mode 1)) + +#+end_src + +** Helpful Help Commands + +[[https://github.com/Wilfred/helpful][Helpful]] adds a lot of very helpful (get it?) information to Emacs' =describe-= command buffers. For example, if you use =describe-function=, you will not only get the documentation about the function, you will also see the source code of the function and where it gets used in other places in the Emacs configuration. It is very useful for figuring out how things work in Emacs. + +#+begin_src emacs-lisp + + (use-package helpful + :commands (helpful-callable helpful-variable helpful-command helpful-key) + :custom + (counsel-describe-function-function #'helpful-callable) + (counsel-describe-variable-function #'helpful-variable) + :bind + ([remap describe-function] . counsel-describe-function) + ([remap describe-command] . helpful-command) + ([remap describe-variable] . counsel-describe-variable) + ([remap describe-key] . helpful-key)) + +#+end_src + +** Text Scaling + +This is an example of using [[https://github.com/abo-abo/hydra][Hydra]] to design a transient key binding for quickly adjusting the scale of the text on screen. We define a hydra that is bound to =C-s t s= and, once activated, =j= and =k= increase and decrease the text scale. You can press any other key (or =f= specifically) to exit the transient key map. + +#+begin_src emacs-lisp + + (use-package hydra + :defer t) + + (defhydra hydra-text-scale (:timeout 4) + "scale text" + ("j" text-scale-increase "in") + ("k" text-scale-decrease "out") + ("f" nil "finished" :exit t)) + + (efs/leader-keys + "ts" '(hydra-text-scale/body :which-key "scale text")) + +#+end_src + +* FlySpell Mode + +#+begin_src emacs-lisp + (defun flyspell-on-for-buffer-type () + "Enable Flyspell appropriately for the major mode of the current buffer. Uses `flyspell-prog-mode' for modes derived from `prog-mode', so only strings and comments get checked. All other buffers get `flyspell-mode' to check all text. If flyspell is already enabled, does nothing." + (interactive) + (if (not (symbol-value flyspell-mode)) ; if not already on + (progn + (if (derived-mode-p 'prog-mode) + (progn + (message "Flyspell on (code)") + (flyspell-prog-mode)) + ;; else + (progn + (message "Flyspell on (text)") + (flyspell-mode 1))) + ;; I tried putting (flyspell-buffer) here but it didn't seem to work + ))) + + + (defun flyspell-toggle () + "Turn Flyspell on if it is off, or off if it is on. When turning on, it uses `flyspell-on-for-buffer-type' so code-vs-text is handled appropriately." + (interactive) + (if (symbol-value flyspell-mode) + (progn ; flyspell is on, turn it off + (message "Flyspell off") + (flyspell-mode -1)) + ; else - flyspell is off, turn it on + (flyspell-on-for-buffer-type))) + + + (defun fd-switch-dictionary() + (interactive) + (let* ((dic ispell-current-dictionary) + (change (if (string= dic "en_GB") "es_MX" "en_GB"))) + (ispell-change-dictionary change) + (message "Dictionary switched from %s to %s" dic change) + )) + + (global-set-key (kbd "C-c f") 'flyspell-toggle) + (add-hook 'find-file-hook 'flyspell-on-for-buffer-type) + (global-set-key (kbd "C-c c") 'fd-switch-dictionary) + +#+end_src + + +* Org Mode + +[[https://orgmode.org/][Org Mode]] is one of the hallmark features of Emacs. It is a rich document editor, project planner, task and time tracker, blogging engine, and literate coding utility all wrapped up in one package. + +** Better Font Faces + +The =efs/org-font-setup= function configures various text faces to tweak the sizes of headings and use variable width fonts in most cases so that it looks more like we're editing a document in =org-mode=. We switch back to fixed width (monospace) fonts for code blocks and tables so that they display correctly. + +#+begin_src emacs-lisp + + (defun efs/org-font-setup () + ;; Replace list hyphen with dot + (font-lock-add-keywords 'org-mode + '(("^ *\\([-]\\) " + (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•")))))) + + ;; Set faces for heading levels + (dolist (face '((org-level-1 . 1.2) + (org-level-2 . 1.1) + (org-level-3 . 1.05) + (org-level-4 . 1.0) + (org-level-5 . 1.1) + (org-level-6 . 1.1) + (org-level-7 . 1.1) + (org-level-8 . 1.1))) + (set-face-attribute (car face) nil :font "Comic Code" :weight 'regular :height (cdr face))) + + ;; Ensure that anything that should be fixed-pitch in Org files appears that way + (set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch) + (set-face-attribute 'org-table nil :inherit 'fixed-pitch) + (set-face-attribute 'org-formula nil :inherit 'fixed-pitch) + (set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch)) + (set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch)) + (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch)) + (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch)) + (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch)) + (set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch) + (set-face-attribute 'line-number nil :inherit 'fixed-pitch) + (set-face-attribute 'line-number-current-line nil :inherit 'fixed-pitch)) + +#+end_src + + +** Basic Config + +This section contains the basic configuration for =org-mode= plus the configuration for Org agendas and capture templates. There's a lot to unpack in here so I'd recommend watching the videos for [[https://youtu.be/VcgjTEa0kU4][Part 5]] and [[https://youtu.be/PNE-mgkZ6HM][Part 6]] for a full explanation. + +#+begin_src emacs-lisp + + (defun efs/org-mode-setup () + (org-indent-mode) + (variable-pitch-mode 1) + (visual-line-mode 1)) + + (use-package org + :pin org + :commands (org-capture org-agenda) + :hook (org-mode . efs/org-mode-setup) + :config + (setq org-ellipsis " ▾") + + (setq org-agenda-start-with-log-mode t) + (setq org-log-done 'time) + (setq org-log-into-drawer t) + + (setq org-agenda-files + '("~/Projects/Code/emacs-from-scratch/OrgFiles/Tasks.org" + "~/Projects/Code/emacs-from-scratch/OrgFiles/Habits.org" + "~/Projects/Code/emacs-from-scratch/OrgFiles/Birthdays.org")) + + (require 'org-habit) + (add-to-list 'org-modules 'org-habit) + (setq org-habit-graph-column 60) + + (setq org-todo-keywords + '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)") + (sequence "BACKLOG(b)" "PLAN(p)" "READY(r)" "ACTIVE(a)" "REVIEW(v)" "WAIT(w@/!)" "HOLD(h)" "|" "COMPLETED(c)" "CANC(k@)"))) + + (setq org-refile-targets + '(("Archive.org" :maxlevel . 1) + ("Tasks.org" :maxlevel . 1))) + + ;; Save Org buffers after refiling! + (advice-add 'org-refile :after 'org-save-all-org-buffers) + + (setq org-tag-alist + '((:startgroup) + ; Put mutually exclusive tags here + (:endgroup) + ("@errand" . ?E) + ("@home" . ?H) + ("@work" . ?W) + ("agenda" . ?a) + ("planning" . ?p) + ("publish" . ?P) + ("batch" . ?b) + ("note" . ?n) + ("idea" . ?i))) + + ;; Configure custom agenda views + (setq org-agenda-custom-commands + '(("d" "Dashboard" + ((agenda "" ((org-deadline-warning-days 7))) + (todo "NEXT" + ((org-agenda-overriding-header "Next Tasks"))) + (tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects"))))) + + ("n" "Next Tasks" + ((todo "NEXT" + ((org-agenda-overriding-header "Next Tasks"))))) + + ("W" "Work Tasks" tags-todo "+work-email") + + ;; Low-effort next actions + ("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0" + ((org-agenda-overriding-header "Low Effort Tasks") + (org-agenda-max-todos 20) + (org-agenda-files org-agenda-files))) + + ("w" "Workflow Status" + ((todo "WAIT" + ((org-agenda-overriding-header "Waiting on External") + (org-agenda-files org-agenda-files))) + (todo "REVIEW" + ((org-agenda-overriding-header "In Review") + (org-agenda-files org-agenda-files))) + (todo "PLAN" + ((org-agenda-overriding-header "In Planning") + (org-agenda-todo-list-sublevels nil) + (org-agenda-files org-agenda-files))) + (todo "BACKLOG" + ((org-agenda-overriding-header "Project Backlog") + (org-agenda-todo-list-sublevels nil) + (org-agenda-files org-agenda-files))) + (todo "READY" + ((org-agenda-overriding-header "Ready for Work") + (org-agenda-files org-agenda-files))) + (todo "ACTIVE" + ((org-agenda-overriding-header "Active Projects") + (org-agenda-files org-agenda-files))) + (todo "COMPLETED" + ((org-agenda-overriding-header "Completed Projects") + (org-agenda-files org-agenda-files))) + (todo "CANC" + ((org-agenda-overriding-header "Cancelled Projects") + (org-agenda-files org-agenda-files))))))) + + (setq org-capture-templates + `(("t" "Tasks / Projects") + ("tt" "Task" entry (file+olp "~/Projects/Code/emacs-from-scratch/OrgFiles/Tasks.org" "Inbox") + "* TODO %?\n %U\n %a\n %i" :empty-lines 1) + + ("j" "Journal Entries") + ("jj" "Journal" entry + (file+olp+datetree "~/Projects/Code/emacs-from-scratch/OrgFiles/Journal.org") + "\n* %<%I:%M %p> - Journal :journal:\n\n%?\n\n" + ;; ,(dw/read-file-as-string "~/Notes/Templates/Daily.org") + :clock-in :clock-resume + :empty-lines 1) + ("jm" "Meeting" entry + (file+olp+datetree "~/Projects/Code/emacs-from-scratch/OrgFiles/Journal.org") + "* %<%I:%M %p> - %a :meetings:\n\n%?\n\n" + :clock-in :clock-resume + :empty-lines 1) + + ("w" "Workflows") + ("we" "Checking Email" entry (file+olp+datetree "~/Projects/Code/emacs-from-scratch/OrgFiles/Journal.org") + "* Checking Email :email:\n\n%?" :clock-in :clock-resume :empty-lines 1) + + ("m" "Metrics Capture") + ("mw" "Weight" table-line (file+headline "~/Projects/Code/emacs-from-scratch/OrgFiles/Metrics.org" "Weight") + "| %U | %^{Weight} | %^{Notes} |" :kill-buffer t))) + + (define-key global-map (kbd "C-c j") + (lambda () (interactive) (org-capture nil "jj"))) + + (efs/org-font-setup)) + +#+end_src + + +*** Nicer Heading Bullets + +[[https://github.com/sabof/org-bullets][org-bullets]] replaces the heading stars in =org-mode= buffers with nicer looking characters that you can control. Another option for this is [[https://github.com/integral-dw/org-superstar-mode][org-superstar-mode]] which we may cover in a later video. + +#+begin_src emacs-lisp + + (use-package org-bullets + :hook (org-mode . org-bullets-mode) + :custom + (org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●"))) + +#+end_src + + +*** Center Org Buffers + +We use [[https://github.com/joostkremers/visual-fill-column][visual-fill-column]] to center =org-mode= buffers for a more pleasing writing experience as it centers the contents of the buffer horizontally to seem more like you are editing a document. This is really a matter of personal preference so you can remove the block below if you don't like the behavior. + +#+begin_src emacs-lisp + + (defun efs/org-mode-visual-fill () + (setq visual-fill-column-width 100 + visual-fill-column-center-text t) + (visual-fill-column-mode 1)) + + (use-package visual-fill-column + :hook (org-mode . efs/org-mode-visual-fill)) + +#+end_src + + +** Configure Babel Languages + +To execute or export code in =org-mode= code blocks, you'll need to set up =org-babel-load-languages= for each language you'd like to use. [[https://orgmode.org/worg/org-contrib/babel/languages.html][This page]] documents all of the languages that you can use with =org-babel=. + +#+begin_src emacs-lisp + + (with-eval-after-load 'org + (org-babel-do-load-languages + 'org-babel-load-languages + '((emacs-lisp . t) + (python . t))) + + (push '("conf-unix" . conf-unix) org-src-lang-modes)) + +#+end_src + + +** Structure Templates + +Org Mode's [[https://orgmode.org/manual/Structure-Templates.html][structure templates]] feature enables you to quickly insert code blocks into your Org files in combination with =org-tempo= by typing =<= followed by the template name like =el= or =py= and then press =TAB=. For example, to insert an empty =emacs-lisp= block below, you can type =