Files
azos/pkgs/elisp/azos-emacs-base.org
T
2024-11-18 09:11:55 +02:00

39 KiB

Aner's Emacs Base Configuration

Base setup

Bootstrapping

(setq
    vc-follow-symlinks t ;Follow symlinks

    ;Backups from https://www.emacswiki.org/emacs/BackupDirectory
    backup-directory-alist `(("." . temporary-file-directory))
    auto-save-file-name-transforms '((".*" temporary-file-directory t))
    backup-by-copying t ;Always copy never link
    delete-old-versions t ;Auto delete old backups
    kept-new-versions 6 ;Number of versions to keep
    kept-old-versions 2
    version-control t ;Backups for files

    ;Garbage collection
    gc-cons-threshold 100000000

    ;Set external cusotm file
    custom-file (expand-file-name "custom.el" user-emacs-directory)
)

Load custom file

(if (file-exists-p custom-file) (load custom-file))

Utility functions

CL

CL is a base library that has a bunch of useful stuff, primarily for lists. We are using the built-in version, no need to pull from anywhere. This just makes sure the code is loaded early on for later use.

(require 'cl-lib)

Copy file name

Defining a function to copy filename.

(defun azos/copy-file-name () (interactive)
       (let ((fpath buffer-file-name))
         (if fpath (kill-new fpath) (message "No current file!"))))

Font candidate

(defun azos/font-candidate (&rest fonts)
    "Return existing font which first match."
    (cl-find-if (lambda (f) (find-font (font-spec :name f))) fonts))

Regex match function

(defun azos/re-seq (regexp string)
  "Get a list of all regexp matches in a string"
  (save-match-data
    (let ((pos 0)
          matches)
      (while (string-match regexp string pos)
        (push (match-string 0 string) matches)
        (setq pos (match-end 0)))
      matches)))

Keymap setup

In this section global keybindings are defined using a global minor mode.

First, utility functions that will be bound are defined.

The first, azos/set-window-width is a helper function that resizes a window. Used because I wanted a function that resizes a window to 85 cols easily.

The second, azos/open-conf-file, opens the configuration file.

(defun azos/set-window-width (n)
    (adjust-window-trailing-edge (selected-window) ( - n (window-width)) t))

(defun azos/open-conf-file ()
    (interactive)
    (find-file (concat user-emacs-directory "config.org")))

Now let's define keybindings. To start, we'd like M-o to be available to us, so let's unbind it.

;Unbind face menu map
(define-key global-map (kbd "M-o") nil)

This creates an "open keymap", a bunch of keybindings we'll use to open basic applications and files. This will be mapped to M-o, and things will be opened form this sub-menu. We'll start it with a binding to open the conf file with M-o o (MOO!)

Setting of keybindings based on this

;We'll define a basic keymap and already load window-manip funcs
(defvar azos/global-minor-mode/open-keymap
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "o") 'azos/open-conf-file)
    map)
  "global keymap for opening stuff on azos")

At this stage a minor-mode-map is defined with keybindings, and an accompanying minor-mode is added.

(defvar azos/global-minor-mode/keymap
  (let ((map (make-sparse-keymap)))

    ;Window movement and manipulation
    (define-key map (kbd "M-h") 'windmove-left)
    (define-key map (kbd "M-l") 'windmove-right)
    (define-key map (kbd "M-k") 'windmove-up)
    (define-key map (kbd "M-j") 'windmove-down)

    (define-key map (kbd "M-<left>") 'windmove-left)
    (define-key map (kbd "M-<right>") 'windmove-right)
    (define-key map (kbd "M-<up>") 'windmove-up)
    (define-key map (kbd "M-<down>") 'windmove-down)
    (define-key map (kbd "M-d M-d") 'delete-window)
    (define-key map (kbd "M-d D") 'kill-buffer-and-window)
    (define-key map (kbd "M-\\") 'split-window-horizontally)
    (define-key map (kbd "M-\-") 'split-window-vertically)
    (define-key map (kbd "M-d R") (lambda () (interactive)
                    (set-window-width 85)))
    (define-key map (kbd "M-o") azos/global-minor-mode/open-keymap)
    map)
  "azos/global-minor-mode keymap.")

(define-minor-mode azos/global-minor-mode
  "A minor mode for azos global keymaps."
  :init-value t
  :lighter "azos"
  :keymap azos/global-minor-mode/keymap)

(azos/global-minor-mode 1)

This keymap will be referenced many times during this document at relevant points.

Keymaps are included with relevant sections.

EVIL mode

This section binds keys for changing window size. Done here because can only do after evil loads.

(setq evil-want-keybinding nil)

(use-package evil
  :init
  (setq evil-want-C-i-jump nil)
  :config
  (require 'evil )
  (evil-mode 1)

  :bind
  (:map azos/global-minor-mode/keymap
        ("M-w h" . evil-window-decreace-width)
        ("M-w l" . evil-window-increase-width)
        ("M-w k" . evil-window-decrease-height)
        ("M-w j" . evil-window-increase-height))
)

Loading evil collection. Functions from this package will be referenced many times later in the configuration.

(use-package evil-collection
  :config
  (setq evil-collection-setup-minibuffer t)
)
(defvar azos/evil-color-normal "LightGoldenrod1")
(defvar azos/evil-color-emacs "LightBlue1")
(defvar azos/evil-color-insert "PaleGreen1")
(defvar azos/evil-color-replace "LightPink")
(defvar azos/evil-color-motion "LightCyan")
(defvar azos/evil-color-visual "LightGray")
(defvar azos/evil-color-operate "sandy brown")

IVY

Enabling IVY. Taken from their website.

Using ivy, hydra, counsel.

(use-package ivy
  :custom
    (ivy-use-virtual-buffers t)
    (enable-recursive-minibuffers t)
    (ivy-count-format "(%d/%d) ")
  :config
    (ivy-mode 1)
)

(use-package ivy-hydra
  :after ivy)
(use-package ivy-avy
  :after ivy)
(use-package counsel
  :after ivy

  :bind
    (:map azos/global-minor-mode/keymap
        ("M-i" . counsel-imenu)
        ("M-b" . counsel-switch-buffer)
        ("C-x C-f" . counsel-find-file))
    (:map azos/global-minor-mode/open-keymap
        ("l" . counsel-linux-app))
)

Using swiper. Replacing evil search with swiper search.

(use-package swiper
    :after ivy evil
    :config
    (setq evil-search-module 'swiper-isearch)

    :bind
    (:map azos/global-minor-mode/keymap
        ("C-s" . swiper-isearch))
)

Setting up keymaps

(evil-collection-ivy-setup)

Assorted utility functions

UI

General

Clean UI

Disabling the toolbar, the splash-screen, the menu-bar and the scroll-bar

(menu-bar-mode -1)   ; no menu bar
(when (display-graphic-p)
    (tool-bar-mode -1)   ; no tool bar with icons
    (scroll-bar-mode -1) ; no scroll bars
    (set-fringe-mode 0))

Background color

(add-to-list 'default-frame-alist '(background-color . "LightYellow"))

Fringe color

While we don't actually want fringes (almost at all), some frames use them.

;; (set-face-attribute 'fringe nil :background "LemonChiffon1")

Window dividers

(setq window-divider-default-bottom-width 1
      window-divider-default-places 'bottom-only)

(window-divider-mode 1)

Tab bar

Base

Prettification of tab bar. We only use tab-bar if the version is greater than 27.1. We also use this section to bind keys.

;; If version greater than 27.1

(defun azos/new-tab-and-rename ()
    "Created for back compatibility with emacs 27"
    (interactive)
    (progn
        (tab-bar-new-tab)
        (call-interactively 'tab-bar-rename-tab)))

(if (version<= "27.1" emacs-version) (progn
    (tab-bar-mode 1)

    (set-face-attribute 'tab-bar nil
                        :box t
                        :background "LightYellow3"
                        :foreground "DarkSlateGrey"
                        :font "LiberationMono"
                        :height 90)

    (set-face-attribute 'tab-bar-tab nil
                        :box '(:color "DarkSlateGrey" :line-width -2)
                        :background "LightYellow3"
                        :weight 'bold)

    (set-face-attribute 'tab-bar-tab-inactive nil
                        :background "LightYellow3"
                        :inherit 'tab-bar)

    (define-key azos/global-minor-mode/keymap
        (kbd "M-<tab>") 'tab-next)
    (define-key azos/global-minor-mode/keymap
        (kbd "M-'") 'tab-previous)
    (define-key azos/global-minor-mode/keymap
        (kbd "M-t r") 'tab-bar-rename-tab)
    (define-key azos/global-minor-mode/keymap
        (kbd "M-t n") 'tab-next)
    (define-key azos/global-minor-mode/keymap
        (kbd "M-t p") 'tab-previous)
    (define-key azos/global-minor-mode/keymap
        (kbd "M-t x") 'tab-bar-close-tab)
    (define-key azos/global-minor-mode/keymap
        (kbd "M-t c") 'azos/new-tab-and-rename)
    (setq tab-bar-close-button-show nil
        tab-bar-new-button-show nil
        tab-bar-separator (propertize " ● " 'face
                                      (list :foreground "LightYellow1"
                                            :box '(:color "DarkSlateGrey")))
        )
    (add-hook 'emacs-startup-hook (lambda () (tab-bar-rename-tab "home" 1)))
))

Right Group Display

(defvar azos/tab-bar/right-update-group '()
  "Functions needed to run to update tab bar")

(defvar azos/tab-bar/right-group '()
    "A list of items to be displayed on the right of the tab-bar")

(defun azos/tab-bar/right-group-func ()
  "Function that returns a string to be displayed on right of tab-bar"
  (concat
    tab-bar-separator
    (mapconcat 'eval
              (remove ""
                      (mapcar 'funcall azos/tab-bar/right-group))
              tab-bar-separator)
    tab-bar-separator))

(defun azos/tab-bar/update-func () "Function to update the tab bar"
       (progn
         (mapc 'funcall azos/tab-bar/right-update-group)
         (force-mode-line-update)))

(if (version<= "28.1" emacs-version) (progn
    (setq tab-bar-format
        '(
        tab-bar-format-history
        tab-bar-format-tabs
        tab-bar-separator
        tab-bar-format-add-tab
        tab-bar-format-align-right
        azos/tab-bar/right-group-func)
        tab-bar-auto-width nil)
    (define-key azos/global-minor-mode/keymap
        (kbd "M-n") 'tab-switch)
    ;; (if (member system-type '(gnu gnu/linux))
    ;;     (azos/run-timer 'tab-timer 'azos/tab-bar/update-func 5))
    ;; No auto-update, maybe some other way
))

Let's define a clock for the tab bar

(defun azos/tab-bar/get-clock-string () "Get tab bar time string"
       (propertize (format-time-string "%a, %b %d %H:%M")
        'face '(:background "LightYellow3" :foreground "DarkSlateGrey")))

(defun azos/tab-bar/enable-clock-display ()
  "Enables clock display in tab bar"
         (cl-pushnew 'azos/tab-bar/get-clock-string
                     azos/tab-bar/right-group))

By default let's enable the clock display

(azos/tab-bar/enable-clock-display)

Tab bar addons

Battery status in tab bar
(defun azos/bat/get-stats () "Gets battery statistics. First value returned
is battery percentage, second one is t if charging"
    (let* ((commandout (string-clean-whitespace (shell-command-to-string
        "upower -i /org/freedesktop/UPower/devices/DisplayDevice"))))
        (list
        (string-to-number (progn
            (string-match "\\(?:percentage\\:\s+\\)\\([0-9]+\\)" commandout)
            (match-string 1 commandout)))
        (progn
                    (string-match "\\(?:state\\:\s+\\)\\([^\s]+\\)" commandout)
                    (match-string 1 commandout)))
            ))

(defvar azos/bat/status-string nil "Holds battery string")

(defun azos/bat/set-status-string () "Sets battery-string"
       (let* ((bat-stats (azos/bat/get-stats))
              (bat-charge-state (nth 1 bat-stats))
              (bat-percentage-number
                (if (string= bat-charge-state "fully-charged") 100
                    (nth 0 bat-stats)))
              (bat-color (if (<= bat-percentage-number 10) "red3"
                          (if (<= bat-percentage-number 20) "DarkOrange"
                            "DarkSlateGrey")))
              (bat-weight (if (<= bat-percentage-number 20) 'bold 'normal))
              (bat-charge-symbol (if (string= bat-charge-state "charging") "↑"
                    (if (string= bat-charge-state "fully-charged") "◼" "↓"))))
          (setq azos/bat/status-string
             (concat
                "⚡" bat-charge-symbol " "
                (propertize (format "%3d" bat-percentage-number)
                             'face (list :foreground bat-color
                                    :box (list :color "DarkSlateGrey")))))))

(defun azos/bat/get-status-string () "Get battery string"
       (if azos/bat/status-string azos/bat/status-string ""))

(defun azos/bat/enable-tab-display ()
  "Enables battery display in tab bar"
    (progn
        (cl-pushnew 'azos/bat/get-status-string azos/tab-bar/right-group)
        (cl-pushnew 'azos/bat/set-status-string azos/tab-bar/right-update-group)
    ))
Network status in tab bar

Code to check for internet connection:

https://emacs.stackexchange.com/questions/7653/elisp-code-to-check-for-internet-connection

(defvar azos/network/status-string nil "Holds network status string")

(defun azos/network/get-status-string () "Gets the network status string"
       (if azos/network/status-string azos/network/status-string ""))

(defun azos/network/set-status-string-sentinel (process event)
    "Sets the network string based on proc run"
    (setq azos/network/status-string
            (concat
                "↹ "
                (if (= 0 (process-exit-status process))
                    (propertize "✓" 'face
                                (list :foreground "green3"
                                    :background "LightYellow3"
                                    :box (list :color "DarkSlateGrey")))
                    (propertize "X" 'face
                                (list :foreground "red3"
                                    :background "LightYellow3"
                                    :box (list :color "DarkSlateGrey")))))))

(defun azos/network/start-test-proc () "Tests whether internet"
       (interactive)
    (set-process-sentinel
        (start-process "wget" nil "wget" "--spider" "--timeout=1"
                       "www.google.com") 'azos/network/set-status-string-sentinel))

(defun azos/network/enable-tab-display ()
  "Enables network display in tab bar"
       (progn
         (cl-pushnew 'azos/network/get-status-string
                     azos/tab-bar/right-group)
         (cl-pushnew 'azos/network/start-test-proc
                     azos/tab-bar/right-update-group)
         ))

Easy Prompt

(defalias 'yes-or-no-p 'y-or-n-p)

Minibuff

(add-hook 'minibuffer-setup-hook
    (lambda ()
        (make-local-variable 'face-remapping-alist)
        (add-to-list 'face-remapping-alist
                    '(default (:background "WhiteSmoke")))))

Bell

Disable bell, who needs the bell?

(setq ring-bell-function (lambda () ()))

Olivetti

Useful to have even if I rarely use it.

(use-package olivetti
  :init
  (setq olivetti-body-width 96))

Modeline

Setting colors

(set-face-attribute 'mode-line nil :box nil :background "AliceBlue")
(set-face-attribute 'mode-line-inactive nil :box nil :background "LightYellow3")

We use this stackoverflow page to make left\right aligned stuff.

We use this article to try and limit the mode name length.

(setq evil-normal-state-tag
    (propertize " NORMAL  " 'face
                (list :background azos/evil-color-normal))
    evil-emacs-state-tag
    (propertize " EMACS   " 'face
                (list :background azos/evil-color-emacs))
    evil-insert-state-tag
    (propertize " INSERT  " 'face
                (list :background azos/evil-color-insert))
    evil-replace-state-tag
    (propertize " REPLACE " 'face
                (list :background azos/evil-color-replace))
    evil-motion-state-tag
    (propertize " MOTION  " 'face
                (list :background azos/evil-color-motion))
    evil-visual-state-tag
    (propertize " VISUAL  " 'face
                (list :background azos/evil-color-visual))
    evil-operator-state-tag
    (propertize " OPERATE " 'face
                (list :background azos/evil-color-operate)))

(defun azos/modeline/modeline-render (left right)
  "Return a string of `window-width' length containing LEFT, and RIGHT
 aligned respectively."
  (let* ((available-width (- (window-width) (length left) 2)))
    (format (format " %%s %%%ds " available-width) left right)))

