Starmacs is yet another set of defaults for emacs, with one (and only one) purpose: it attempts to get out of your way, and add as little magic as possible.
Starmacs is not a full distribution, like Doom or Spacemacs, but is more akin to Prelude, although much more amateur.
Starmacs’s config lives in a single file: README.org
.
This is entirely in an effort to make things easier to grok for new users.
This way, there is only one file to be perused, and users need not be bothered to learn how packages work.
The use of an org file rather than an elisp file is to improve discoverability. Users can simply expand and collapse sections to painlessly explore the configuration.
Starmacs intends to be a set of sane defaults for emacs, and nothing more. As such, dependency on packages is minimized as much as is practical.
Ideally, Starmacs is mostly an aesthetic overhaul, with the only major functional changes being the inclusion of magit and eglot.
This is intended to allow a new emacs user to learn emacs (and not a custom layer sitting on it) without sacrificing the kinds of features present in their old editor. LSP is only becoming more relevant, and magit is the only thing close to the kind of git-integration that is becoming expected in the modern world of editors.
Settings for some languages have been pre-configured (primarily Go and Julia) this is unabashedly because they are languages I use often, and Starmacs is developed primarily for my own use.
Starmacs is not necessarily for everyone; you may prefer one of the following:
The magit
package installed by Starmacs expects you to have sqlite
installed on your system.
Installation will vary based on your system, but it is generally available as a package for most package managers.
Simply clone this repository into your ~/.emacs.d
directory.
The next time you start emacs, it will automatically install all of the packages and set up the configuration.
As is mentioned later in this document, any custom configuration should be added to the ~/usr
directory.
This prevents the need to merge changes when the repository is updated.
Feel free to update this file directly if you wish, but be aware that pulling updates will become a headache.
Alternately, after cloning this repository, you can simply delete the .git
directory and start a new repository.
That way, Starmacs can simply serve as a starting point for your own configuration, rather than a living distribution.
Either way is fine, and the choice is yours!
When you first start up Starmacs, there will be a prompt to build the sqlite-api
.
After entering ‘yes’, the installation will proceed as normal.
When files on disk change, open buffers should be automatically updated to reflect those changes.
(global-auto-revert-mode t)
Don’t create backup~
or #autosave#
files.
(setq make-backup-files nil)
(setq auto-save-default nil)
(use-package exec-path-from-shell
:config
(exec-path-from-shell-initialize))
When text is highlighted, typing should delete the highlighted text and insert what is typed.
(delete-selection-mode 1)
If Emacs is run in the terminal, the mouse should continue to work.
(xterm-mouse-mode 1)
Trailing whitespace should be highlighted, and deleted on save. In addition, tabs and newlines should be displayed in a subtle way, allowing for users to more easily check the formatting used.
(add-hook 'prog-mode-hook (lambda () (setq show-trailing-whitespace t)))
(add-hook 'before-save-hook 'delete-trailing-whitespace)
(setq-default tab-width 4)
(setq whitespace-style (quote (face tabs newline tab-mark newline-mark)))
(setq whitespace-display-mappings
'((newline-mark 10 [172 10])
(tab-mark 9 [187 9] [92 9])))
(global-whitespace-mode 't)
(custom-set-faces
'(whitespace-tab((t (:foreground "#525252"))))
'(whitespace-newline((t (:foreground "#525252")))))
Autothemer is a requirement for anisochromatic-theme
, and must be loaded in first.
(use-package autothemer
:ensure t)
Anisochromatic is a theme created by Isomatter::Labs (the creators of Starmacs), and is a color theme meant to be both pleasing to the eye, a little retro, and comfortable.
It also intentionally uses the same (or very similar) color assignments as the default Github color theme. This is done to reduce mental friction when alternating between one’s editor and code in the browser.
While the color attributions are intentionally copied, the colors themselves are original, and were carefully chosen to create a pleasing palette.
A notable exception to the color attirbutions are strings, which Github lumps with other constants as blue, but which most color schemes tend to assign green. In order to assure the least friction reasonable, Anisochromatic opted for teal.
(use-package anisochromatic-theme
:straight (:host github :repo "isomatter-labs/anisochromatic-emacs" :files ("dist" "*.el"))
:ensure t
:config
(load-theme 'anisochromatic t))
While most Emacs users prefer to use org-mode
for rich text documents
(such as this one), one will nevertheless encounter Markdown frequently,
so Markdown should also be rendered nicely.
(use-package markdown-mode
:ensure t
:mode ("README\\.md\\'" . gfm-mode)
:init (setq markdown-command "multimarkdown"))
base-line is an Emacs modeline maintained by Isomatter::Labs that is heavily based on mood-line by Jessie Hildebrandt.
(use-package base-line
:straight (:host github :repo "isomatter-labs/base-line" :files ("dist" "*.el"))
:ensure t
:hook (after-init . base-line-mode))
(defun starmacs/set-modeline-box-bg (face new-bg)
(set-face-attribute face nil
:background new-bg
:box `(:line-width 8 :color ,new-bg)
:overline nil
:underline nil))
(defun starmacs/fix-modeline ()
(interactive)
(starmacs/set-modeline-box-bg 'mode-line-active (face-background 'mode-line-active))
(starmacs/set-modeline-box-bg 'mode-line (face-background 'mode-line))
(starmacs/set-modeline-box-bg 'mode-line-inactive (face-background 'mode-line-inactive)))
(starmacs/fix-modeline)
(setq inhibit-startup-message t)
(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
(toggle-frame-maximized) ; Always start maximized
Instead of ringing an obnoxious bell, simply flash the modeline.
(setq visible-bell t)
(setq ring-bell-function
(lambda ()
(let ((orig-bg (face-background 'mode-line-active)))
(set-face-background 'mode-line-active "#ef8e49")
(starmacs/set-modeline-box-bg 'mode-line-active "#ef8e49")
(run-with-idle-timer 0.1 nil
(lambda (bg) (progn (set-face-background 'mode-line-active bg)
(starmacs/set-modeline-box-bg 'mode-line-active bg)))
orig-bg))))
Display line numbers everywhere, except for things like terminals, where it doesn’t make much sense.
(column-number-mode)
(global-display-line-numbers-mode t)
;; Disable line numbers for some modes
(dolist (mode '(org-mode-hook
term-mode-hook
shell-mode-hook
eshell-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))
Set up pixel-scrolling for a nice, modern-feeling experience
(pixel-scroll-precision-mode 1)
Default the cursor to a blinking bar, which is more familiar than the default box.
(setq-default cursor-type '(bar . 2))
By default, do not wrap lines around the window, but instead truncate them at the edge.
Use diamonds to indicate when these truncations happen, rather than the default right-arrows.
(set-default 'truncate-lines t)
(define-fringe-bitmap 'right-arrow
[#b00000000
#b00011000
#b00111100
#b01111110
#b01111110
#b00111100
#b00011000
#b00000000])
(define-fringe-bitmap 'left-arrow
[#b00000000
#b00011000
#b00111100
#b01111110
#b01111110
#b00111100
#b00011000
#b00000000])
Highlight the line the cursor is currently on, to make it easier to quickly locate the cursor.
(if (window-system)
(global-hl-line-mode 1))
Highlight the words “TODO” and “FIXME” in comments, allowing them to be more easily found.
(use-package hl-todo
:ensure t
:config
(global-hl-todo-mode 1))
Present users with a friendly and fun welcome screen on initial startup.
(defun no-linum ()
(display-line-numbers-mode -1))
(defun starmacs/welcome ()
(interactive)
"Show minimal *welcome* buffer"
(delete-other-windows)
(with-current-buffer (get-buffer-create "*Welcome*")
(setq truncate-lines t)
(no-linum)
(let* ((buffer-read-only)
(image-path "~/.emacs.d/img/emacs.png")
(image (create-image image-path))
(size (image-size image))
(height (cdr size))
(width (car size))
(top-margin (floor (/ (- (window-height) height 3) 2)))
(left-margin (floor (/ (- (window-width) width) 2)))
(title "A hackable text editor for the 21st Century!"))
(erase-buffer)
(setq mode-line-format nil)
(goto-char (point-min))
(insert (make-string top-margin ?\n ))
(insert (make-string left-margin ?\ ))
(insert-image image)
(insert "\n\n\n")
(insert (make-string (floor (/ (- (window-width) (string-width title)) 2)) ?\ ))
(insert title))
(setq cursor-type nil)
(read-only-mode +1)
(switch-to-buffer (current-buffer))
(local-set-key (kbd "q") 'kill-this-buffer)))
(when (< (length command-line-args) 2)
(add-hook 'emacs-startup-hook (lambda ()
(when (display-graphic-p)
(starmacs/welcome)))))
Color parentheses based on their nesting, so allow quick and easy matching, as well as keeping track of the current scope
(use-package rainbow-delimiters
:ensure t
:hook
(prog-mode . rainbow-delimiters-mode)
(org-mode . rainbow-delimiters-mode))
Starmacs comes with a set of default fonts, which are are listed and attributed below:
- Iosevka: A monospaced font with a distinct look, and a wide range of weights.
- Mona Sans: A strong and versitile typeface inspired by industrial-era grotesques made by GitHub.
- Hubot-Sans: The typeface is designed with more geometric accents to lend a technical and idiosyncratic feel—perfect for headers and pull-quotes. Also made by GitHub.
All three licenses are distributed under the SIL Open Font License, and are available for free.
If you have fonts that you prefer, the easiest way to override these defaults is to duplicate this config (with your preferred fonts) inside the /usr
directory.
Ensure that the fonts packaged with Starmacs are installed correctly. Currently, this assumes that the user is using macOS.
This will be later expanded to support all *nix, and perhaps Windows.
(defun install-default-fonts ()
(when (window-system)
(progn
(message "Installing Default Fonts")
(shell-command (expand-file-name "install-fonts.sh"))
(message "Installed Default Fonts"))))
(defvar starmacs/fixed-pitch-height 150)
(defvar starmacs/variable-pitch-height 130)
(setq-default line-spacing 0.2)
(if (not (and (member "Iosevka" (font-family-list))(member "Hubot-Sans" (font-family-list)) (member "Mona Sans" (font-family-list))))
(install-default-fonts))
(defvar starmacs/variable-pitch-font "Mona Sans")
(defvar starmacs/title-font "Hubot-Sans")
(defvar starmacs/fixed-pitch-font "Iosevka")
(set-face-attribute 'default nil :font starmacs/fixed-pitch-font :height starmacs/fixed-pitch-height)
(set-face-attribute 'fixed-pitch nil :font starmacs/fixed-pitch-font :height starmacs/fixed-pitch-height)
(set-face-attribute 'variable-pitch nil :font starmacs/variable-pitch-font :height starmacs/variable-pitch-height)
(set-face-attribute 'mode-line nil
:font starmacs/fixed-pitch-font)
Allow the use of ligatures in code, prettying up the noisy symbol-salad that most programming languages consist of.
(use-package ligature
:config
;; Enable the "www" ligature in every possible major mode
(ligature-set-ligatures 't '("www"))
;; Enable traditional ligature support in eww-mode, if the
;; `variable-pitch' face supports it
(ligature-set-ligatures 'eww-mode '("ff" "fi" "ffi"))
(ligature-set-ligatures 'prog-mode '("|||>" "<|||" "<==>" "<!--" "####" "~~>" "***" "||=" "||>"
":::" "::=" "=:=" "===" "==>" "=!=" "=>>" "=<<" "=/=" "!=="
"!!." ">=>" ">>=" ">>>" ">>-" ">->" "->>" "-->" "---" "-<<"
"<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->"
"<--" "<-<" "<<=" "<<-" "<<<" "<+>" "</>" "###" "#_(" "..<"
"..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~="
"~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|"
"[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:"
">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:"
"<$" "<=" "<>" "<-" "<<" "<+" "</" "#{" "#[" "#:" "#=" "#!"
"##" "#(" "#?" "#_" "%%" ".=" ".-" ".." ".?" "+>" "++" "?:"
"?=" "?." "??" ";;" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)"
"\\\\" "://" "<-"))
;; Enables ligature checks globally in all buffers. You can also do it
;; per mode with `ligature-mode'.
(global-ligature-mode t))
This mode allows any SQL queries embedded in strings to be evaluated as if they
were in a dedicated SQL buffer. All that is required is to add comments at the
beginning and end of the query of the form --SQL
and --SQL-END
, and all of the
text between them will be treated as a SQL query.
(add-to-list 'auto-mode-alist '("\\.sqli\\'" . sql-mode))
(use-package mmm-mode
:ensure t
:custom
(mmm-global-mode 'maybe)
:config
(set-face-background 'mmm-default-submode-face nil)
(mmm-add-classes
'((embedded-sql
:submode sql-mode
:face mmm-code-submode-face
:front "\\(--SQL\\)"
:back "\\(--SQL-END\\)")))
(mmm-add-mode-ext-class 'prog-mode nil 'embedded-sql))
This binds both <f5>
and Cmd-R to a function that will reload the current
buffer from it’s file. This comes in handy more often than would be thought,
for example when forcing LSP to re-evaluate a buffer.
(defun revert-buffer-no-confirm ()
"Revert the current buffer without asking permission"
(interactive)
(revert-buffer :ignore-auto :noconfirm))
(global-set-key (kbd "<f5>") 'revert-buffer-no-confirm)
(global-set-key (kbd "s-r") 'revert-buffer-no-confirm)
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.
(use-package which-key
:ensure t
:init (which-key-mode)
:diminish which-key-mode
:config
(setq which-key-idle-delay 1))
When more than two windows are visible in the frame,
C-x o
will add a red number to each pane, allowing the user to select which
pane they mean to move to.
This prevents the endless pane-cycling many users are familiar with.
(use-package ace-window
:ensure t
:config
(global-set-key (kbd "C-x o") 'ace-window))
Although Emacs has built-in SQLite support since Emacs 29.1, it is manually installed here to prevent annoying warnings.
(use-package sqlite3
:ensure t)
Meow keybindings are a set of Emacs keybindings popularized by meow
.
Meow aims to improve Emacs usability by reducing the need to use modifier keys
(such as control and shift) when executing Emacs commands. Instead, meow uses
single letter keys mapped to command sequences, similar to Vim’s modal editing.
For example, users can scroll up by pressing j
or execute a buffer save by
pressing s
. Meow also provides a range of movement commands, allowing users
to jump to specific lines or characters in the buffer quickly. Meow keybindings
can simplify Emacs usage for users who prefer a more modal interface.
(defun meow-setup ()
(setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty)
(meow-motion-overwrite-define-key
'("j" . meow-next)
'("k" . meow-prev)
'("<escape>" . ignore))
(meow-leader-define-key
;; SPC j/k will run the original command in MOTION state.
'("j" . "H-j")
'("k" . "H-k")
;; Use SPC (0-9) for digit arguments.
'("1" . meow-digit-argument)
'("2" . meow-digit-argument)
'("3" . meow-digit-argument)
'("4" . meow-digit-argument)
'("5" . meow-digit-argument)
'("6" . meow-digit-argument)
'("7" . meow-digit-argument)
'("8" . meow-digit-argument)
'("9" . meow-digit-argument)
'("0" . meow-digit-argument)
'("/" . meow-keypad-describe-key)
'("?" . meow-cheatsheet))
(meow-normal-define-key
'("0" . meow-expand-0)
'("9" . meow-expand-9)
'("8" . meow-expand-8)
'("7" . meow-expand-7)
'("6" . meow-expand-6)
'("5" . meow-expand-5)
'("4" . meow-expand-4)
'("3" . meow-expand-3)
'("2" . meow-expand-2)
'("1" . meow-expand-1)
'("-" . negative-argument)
'(";" . meow-reverse)
'("," . meow-inner-of-thing)
'("." . meow-bounds-of-thing)
'("[" . meow-beginning-of-thing)
'("]" . meow-end-of-thing)
'("a" . meow-append)
'("A" . meow-open-below)
'("b" . meow-back-word)
'("B" . meow-back-symbol)
'("c" . meow-change)
'("d" . meow-delete)
'("D" . meow-backward-delete)
'("e" . meow-next-word)
'("E" . meow-next-symbol)
'("f" . meow-find)
'("g" . meow-cancel-selection)
'("G" . meow-grab)
'("h" . meow-left)
'("H" . meow-left-expand)
'("i" . meow-insert)
'("I" . meow-open-above)
'("j" . meow-next)
'("J" . meow-next-expand)
'("k" . meow-prev)
'("K" . meow-prev-expand)
'("l" . meow-right)
'("L" . meow-right-expand)
'("m" . meow-join)
'("n" . meow-search)
'("o" . meow-block)
'("O" . meow-to-block)
'("p" . meow-yank)
'("q" . meow-quit)
'("Q" . meow-goto-line)
'("r" . meow-replace)
'("R" . meow-swap-grab)
'("s" . meow-kill)
'("t" . meow-till)
'("u" . meow-undo)
'("U" . meow-undo-in-selection)
'("v" . meow-visit)
'("w" . meow-mark-word)
'("W" . meow-mark-symbol)
'("x" . meow-line)
'("X" . meow-goto-line)
'("y" . meow-save)
'("Y" . meow-sync-grab)
'("z" . meow-pop-selection)
'("'" . repeat)
'("<escape>" . ignore)))
Starmacs assumes that you do not want to use the meow keybindings.
If you would like to enable meow,
simply bind the variable *starmacs/enable-meow*
to t
.
(use-package meow
:ensure t
:config
(when (and (boundp '*starmacs/enable-meow*)
*starmacs/enable-meow*)
(meow-setup)
(meow-global-mode)))
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.
(use-package org
:demand t
:straight t
:hook
(org-mode . visual-line-mode)
(org-mode . variable-pitch-mode)
(org-mode . (lambda () (indent-tabs-mode -1)))
(org-mode . (lambda () (set-face-attribute 'org-block nil :foreground nil :font starmacs/fixed-pitch-font :height 120 :inherit 'fixed-pitch)))
:custom
(org-startup-with-inline-images t)
(org-hide-emphasis-markers t)
(org-pretty-entities t)
:config
(dolist (face '((org-level-1 . 1.30)
(org-level-2 . 1.20)
(org-level-3 . 1.10)
(org-level-4 . 1.05)
(org-level-5 . 1.05)
(org-level-6 . 1.05)
(org-level-7 . 1.05)
(org-level-8 . 1.05)))
(set-face-attribute (car face) nil :font starmacs/title-font :weight 'thin :height (cdr face)))
(set-face-attribute 'org-document-title nil :font starmacs/title-font :height 1.50 :weight 'regular)
(set-face-attribute 'org-document-info nil :font starmacs/title-font :inherit '(shadow) :height 1.20 :weight 'thin)
(set-face-attribute 'org-block nil :foreground nil :font starmacs/fixed-pitch-font :height 120 :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :font starmacs/fixed-pitch-font :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-table nil :font starmacs/fixed-pitch-font :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :font starmacs/fixed-pitch-font :inherit '(shadow fixed-pitch)))
Org-roam is an Emacs package that enables users to create a network of linked notes and documents in plain text, providing a powerful tool for organizing knowledge and personal information management. With org-roam, users can easily create, link, and navigate between notes, making it ideal for researchers, writers, and anyone looking for a simple and effective way to manage their digital life. Whether you’re looking to organize your thoughts, plan a project, or keep track of your research, org-roam makes it easy to stay organized and focused. With its intuitive interface and robust features, org-roam is a must-have tool for anyone looking to streamline their workflow and simplify their digital life.
(use-package org-roam
:ensure t
:init
(setq org-roam-v2-ack t)
:custom
(org-roam-directory "~/Zettelkasten")
(org-roam-completion-everywhere t)
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
:map org-mode-map
("C-M-i" . completion-at-point))
:config
(require 'org-fold) ; Required to ensure the library loads for reasons I cannot yet fathom
(org-roam-setup))
project.el
is an Emacs library that provides a unified way to manage and
navigate projects in an efficient manner.
It allows users to define and work on groups of files as projects, providing
navigation commands to move between project-related files, search for files in
the project, and perform batch operations such as renaming or deleting files.
project.el
also integrates with version control systems, automatically
detecting and associating projects with their respective repositories.
Overall, project.el simplifies project navigation and organization, improving
productivity for Emacs users who work with multiple projects.
project.el
has been built-in to Emacs 29+.
(use-package project
:ensure t)
Vertico, Consult, Orderless, and Helpful are four packages for Emacs that are designed to enhance the user’s experience and productivity. Vertico is a flexible completion system that allows users to quickly navigate and select from a list of options. Consult provides a powerful search tool that makes it easy to find files, buffers, and other resources within Emacs. Orderless is a customizable matching system that allows users to search for text using a variety of patterns and options. Finally, Helpful is a documentation viewer that provides contextual help and advice on Emacs commands and functions.
(use-package vertico
:ensure t
:bind (:map vertico-map
("C-j" . vertico-next)
("C-k" . vertico-previous)
("C-f" . vertico-exit)
:map minibuffer-local-map
("M-h" . backward-kill-word))
:custom
(vertico-cycle t)
:init
(vertico-mode))
(use-package savehist
:init
(savehist-mode))
(use-package marginalia
:after vertico
:ensure t
:custom
(marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
:init
(marginalia-mode))
;; Example configuration for Consult
(use-package consult
;; Replace bindings. Lazily loaded due by `use-package'.
:bind (;; C-c bindings (mode-specific-map)
("C-s" . consult-line)
("C-c h" . consult-history)
("C-c m" . consult-mode-command)
("C-c k" . consult-kmacro)
;; C-x bindings (ctl-x-map)
("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command
("C-x b" . consult-buffer) ;; orig. switch-to-buffer
("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer
;; Custom M-# bindings for fast register access
("M-#" . consult-register-load)
("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated)
("C-M-#" . consult-register)
;; Other custom bindings
("M-y" . consult-yank-pop) ;; orig. yank-pop
;; M-g bindings (goto-map)
("M-g e" . consult-compile-error)
("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
("M-g g" . consult-goto-line) ;; orig. goto-line
("M-g M-g" . consult-goto-line) ;; orig. goto-line
("M-g o" . consult-outline) ;; Alternative: consult-org-heading
("M-g m" . consult-mark)
("M-g k" . consult-global-mark)
("M-g i" . consult-imenu)
("M-g I" . consult-imenu-multi)
;; M-s bindings (search-map)
("M-s d" . consult-find)
("M-s D" . consult-locate)
("M-s g" . consult-grep)
("M-s G" . consult-git-grep)
("M-s r" . consult-ripgrep)
("M-s l" . consult-line)
("M-s L" . consult-line-multi)
("M-s m" . consult-multi-occur)
("M-s k" . consult-keep-lines)
("M-s u" . consult-focus-lines)
;; Isearch integration
("M-s e" . consult-isearch-history)
:map isearch-mode-map
("M-e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s l" . consult-line) ;; needed by consult-line to detect isearch
("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch
;; Minibuffer history
:map minibuffer-local-map
("M-s" . consult-history) ;; orig. next-matching-history-element
("M-r" . consult-history)) ;; orig. previous-matching-history-element
;; Enable automatic preview at point in the *Completions* buffer. This is
;; relevant when you use the default completion UI.
:hook (completion-list-mode . consult-preview-at-point-mode)
;; The :init configuration is always executed (Not lazy)
:init
;; Optionally configure the register formatting. This improves the register
;; preview for `consult-register', `consult-register-load',
;; `consult-register-store' and the Emacs built-ins.
(setq register-preview-delay 0.5
register-preview-function #'consult-register-format)
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
(advice-add #'register-preview :override #'consult-register-window)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
;; Configure other variables and modes in the :config section,
;; after lazily loading the package.
:config
;; Optionally configure preview. The default value
;; is 'any, such that any key triggers the preview.
;; (setq consult-preview-key 'any)
;; (setq consult-preview-key (kbd "M-."))
;; (setq consult-preview-key (list (kbd "<S-down>") (kbd "<S-up>")))
;; For some commands and buffer sources it is useful to configure the
;; :preview-key on a per-command basis using the `consult-customize' macro.
(consult-customize
consult-theme
:preview-key '(:debounce 0.2 any)
consult-ripgrep consult-git-grep consult-grep
consult-bookmark consult-recent-file consult-xref
consult--source-bookmark consult--source-recent-file
consult--source-project-recent-file)
;; Optionally configure the narrowing key.
;; Both < and C-+ work reasonably well.
(setq consult-narrow-key "<") ;; (kbd "C-+")
;; Optionally make narrowing help available in the minibuffer.
;; You may want to use `embark-prefix-help-command' or which-key instead.
;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)
;; By default `consult-project-function' uses `project-root' from project.el.
;; Optionally configure a different project root function.
;; There are multiple reasonable alternatives to chose from.
;;;; 1. project.el (the default)
;; (setq consult-project-function #'consult--default-project--function)
;;;; 2. projectile.el (projectile-project-root)
;; (autoload 'projectile-project-root "projectile")
;; (setq consult-project-function (lambda (_) (projectile-project-root)))
;;;; 3. vc.el (vc-root-dir)
;; (setq consult-project-function (lambda (_) (vc-root-dir)))
;;;; 4. locate-dominating-file
;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git")))
)
(use-package orderless
:ensure t
:custom
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles basic partial-completion)))))
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.
(use-package helpful
:ensure t
:bind
([remap describe-function] . helpful-function)
([remap describe-command] . helpful-command)
([remap describe-variable] . helpful-variable)
([remap describe-key] . helpful-key))
Magit is a Git user interface for Emacs. It provides a complete Git toolset within Emacs and allows users to interact with Git repositories directly from their text editor, without needing to switch to a separate Git client. Magit features include status information, branch visualization, diff viewing, commit creation, file staging, and more. It is highly customizable, scriptable, and integrates seamlessly with Emacs workflows.
Magit can be a great time-saver for developers working with Git repositories.
(use-package magit
:ensure t)
;; forge allows magit to connect to Github
(use-package forge
:ensure t
:after magit)
The left-hand fringe of Emacs is known as the gutter.
Using git-gutter
, symbols can be added in this fringe to visualize what changes
have been made to the current buffer since the last git
commit.
(use-package git-gutter
:ensure t
:config
(global-git-gutter-mode 't))
why-this
shows blame information for the currently selected line (or region) along the right side of the current line
(use-package why-this
:ensure t
:custom (why-this-idle-delay 0)
:bind
("C-c b" . why-this-mode)
("C-c w" . why-this))
Flycheck is an on-the-fly syntax checking and linting tool for Emacs. It automatically highlights errors and warnings in source code in real-time, helping to identify typos, syntax errors, and other mistakes quickly. Flycheck supports multiple programming languages and integrates with a variety of additional tools such as syntax checkers, linters, and spell checkers. Its modular architecture enables users to extend its functionality with additional checkers and customizations.
(use-package flycheck
:ensure t
:custom (flycheck-check-syntax-automatically '(save mode-enabled))
:init (global-flycheck-mode))
(defvar-local starmacs--mode-line-flycheck "")
(defun starmacs/mode-line-update-flycheck (&rest _)
(setq starmacs--mode-line-flycheck
(if (bound-and-true-p flycheck-mode)
(concat
" "
(pcase flycheck-last-status-change
(`not-checked (propertize "-/-" 'help-echo "Flycheck: not checked"))
(`no-checker (propertize "-" 'help-echo "Flycheck: no checker"))
(`running (propertize "*/*" 'help-echo "Flycheck: checking"))
(`errored (propertize "!" 'help-echo "Flycheck: error"))
(`finished
(let-alist (flycheck-count-errors flycheck-current-errors)
(propertize (format "%s/%s" (or .error 0) (or .warning 0))
'help-echo (if (or .error .warning)
(concat "Flycheck: "
(when .error (format "%d errors%s" .error (if .warning ", " "")))
(when .warning (format "%d warnings" .warning))
"\nmouse-1: list errors")
"Flycheck: no errors or warnings")
'local-map 'flycheck-error-list-mode-line-map)))
(`interrupted (propertize "x" 'help-echo "Flycheck: interrupted"))
(`suspicious (propertize "?" 'help-echo "Flycheck: suspicious"))))
"")))
(add-hook 'flycheck-status-changed-functions #'starmacs/mode-line-update-flycheck)
(add-hook 'flycheck-mode-hook #'starmacs/mode-line-update-flycheck)
Github Copilot is an artificial intelligence (AI) code autocompletion system that can suggest code snippets to developers as they write code. It uses advanced deep learning models trained on vast amounts of existing code to generate suggestions in real-time. Github Copilot aims to reduce the time needed to write code by automating some repetitive tasks and suggesting efficient code structures.
C-f
, as well as the right arrow key, are bound to complete suggestions made
by copilot. This is to distinguish them from completions given from
company-mode
, and therefore LSP, which are completed with <Tab>
.
This config assumes you do not have copilot access, or that you have not
logged in on this machine. In order to enable copilot, bind the variable
*starmacs/copilot-enabled*
to t
.
(defun starmacs/copilot-mode-hook ()
(when (and (boundp '*starmacs/copilot-enabled*)
*starmacs/copilot-enabled*)
copilot-mode-hook))
(use-package copilot
:straight (:host github :repo "zerolfx/copilot.el" :files ("dist" "*.el"))
:hook (prog-mode . copilot-mode)
:config
(define-key copilot-completion-map (kbd "C-f") 'copilot-accept-completion) ; using forward motion to accept completion like Warp
(define-key copilot-completion-map (kbd "<right>") 'copilot-accept-completion)
(unless (copilot-installed-version)
(copilot-install-server))
:ensure t)
(use-package company
:ensure t
:hook ((prog-mode) . (lambda () (company-mode)))
:bind (:map company-mode-map
("<tab>" . 'company-indent-or-complete-common)
:map company-active-map
("C-n" . 'company-select-next-or-abort)
("C-p" . 'company-select-previous-or-abort))
:custom
(company-idle-delay nil) ; don't try to complete until asked
(company-minimum-prefix-length 1)
(company-tooltip-align-annotations t)
(lsp-completion-provider :capf) ; used for eglot integration
(company-show-quick-access t)
:config
(company-tng-configure-default))
(use-package company-box
:ensure t
:hook (company-mode . company-box-mode))
(setq tab-always-indent 'complete)
While Emacs Lisp is the language Emacs is configured in, as well as what this code is in, it’s very likely that users will eventually encounter another Lisp.
Common Lisp is the most common variant users can expect to see inthe wild, and Sly is the best solution out there for working on it.
Sly is a Common Lisp IDE for Emacs that provides a variety of features for interactive programming, development, and debugging. It is an alternative to the more popular package Slime, but is designed to be more lightweight and modern. With sly, you can connect to a running Lisp process, evaluate code, inspect variables, and so much more. If you use Common Lisp or are interested in learning it, sly is definitely a package to consider.
(use-package sly
:ensure t)
;; paredit allows for some now keybinding that make working with parens suck less
(use-package paredit
:init
(progn
(add-hook 'emacs-lisp-mode-hook 'paredit-mode)
(add-hook 'common-lisp-mode-hook 'paredit-mode)))
LSP stands for Language Server Protocol. It is a protocol that enables the development of tools to provide language-specific intelligent features such as auto-completion, go to definition, find all references, hover information, and other language-related features in text editors and integrated development environments (IDEs) using separate language servers.
Emacs 29+ comes with eglot
, an LSP system, built-in.
(use-package eglot
:bind
(("s-." . eglot-code-actions)
("<f12>" . eglot-find-typeDefinition)
("<f2>" . eglot-rename))
:hook
(typescript-mode . eglot-ensure)
(typescript-ts-mode . eglot-ensure)
(tsx-ts-mode . eglot-ensure)
(python-ts-mode . eglot-ensure)
(go-ts-mode . eglot-ensure)
(f90-mode . eglot-ensure)
(zig-mode . eglot-ensure)
:config (setq lsp-prefer-flymake nil))
(use-package eldoc-box
:hook
(eglot-managed-mode . eldoc-box-hover-mode))
Tree-sitter is a parsing system and library designed for use in text editors. It can parse source code or other textual content and provide a detailed representation of the syntax tree, which can be used to perform powerful code analysis. It is particularly useful for support of advanced features such as syntax highlighting, code folding, and code navigation. Tree-sitter is fast, efficient and supports multiple programming languages.
(require 'treesit)
(setq treesit-font-lock-level 4)
(setq treesit-language-source-alist
'((bash "https://github.com/tree-sitter/tree-sitter-bash")
(cmake "https://github.com/uyha/tree-sitter-cmake")
(css "https://github.com/tree-sitter/tree-sitter-css")
(elisp "https://github.com/Wilfred/tree-sitter-elisp")
(go "https://github.com/tree-sitter/tree-sitter-go")
(html "https://github.com/tree-sitter/tree-sitter-html")
(javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")
(json "https://github.com/tree-sitter/tree-sitter-json")
(make "https://github.com/alemuller/tree-sitter-make")
(markdown "https://github.com/ikatyang/tree-sitter-markdown")
(python "https://github.com/tree-sitter/tree-sitter-python")
(toml "https://github.com/tree-sitter/tree-sitter-toml")
(tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")
(typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")
(yaml "https://github.com/ikatyang/tree-sitter-yaml")))
(defun starmacs/install-grammers ()
"Download and compile all of the grammers in treesit-language"
(interactive)
(mapc #'treesit-install-language-grammar (mapcar #'car treesit-language-source-alist)))
(if (not (file-exists-p (expand-file-name "tree-sitter" user-emacs-directory)))
(starmacs/install-grammers))
;; (use-package treesit-auto
;; :config
;; (treesit-auto-add-to-auto-mode-alist 'all)
;; (global-treesit-auto-mode))
Due to its usefulness for unsticking oneself while programming, a ChatGPT
client has been bundled in. To use it, simply put your OpenAI API key in the file
~/.emacs.d/chatgpt-api-key.txt
, and it will be automatically read when
a new shell is opened with M-x chatgpt-shell
(setq starmacs/chatgpt-api-key (expand-file-name "chatgpt-api-key.txt"))
(use-package chatgpt-shell
:ensure t
:straight (:host github :repo "xenodium/chatgpt-shell" :files ("dist" "*.el"))
:config
(unless
(file-exists-p starmacs/chatgpt-api-key)
(make-empty-file starmacs/chatgpt-api-key))
(setq chatgpt-shell-openai-key (replace-regexp-in-string "\n\\'" "" (with-temp-buffer
(insert-file-contents (expand-file-name "chatgpt-api-key.txt"))
(buffer-string)))))
In order to allow the user to use a better editing environment when adding your own
code to Starmacs, the usr
directory is added to the load-path. This means that
any file added in ./usr/
will we automatically evaluated when
Emacs is launched.. This way, Emacs Lisp code can be edited in a dedicated
buffer, rather than in a source block in an org document
(let ((default-directory user-emacs-directory))
(normal-top-level-add-subdirs-to-load-path))
(defun starmacs/load-user-code (dir)
"`load' all elisp libraries in directory DIR which are not already loaded."
(interactive "D")
(let ((libraries-loaded (mapcar #'file-name-sans-extension
(delq nil (mapcar #'car load-history)))))
(dolist (file (directory-files dir t ".+\\.elc?$"))
(let ((library (file-name-sans-extension file)))
(unless (member library libraries-loaded)
(load library nil t)
(push library libraries-loaded))))))
(when (file-exists-p (expand-file-name "./usr"))
(starmacs/load-user-code (expand-file-name "./usr")))
If you’re starting up for the first time, a bunch of warnings and windows and such are created. Let’s get rid of those and show you the dashboard
(when starmacs/initial-install
(starmacs/welcome)
(move-beginning-of-line nil))