From Scratch to Emacs, The Adventurous Configurator’s Handbook
Emacs, the world-class, extensible, customisable, free/libre text editor, has stood the test of time and continues to be a powerful tool for both developers and writers alike. Its reputation for complexity belies its potential: it is an undiscovered country, a treasure chest filled with gold, jewels, and priceless artifacts. Embarking on a journey with Emacs is much like setting sail on the high seas of productivity, and in this guide, we aim to help you navigate these waters with ease.
This guide is a treasure map, of sorts, to help you chart your course in the vast ocean of Emacs functionalities. We will help you equip your Emacs ship with an arsenal of powerful tools and configurations to bolster your productivity, simplify your workflow, and make your voyage smoother. From the helm to the cannon, from the crow’s nest to the rigging, you’ll find that your Emacs ship will be ready for whatever storm the high seas might throw at you.
Whether you’re a seasoned Emacs sailor or a landlubber who’s only just beginning to learn the ropes, this guide is intended to help you tailor your Emacs experience to your needs and preferences. By the end of our journey together, you’ll have transformed your Emacs from a humble sailboat to a powerful, fully-equipped galleon, ready to tackle the toughest coding or writing challenges you might face.
So, hoist the Jolly Roger, set your course, and let’s set sail on the open sea of Emacs optimisation!
Chapter 1: Sailing the Seas
Packages: The Mariner’s Charts and Tools
Our maiden voyage begins by setting our charts and readying our tools. Just as a ship needs maps to navigate the high seas, so do we need the MELPA1 repository, our trove of packages to steer Emacs.
Add the following markings to your captain’s log (init.el
), to invite MELPA onboard and ensure our tools are always shiny and ready. For every new dawn we sail, our package list shall be refreshed.
require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("org" . "http://orgmode.org/elpa/")
("gnu" . "http://elpa.gnu.org/packages/")))
(
(package-initialize)
unless package-archive-contents
( (package-refresh-contents))
Evil Mode: Hoisting the Jolly Roger of Editing
Our ship now sails under the black flag of “Evil mode”2, an homage to the legendary seafarers of Vim, allowing us to navigate our text with precision and ease. Heave the following ropes into your init.el
logbook to hoist the black flag.
require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("org" . "http://orgmode.org/elpa/")
("gnu" . "http://elpa.gnu.org/packages/")))
(
(package-initialize)
unless package-archive-contents
(
(package-refresh-contents))
unless (package-installed-p 'evil)
('evil))
(package-install
require 'evil)
(1) (evil-mode
Window Size: Calibrating the Spyglass
Our ship’s porthole is our window into the vast sea of code. Currently, it’s too small, like a miser’s eyepiece. We can widen our view with the following enchantment:
require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("org" . "http://orgmode.org/elpa/")
("gnu" . "http://elpa.gnu.org/packages/")))
(
(package-initialize)
unless package-archive-contents
(
(package-refresh-contents))
unless (package-installed-p 'evil)
('evil))
(package-install
require 'evil)
(1)
(evil-mode
'default-frame-alist '(height . 40))
(add-to-list 'default-frame-alist '(width . 90)) (add-to-list
For the sake of our journey, we won’t veer too far off course, but remember, the horizon is yours to command.
Fonts: Inking the Captain’s Quill
Our final touch for this chapter of the voyage, we shall imbue the ship with a touch of elegance, by changing the ship’s lettering, the font of all frames. Here, we choose the scribe’s favorite, “Fira Code”.
require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("org" . "http://orgmode.org/elpa/")
("gnu" . "http://elpa.gnu.org/packages/")))
(
(package-initialize)
unless package-archive-contents
(
(package-refresh-contents))
unless (
(
'evil)
package-installed-p 'evil))
(package-install
require 'evil)
(1)
(evil-mode
'default-frame-alist '(height . 40))
(add-to-list 'default-frame-alist '(width . 90))
(add-to-list
"Fira Code-12" nil t) (set-frame-font
Mini-frame: The Crow’s Nest of Display
Observe your Emacs environment from a higher perspective with the mini-frame. Install it and place it at the top for an optimal viewing experience.
;; Mini-frame
unless (package-installed-p 'mini-frame)
('mini-frame))
(package-install
require 'mini-frame)
(1)
(mini-frame-mode
setq mini-frame-show-parameters
(0)
'((top . 0.7)
(width . 0.5))) (left .
Ivy: The Rigging of Completion
Ivy5 is your personal assistant for completion in Emacs. Enhance its functionalities by integrating ivy-posframe
6 which displays Ivy in a child frame. Here we’ll install both packages and configure them.
;; Ivy support
unless (package-installed-p 'ivy)
('ivy))
(package-install
unless (package-installed-p 'ivy-posframe)
('ivy-posframe))
(package-install
require 'ivy)
(1)
(ivy-mode
require 'ivy-posframe)
(setq ivy-display-function #'ivy-posframe-display-at-frame-center)
(setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-center)))
(1) (ivy-posframe-mode
Doom modeline: The Jolly Roger of Status Lines
Now we install an improved modeline, which is the Doom modeline7.
;; Doom modeline
unless (package-installed-p 'doom-modeline)
('doom-modeline))
(package-install
require 'doom-modeline)
(1) (doom-modeline-mode
Startup projects: The Voyage’s Beginnings
Always keep your projects within reach by displaying a list of recent projects every time Emacs starts. To do this, we tell it to remember your recent projects. The alien indexing method will cause Projectile to use external utilities like git to provide a speed boost. The ivy
completion system will use Ivy for project selection. A function creates a new buffer called *Projectile Projects*
, erases any existing content in it, inserts a list of the projects known to Projectile, and displays the buffer.
The new “Projectile” section will look like this:
;; Projectile
unless (package-installed-p 'projectile)
('projectile))
(package-install
require 'projectile)
(
;;; Enable Projectile and configure it to remember recent projects
(projectile-mode +1)setq projectile-switch-project-action 'projectile-dired)
(setq projectile-indexing-method 'alien)
(setq projectile-completion-system 'ivy)
(
;;; Create a function to display recent projects on startup
defun display-projectile-list-on-startup ()
(let ((buf (get-buffer-create "*Projectile Projects*")))
(
(with-current-buffer buf
(erase-buffer)dolist (project (projectile-relevant-known-projects))
("\n")))
(insert project (switch-to-buffer buf)))
The page is still quite bare-bones, but we’ll add more features as we go along.
Markdown: The Sea Chart of Formatting
Since we’re writing this page in Markdown, let’s go ahead and install a Markdown mode8. We’ll install a Markdown major mode, a TOC generation package, and a formatting package. We also need to tell Emacs to use the Markdown mode for files with the .md
extension.
;; Markdown
dolist (package '(markdown-mode markdown-toc markdownfmt))
(unless (package-installed-p package)
(package)))
(package-install
require 'markdown-mode)
('auto-mode-alist '("\\.md\\'" . markdown-mode)) (add-to-list
But … wait. The code blocks are ugly and do not have syntax highlighting. To fix this, we first enable global font lock mode, which will enable syntax highlighting for all major modes. Then we tell Emacs to use the markdown-fontify-code-blocks-natively
function to highlight code blocks. markdown-mode
should automatically use syntax highlighting for code blocks, but it depends on the major mode associated with the language used in the code block. We also have to make sure the major mode for that language is installed. For example, if you have a Python code block, you would need python-mode (actually, this also comes with Emacs).
;;; Enable font-lock globally (syntax highlighting for code blocks)
1)
(global-font-lock-mode
;; ...
setq markdown-fontify-code-blocks-natively t) (
Looks better now!
Scrolling conservatively: The Steady Course of Viewing
By default, Emacs scrolls by nearly “full screens” (the exact behavior is influenced by the scroll-step and scroll-conservatively variables).
To make Emacs scroll line by line, you can set the scroll-conservatively variable to a high value. You can add the following line to your init.el
file:
setq scroll-conservatively 101) (
The number 101
is somewhat arbitrary, it just needs to be greater than 100
. When scroll-conservatively is set to a value greater than 100
, Emacs will always keep the cursor at least that many lines from the top and bottom of the window, effectively causing it to scroll one line at a time.
Speedbar: The Swift Current of Shortcuts
One of my favourite features in Doom Emacs is the speedbar. Doom Emacs uses a package named which-key
to provide this and it is a package that displays available keybindings in a popup.
This package is very handy to discover available keybindings and to learn new ones. which-key-mode
makes it so that whenever you start a key sequence, and then wait for a short period of time, which-key
will pop up a buffer with all possible completions of the key sequence. This sequence (sometimes called the “leader key”) will be set in the config as M-SPC
.
We will also use general.el, a package that provides a more convenient way to define key bindings. The first keybindings we will define is the p
for a “projects” section and f
to find all files in a project.
;; Speed bar
dolist (package '(which-key general))
(unless (package-installed-p package)
(package)))
(package-install
require 'which-key)
(
(which-key-mode)
require 'general)
(
(general-create-definer my-leader-def
:states '(normal visual insert emacs)"M-SPC"
:prefix "M-SPC")
:non-normal-prefix
(my-leader-def"p" '(:ignore t :which-key "projects")
"pf" 'projectile-find-file)
setq which-key-idle-delay 0.5) ;; default 0.5 (
A Few Cosmetic Changes: Polishing the Captain’s Quarters
We will now do a few cosmetic changes. The theme we will use is modus-operandi
9. This theme is bundled with Emacs 27, so we don’t need to install it. We will also change the font in the Markdown code blocks to the same as the main font. Additionally, we will add syntax highlighting in Markdown mode to wikilinks.
;; Font name
defvar my-font-name "Fira Code")
(
"-12") nil t)
(set-frame-font (concat my-font-name 'fixed-pitch nil :family my-font-name :height 120)
(set-face-attribute
;;; ...
setq markdown-enable-wiki-links t)
(
;; Match Markdown font main one
'markdown-code-face nil :family my-font-name)
(set-face-attribute 'markdown-pre-face nil :family my-font-name)
(set-face-attribute
;;; ...
;; Modus operandi
'modus-operandi t) (load-theme
Buffer splitting: Dividing the Ship’s Log
Something I use quite offen is splitting the window vertically or horizontally. In addition, if I’m inside a project, I want the new window to be in the same project and show me a list of files so that I can easily open one of them. To do this, we define two functions, one for vertical splitting and one for horizontal splitting and assign to keys for the speedbar. The keys will be M-SPC b s r
(Buffers -> split -> right) and M-SPC b s t
(Buffers -> split -> top) for vertical and horizontal splitting, respectively.
;; Buffer splitting
defun split-right-and-list-project-files ()
("Split the current window into two, left and right. The left one contains the current contents and the right one contains a projectile-list of all the files in the project."
(interactive)
(split-window-right)1)
(other-window
(projectile-find-file))
defun split-below-and-list-project-files ()
("Split the current window into two, top and bottom. The top one contains the current contents and the bottom one contains a projectile-list of all the files in the project."
(interactive)
(split-window-below)1)
(other-window
(projectile-find-file))
(my-leader-def"b" '(:ignore t :which-key "Buffers")
"bs" '(:ignore t :which-key "Split")
"bsr" '(split-right-and-list-project-files :which-key "Right split")
"bst" '(split-below-and-list-project-files :which-key "Top split"))
Chapter 2: The Archipelago of Languages
Rust: The Ironclad Island
To add support for Rust we use the rustic
10 package. rustic
provides a more comprehensive environment for Rust development essentially combinating several packages (rust-mode
, cargo
, flycheck
, lsp-mode
, etc.) providing syntax highlighting, formatting, linting, running Cargo commands and so on.
We also will use rustic-lsp-server
with Rust Analyzer11 as the language server (altough RLS is also supported).
company
will be added for autocompletion and rustic-lsp-server
’s inlay type hints will be enabled.
rustic
will have auto-formatting on save enabled.
;; Rust
unless (package-installed-p 'rustic)
('rustic))
(package-install
require 'rustic)
(
;; use rust-analyzer as the LSP server
setq rustic-lsp-server 'rust-analyzer)
(
;;; Company
unless (package-installed-p 'company)
('company))
(package-install
require 'company)
(;; Enable company mode in all buffers
'after-init-hook 'global-company-mode)
(add-hook ;; Set company backends for lsp-mode
push 'company-capf company-backends)
(
;;; lsp-mode
unless (package-installed-p 'lsp-mode)
('lsp-mode))
(package-install
require 'lsp-mode)
(;; Enable lsp-mode in rustic-mode
'rustic-mode-hook #'lsp)
(add-hook ;; Use company-capf as the completion provider
'lsp-mode-hook (lambda () (set (make-local-variable 'company-backends) '(company-capf))))
(add-hook
;; Enable rustfmt on save
setq rustic-format-on-save t)
(
;; Enable inlay hints
setq lsp-rust-analyzer-display-inlay-hints t)
(setq lsp-inlay-hints-mode t) (
We will also add keybindings for common Rust/Cargo commands, such a build, run, test, format, check and clippy.
;;; Speedbar for Rust
(my-leader-def
:states '(normal visual emacs)'override
:keymaps "l" '(:ignore t :which-key "Language")
"r" '(:ignore t :which-key "Rust"))
(my-leader-def
:states '(normal visual emacs)'override
:keymaps "l r b" '(rustic-cargo-build :which-key "Build")
"l r r" '(rustic-cargo-run :which-key "Run")
"l r t" '(rustic-cargo-test :which-key "Test")
"l r f" '(rustic-cargo-fmt :which-key "Format")
"l r c" '(rustic-cargo-check :which-key "Check")
"l r p" '(rustic-cargo-clippy :which-key "Clippy"))
Python: The Serpent’s Atoll
In this section, we make Python programming in Emacs a breeze by integrating the Elpy12 package. Elpy adds a multitude of enhancements to the Python editing experience, including code navigation, automatic formatting, refactoring helpers, and more.
First, we check if Elpy is installed and install it if necessary:
unless (package-installed-p 'elpy)
('elpy))
(package-install require 'elpy) (
Next, we enable Elpy for all Python buffers and configure IPython
to be the default Python interpreter:
(elpy-enable)setq python-shell-interpreter "ipython"
("-i --simple-prompt") python-shell-interpreter-args
We also specify the Python 3 interpreter for Elpy’s RPC and enable the Python Language Server Protocol (LSP) for Python mode:
setq elpy-rpc-python-command "python3")
('python-mode-hook #'lsp-deferred)
(add-hook setq lsp-python-ms-python-executable-cmd "python3") (
Flycheck13, a modern syntax checking package, is then configured to replace Elpy’s default Flymake:
when (require 'flycheck nil t)
(setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
('elpy-mode-hook 'flycheck-mode)) (add-hook
Our scripting journey gets even more exciting as we set sail to the land of Virtual Environments. We define a function set-python-virtualenv
that automatically sets the Python virtual environment based on the Projectile project root:
defun set-python-virtualenv ()
("Set `python-shell-virtualenv-root' based on projectile's project root."
(interactive)
... )'python-mode-hook 'set-python-virtualenv) (add-hook
Lastly, we bind the treasure map (which-key) with commonly used Python commands, helping us navigate the Python seas smoothly:
(my-leader-def
:states '(normal visual emacs)'override
:keymaps "lp" '(:ignore t :which-key "Python")
"lpv" '(set-python-virtualenv :which-key "Set Virtualenv")
"lpr" '(run-python :which-key "Run Python REPL")
"lpf" '(python-format-buffer :which-key "Format buffer")
"lpd" '(elpy-goto-definition :which-key "Go to definition"))
This marks the end of our Python setup chapter. We have set up a powerful Python development environment in Emacs, complete with syntax checking, virtual environment support, and interactive Python commands, all just a few key presses away. With these tools at hand, your Python adventure in Emacs will be a sailing pleasure!
Go: The Swift Current Isle
As our adventure in this programming environment continues, we delve into the rich ecosystem of Go, bringing out its full potential in Emacs.
The story begins with the installation of the go-mode
14 package. If the package isn’t already part of the inventory (installed), our script takes the initiative to acquire it:
unless (package-installed-p 'go-mode)
('go-mode)) (package-install
Following this, we require
or load the go-mode
package to prepare Emacs for Go development:
require 'go-mode) (
The support crew, company
mode, is called upon to enhance the user experience by providing autocompletion features globally:
'after-init-hook 'global-company-mode) (add-hook
Next, Language Server Protocol (LSP) support is hooked into go-mode
to offer a plethora of language features like linting, code navigation, and much more:
'go-mode-hook #'lsp-deferred)
(add-hook setq lsp-gopls-server-path (expand-file-name "~/go/bin/gopls"))
(setq lsp-enable-snippet nil) ;; disable snippet support
(setq lsp-gopls-staticcheck t) ;; enable gopls' staticcheck linter
(setq lsp-eldoc-render-all t) ;; display documentation in minibuffer while typing (
To keep our code neat and imports organised, gofmt
(set to goimports
) is triggered before every save. Additional save hooks are also set up to automatically format the buffer and organise imports on saving a Go file:
setq gofmt-command "goimports")
('before-save-hook 'gofmt-before-save) (add-hook
(defun lsp-go-install-save-hooks ()
(add-hook 'before-save-hook #'lsp-format-buffer t t)
(add-hook 'before-save-hook #'lsp-organize-imports t t))
(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)
The adventure wouldn’t be complete without a handy map and compass. So, we set up key bindings (using which-key
) under M-SPC l g
for Go:
(my-leader-def
:states '(normal visual emacs)'override
:keymaps "lg" '(:ignore t :which-key "Go")
"lgf" '(gofmt :which-key "Format code")
"lgt" '(compile :which-key "Run test")
"lgi" '(lsp-goto-implementation :which-key "Go to implementation")
"lgd" '(lsp-find-definition :which-key "Go to definition")
"lgr" '(lsp-find-references :which-key "Find references")
"lgh" '(lsp-describe-thing-at-point :which-key "Describe thing at point"))
This setup offers a more navigable and interactive environment, enabling you to journey through your Go code like an expert adventurer, efficiently uncovering the treasures of your project.
YAML: Charting the Indentation Ocean
;; First, we ensure that the yaml-mode package is installed. If not, Emacs is instructed to download and install it.
unless (package-installed-p 'yaml-mode)
(
(package-refresh-contents)'yaml-mode)) (package-install
With the indispensable yaml-mode
installed and readied, our vessel for navigating the YAML seas, we now link it with every YAML file we encounter during our journey.
require 'yaml-mode)
('auto-mode-alist '("\\.ya?ml\\'" . yaml-mode)) (add-to-list
One of the quirks of our YAML sea is the importance of proper indentation. But worry not! We’ve equipped our ship with an auto-indenting feature. Whenever you press the enter key (C-m
), a new line is created, and the cursor is automatically positioned with the correct indentation.
'yaml-mode-hook
(add-hook lambda ()
("\C-m" 'newline-and-indent))) (define-key yaml-mode-map
Our journey in the YAML sea often involves vast and complex structures. To make our journey manageable, we employ code folding, a valuable map that allows us to hide and reveal portions of our code as needed.
'yaml-mode-hook
(add-hook lambda ()
(1))) (hs-minor-mode
As we chart our course, we also enable company-mode
to provide us with suggestions, turning our journey into a collective effort with a supportive crew.
'yaml-mode-hook 'company-mode) (add-hook
We’re not alone on these seas. To keep us from straying off course, we enlist the help of a yamllint
lookout in our crow’s nest, alerting us whenever we deviate from the ideal YAML structure. Before we embark, ensure you’ve enlisted yamllint
by installing it with pip install yamllint
.
;; Add YAML lint. Must have `pip install yamllint` installed.
'yaml-mode-hook 'flycheck-mode) (add-hook
Lastly, to aid our navigation through the layers of indentation, we make use of indent-guide
. Like a dotted line in the ocean, it illuminates our path, making the structure of our YAML document clear and visible.
unless (package-installed-p 'indent-guide)
('indent-guide))
(package-install
require '
(
indent-guide)'yaml-mode-hook 'indent-guide-mode)
(add-hook 'indent-guide-face "lightgray")
(set-face-foreground 'indent-guide-face nil)
(set-face-background setq indent-guide-char ":") (
With these tools at our disposal, our journey through the YAML seas will be a breeze, and we’ll be able to navigate the waves of indentation with ease and confidence.
Chapter 3: In the Hold: The Craftsman’s Kit
Kubernetes: Commanding the Container Fleet
Once upon a time, in the deep blue Emacs sea, there was a brave adventurer on a quest to tame the fearsome beast of Kubernetes. The tale begins with the collection of tools required for the daring voyage.
unless (package-installed-p 'kubernetes)
('kubernetes))
(package-install
require 'kubernetes)
(
'kubernetes
(with-eval-after-load unless (package-installed-p 'kubernetes-evil)
(
(package-refresh-contents)'kubernetes-evil))) (package-install
Our mariner, with the trusty map of package-installed-p
, first ensured the company of the mighty warrior, kubernetes
. When found missing, package-install
was invoked to summon the warrior. The brave kubernetes
16 was then made to pledge allegiance to the mariner. A similar course of action was taken with the wily mercenary, kubernetes-evil
, ensuring a formidable party for the adventure ahead.
setq kubernetes-parent-directories '("k8s" "manifests" "config")) (
With the team assembled, the mariner set out on the mighty vessel, seeking out the treacherous terrains named k8s, manifests, and config. The name of these lands was encrypted in a secret scroll labeled kubernetes-parent-directories
.
;; Function to check if a parent directory exists
defun kubernetes-enable-mode-if-parent-directory-exists ()
(let ((parent-dir (file-name-nondirectory (directory-file-name (file-name-directory buffer-file-name)))))
(when (member parent-dir kubernetes-parent-directories)
(
(kubernetes-mode))))
;; Add a hook to enable kubernetes-mode based on parent directory
'yaml-mode-hook 'kubernetes-enable-mode-if-parent-directory-exists) (add-hook
With a clever device - a hook paired with a function, our mariner ensured that upon sailing through the stormy YAML sea, the presence of one of the desired lands triggered the transformation of the ship, morphing it into a kubernetes-mode
leviathan, ready to face any storm.
setq kubernetes-namespace "default") (
As they ventured forth, the mariner christened their current realm as the default
namespace - their home in the chaotic sea, their sanctuary amidst the turmoil.
;; Function to deploy the current buffer in Kubernetes
defun kubernetes-deploy-buffer ()
("Deploy the currently opened buffer using kubectl apply -f."
(interactive)let ((file (buffer-file-name)))
(if (not (and file (file-exists-p file)))
("Buffer is not visiting a file.")
(message "kubectl apply -f " file))))) (async-shell-command (concat
Armed with a magical charm, the kubernetes-deploy-buffer
, the mariner could summon their mighty forces into action at will. A mere invocation was enough to deploy the fleet on the battlefield.
;; Function to list Kubernetes namespaces and switch to selected namespace
defun kubernetes-switch-namespace ()
("List available namespaces and switch to selected namespace."
(interactive)let ((output-buffer (get-buffer-create "*kubernetes-namespace*")))
(
(with-current-buffer output-buffer
(erase-buffer)"kubectl" nil t nil "get" "namespaces"))
(call-process let ((namespace (completing-read "Switch to namespace: "
("\n" t))))
(split-string (with-current-buffer output-buffer (buffer-string)) unless (string-empty-p namespace)
("kubectl config set-context --current --namespace=" namespace))
(async-shell-command (concat "Switched to namespace: %s" namespace))))) (message
The mariner also possessed the mystical power to switch their ship to any other namespace with the spell, kubernetes-switch-namespace
. This allowed them to nimbly navigate through the whirlpools of the Kube-sea.
(my-leader-def
:states '(normal visual emacs)'override
:keymaps "k" '(:ignore t :which-key "Kubernetes")
"kf" '(kubernetes-forward-resource :which-key "Forward resource")
"kb" '(kubernetes-backward-resource :which-key "Backward resource")
"kcr" '(kubernetes-create-resource :which-key "Create resource")
"kdel" '(kubernetes-delete-resource :which-key "Delete resource")
"ked" '(kubernetes-describe-resource :which-key "Describe resource")
"kex" '(kubernetes-exec-popup :which-key "Execute command in resource")
"kl" '(kubernetes-logs-popup :which-key "View resource logs")
"kp" '(kubernetes-pods :which-key "List pods")
"ks" '(kubernetes-set-namespace :which-key "Set namespace")
"kd" '(kubernetes-deploy-buffer :which-key "Deploy buffer")
"kn" '(kubernetes-switch-namespace :which-key "Switch namespace")
"ko" '(kubernetes-overview :which-key "Kubernetes overview"))
Lastly, a grand tapestry was woven, a guide to the whole adventure. Each spell, each charm, and each command were carefully etched onto this map, creating a comprehensive guide for our brave mariner.
This tale, fellow Emacs sailor, is one of thrill, exploration, and conquest, sailing the tumultuous Kubernetes sea. With tools and treasures abound, we traverse these waters, ready for what lies ahead. May your Emacs voyage be as fruitful and your adventures as exciting as our brave mariner’s journey.
Containers: The Legend of the Layered Vessel
Ahoy there, brave Emacs sailor! Let’s prepare for our new adventure in the stormy Docker seas, in search of legendary Containers, each akin to a floating island, ripe with opportunities and treasures!
unless (package-installed-p 'docker)
('docker))
(package-install
require 'docker)
('docker-mode-hook (lambda () (docker-container-ls))) (add-hook
The journey begins in our homeland, ensuring that the courageous Docker is aboard, ready to guide us through treacherous tides. With the trusty docker-mode-hook
, our ship is ever-ready to unfurl its sails, revealing a tableau of Docker containers, awaiting exploration.
defun docker-container-prompt (prompt)
("Prompt for a Docker container name."
(completing-read prompt (docker-container-names)))
defun docker-container-names ()
("Retrieve a list of Docker container names."
"docker ps -a --format '{{.Names}}'") "\n" t)) (split-string (shell-command-to-string
Our mariner conjured the spell docker-container-prompt
that whispered the names of all Docker containers, calling upon them like sirens of the sea. An even more potent spell docker-container-names
was forged to summon the entire list of container names, each echoing like a chant from the deep Docker sea.
defun docker-kill-prompt ()
("Prompt and kill a Docker container."
(interactive)let ((container-name (docker-container-prompt "Kill container:")))
(
(docker-container-kill container-name)))
defun docker-restart-prompt ()
("Prompt and restart a Docker container."
(interactive)let ((container-name (docker-container-prompt "Restart container:")))
(
(docker-container-restart container-name)))
defun docker-start-prompt ()
("Prompt and start a Docker container."
(interactive)let ((container-name (docker-container-prompt "Start container:")))
(
(docker-container-start container-name)))
defun docker-stop-prompt ()
("Prompt and stop a Docker container."
(interactive)let ((container-name (docker-container-prompt "Stop container:")))
(
(docker-container-stop container-name)))
defun docker-tag-prompt ()
("Prompt and tag a Docker container."
(interactive)let ((container-name (docker-container-prompt "Tag container:")))
( (docker-container-tag container-name)))
The mariner’s toolkit contained many powerful charms, each more wondrous than the last. One could subdue an unruly container, the docker-kill-prompt
. Another breathed life into a dormant one, the docker-start-prompt
. If a container became sluggish, docker-restart-prompt
was used to rejuvenate it, while docker-stop-prompt
could coax an overly active one into submission. Lastly, the docker-tag-prompt
was used to mark the containers with unique insignia, aiding the mariner in their journeys.
(my-leader-def
:states '(normal visual emacs)'override
:keymaps "c" '(:ignore t :which-key "Containers")
"ci" '(docker-images :which-key "Images (New Buffer)")
"cl" '(docker-logs :which-key "Logs (New Buffer)")
"cn" '(docker-network :which-key "Network (New Buffer)")
"cp" '(docker-ps :which-key "PS (New Buffer)")
"ck" '(docker-kill-prompt :which-key "Kill (Prompt)")
"cr" '(docker-restart-prompt :which-key "Restart (Prompt)")
"cs" '(docker-start-prompt :which-key "Start (Prompt)")
"cS" '(docker-stop-prompt :which-key "Stop (Prompt)")
"ct" '(docker-tag-prompt :which-key "Tag (Prompt)")
"ca" '(docker-attach :which-key "Attach")
"cb" '(docker-build-buffer :which-key "Build Buffer")
"cc" '(docker-compose :which-key "Compose")
"ce" '(docker-exec :which-key "Exec"))
Then a grand guide was etched onto a gleaming shell, the ‘my-leader-def’. This was a guide to navigate the Docker sea with ease, with each container under the mariner’s command. Be it the birth of new containers or their demise, the mariner stood at the helm, orchestrating their symphony.
Such is our tale, dear sailor, of an epic adventure in the Docker sea. Now, it’s time for you to write your own legend in the annals of the Emacs sea.
Chapter 4. Taming the Kraken: An Adventure in Org-Mode
Anchors Aweigh: Setting Up Org-Mode
Arrr, step aboard the mighty vessel of knowledge, the S.S. Org-Mode! This be not your regular ship, it be a floating archive of ye thoughts, a library of knowledge, a ship to navigate the vast ocean of ideas. Let’s hoist the sails!
unless (package-installed-p 'org)
('org)) (package-install
We’re stocking up on our provisions, ye see. Without the trusty Org17, we’d be set adrift. Be it organising your thoughts like stowing cargo or keeping a captain’s log, it be essential.
defvar my-org-root-directory "~/notes/org/"
("Root directory for Org mode files.")
setq org-directory my-org-root-directory) (
In the heart of our ship, a chest - the root directory. A grand treasure map of sorts, guiding us to all our Org files.
defun my-org-open-index-file ()
("Open the index file for Org mode."
(interactive)"index.org" my-org-root-directory))) (find-file (expand-file-name
Ahoy, the captain’s log! A simple incantation to unfurl it, my-org-open-index-file
, and it’s open for us to pen our thoughts, musings, and tales.
1.5) variable-pitch)
(setq-local face-remapping-alist '((default (:height 4.0) variable-pitch)
(header-line (:height 1.75) org-document-title)
(org-document-title (:height 1.55) org-code)
(org-code (:height 1.55) org-verbatim)
(org-verbatim (:height 1.25) org-block)
(org-block (:height 0.7) org-block))) (org-block-begin-line (:height
The captain likes his scrolls a particular way, see. A custom array, face-remapping-alist
, sets the parchment just right, tuning the height of different parts like adjusting the tension in the rigging of a ship.
unless (package-installed-p 'org-modern)
('org-modern))
(package-install
'org-mode-hook #'org-modern-mode) (add-hook
Nothing like a bit of modern charm on the old Org-Mode. With ‘org-modern’, our ship stays seaworthy and trendy.
'org-mode-hook (lambda () (org-indent-mode))) (add-hook
The captain insists on keeping the ship’s log neat and tidy. Indentation be the order of the day!
setq
(;; Edit settings
nil
org-auto-align-tags 0
org-tags-column 'show-and-error
org-catch-invisible-edits t
org-special-ctrl-a/e t
org-insert-heading-respect-content ;; Org styling, hide markup etc.
t
org-hide-emphasis-markers t
org-pretty-entities "…"
org-ellipsis
;; Agenda styling
0
org-agenda-tags-column
org-agenda-block-separator ?─
org-agenda-time-grid
'((daily today require-timed)800 1000 1200 1400 1600 1800 2000)
(" ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")
org-agenda-current-time-string"⭠ now ─────────────────────────────────────────────────")
A flurry of captain’s orders followed, fine-tuning the look and feel of our ship’s logs - the visibility of emphasis markers, the style of ellipses, and more.
setq org-modern-indent t)
(
(custom-set-facest (:inherit outline-1 :height 1.5)))))
'(org-document-title ((
(custom-set-facest (:inherit outline-1 :height 1.1)))))
'(org-level-1 ((
setq org-todo-keywords
(sequence "TODO" "LATER" "|" "DONE"))) '((
More customization followed, the captain being a detail-oriented fellow. Everything, from the inheritance of the document title to the task keywords, had to be shipshape.
(global-org-modern-mode)
The whole ship was adorned with the ‘org-modern’ charm, setting the tone for our long voyage.
setq org-default-notes-file (expand-file-name "inbox.org" my-org-root-directory))
(setq org-capture-templates
("c" "Capture" entry (file+headline org-default-notes-file "LATER")
`(("* LATER %?\n\n %i\n\n %a")))
The captain had an ingenious system for capturing fleeting ideas. Into the ‘inbox.org’ they went, to be sorted and dealt with later.
(my-leader-def
:states '(normal visual emacs)'override
:keymaps "o" '(:ignore t :which-key "Org Mode")
"oi" '(my-org-open-index-file :which-key "Open Index File")
"oc" '(org-capture :which-key "Capture"))
Lastly, the captain etched onto his map - the leader definition. It contained the quickest routes to key tasks: opening the index file and capturing thoughts. One could sail the sea of ideas with ease.
So, fellow sailor, that be our tale. The ship be prepared, the sails set. The vast sea of thoughts, ideas, and knowledge awaits us!
Footnotes
https://melpa.org/↩︎
https://github.com/emacs-evil/evil↩︎
https://github.com/bbatsov/projectile↩︎
https://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html↩︎
https://github.com/abo-abo/swiper↩︎
https://github.com/tumashu/ivy-posframe↩︎
https://github.com/seagle0128/doom-modeline↩︎
https://github.com/jrblevin/markdown-mode↩︎
https://protesilaos.com/emacs/modus-themes↩︎
https://github.com/brotzeit/rustic↩︎
https://rust-analyzer.github.io/↩︎
https://github.com/jorgenschaefer/elpy↩︎
https://www.flycheck.org/en/latest/↩︎
https://github.com/dominikh/go-mode.el↩︎
https://magit.vc/↩︎
https://github.com/kubernetes-el/kubernetes-el↩︎
https://orgmode.org/↩︎