(setq-default mode-line-buffer-identification
    (list -80 (propertized-buffer-identification "%12b")))

(setq-default mode-line-format
    '((:eval (azos/modeline/modeline-render
        ;;Left
        (concat
            (propertize (format-mode-line "%b") 'face '((:foreground "maroon")))
            (format-mode-line " (%m) "))
        ;;Right
        (concat
            (format-mode-line "%5lL%4cC ")
            evil-mode-line-tag)))))

Notifications

(require 'notifications)

Which-Key

(use-package which-key
  :config
    (which-key-mode))

Text

YASnippet

Loading yasnippet. Useful for snippeting. Mode-specific snippets defined in relevant sections.

(use-package yasnippet
  :config
    (yas-global-mode 1)
)

Text font

This section configures the base fonts. We select fonts if available (have configurations for good defaults in Linux and Windows).

Also setting default fixed-pitch and variable-pitch fonts.

Setting font size to 10. The value to place is font-size * 10

Font size 12 for variable pitch.

The function font-candidate is from https://www.gnu.org/software/emacs/manual/html_mono/cl.html.

(let ((variable-font (azos/font-candidate
                      "Liberation Serif" "Microsoft Sans Serif")))
    (if variable-font
        (set-face-attribute 'variable-pitch nil :font variable-font)))

(let ((fixed-font (azos/font-candidate
                   "Source Code Pro" "LiberationMono" "Consolas")))
    (if fixed-font (progn
        (set-face-attribute 'default nil :font fixed-font)
        (set-face-attribute 'fixed-pitch nil :font fixed-font))))

(set-face-attribute 'default nil :height 100)
(set-face-attribute 'variable-pitch nil
    :height 130
    :weight 'normal
    :width 'normal)

(set-face-attribute 'fixed-pitch nil
    :height 100
    :weight 'normal
    :width 'normal)

(defun azos/default-variable-pitch ()
    (face-remap-add-relative 'default '(:inherit 'variable-pitch)))

Line numbering

We want line numbering, but only in modes where it makes sense.

To do this, a custom minor-mode, azos/global-linum-mode, is created. This mode selectively activates linum-mode if the mode is not one of a selected exempt modes. These exempt modes are defined in display-line-numbers-exempt-modes.

Taken from this wiki entry.

(use-package display-line-numbers
    :init
        (defcustom azos/display-line-numbers-exempt-modes
            '(vterm-mode
              eshell-mode
              shell-mode
              term-mode
              ansi-term-mode
              magit-mode
              magit-diff-mode
              notmuch-hello
              pdf-view-mode)
            "Major modes on which to disable the linum mode, exempts them."
            :group 'display-line-numbers
            :type 'list
            :version "green")

        (define-global-minor-mode azos/global-linum-mode
            display-line-numbers-mode
            (lambda () (if (and
                (not (apply 'derived-mode-p
                            azos/display-line-numbers-exempt-modes))
                (not (minibufferp)))
            (display-line-numbers-mode))))

        (setq display-line-numbers-type 'visual
            display-line-numbers-grow-only 1
            display-line-numbers-width-start 1)

    :config
        (azos/global-linum-mode 1)
        (set-face-attribute 'line-number nil
            :family (face-attribute 'fixed-pitch :family))
)

Line highlight

Highlighting line with cursor.

Modification done to use EVIL colors on highlighted line.

(global-hl-line-mode)
(set-face-attribute 'hl-line nil :background azos/evil-color-emacs)

(defface hl-line-normal
  (list (list t (list :inherit 'hl-line :background  azos/evil-color-normal
                      :extend t)))
    "Highlight face for evil normal mode."
    :group 'hl-line)

(defface hl-line-insert
  (list (list t (list :inherit 'hl-line :background  azos/evil-color-insert
                      :extend t)))
    "Highlight face for evil insert mode."
    :group 'hl-line)

(defface hl-line-emacs
  (list (list t (list :inherit 'hl-line :background  azos/evil-color-emacs
                      :extend t)))
    "Highlight face for evil insert mode."
    :group 'hl-line)

(defface hl-line-replace
  (list (list t (list :inherit 'hl-line :background  azos/evil-color-replace
                      :extend t)))
    "Highlight face for evil insert mode."
    :group 'hl-line)

(defface hl-line-motion
  (list (list t (list :inherit 'hl-line :background  azos/evil-color-motion
                      :extend t)))
    "Highlight face for evil insert mode."
    :group 'hl-line)

(defface hl-line-visual
  (list (list t (list :inherit 'hl-line :background  azos/evil-color-visual
                      :extend t)))
    "Highlight face for evil insert mode."
    :group 'hl-line)

(defface hl-line-operate
  (list (list t (list :inherit 'hl-line :background  azos/evil-color-operate
                      :extend t)))
    "Highlight face for evil insert mode."
    :group 'hl-line)

(defun azos/hl-line-evil/set-hl-state (state-face)
  "Refresh hl-line to be state-face"
  (progn
    (global-hl-line-unhighlight)
    (setq-local hl-line-face state-face)
    (global-hl-line-highlight)))
(add-hook 'evil-insert-state-entry-hook
          (lambda () (azos/hl-line-evil/set-hl-state 'hl-line-insert)))
(add-hook 'evil-normal-state-entry-hook
          (lambda () (azos/hl-line-evil/set-hl-state 'hl-line-normal)))
(add-hook 'evil-emacs-state-entry-hook
          (lambda () (azos/hl-line-evil/set-hl-state 'hl-line-emacs)))
(add-hook 'evil-replace-state-entry-hook
          (lambda () (azos/hl-line-evil/set-hl-state 'hl-line-replace)))
(add-hook 'evil-motion-state-entry-hook
          (lambda () (azos/hl-line-evil/set-hl-state 'hl-line-motion)))
(add-hook 'evil-visual-state-entry-hook
          (lambda () (azos/hl-line-evil/set-hl-state 'hl-line-visual)))
(add-hook 'evil-operate-state-entry-hook
          (lambda () (azos/hl-line-evil/set-hl-state 'hl-line-operate)))

Line wrap

Don't want to have to scroll to see more chars.

(global-visual-line-mode t)

Parenthesis

Highlight matching parenthesis

(show-paren-mode 1)

Tabs

Using spaces instead of tabs, default offset is 4.

(setq-default indent-tabs-mode nil
              tab-width 4
              c-basic-offset 4
              tab-always-indent 'complete)

BIDI and lang

Setting up Hebrew as alternative input, using bidi mode so that every line is aligned left\right accordingly.

(setq-default default-input-method "hebrew"
              bidi-display-reordering t
              bidi-paragraph-direction 'nil)

(defun azos/set-bidi-env ()
    (setq bidi-paragraph-direction 'nil)
)

(define-key azos/global-minor-mode/keymap
    (kbd "C-SPC") 'toggle-input-method)

Whitespace mode

We define a custom global-whitespace-mode in order to enable it only on relevant modes.

We check if the current mode doesn't derive from a set of blacklisted mode, the main culprit being terminal modes where whitespace occur naturally and are a pain to see all the time.

(setq-default whitespace-style
      '(face tabs trailing tab-mark
             lines-tail indentation))

(defun azos/whitespace-mode-func ()
  (interactive)
    (if (derived-mode-p 'text-mode 'prog-mode 'org-mode)
        (whitespace-mode 1) (whitespace-mode -1)))

(add-hook 'after-change-major-mode-hook 'azos/whitespace-mode-func)

Commenter

Quick keybindings to comment out regions.

(use-package evil-nerd-commenter
  :config
  (define-key evil-normal-state-map (kbd "C-;")
    'evilnc-comment-or-uncomment-lines))

Company mode

Auto completion framework.

(use-package company
  :ensure t
  :defer t
  :init (add-hook 'after-init-hook 'global-company-mode)
  :config
  ;; (use-package company-irony :ensure t :defer t)
  (setq
        company-minimum-prefix-length   2
        company-show-numbers            t
        company-tooltip-limit           20
        company-idle-delay              0.2
  )
  :bind ("C-;" . company-complete-common)
  ;; :hook (irony-mode . company-mode)
  )

Folding

(add-hook 'prog-mode-hook 'hs-minor-mode)

Mode specific

Undo tree

Loading undo-tree for undo/redo functionality with evil.

Redo taken from https://github.com/syl20bnr/spacemacs/issues/14036

(use-package undo-tree
  :after evil
  :config
    (evil-set-undo-system 'undo-tree)
    (setq undo-tree-history-directory-alist
        (list (cons "." (concat user-emacs-directory "undo-tree"))))
    (global-undo-tree-mode 1)
)

Projectile

Startup up projectile.

A config line here disables modeline display because I don't want my modeline to be cluttered.

Mapping modeline commands to M-p prefix. Also adding a shortcut to add project.

(use-package projectile
  :config
    (projectile-mode +1)
    (setq projectile-mode-line-function (lambda () ""))
  :bind
    (:map projectile-command-map
          ("a" . projectile-add-known-project)
    )
    (:map azos/global-minor-mode/keymap
          ("M-p" . projectile-command-map))
)

Ivy for projectile: Parts taken from this post and this post from StackOverflow.

Helps with many functions to use counsel's/ivy's autocomplete with projectile.

(use-package counsel-projectile
  :after counsel projectile
  :config
    (counsel-projectile-mode +1)
    (setq projectile-completion-system 'ivy)
    ;Making counsel start with empty regex
    (when (commandp 'counsel-M-x)
        (global-set-key [remap execute-extended-command] 'counsel-M-x))
    (setcdr (assoc 'counsel-M-x ivy-initial-inputs-alist) "")
)

Tramp

Ensuring tramp is loaded, and loading counsel-tramp for easy tramping.

(use-package tramp
  :straight (:type built-in))

(use-package counsel-tramp)

Dired

Need to autoload dired-x for dired-omit

;; (autoload 'dired-omit-mode "dired-x")
(setq dired-omit-files "^\\...+$")
(add-hook 'dired-mode-hook 'dired-omit-mode)
(add-hook 'dired-mode-hook 'dired-hide-details-mode)
(evil-collection-dired-setup)
(use-package dired-subtree
    :config
    (evil-collection-define-key 'normal 'dired-mode-map
        (kbd "SPC") 'dired-subtree-toggle
        (kbd "TAB") 'dired-subtree-cycle
        )
    (setq dired-subtree-use-backgrounds nil)
    ;Evil collection binds these keys, we need them for window movement
    (evil-collection-define-key 'normal 'dired-mode-map
        (kbd "M-j") nil
        (kbd "M-k") nil)
)

Magit

(use-package magit
    :config
        (evil-collection-magit-setup)
    :bind
        (:map azos/global-minor-mode/open-keymap
            ("g" . 'magit-status))
)

Org

Base

(require 'org-faces)
(defun azos/set-org-mode-fixed-pitch-faces ()
    (mapc (lambda (face) (set-face-attribute face nil
                :font (face-attribute 'fixed-pitch :font)
                :height (face-attribute 'fixed-pitch :height)))
    `(line-number
        org-block
        org-special-keyword
        org-drawer
        org-todo
        org-done
        org-priority
        org-checkbox
        org-block-end-line
        org-block-begin-line
        org-table
        org-verbatim)))

(use-package org
    :hook
        (org-mode . variable-pitch-mode)
        (org-mode . azos/set-bidi-env)
        (org-mode . (lambda ()
            (setq-local whitespace-style '(face tabs trailing tab-mark
            indentation))))
    :config
        (azos/set-org-mode-fixed-pitch-faces)
        (setq org-src-tab-acts-natively t
              org-adapt-indentation nil
              org-startup-folded t
              org-hide-emphasis-markers t)
        (set-face-attribute 'org-code nil
            :family (face-attribute 'fixed-pitch :family))
        (set-face-attribute 'org-block nil
            :family (face-attribute 'fixed-pitch :family))
    :bind
        ("C-a" . nil)
        ("C-a l" . org-toggle-latex-fragment)
)

#+end_src

Code blocks

The following displays the contents of code blocks in Org-mode files using the major-mode of the code. It also changes the behavior of TAB to as if it were used in the appropriate major mode.

(setq org-src-fontify-natively t
      org-src-tab-acts-natively t
      org-src-preserve-indentation t)

(set-face-attribute 'org-block nil
    :background "LemonChiffon1")
(set-face-attribute 'org-block-begin-line nil
    :background "LightYellow2")
(set-face-attribute 'org-block-end-line nil
    :background "LightYellow2")

Babel

Define languages to use

(require 'ob)
(require 'ob-tangle)

;; TODO Not sure I like this here
(org-babel-do-load-languages
 'org-babel-load-languages
 '((shell . t)
   (emacs-lisp . t)
   (python . t)
   (org . t)
   (lilypond . t)
   (latex . t)
   (js . t)
   (java . t)
   (dot . t)
   (C . t)))

;; TODO move these around
;; (add-to-list 'org-src-lang-modes (quote ("dot". graphviz-dot)))
;; (add-to-list 'org-src-lang-modes (quote ("plantuml" . fundamental)))
;; (add-to-list 'org-babel-tangle-lang-exts '("clojure" . "clj"))

This section makes code-indentation correction work inside source blocks. Taken from: https://github.com/emacs-evil/evil/issues/1288

(defun azos/org/evil-org-insert-state-in-edit-buffer (fun &rest args)
  "Bind `evil-default-state' to `insert' before calling FUN with ARGS."
  (let ((evil-default-state 'insert)
        ;; Force insert state
        evil-emacs-state-modes
        evil-normal-state-modes
        evil-motion-state-modes
        evil-visual-state-modes
        evil-operator-state-modes
        evil-replace-state-modes)
    (apply fun args)
    (evil-refresh-cursor)))

(advice-add 'org-babel-do-key-sequence-in-edit-buffer
            :around #'azos/org/evil-org-insert-state-in-edit-buffer)

Fonts

Fonts

;; (set-face-attribute 'org-document-title nil :height 200 :underline t)

Inline images

(setq org-startup-with-inline-images t)

(defun azos/org/shk-fix-inline-images ()
  (when org-inline-image-overlays
    (org-redisplay-inline-images)))

(with-eval-after-load 'org
  (add-hook 'org-babel-after-execute-hook 'azos/org/shk-fix-inline-images))

Snippets

Want to create snippets for latex insertion. There is one template for inline and one template for standalone latex snippets. Each template is defind by two templates. One for other langauges and one for standard input. This is done to toggle back to the original language once done with the function toggle-input-method.

(defun azos/org/toggle-input-method ()
    (if current-input-method (toggle-input-method))
)
;Inline
(add-hook 'org-mode-hook (lambda () (progn
    (yas-define-snippets 'org-mode (list (list
                                      nil
                                      "\$$1\$$0"
                                      "ORG_LATEX_INLINE_SNIPPET_ENG"
                                      '(not (eval current-input-method))
                                      nil
                                      nil
                                      nil
                                      "C-l"
                                      nil
                                      nil
                                      )))

    (yas-define-snippets 'org-mode (list (list
                                      nil
                                      "\$$1\$$0"
                                      "ORG_LATEX_INLINE_SNIPPET_OTHER_LANG"
                                      '(eval current-input-method)
                                      nil
                                      '((unused (azos/org/toggle-input-method))
                                        (yas-after-exit-snippet-hook 'toggle-input-method))
                                      nil
                                      "C-l"
                                      nil
                                      nil
                                      )))

    ;Not inline
    (yas-define-snippets 'org-mode (list (list
                                      nil
                                      "\$\$$1\$\$$0"
                                      "ORG_LATEX_OUTLINE_SNIPPET_ENG"
                                      '(not (eval current-input-method))
                                      nil
                                      nil
                                      nil
                                      "C-S-l"
                                      nil
                                      nil
                                      )))
    (yas-define-snippets 'org-mode (list (list
                                      nil
                                      "\$\$$1\$\$$0"
                                      "ORG_LATEX_OUTLINE_SNIPPET_OTHER_LANG"
                                      '(eval current-input-method)
                                      nil
                                      '((unused (azos/org/toggle-input-method))
                                        (yas-after-exit-snippet-hook 'toggle-input-method))
                                      nil
                                      "C-S-l"
                                      nil
                                      nil
                                      )))
    )))

Snippet for src blocks

(add-hook 'org-mode-hook (lambda () (progn
    (yas-define-snippets 'org-mode (list (list
                                      nil
                                      "#+begin_src $1\n$0\n#+end_src"
                                      "ORG_SRC_BLOCK"
                                      nil
                                      nil
                                      nil
                                      nil
                                      "C-c i b"
                                      nil
                                      nil
                                      )))

    (yas-define-snippets 'org-mode (list (list
                                      nil
                                      (concat
                                        "#+begin_export latex\n"
                                        "\\begin{english}\n"
                                        "#+end_export\n"
                                        "#+begin_src $1\n"
                                        "$0\n#+end_src\n"
                                        "#+begin_export latex\n"
                                        "\\end{english}\n"
                                        "#+end_export")
                                      "ORG_SRC_ENGLISH_BLOCK"
                                      nil
                                      nil
                                      nil
                                      nil
                                      "C-c i B"
                                      nil
                                      nil
                                      )))
)))

Imenu quirks

(add-to-list 'org-show-context-detail '(isearch . tree))
(add-to-list 'org-show-context-detail '(default . tree))

Ibuffer

(evil-collection-ibuffer-setup)
(define-key azos/global-minor-mode/keymap
    (kbd "C-x C-b") 'ibuffer)

Dashboard

(setq inhibit-startup-screen t)
(use-package dashboard
  :config
  (add-hook 'after-init-hook
            (lambda () (dashboard-insert-startupify-lists)))
  (add-hook 'emacs-startup-hook (lambda ()
                                  (switch-to-buffer dashboard-buffer-name)
                                  (goto-char (point-min))
                                  (redisplay)
                                  (run-hooks 'dashboard-after-initialize-hook)))
  (add-to-list 'evil-emacs-state-modes 'dashboard-mode)
  (setq dashboard-items '((recents  . 5)
                          (bookmarks . 5)
                          (projects . 5))
        dashboard-center-content t
        dashboard-banner-logo-title nil
        dashboard-set-init-info nil
        dashboard-set-footer nil
        dashboard-startup-banner 'ascii
        dashboard-banner-ascii "azos"))

VTerm

;; (use-package xterm-color :ensure t)
;; (use-package eterm-256color :ensure t
;;   :config
;;   (add-hook 'term-mode-hook #'eterm-256color-mode)
;;   (add-hook 'vterm-mode-hook #'eterm-256color-mode)
;;   )
(use-package vterm
  :if  (member system-type '(gnu gnu/linux))
  :config
    (add-hook 'vterm-mode-hook
            (lambda () (setq-local global-hl-line-mode nil)))

    (evil-collection-define-key 'normal 'vterm-mode-map
      (kbd "p") 'vterm-yank)
    (setq vterm-timer-delay 0.01
          vterm-term-environment-variable "xterm-256color"))

Boomkark

(use-package bookmark
    :straight
        (:type built-in)
    :config
    (evil-collection-bookmark-setup)
)

Provide

(provide 'azos-emacs-base)
(add-hook 'after-init-hook (lambda () (require 'azos-emacs-base)))