#+TITLE: Blendoit's literate GNU Emacs config #+AUTHOR: Marius Peter #+DATE: <2020-07-23 Thu> #+STARTUP: customtime showall #+SETUPFILE: ~/org/templates/documents/personal.org #+INCLUDE: ~/org/templates/documents/personal-title.org \begin{abstract} GNU Emacs is most often used as a text editor. The utmost level of customisation is afforded by enabling the user to rewrite /any/ part of the source code and observe the editor's modified behaviour in real time. Since its inception in 1984, GNU Emacs has grown to be much more than a full-featured, high-productivity text editor---new /modes/ have been written to interact with hundreds of file formats, including =.txt=, =.pdf=, =.jpg=, =.csv=, and =.zip= just to name a few. This configuration file itself was written in /Org mode/, a collection of functions enabling the harmonious mixing of code and comments in view of publication: this is the endgame of /literate programming/. \end{abstract} # ** Test # #+BEGIN_SRC emacs-lisp # (org-babel-load-file "~/.emacs.d/blendoit/test.org") # #+END_SRC * Preliminary setup ** Garbage collection First, we increase the RAM threshold beyond which the garbage collector is activated. #+NAME: garbage-collection #+BEGIN_SRC emacs-lisp (setq gc-cons-threshold 100000000) #+END_SRC ** Emacs client Makes opening emacs faster for following instances. #+NAME: emacs-client #+BEGIN_SRC emacs-lisp ; (setq initial-buffer-choice (lambda () (get-buffer "*dashboard*"))) #+END_SRC ** Profiling --- start We start the profiler now , and will interrupt it in section [[Profiling --- stop]]. We will then present profiling report in [[Profiling --- report]]. #+NAME: profiler-start #+BEGIN_SRC emacs-lisp ; (profiler-start) #+END_SRC ** Custom file Load settings created automatically by GNU Emacs Custom. (For example, any clickable option/toggle is saved here.) Useful for fooling around with M-x customize-group . #+NAME: custom-file #+BEGIN_SRC emacs-lisp (setq custom-file "~/.emacs.d/init-custom.el") (load custom-file) #+END_SRC ** Customization shortcuts We begin by defining a user shortcut to this very file: #+NAME: shortcut-config #+BEGIN_SRC emacs-lisp (defun find-init-blendoit () "Jump to this very file." (interactive) (find-file "~/.emacs.d/blendoit/init-blendoit.org")) (global-set-key (kbd "C-c c") 'find-init-blendoit) #+END_SRC Now, different shortcuts for other customization actions: #+NAME: shortcuts-customization #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-c v") 'customize-variable) (global-set-key (kbd "C-c f") 'customize-face) #+END_SRC ** Backups Backups are so important that they should be described right after the shortcut to this file. #+BEGIN_SRC emacs-lisp (setq backup-directory-alist `((".*" . ,temporary-file-directory)) auto-save-file-name-transforms `((".*" ,temporary-file-directory t)) backup-by-copying t ; Don't delink hardlinks version-control t ; Use version numbers on backups delete-old-versions t ; Automatically delete excess backups kept-new-versions 20 ; how many of the newest versions to keep kept-old-versions 5 ; and how many of the old ) #+END_SRC ** Secrets #+INCLUDE: ./secrets.org #+BEGIN_SRC emacs-lisp (setq user-full-name "Marius Peter" user-mail-address "blendoit@gmail.com") #+END_SRC * Global key bindings The following bindings strive to further enhance CUA[fn::Common User Access.] mode. ** Navigation #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-`") 'delete-other-windows) (global-set-key (kbd "C-s") 'save-buffer) (global-set-key (kbd "C-b") 'ibuffer-sidebar-toggle-sidebar) (global-set-key (kbd "C-o") 'menu-find-file-existing) (global-set-key (kbd "C-r") 'counsel-recentf) (global-set-key (kbd "C-n") 'make-frame) #+END_SRC The following bindings lead to more natural exit behaviors. #+BEGIN_SRC emacs-lisp (defun delete-window-or-previous-buffer () "Delete window; if sole window, previous buffer." (interactive) (if (> (length (window-list)) 2) (delete-window) (previous-buffer))) (global-set-key (kbd "C-w") 'delete-window-or-previous-buffer) (global-set-key (kbd "C-q") 'save-buffers-kill-terminal) #+END_SRC ** Mouse zoom Zoom in/out of selected buffer using Alt + mouse wheel. #+BEGIN_SRC emacs-lisp (global-set-key [M-mouse-4] 'text-scale-increase) (global-set-key [M-mouse-5] 'text-scale-decrease) #+END_SRC * Packages ** Package archives List of package archives. #+NAME: packages #+BEGIN_SRC emacs-lisp (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t) (package-initialize) #+END_SRC ** use-package Ensure =use-package= is installed, as well as all packages described in this configuration file. #+BEGIN_SRC emacs-lisp (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package) (eval-when-compile (require 'use-package))) (setq use-package-always-ensure t) #+END_SRC ** Ivy Auto completion. #+BEGIN_SRC emacs-lisp (use-package ivy :config (setq ivy-use-virtual-buffers t ivy-count-format "%d/%d " enable-recursive-minibuffers t)) (ivy-mode t) #+END_SRC ** Evil Forgive me, for I have sinned. #+BEGIN_SRC emacs-lisp (use-package evil) ;; (evil-mode 1) #+END_SRC *** Counsel Wonderful counsellor! #+BEGIN_SRC emacs-lisp (use-package counsel :bind ("M-x" . counsel-M-x) :config (counsel-mode t)) (global-set-key (kbd "C-f") 'counsel-grep-or-swiper) #+END_SRC *** Swiper #+BEGIN_SRC emacs-lisp (use-package swiper :bind (("C-f" . counsel-grep-or-swiper))) #+END_SRC ** Org Phew, I can finally introduce Org mode! I am so *excited*. Org mode replaces aword processor, a presentation creator, and a spreadsheet editor. IMHO, the spreadsheet ability captures more than 80% use cases wherein one wishes to include a table in a text document destined for physical publication. (It is clear that Excel spreadsheets are /not/ destined for physical publication---simply attempt to print an Excel spreadsheet with the default settings.) In my opinion, Org mode matches all /useful/ features of the Microsoft Office suite 1-to-1. What follows are customizations designed to make Org mode behave more like Microsoft Word. The end goal is, once again, to draw as many new users to Emacs as possible! *** Basic customization First, we hide markup symbols for *bold*, /italic/, _underlined_ and +strikethrough+ text, and ensure our document appears indented upon loading:[fn::It /appears/ indented, but the underlying plaintext file does not contain tab characters!] #+NAME: org-basic #+BEGIN_SRC emacs-lisp (setq org-hide-emphasis-markers t) (setq org-startup-indented t) #+END_SRC Then, we customize Org headings to emulate WYSIWYG[fn::What You See Is What You Get (input and output are identical), as opposed to What You See Is What You Mean (the input contains instructions that can modify the output).] behavior normally found in Word: #+NAME: org-list-bullets #+BEGIN_SRC emacs-lisp (setq org-directory "~/org") (font-lock-add-keywords 'org-mode '(("^ *\\([-]\\) " (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•")))))) #+END_SRC - Look at - This beautifully indented - List... - Of lists! - (Rendered with pretty bullets in Emacs) The following prettifies Org mode heading bullets: #+NAME: org-headings-bullets #+BEGIN_SRC emacs-lisp (use-package org-bullets :hook (org-mode . org-bullets-mode) ) #+END_SRC Thank you Diego Zamboni![fn::https://zzamboni.org/post/beautifying-org-mode-in-emacs/] #+NAME: org-cosmetics #+BEGIN_SRC emacs-lisp ;; (let* ((variable-tuple ;; (cond ((x-list-fonts "Dejavu Sans") '(:font "Dejavu Sans")) ;; ((x-family-fonts "Sans Serif") '(:family "Sans Serif")) ;; (nil (warn "Cannot find a Sans Serif Font. Install Source Sans Pro.")))) ;; (base-font-color (face-foreground 'default nil 'default)) ;; (headline `(:inherit default :weight bold))) ;; (custom-theme-set-faces ;; 'user ;; `(org-level-8 ((t (,@headline ,@variable-tuple)))) ;; `(org-level-7 ((t (,@headline ,@variable-tuple)))) ;; `(org-level-6 ((t (,@headline ,@variable-tuple)))) ;; `(org-level-5 ((t (,@headline ,@variable-tuple)))) ;; `(org-level-4 ((t (,@headline ,@variable-tuple :height 1.1)))) ;; `(org-level-3 ((t (,@headline ,@variable-tuple :height 1.25)))) ;; `(org-level-2 ((t (,@headline ,@variable-tuple :height 1.5)))) ;; `(org-level-1 ((t (,@headline ,@variable-tuple :height 1.75)))) ;; `(org-document-title ((t (,@headline ,@variable-tuple :height 2.0 :underline nil)))))) ;(custom-theme-set-faces ; 'user ; '(variable-pitch ((t (:family "Liberation Sans")))) ; '(fixed-pitch ((t ( :family "Hack"))))) #+END_SRC *** Invisible edits #+BEGIN_SRC emacs-lisp (setq org-catch-invisible-edits t) #+END_SRC *** Agenda The agenda displays a chronological list of headings across all agenda files for which the heading or body contain a matching =org-time-stamp=.[fn::An =org-time-stamp= can be inserted with =C-c .= (period)] #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-c a") 'org-agenda) #+END_SRC *** Publish In the following /alist/ (association list), we describe the projects publishable via =org-publish=. We separate the publishing of =.org= files and attachments, because an online tutorial recommended we do so. #+BEGIN_SRC emacs-lisp (require 'ox-publish) (setq org-publish-project-alist '( ("Safran-VIP-html" :base-directory "~/org/WORK/Safran/programs/B787/VIP/doc/org/" :base-extension "org" :publishing-directory "~/org/WORK/Safran/programs/B787/VIP/doc/wiki/" :recursive t :publishing-function org-html-publish-to-html :auto-preamble t :auto-sitemap t :sitemap-title "" ) ("Safran-VIP-static" :base-directory "~/org/WORK/Safran/programs/B787/VIP/doc/org/" :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|mp4\\|ogg\\|swf" :publishing-directory "~/org/WORK/Safran/programs/B787/VIP/doc/wiki/" :recursive t :publishing-function org-publish-attachment ) ("Safran-VIP-all" :components ("Safran-VIP-html" "Safran-VIP-static")) ("Safran-MA700-html" :base-directory "~/org/WORK/Safran/programs/MA700/doc/org/" :base-extension "org" :publishing-directory "~/org/WORK/Safran/programs/MA700/doc/wiki/" :recursive t :publishing-function org-html-publish-to-html :auto-preamble t :auto-sitemap t :sitemap-title "" ) ("Safran-MA700-static" :base-directory "~/org/WORK/Safran/programs/MA700/doc/org/" :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|mp4\\|ogg\\|swf" :publishing-directory "~/org/WORK/Safran/programs/MA700/doc/wiki/" :recursive t :publishing-function org-publish-attachment ) ("Safran-MA700-all" :components ("Safran-MA700-html" "Safran-MA700-static")))) (add-to-list 'org-latex-packages-alist '("table" "xcolor" t ("pdflatex"))) (add-to-list 'org-latex-packages-alist '("AUTO" "babel" t ("pdflatex"))) (add-to-list 'org-latex-packages-alist '("AUTO" "polyglossia" t ("xelatex" "lualatex"))) #+END_SRC *** Export This creates a shorter binding for the most common Org export: Org \rightarrow LaTeX \rightarrow PDF. #+BEGIN_SRC emacs-lisp (defun blendoit-org-quick-export () "Org export to PDF and open. This basically reimplements `C-c C-e l o'." (interactive) (org-latex-export-to-pdf) (org-open-file (concat (substring buffer-file-truename 0 -3) "pdf"))) (global-set-key (kbd "C-c e") 'blendoit-org-quick-export) #+END_SRC ** undo tree #+BEGIN_SRC emacs-lisp (global-undo-tree-mode) #+END_SRC ** dumb jump #+BEGIN_SRC emacs-lisp (use-package dumb-jump) #+END_SRC ** gnuplot #+BEGIN_SRC emacs-lisp (use-package gnuplot) #+END_SRC ** Ledger #+BEGIN_SRC emacs-lisp (use-package ledger-mode :bind ("C-c r" . ledger-report) ("C-c C" . ledger-mode-clean-buffer)) #+END_SRC ** ibuffer-sidebar #+BEGIN_SRC emacs-lisp (use-package ibuffer-sidebar) (ibuffer-sidebar-show-sidebar) ; :bind ("mouse-1" . ibuffer-mouse-visit-buffer) ; :bind ("mouse-3" . ibuffer-mouse-toggle-mark)) ; (add-hook 'ibuffer-sidebar-mode-hook ; (lambda () ; (local-unset-key (quote mouse-1)) ; (local-unset-key (quote mouse-2)) ; (local-set-key (quote mouse-1) (quote ibuffer-mouse-visit-buffer)) ; (local-set-key (quote mouse-2) (quote ibuffer-mouse-toggle-mark)))) #+END_SRC ** Which-key #+BEGIN_SRC emacs-lisp (use-package which-key :init (which-key-mode) ;; :config ;; (setq which-key-idle-delay 1000) ;; (setq which-key-idle-secondary-delay 0.05) ;; (setq which-key-show-early-on-C-h t) ) #+END_SRC ** Company #+NAME: company #+BEGIN_SRC emacs-lisp (add-hook 'after-init-hook 'global-company-mode) #+END_SRC ** Flycheck #+NAME: flycheck #+BEGIN_SRC emacs-lisp (use-package flycheck :init (global-flycheck-mode)) #+END_SRC ** CSV #+BEGIN_SRC emacs-lisp (use-package csv-mode) #+END_SRC * JSON Oí, Jason! #+BEGIN_SRC emacs-lisp (use-package json-mode) #+END_SRC ** Magit #+BEGIN_SRC emacs-lisp (use-package magit :bind ("C-c g" . magit-status)) #+END_SRC ** PDF-tools #+BEGIN_SRC emacs-lisp (use-package pdf-tools :config (pdf-loader-install)) #+END_SRC ** Dashboard We replace the standard welcome screen with our own. #+BEGIN_SRC emacs-lisp (setq inhibit-startup-message t) (use-package dashboard :config (dashboard-setup-startup-hook) (setq dashboard-startup-banner "~/.emacs.d/blendoit/img/logo-blendux_small.png") (setq dashboard-items '((recents . 5) (projects . 5))) (setq dashboard-banner-logo-title "The editor for the 2nd millenium.")) #+END_SRC ** rainbow This highlights hexadecimal numbers which look like colors, in that same color. #+BEGIN_SRC emacs-lisp (use-package rainbow-mode :ensure t :init (add-hook 'prog-mode-hook 'rainbow-mode)) #+END_SRC ** Projectile This enables us to better manage our =.git= projects. #+BEGIN_SRC emacs-lisp (use-package projectile :bind ("C-c p" . 'projectile-command-map) :init (projectile-mode 1) (setq projectile-completion-system 'ivy)) #+END_SRC ** Better parentheses #+BEGIN_SRC emacs-lisp (show-paren-mode 1) (use-package smartparens :config (add-hook 'prog-mode-hook #'smartparens-mode)) (use-package rainbow-delimiters :config (add-hook 'prog-mode-hook #'rainbow-delimiters-mode)) #+END_SRC * Cosmetics ** Faces & cursors In order to imitate other modern text editors, we'll resort to a blinking bar cursor. We choose red, the most captivating color, because the cursor is arguably the region on our screen: 1. most often looked at; 2. most often searched when lost. The default cursor already blinks. *** Default cursor In files containing only fixed-pitch fonts (i.e. files containing only code), the cursor becomes a high-visibility box. #+BEGIN_SRC emacs-lisp (setq-default cursor-type (quote box)) #+END_SRC *** Mixed pitch in Org mode Fixed-pitch and variable-pitch fonts will be used intelligently in all hooked modes. #+BEGIN_SRC emacs-lisp (use-package mixed-pitch :hook ((org-mode . mixed-pitch-mode) (Info-mode . mixed-pitch-mode))) #+END_SRC ** Initial frame These settings affect the first and subsequent frames spawned by Emacs. Thank you Xah Lee![fn::http://ergoemacs.org/emacs/emacs_customize_default_window_size.html] #+BEGIN_SRC emacs-lisp (if (display-graphic-p) (progn (setq initial-frame-alist '( (tool-bar-lines . 1) (width . 100) ; chars (height . 52) ; lines (alpha . (90 . 50)))) (setq default-frame-alist '( (tool-bar-lines . 1) (width . 100) (height . 52) (alpha . (90 . 50)))))) #+END_SRC ** Theme #+BEGIN_SRC emacs-lisp ;; (use-package zenburn-theme ;; :config ;; (load-theme 'zenburn)) (load-theme 'blendoit) #+END_SRC ** All the icons #+BEGIN_SRC emacs-lisp (use-package all-the-icons) #+END_SRC * Editing preferences These customizations enhance editor usability. #+BEGIN_SRC emacs-lisp (setq-default fill-column 79) (defalias 'yes-or-no-p 'y-or-n-p) #+END_SRC Disable minibuffer scroll bar. #+BEGIN_SRC emacs-lisp (set-window-scroll-bars (minibuffer-window) nil nil) ; (set-window-scroll-bars (ibuffer-sidebar-window) nil nil) #+END_SRC ** Clean up menus We reduce the burden on the user by reducing total amount of entries in GUI menus. *** File #+BEGIN_SRC emacs-lisp (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-file-menu [print-buffer] nil) (define-key menu-bar-file-menu [print-region] nil) (define-key menu-bar-file-menu [ps-print-buffer-faces] nil) (define-key menu-bar-file-menu [ps-print-region-faces] nil) (define-key menu-bar-file-menu [ps-print-buffer] nil) (define-key menu-bar-file-menu [ps-print-region] nil) (define-key menu-bar-file-menu [split-window-below] nil) (define-key menu-bar-file-menu [split-window-right] nil) (define-key menu-bar-file-menu [dired] nil) #+END_SRC *** Edit #+BEGIN_SRC emacs-lisp (define-key menu-bar-help-menu [emacs-psychotherapist] nil) (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-help-menu [emacs-psychotherapist] nil) #+END_SRC *** Options #+BEGIN_SRC emacs-lisp (define-key menu-bar-help-menu [emacs-psychotherapist] nil) (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-help-menu [emacs-psychotherapist] nil) #+END_SRC *** Buffers #+BEGIN_SRC emacs-lisp (define-key menu-bar-help-menu [emacs-psychotherapist] nil) (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-help-menu [emacs-psychotherapist] nil) #+END_SRC *** Tools #+BEGIN_SRC emacs-lisp (define-key menu-bar-help-menu [emacs-psychotherapist] nil) (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-help-menu [emacs-psychotherapist] nil) #+END_SRC *** Org #+BEGIN_SRC emacs-lisp (define-key menu-bar-help-menu [emacs-psychotherapist] nil) (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-help-menu [emacs-psychotherapist] nil) #+END_SRC *** Tbl #+BEGIN_SRC emacs-lisp (define-key menu-bar-help-menu [emacs-psychotherapist] nil) (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-help-menu [emacs-psychotherapist] nil) #+END_SRC *** Text #+BEGIN_SRC emacs-lisp (define-key menu-bar-help-menu [emacs-psychotherapist] nil) (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-help-menu [emacs-psychotherapist] nil) #+END_SRC *** Projectile #+BEGIN_SRC emacs-lisp (define-key menu-bar-help-menu [emacs-psychotherapist] nil) (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-help-menu [emacs-psychotherapist] nil) #+END_SRC *** Help #+BEGIN_SRC emacs-lisp (define-key menu-bar-help-menu [emacs-psychotherapist] nil) (define-key menu-bar-file-menu [dired] nil) (define-key menu-bar-help-menu [emacs-psychotherapist] nil) #+END_SRC ** Coding standards This is just a better default. #+BEGIN_SRC emacs-lisp (setq c-default-style "linux" c-basic-offset 4) #+END_SRC ** Tabs #+BEGIN_SRC emacs-lisp (use-package tabbar) #+END_SRC Thank you https://andreyorst.gitlab.io/posts/2020-05-10-making-emacs-tabs-look-like-in-atom/ #+BEGIN_SRC emacs-lisp (when (and window-system (not (version< emacs-version "27"))) (use-package tab-line :hook (after-init . global-tab-line-mode) :config (defun tab-line-close-tab (&optional e) "Close the selected tab. If tab is presented in another window, close the tab by using `bury-buffer` function. If tab is unique to all existing windows, kill the buffer with `kill-buffer` function. Lastly, if no tabs left in the window, it is deleted with `delete-window` function." (interactive "e") (let* ((posnp (event-start e)) (window (posn-window posnp)) (buffer (get-pos-property 1 'tab (car (posn-string posnp))))) (with-selected-window window (let ((tab-list (tab-line-tabs-window-buffers)) (buffer-list (flatten-list (seq-reduce (lambda (list window) (select-window window t) (cons (tab-line-tabs-window-buffers) list)) (window-list) nil)))) (select-window window) (if (> (seq-count (lambda (b) (eq b buffer)) buffer-list) 1) (progn (if (eq buffer (current-buffer)) (bury-buffer) (set-window-prev-buffers window (assq-delete-all buffer (window-prev-buffers))) (set-window-next-buffers window (delq buffer (window-next-buffers)))) (unless (cdr tab-list) (ignore-errors (delete-window window)))) (and (kill-buffer buffer) (unless (cdr tab-list) (ignore-errors (delete-window window))))))))) (defcustom tab-line-tab-min-width 10 "Minimum width of a tab in characters." :type 'integer :group 'tab-line) (defcustom tab-line-tab-max-width 30 "Maximum width of a tab in characters." :type 'integer :group 'tab-line) (defcustom tab-line-ellipsis-string "…" "String for indicating truncated names" :type 'string :group 'tab-line) (defun aorst/tab-line--tab-width (window-width tab-amount) "Calculate width of single tab dividing WINDOW-WIDTH by TAB-AMOUNT." (let* ((close-button-size (if tab-line-close-button-show (length (substring-no-properties tab-line-close-button)) 0)) (tab-width (/ window-width tab-amount))) (- (cond ((< window-width 0) tab-line-tab-min-width) ((>= tab-width tab-line-tab-max-width) tab-line-tab-max-width) ((< tab-width tab-line-tab-min-width) tab-line-tab-min-width) (t tab-width)) close-button-size))) (defun aorst/tab-line--max-width (window) "Calculate free width of the WINDOW. Free width means amount of space we can use to display tabs without truncation." (- (window-width window) (length (substring-no-properties tab-line-left-button)) (length (substring-no-properties tab-line-right-button)) (if tab-line-new-button-show (length (substring-no-properties tab-line-new-button)) 0))) (defun aorst/tab-line--make-pad (tab-width name-width) "Generate padding string based on TAB-WIDTH and NAME-WIDTH." (let* ((width (- tab-width name-width)) (padding (/ (if (oddp width) (+ width 1) width) 2))) (make-string padding ?\s))) (defun aorst/tab-line-name-buffer (buffer &rest _buffers) "Create name for tab with padding and truncation. If buffer name is shorter than `tab-line-tab-max-width' it gets centered with spaces, otherwise it is truncated, to preserve equal width for all tabs. This function also tries to fit as many tabs in window as possible, so if there are no room for tabs with maximum width, it calculates new width for each tab and truncates text if needed. Minimal width can be set with `tab-line-tab-min-width' variable." (with-current-buffer buffer (let* ((amount (length (tab-line-tabs-window-buffers))) (width (aorst/tab-line--tab-width (aorst/tab-line--max-width (get-buffer-window buffer)) amount)) (buffer (string-trim (buffer-name))) (name-width (length buffer)) (right-pad (if tab-line-close-button-show "" " ")) (truncate-width (- width (length tab-line-ellipsis-string) (length right-pad)))) (if (>= name-width truncate-width) (concat " " (truncate-string-to-width buffer truncate-width) tab-line-ellipsis-string right-pad) (let* ((padding (aorst/tab-line--make-pad width name-width)) (tab-text (concat padding buffer)) (text-width (length tab-text))) (concat tab-text (make-string (- width text-width) ?\s))))))) (setq tab-line-close-button-show t tab-line-new-button-show nil tab-line-separator "" tab-line-tab-name-function #'aorst/tab-line-name-buffer tab-line-right-button (propertize (if (char-displayable-p ?▶) " ▶ " " > ") 'keymap tab-line-right-map 'mouse-face 'tab-line-highlight 'help-echo "Click to scroll right") tab-line-left-button (propertize (if (char-displayable-p ?◀) " ◀ " " < ") 'keymap tab-line-left-map 'mouse-face 'tab-line-highlight 'help-echo "Click to scroll left") tab-line-close-button (propertize (if (char-displayable-p ?×) " × " " x ") 'keymap tab-line-tab-close-map 'mouse-face 'tab-line-close-highlight 'help-echo "Click to close tab")) (let ((bg (if (facep 'solaire-default-face) (face-attribute 'solaire-default-face :background) (face-attribute 'default :background))) (fg (face-attribute 'default :foreground)) (base (if (facep 'solaire-default-face) (face-attribute 'default :background) (face-attribute 'mode-line :background))) (box-width (/ (line-pixel-height) 2))) (when (and (color-defined-p bg) (color-defined-p fg) (color-defined-p base) (numberp box-width)) (set-face-attribute 'tab-line nil :background base :foreground fg :height 1.0 :inherit nil :box (list :line-width -1 :color base)) (set-face-attribute 'tab-line-tab nil :foreground fg :background bg :weight 'normal :inherit nil :box (list :line-width box-width :color bg)) (set-face-attribute 'tab-line-tab-inactive nil :foreground fg :background base :weight 'normal :inherit nil :box (list :line-width box-width :color base)) (set-face-attribute 'tab-line-tab-current nil :foreground fg :background bg :weight 'normal :inherit nil :box (list :line-width box-width :color bg)))) (setq tab-line-exclude-modes '()) (dolist (mode '(ediff-mode process-menu-mode term-mode vterm-mode)) (add-to-list 'tab-line-exclude-modes mode)) (defun aorst/tab-line-drop-caches () "Drops `tab-line' cache in every window." (dolist (window (window-list)) (set-window-parameter window 'tab-line-cache nil))) (add-hook 'window-configuration-change-hook #'aorst/tab-line-drop-caches))) #+END_SRC ** auto fill Automatically break lines longer than =fill-column=. #+BEGIN_SRC emacs-lisp (add-hook 'org-mode-hook 'turn-on-auto-fill) #+END_SRC ** Recent files #+BEGIN_SRC emacs-lisp (recentf-mode 1) (setq recentf-max-menu-items 25) (setq recentf-max-saved-items 25) (run-at-time nil (* 5 60) 'recentf-save-list) #+END_SRC * Profiling --- stop #+BEGIN_SRC emacs-lisp ;; (profiler-stop) #+END_SRC * Profiling --- report #+BEGIN_SRC emacs-lisp ;; (profiler-report) #+END_SRC