Compare commits
12
Commits
625713cbb4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c43ff55d32 | ||
|
|
62e4feba61 | ||
|
|
d2e47dec2a | ||
|
|
d2de783f3b | ||
|
|
1c4f950e3f | ||
|
|
2e6bbc77fd | ||
|
|
60c8d863d3 | ||
|
|
30c87a36af | ||
|
|
5ddfe643c3 | ||
|
|
ce6b1aa6f0 | ||
|
|
8313889ac4 | ||
|
|
9b63be7856 |
+11
-13
@@ -1,23 +1,21 @@
|
||||
config/emacs/backups/
|
||||
config/emacs/eln-cache/
|
||||
config/emacs/elpa/
|
||||
config/emacs/auto-save/
|
||||
config/emacs/auto-save-list/
|
||||
config/emacs/custom.el
|
||||
config/emacs/places.eld
|
||||
config/emacs/projects.eld
|
||||
config/emacs/recentf.eld
|
||||
# emacs
|
||||
config/emacs/.ignore
|
||||
config/emacs/session*
|
||||
config/emacs/history
|
||||
config/emacs/var/
|
||||
config/emacs/elfeed/
|
||||
config/emacs/eshell/
|
||||
config/emacs/auto-save-list/
|
||||
# fish
|
||||
config/fish/conf.d
|
||||
config/fish/functions
|
||||
config/fish/fish_variables
|
||||
config/fish/generated_completions/
|
||||
# vim/nvim
|
||||
config/vim/autoload/
|
||||
config/vim/pack/
|
||||
config/vim/.netrwhist
|
||||
config/nvim/nvim-pack-lock.json
|
||||
config/awesome/bling
|
||||
scripts/bin/Obsidian
|
||||
# other
|
||||
scripts/bin/ols
|
||||
scripts/bin/deno
|
||||
scripts/bin/yt-dlp
|
||||
scripts/bin/tiled
|
||||
@@ -1,40 +0,0 @@
|
||||
;;;; Markdown
|
||||
(use-package markdown-mode)
|
||||
|
||||
;;;; Odin
|
||||
(use-package odin-mode
|
||||
:vc (:url "https://github.com/mattt-b/odin-mode"
|
||||
:rev :newest)
|
||||
:mode "\\.odin\\'"
|
||||
:hook (odin-mode . eglot-ensure))
|
||||
|
||||
(use-package eglot
|
||||
:ensure nil
|
||||
:config
|
||||
(setq eglot-autoshutdown t)
|
||||
(add-to-list 'eglot-ignored-server-capabilities :signatureHelpProvider)
|
||||
|
||||
;; Explicit OLS configuration.
|
||||
(add-to-list
|
||||
'eglot-server-programs
|
||||
'(odin-mode
|
||||
. ("/home/jason/.local/bin/ols"
|
||||
:initializationOptions
|
||||
(:odin_command "/home/jason/.odin/odin"
|
||||
:enable_document_symbols t
|
||||
:enable_format t
|
||||
:collections
|
||||
[(:name "core"
|
||||
:path "/home/jason/.odin/core")
|
||||
(:name "vendor"
|
||||
:path "/home/jason/.odin/vendor")])))))
|
||||
|
||||
;; OLS built-in definitions.
|
||||
(setenv "OLS_BUILTIN_FOLDER" "/home/jason/ThirdParty/ols/builtin")
|
||||
|
||||
;; Vim-style code navigation.
|
||||
(evil-define-key '(normal motion) 'global
|
||||
"gd" #'xref-find-definitions
|
||||
"gD" #'xref-find-references
|
||||
"K" #'eldoc
|
||||
(kbd "C-t") #'xref-go-back)
|
||||
@@ -1,8 +1,6 @@
|
||||
;;; early-init.el --- Pre-init: GC ceiling and frame chrome -*- lexical-binding: t; -*-
|
||||
|
||||
;;; Commentary:
|
||||
;; Runs before package.el initialises and before the first frame is drawn, so
|
||||
;; it is the only place two things can take effect:
|
||||
;; Runs before package.el initialises and first frame is drawn, the only place these take effect:
|
||||
;; 1. Raising the GC ceiling, so the whole startup (package load + init.el)
|
||||
;; runs without garbage-collection pauses.
|
||||
;; 2. Removing the menu/tool/scroll bars via `default-frame-alist', so they
|
||||
@@ -10,17 +8,11 @@
|
||||
;; them and then removes them, a visible flicker on launch.
|
||||
;;
|
||||
;; Nothing here may depend on a package: none are loaded yet.
|
||||
;;
|
||||
;; IMPORTANT: the GC bump below is only half the pair. Restore a working value
|
||||
;; once startup is done by adding this to init.el:
|
||||
;;
|
||||
;; (add-hook 'emacs-startup-hook
|
||||
;; (lambda () (setq gc-cons-threshold (* 16 1024 1024))))
|
||||
;;
|
||||
;; Without it, GC never runs again and Emacs slowly eats memory.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(startup-redirect-eln-cache (expand-file-name "var/eln-cache/" user-emacs-directory))
|
||||
(setq package-user-dir (expand-file-name "var/elpa/" user-emacs-directory))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Garbage Collection
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
+62
-107
@@ -1,20 +1,40 @@
|
||||
;;; init.el --- Minimal Emacs: built-ins + evil + consult -*- lexical-binding: t; -*-
|
||||
;; Learning: F1 k KEY, F1 f FUNCTION, F1 v VARIABLE,
|
||||
;; F1 m (modes), F1 b (bindings).
|
||||
;; C-h works too, except in normal/motion state where it moves
|
||||
;; to the window on the left.
|
||||
;;; Code:
|
||||
;; Learning: F1 k KEY, F1 f FUNCTION, F1 v VARIABLE, F1 m (modes), F1 b (bindings).
|
||||
;; C-h works too, except in normal/motion state where it moves to the window on the left.
|
||||
|
||||
;;;; 1. Basics
|
||||
(let ((bin (expand-file-name "~/.local/bin")))
|
||||
;;; Code:
|
||||
;;;; 1. Emac setup, gc, files, packages
|
||||
(add-hook 'emacs-startup-hook
|
||||
(lambda () (setq gc-cons-threshold (* 16 1024 1024))))
|
||||
|
||||
(dolist (bin (list (expand-file-name "~/.local/bin")
|
||||
(expand-file-name "~/.go/bin")))
|
||||
(add-to-list 'exec-path bin)
|
||||
(setenv "PATH" (concat bin path-separator (getenv "PATH"))))
|
||||
|
||||
;; Custom's output goes to its own file, not here.
|
||||
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
|
||||
;; Add the themes directory to the load path
|
||||
(add-to-list 'custom-theme-load-path (expand-file-name "themes" user-emacs-directory))
|
||||
|
||||
;; all the emacs runtime files live in var/.
|
||||
;; early-init.el redirects eln-cache and elpa.
|
||||
(defvar my/var (locate-user-emacs-file "var/"))
|
||||
(make-directory (concat my/var "transient/") t)
|
||||
(setq savehist-file (concat my/var "history")
|
||||
save-place-file (concat my/var "places.eld")
|
||||
recentf-save-file (concat my/var "recentf.eld")
|
||||
project-list-file (concat my/var "projects.eld")
|
||||
transient-history-file (concat my/var "transient/history.el")
|
||||
transient-levels-file (concat my/var "transient/levels.el")
|
||||
transient-values-file (concat my/var "transient/values.el"))
|
||||
|
||||
;; Custom output goes to its own file, not here.
|
||||
(setq custom-file (expand-file-name "var/custom.el" user-emacs-directory))
|
||||
(load custom-file 'noerror 'nomessage)
|
||||
|
||||
;; Package archives: GNU and NonGNU are built in, MELPA is added at lowest priority.
|
||||
;; No session manager save: stops the empty session.* files.
|
||||
(add-hook 'emacs-save-session-functions #'always)
|
||||
|
||||
;; Package GNU, NonGNU are built in melpa additional lowest priority.
|
||||
(require 'package)
|
||||
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
|
||||
(setq package-archive-priorities '(("gnu" . 3) ("nongnu" . 2) ("melpa" . 1)))
|
||||
@@ -23,21 +43,20 @@
|
||||
(require 'use-package)
|
||||
(setq use-package-always-ensure t)
|
||||
|
||||
;;;; 2. UI
|
||||
;;;; 2. Ui settings, theme setup and fonts
|
||||
(add-to-list 'default-frame-alist '(fullscreen . maximized))
|
||||
(menu-bar-mode -1)
|
||||
(tool-bar-mode -1)
|
||||
(scroll-bar-mode -1)
|
||||
(blink-cursor-mode -1)
|
||||
|
||||
(setq inhibit-startup-screen t
|
||||
initial-scratch-message nil
|
||||
ring-bell-function #'ignore
|
||||
use-short-answers t
|
||||
scroll-conservatively 101
|
||||
scroll-margin 15)
|
||||
scroll-margin 20)
|
||||
|
||||
(setq-default indent-tabs-mode nil
|
||||
tab-width 4)
|
||||
(setq-default indent-tabs-mode nil tab-width 4)
|
||||
|
||||
(global-hl-line-mode 1)
|
||||
(global-display-line-numbers-mode 1)
|
||||
@@ -46,43 +65,26 @@
|
||||
(electric-pair-mode 1)
|
||||
(which-key-mode 1)
|
||||
|
||||
;; Jellybeans theme.
|
||||
(add-to-list 'warning-suppress-types '(files))
|
||||
(use-package jbeans-theme
|
||||
:config
|
||||
(load-theme 'jbeans t))
|
||||
;; Load the compline theme
|
||||
(load-theme 'minimal t)
|
||||
|
||||
;; Font, on a darker background than the theme's.
|
||||
(set-face-attribute 'default nil
|
||||
:family "JetBrainsMono Nerd Font"
|
||||
:height 120
|
||||
:background "#131313")
|
||||
|
||||
;; Mode line at the top of each window: the header line takes over its
|
||||
;; format and look, on the editor background.
|
||||
;; set mode line at the top of each window
|
||||
(setq-default header-line-format mode-line-format mode-line-format nil)
|
||||
(set-face-attribute 'header-line nil :inherit 'mode-line :background "#131313")
|
||||
|
||||
(set-face-attribute 'default nil :family "JetBrainsMono Nerd Font" :height 120)
|
||||
(setq-default line-spacing '(4 . 4))
|
||||
|
||||
;; Command launcher.
|
||||
(keymap-global-set "C-S-p" #'execute-extended-command)
|
||||
|
||||
;; Escape cancels prompts. keyboard-quit can't leave the minibuffer, so there
|
||||
;; Escape runs abort-minibuffers, as C-g does.
|
||||
;; Escape behaves like C-g
|
||||
(keymap-global-set "<escape>" #'keyboard-quit)
|
||||
(keymap-set minibuffer-local-map "<escape>" #'abort-minibuffers)
|
||||
|
||||
(add-to-list 'default-frame-alist '(fullscreen . maximized))
|
||||
|
||||
;;;; 3. Files
|
||||
(dolist (d '("backups/" "auto-save/"))
|
||||
(make-directory (locate-user-emacs-file d) t))
|
||||
|
||||
(setq backup-directory-alist
|
||||
`(("." . ,(locate-user-emacs-file "backups/")))
|
||||
auto-save-file-name-transforms
|
||||
`((".*" ,(locate-user-emacs-file "auto-save/") t))
|
||||
(setq make-backup-files nil
|
||||
auto-save-default nil
|
||||
auto-save-list-file-prefix nil
|
||||
create-lockfiles nil
|
||||
confirm-kill-processes nil
|
||||
vc-follow-symlinks t)
|
||||
@@ -93,8 +95,7 @@
|
||||
(global-auto-revert-mode 1)
|
||||
|
||||
;;;; 4. Completion
|
||||
;; C-n/C-p move through candidates: Vertico remaps next-line/previous-line,
|
||||
;; and section 5 stops Evil from taking those keys in the minibuffer.
|
||||
;; C-n/C-p navigates up and down, section 5 stops evil from overrriding
|
||||
(use-package vertico
|
||||
:init
|
||||
(vertico-mode 1)
|
||||
@@ -117,7 +118,6 @@
|
||||
(vertico-posframe-mode 1))
|
||||
|
||||
;;;; 5. Evil
|
||||
;; Evil 1.15.0 on Emacs 31 reads this legacy variable, which Emacs no longer defines.
|
||||
(defvar evil-mode-buffers nil)
|
||||
|
||||
(defun my/insert-tab ()
|
||||
@@ -127,38 +127,27 @@
|
||||
|
||||
(use-package evil
|
||||
:init
|
||||
;; evil-want-keybinding: Evil Collection (below) supplies mode bindings instead
|
||||
;; of Evil's small built-in set. It has to be set before Evil loads.
|
||||
(setq evil-want-C-u-scroll t
|
||||
evil-undo-system 'undo-redo
|
||||
evil-want-keybinding nil)
|
||||
|
||||
:config
|
||||
(evil-mode 1)
|
||||
|
||||
(evil-define-key 'insert 'global
|
||||
;; Literal tab. <tab> as well, or a mode's own <tab> binding wins in GUI frames.
|
||||
(kbd "TAB") #'my/insert-tab
|
||||
(kbd "<tab>") #'my/insert-tab
|
||||
(kbd "C-SPC") #'completion-at-point)
|
||||
|
||||
;; C-SPC: complete using the buffer's completion sources.
|
||||
(kbd "C-SPC") #'completion-at-point
|
||||
(kbd "C-@") #'completion-at-point)
|
||||
|
||||
;; Global navigation.
|
||||
;; C-p, C-f and C-b are assigned to Consult below.
|
||||
;; C-p and C-f are assigned to Consult below, C-m to ibuffer.
|
||||
(evil-define-key '(normal motion) 'global
|
||||
(kbd "C-e") #'dired-jump))
|
||||
|
||||
;; Evil Collection: vim-style bindings for other packages, one mode at a time.
|
||||
;; Info here (F1 i); Magit, Magit sections and commit messages in git.el.
|
||||
(use-package evil-collection
|
||||
:after evil
|
||||
:custom
|
||||
;; Don't add its global [b ]b [e ]e ... bindings.
|
||||
(evil-collection-want-unimpaired-p nil)
|
||||
:config
|
||||
(evil-collection-init '(info)))
|
||||
(evil-collection-init '(info ibuffer)))
|
||||
|
||||
;; Minibuffer. Vertico
|
||||
(with-eval-after-load 'vertico
|
||||
@@ -171,15 +160,6 @@
|
||||
(evil-define-key '(insert normal) minibuffer-local-map
|
||||
(kbd "<escape>") #'abort-minibuffers)
|
||||
|
||||
;; Window navigation (normal/motion state): Ctrl+hjkl move, Ctrl+` closes.
|
||||
;; GUI only for C-`: terminals send it as C-@.
|
||||
(evil-define-key '(normal motion) 'global
|
||||
(kbd "C-h") #'windmove-left
|
||||
(kbd "C-j") #'windmove-down
|
||||
(kbd "C-k") #'windmove-up
|
||||
(kbd "C-l") #'windmove-right
|
||||
(kbd "C-`") #'delete-window)
|
||||
|
||||
;; Result buffers: hjkl motions and RET to jump to a result.
|
||||
(dolist (m '(occur-mode grep-mode xref--xref-buffer-mode))
|
||||
(evil-set-initial-state m 'motion))
|
||||
@@ -206,22 +186,16 @@
|
||||
;; Searches start at the project root when there is one, else the current directory.
|
||||
(use-package consult
|
||||
:config
|
||||
;; Hide noise from the buffer picker.
|
||||
(dolist (re '("\\`\\*scratch\\*\\'"
|
||||
"\\`\\*Messages\\*\\'"
|
||||
"\\`\\*Warnings\\*\\'"
|
||||
"\\`\\*xref\\*\\'"))
|
||||
(add-to-list 'consult-buffer-filter re))
|
||||
|
||||
;; Don't re-run the preview on every keystroke while typing a search.
|
||||
(consult-customize consult-ripgrep
|
||||
:preview-key '(:debounce 0.4 any)))
|
||||
|
||||
;; Bind immediately, without waiting for consult to load.
|
||||
;; C-m opens the full ibuffer list (evil-collection provides its navigation).
|
||||
(evil-define-key '(normal motion) 'global
|
||||
(kbd "C-p") #'consult-fd
|
||||
(kbd "C-f") #'consult-ripgrep
|
||||
(kbd "C-b") #'consult-buffer)
|
||||
(kbd "C-m") #'ibuffer)
|
||||
|
||||
;;;; 7. Dired
|
||||
(setq dired-dwim-target t
|
||||
@@ -231,50 +205,31 @@
|
||||
delete-by-moving-to-trash t)
|
||||
|
||||
(with-eval-after-load 'dired
|
||||
(require 'dired-x)
|
||||
(setq dired-omit-files "\\`\\.")
|
||||
(add-hook 'dired-mode-hook #'dired-omit-mode)
|
||||
(evil-set-initial-state 'dired-mode 'motion)
|
||||
|
||||
(evil-define-key 'motion dired-mode-map
|
||||
"h" #'dired-up-directory
|
||||
"l" #'dired-find-file
|
||||
"." #'dired-omit-mode
|
||||
(kbd "RET") #'dired-find-file))
|
||||
|
||||
;;;; 8. Build
|
||||
(setq compile-command "./build.sh"
|
||||
compilation-read-command nil
|
||||
compilation-ask-about-save nil
|
||||
compilation-scroll-output t)
|
||||
;;;; Core config ends here.
|
||||
;;;; -----------------------------------------------------------------
|
||||
;;;; 8. Modules - additional functionality outside of the core init.el
|
||||
|
||||
(add-hook 'compilation-filter-hook #'ansi-color-compilation-filter)
|
||||
;; Setup for orgmode
|
||||
(load (locate-user-emacs-file "modules/org.el") nil 'nomessage)
|
||||
|
||||
;; Compilation buffer always at the bottom, full frame width.
|
||||
(add-to-list 'display-buffer-alist
|
||||
'((derived-mode . compilation-mode)
|
||||
(display-buffer-reuse-window display-buffer-at-bottom)
|
||||
(window-height . 0.45)))
|
||||
;; Magit and the :git command live in modules/git.el.
|
||||
(load (locate-user-emacs-file "modules/git.el") nil 'nomessage)
|
||||
|
||||
;; C-c C-c builds from the project root.
|
||||
;; C-c b asks first: the prompt is pre-filled with ./build.sh, so type the args after it.
|
||||
(defun my/project-compile-prompt ()
|
||||
"Run `project-compile', prompting to edit the command."
|
||||
(interactive)
|
||||
(let ((compilation-read-command t))
|
||||
(call-interactively #'project-compile)))
|
||||
;; Setup for personal build commands and system.
|
||||
(load (locate-user-emacs-file "modules/build.el") nil 'nomessage)
|
||||
|
||||
(keymap-global-set "C-c C-c" #'project-compile)
|
||||
(keymap-global-set "C-c b" #'my/project-compile-prompt)
|
||||
|
||||
;; Focus the compilation window when a build starts.
|
||||
(add-hook 'compilation-start-hook
|
||||
(lambda (proc)
|
||||
(when-let* ((win (get-buffer-window (process-buffer proc))))
|
||||
(select-window win))))
|
||||
|
||||
;;;; 9. Languages
|
||||
;; Setup for dev languages, modes, lsp and lsp keybinds.
|
||||
(load (locate-user-emacs-file "development.el") nil 'nomessage)
|
||||
|
||||
;;;; 10. Git
|
||||
;; Magit and the :git command live in git.el, next to this file.
|
||||
(load (locate-user-emacs-file "git.el") nil 'nomessage)
|
||||
(load (locate-user-emacs-file "modules/dev.el") nil 'nomessage)
|
||||
|
||||
;;; init.el ends here
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
;;; build.el --- Project build, set up for Evil -*- lexical-binding: t; -*-
|
||||
;;; Commentary:
|
||||
;; Loaded from init.el after Evil.
|
||||
;;
|
||||
;; :build Run ./build.sh from the nearest ancestor dir containing it.
|
||||
;; :build ARGS Run ./build.sh ARGS, e.g. :build release -v
|
||||
;;
|
||||
;; If no build.sh is found (or it isn't executable), report it and do nothing.
|
||||
;;
|
||||
;; The compilation buffer opens at the bottom (45% height, full width) and
|
||||
;; takes focus when the build starts. ANSI colours are rendered.
|
||||
;; Kill a running build with M-x kill-compilation.
|
||||
;;; Code:
|
||||
|
||||
(setq compilation-read-command nil ; run without prompting
|
||||
compilation-ask-about-save nil
|
||||
compilation-scroll-output t)
|
||||
|
||||
(add-hook 'compilation-filter-hook #'ansi-color-compilation-filter)
|
||||
|
||||
;; Compilation buffer at the bottom, full frame width.
|
||||
(add-to-list 'display-buffer-alist
|
||||
'((derived-mode . compilation-mode)
|
||||
(display-buffer-reuse-window display-buffer-at-bottom)
|
||||
(window-height . 0.45)))
|
||||
|
||||
;; Focus the compilation window when a build starts.
|
||||
(add-hook 'compilation-start-hook
|
||||
(lambda (proc)
|
||||
(when-let* ((win (get-buffer-window (process-buffer proc))))
|
||||
(select-window win))))
|
||||
|
||||
;; :build runs ./build.sh; :build ARGS appends ARGS.
|
||||
(evil-define-command my/ex-build (args)
|
||||
"Run `./build.sh ARGS' from the nearest directory containing build.sh."
|
||||
(interactive "<a>")
|
||||
(let ((root (locate-dominating-file default-directory "build.sh")))
|
||||
(unless root
|
||||
(user-error "No build.sh found"))
|
||||
(let ((default-directory root))
|
||||
(unless (file-executable-p "build.sh")
|
||||
(user-error "build.sh is not executable"))
|
||||
(compile (string-trim (concat "./build.sh " args)))))) ; nil args -> ""
|
||||
|
||||
(evil-ex-define-cmd "build" #'my/ex-build)
|
||||
|
||||
;;; build.el ends here
|
||||
@@ -0,0 +1,99 @@
|
||||
;;; development.el --- Languages, Eglot and code navigation -*- lexical-binding: t; -*-
|
||||
;;; Commentary:
|
||||
;; Loaded from init.el. Requires Evil.
|
||||
;;
|
||||
;; Languages:
|
||||
;; Markdown markdown-mode.
|
||||
;; PHP php-mode, PSR-2 style, 4 spaces.
|
||||
;; Odin odin-mode from git (needs Emacs 30+ for :vc), Eglot + OLS.
|
||||
;; Go go-mode, Eglot + gopls; organize imports and format on save.
|
||||
;;
|
||||
;; Normal/motion state:
|
||||
;; gd definitions gD references K eldoc
|
||||
;; C-t jump back ESC closes any open eldoc window.
|
||||
;;; Code:
|
||||
|
||||
;;;; Markdown
|
||||
(use-package markdown-mode)
|
||||
|
||||
;;;; PHP
|
||||
(use-package php-mode
|
||||
:mode "\\.php\\'"
|
||||
:hook
|
||||
(php-mode . (lambda ()
|
||||
(setq-local indent-tabs-mode nil)
|
||||
(setq-local tab-width 4)
|
||||
(setq-local c-basic-offset 4)))
|
||||
:custom
|
||||
(php-mode-coding-style 'psr2))
|
||||
|
||||
;;;; Odin
|
||||
(use-package odin-mode
|
||||
:vc (:url "https://github.com/mattt-b/odin-mode"
|
||||
:rev :newest)
|
||||
:mode "\\.odin\\'"
|
||||
:hook (odin-mode . eglot-ensure))
|
||||
|
||||
;;;; Go
|
||||
;; Emacs started from the desktop doesn't inherit fish env.
|
||||
(dolist (d '("/usr/local/go/bin" "/home/jason/.go/bin"))
|
||||
(add-to-list 'exec-path d)
|
||||
(setenv "PATH" (concat d ":" (getenv "PATH"))))
|
||||
(setenv "GOPATH" "/home/jason/.go")
|
||||
(setenv "GOCACHE" "/home/jason/.go/cache")
|
||||
|
||||
(defun my/go-before-save ()
|
||||
"Organize imports and format the buffer through Eglot."
|
||||
(when (eglot-managed-p)
|
||||
(eglot-code-actions nil nil "source.organizeImports" t)
|
||||
(eglot-format-buffer)))
|
||||
|
||||
(use-package go-mode
|
||||
:mode "\\.go\\'"
|
||||
:hook ((go-mode . eglot-ensure)
|
||||
(go-mode . (lambda ()
|
||||
(setq-local tab-width 4)
|
||||
(add-hook 'before-save-hook #'my/go-before-save nil t)))))
|
||||
|
||||
;;;; Eglot
|
||||
(use-package eglot
|
||||
:ensure nil
|
||||
:config
|
||||
(setq eglot-autoshutdown t)
|
||||
(add-to-list 'eglot-ignored-server-capabilities :signatureHelpProvider)
|
||||
|
||||
;; Explicit OLS configuration.
|
||||
(add-to-list
|
||||
'eglot-server-programs
|
||||
'(odin-mode
|
||||
. ("/home/jason/.local/bin/ols"
|
||||
:initializationOptions
|
||||
(:odin_command "/home/jason/.odin/odin"
|
||||
:enable_document_symbols t
|
||||
:enable_format t
|
||||
:collections
|
||||
[(:name "core"
|
||||
:path "/home/jason/.odin/core")
|
||||
(:name "vendor"
|
||||
:path "/home/jason/.odin/vendor")])))))
|
||||
|
||||
;; OLS built-in definitions.
|
||||
(setenv "OLS_BUILTIN_FOLDER" "/home/jason/ThirdParty/ols/builtin")
|
||||
|
||||
;;;; Code navigation
|
||||
;; Vim-style code navigation.
|
||||
(evil-define-key '(normal motion) 'global
|
||||
"gd" #'xref-find-definitions
|
||||
"gD" #'xref-find-references
|
||||
"K" #'eldoc
|
||||
(kbd "C-t") #'xref-go-back)
|
||||
|
||||
;; ESC closes any open eldoc window.
|
||||
(defun my/eldoc-close (&rest _)
|
||||
"Quit every window showing an *eldoc* buffer."
|
||||
(dolist (w (window-list))
|
||||
(when (string-prefix-p "*eldoc" (buffer-name (window-buffer w)))
|
||||
(quit-window nil w))))
|
||||
(advice-add 'evil-force-normal-state :after #'my/eldoc-close)
|
||||
|
||||
;;; development.el ends here
|
||||
@@ -0,0 +1,58 @@
|
||||
;;; org.el --- Org appearance -*- lexical-binding: t; -*-
|
||||
;;; Code:
|
||||
|
||||
;; Styled stars, bullets, tags, tables and blocks.
|
||||
(use-package org-modern
|
||||
:hook (org-mode . org-modern-mode))
|
||||
|
||||
(setq org-directory "~/Projects/notebook")
|
||||
(setq org-startup-indented t ; visual indent per level, no real spaces
|
||||
org-hide-emphasis-markers t ; *bold* shows bold, markers hidden
|
||||
org-pretty-entities t ; \rarr, \alpha etc. as symbols
|
||||
org-ellipsis " ▾" ; folded-heading marker
|
||||
org-startup-folded 'show2levels ; open with headings only
|
||||
org-fontify-whole-heading-line t
|
||||
org-fontify-done-headline t
|
||||
org-fontify-quote-and-verse-blocks t
|
||||
org-src-fontify-natively t ; highlight src blocks with their own mode
|
||||
org-src-tab-acts-natively t
|
||||
org-edit-src-content-indentation 0
|
||||
org-return-follows-link t)
|
||||
|
||||
;; org-modern's recommended settings.
|
||||
(setq org-auto-align-tags nil
|
||||
org-tags-column 0
|
||||
org-catch-invisible-edits 'show-and-error
|
||||
org-special-ctrl-a/e t
|
||||
org-insert-heading-respect-content t)
|
||||
|
||||
(add-hook 'org-mode-hook #'visual-line-mode) ; wrap at window edge
|
||||
(add-hook 'org-mode-hook (lambda () (display-line-numbers-mode -1))) ; prose reads better without
|
||||
|
||||
;; doom-themes' own Org fontification fixes (blocks, headings).
|
||||
(doom-themes-org-config)
|
||||
|
||||
;; Heading sizes; 'user survives theme reloads, same as in init.el.
|
||||
(doom-themes-set-faces 'user
|
||||
'(org-document-title :height 1.3 :weight 'bold)
|
||||
'(org-level-1 :height 1.2 :weight 'bold)
|
||||
'(org-level-2 :height 1.15 :weight 'bold)
|
||||
'(org-level-3 :height 1.1 :weight 'bold)
|
||||
'(org-level-4 :height 1.0 :weight 'bold))
|
||||
|
||||
(defun my/notes-index ()
|
||||
"Open the notes index."
|
||||
(interactive)
|
||||
(find-file (expand-file-name "index.org" org-directory)))
|
||||
|
||||
(keymap-global-set "C-c n" #'my/notes-index)
|
||||
|
||||
;; Evil's TAB (= C-i, jump-forward) shadows Org's. Rebind for Org buffers only.
|
||||
(with-eval-after-load 'org
|
||||
(evil-define-key 'normal org-mode-map
|
||||
(kbd "TAB") #'org-cycle ; fold/unfold the heading at point
|
||||
(kbd "<tab>") #'org-cycle ; GUI emits <tab>, so bind both
|
||||
(kbd "RET") #'org-open-at-point
|
||||
(kbd "<backtab>") #'org-shifttab)) ; S-TAB: cycle all headings
|
||||
|
||||
;;; org.el ends here
|
||||
@@ -0,0 +1,360 @@
|
||||
;;; minimal-theme.el --- Minimal high-functionality Ujelly port -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Built on the compline-theme face structure, updated with the color palette
|
||||
;; from Ujelly (color-theme-ujelly by marktran).
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(deftheme minimal
|
||||
"Created 2026-10-26.")
|
||||
|
||||
(custom-theme-set-faces
|
||||
'minimal
|
||||
|
||||
;;;; Core
|
||||
'(default ((t (:inherit nil :extend nil :stipple nil :background "#151515" :foreground "#e8e8d3" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight regular :height 143 :width normal))))
|
||||
'(cursor ((t (:background "#8fbfdc"))))
|
||||
'(fixed-pitch ((t (:height 140))))
|
||||
'(variable-pitch ((t (:height 140))))
|
||||
'(escape-glyph ((t (:foreground "#8fbfdc"))))
|
||||
'(homoglyph ((t (:foreground "#8fbfdc"))))
|
||||
'(minibuffer-prompt ((t (:foreground "#8fbfdc"))))
|
||||
'(highlight ((t (:foreground "#e8e8d3" :background "#303030" :weight bold))))
|
||||
'(hl-line ((t (:extend t :background "#1b1b1b"))))
|
||||
'(region ((t (:extend t :background "#404040"))))
|
||||
'(shadow ((t (:foreground "#7f7f7f"))))
|
||||
'(secondary-selection ((t (:extend t :background "#404040"))))
|
||||
'(trailing-whitespace ((t (:background "#cf6a4c"))))
|
||||
'(vertical-border ((t (:foreground "#262626"))))
|
||||
'(error ((t (:foreground "#cf6a4c"))))
|
||||
'(warning ((t (:foreground "#fad07a"))))
|
||||
'(success ((t (:foreground "#99ad6a"))))
|
||||
|
||||
;;;; Line numbers
|
||||
'(line-number ((t (:foreground "#404040"))))
|
||||
'(line-number-current-line ((t (:foreground "#e8e8d3"))))
|
||||
|
||||
;;;; Font lock
|
||||
'(font-lock-bracket-face ((t (:inherit (font-lock-punctuation-face)))))
|
||||
'(font-lock-builtin-face ((t (:foreground "#8fbfdc"))))
|
||||
'(font-lock-comment-delimiter-face ((default (:inherit (font-lock-comment-face)))))
|
||||
'(font-lock-comment-face ((t (:foreground "#767676"))))
|
||||
'(font-lock-constant-face ((t (:foreground "#c6b5ed"))))
|
||||
'(font-lock-delimiter-face ((t (:inherit (font-lock-punctuation-face)))))
|
||||
'(font-lock-doc-face ((t (:foreground "#767676" :inherit (font-lock-comment-face)))))
|
||||
'(font-lock-doc-markup-face ((t (:inherit (font-lock-constant-face)))))
|
||||
'(font-lock-escape-face ((t (:inherit (font-lock-regexp-grouping-backslash)))))
|
||||
'(font-lock-function-call-face ((t (:slant italic :foreground "#8fbfdc" :inherit (font-lock-function-name-face)))))
|
||||
'(font-lock-function-name-face ((t (:foreground "#8fbfdc"))))
|
||||
'(font-lock-keyword-face ((t (:foreground "#fad07a"))))
|
||||
'(font-lock-negation-char-face ((t (:foreground "#cf6a4c" :inherit (bold)))))
|
||||
'(font-lock-number-face ((t (:foreground "#cf6a4c"))))
|
||||
'(font-lock-misc-punctuation-face ((t (:inherit (font-lock-punctuation-face)))))
|
||||
'(font-lock-operator-face ((t (:foreground "#a0a8b0"))))
|
||||
'(font-lock-preprocessor-face ((t (:foreground "#fad07a" :inherit (bold)))))
|
||||
'(font-lock-property-name-face ((t (:weight bold :foreground "#8fbfdc"))))
|
||||
'(font-lock-property-use-face ((t (:weight regular :inherit (font-lock-property-name-face)))))
|
||||
'(font-lock-punctuation-face ((t (:foreground "#a0a8b0"))))
|
||||
'(font-lock-regexp-grouping-backslash ((t (:foreground "#fad07a" :inherit (bold)))))
|
||||
'(font-lock-regexp-grouping-construct ((t (:foreground "#fad07a" :inherit (bold)))))
|
||||
'(font-lock-string-face ((t (:foreground "#99ad6a"))))
|
||||
'(font-lock-type-face ((t (:foreground "#ffb17a"))))
|
||||
'(font-lock-variable-name-face ((t (:foreground "#e8e8d3"))))
|
||||
'(font-lock-variable-use-face ((t (:foreground "#e8e8d3" :inherit (font-lock-variable-name-face)))))
|
||||
'(font-lock-warning-face ((t (:inherit (warning)))))
|
||||
|
||||
;;;; Links, buttons, tooltips
|
||||
'(button ((t (:inherit (link)))))
|
||||
'(link ((t (:weight bold :underline (:color foreground-color :style line :position nil) :foreground "#8fbfdc"))))
|
||||
'(link-visited ((t (:inherit link :foreground "#c6b5ed"))))
|
||||
'(fringe ((t (:foreground "#404040" :inherit (default)))))
|
||||
'(tooltip ((t (:foreground "#e8e8d3" :background "#1b1b1b"))))
|
||||
|
||||
;;;; Mode line
|
||||
'(header-line ((t (:inherit (mode-line)))))
|
||||
'(mode-line ((t (:background "#1c1c1c" :foreground unspecified))))
|
||||
'(mode-line-buffer-id ((t (:weight bold))))
|
||||
'(mode-line-emphasis ((t (:foreground "#fad07a"))))
|
||||
'(mode-line-highlight ((t (:inherit (highlight)))))
|
||||
'(mode-line-inactive ((t (:foreground "#767676" :background "#121212"))))
|
||||
|
||||
;;;; Tab bar
|
||||
'(tab-bar ((t (:inherit default :background "#151515" :foreground "#767676"))))
|
||||
'(tab-bar-tab ((t (:inherit tab-bar :background "#262626" :foreground "#e8e8d3" :weight bold :box nil))))
|
||||
'(tab-bar-tab-inactive ((t (:inherit tab-bar :background "#151515" :foreground "#999999" :weight normal :box nil))))
|
||||
|
||||
;;;; Search & Completions
|
||||
'(isearch ((t (:weight bold :inherit (lazy-highlight)))))
|
||||
'(isearch-fail ((t (:weight bold :foreground "#151515" :background "#cf6a4c"))))
|
||||
'(lazy-highlight ((t (:weight bold :foreground "#e8e8d3" :background "#303030"))))
|
||||
'(match ((t (:weight bold :foreground "#99ad6a" :background "#151515"))))
|
||||
'(next-error ((t (:inherit (region)))))
|
||||
'(query-replace ((t (:inherit (isearch)))))
|
||||
|
||||
;;;; VC gutter: added = green, deleted = red, modified = sand/yellow
|
||||
'(diff-hl-insert ((t (:foreground "#99ad6a" :background "#99ad6a"))))
|
||||
'(diff-hl-delete ((t (:foreground "#cf6a4c" :background "#cf6a4c"))))
|
||||
'(diff-hl-change ((t (:foreground "#fad07a" :background "#fad07a"))))
|
||||
'(git-gutter:added ((t (:foreground "#99ad6a" :background "#99ad6a"))))
|
||||
'(git-gutter:deleted ((t (:foreground "#cf6a4c" :background "#cf6a4c"))))
|
||||
'(git-gutter:modified ((t (:foreground "#fad07a" :background "#fad07a"))))
|
||||
'(git-gutter-fr:added ((t (:foreground "#99ad6a"))))
|
||||
'(git-gutter-fr:deleted ((t (:foreground "#cf6a4c"))))
|
||||
'(git-gutter-fr:modified ((t (:foreground "#fad07a"))))
|
||||
|
||||
;;;; gnus: group buffer
|
||||
'(gnus-group-news-1 ((t (:foreground "#e8e8d3" :weight bold))))
|
||||
'(gnus-group-news-1-empty ((t (:foreground "#e8e8d3" :weight normal))))
|
||||
'(gnus-group-news-2 ((t (:foreground "#8fbfdc" :weight bold))))
|
||||
'(gnus-group-news-2-empty ((t (:foreground "#8fbfdc" :weight normal))))
|
||||
'(gnus-group-news-3 ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(gnus-group-news-3-empty ((t (:foreground "#fad07a" :weight normal))))
|
||||
'(gnus-group-news-low ((t (:foreground "#767676" :weight bold))))
|
||||
'(gnus-group-news-low-empty ((t (:foreground "#404040" :weight normal))))
|
||||
'(gnus-group-mail-1 ((t (:foreground "#99ad6a" :weight bold))))
|
||||
'(gnus-group-mail-1-empty ((t (:foreground "#99ad6a" :weight normal))))
|
||||
'(gnus-group-mail-2 ((t (:foreground "#c6b5ed" :weight bold))))
|
||||
'(gnus-group-mail-2-empty ((t (:foreground "#c6b5ed" :weight normal))))
|
||||
'(gnus-group-mail-3 ((t (:foreground "#ffb17a" :weight bold))))
|
||||
'(gnus-group-mail-3-empty ((t (:foreground "#ffb17a" :weight normal))))
|
||||
'(gnus-group-mail-low ((t (:foreground "#767676" :weight bold))))
|
||||
'(gnus-group-mail-low-empty ((t (:foreground "#404040" :weight normal))))
|
||||
|
||||
;;;; gnus: summary buffer
|
||||
'(gnus-summary-normal-unread ((t (:foreground "#e8e8d3" :weight bold))))
|
||||
'(gnus-summary-normal-read ((t (:foreground "#767676" :weight normal))))
|
||||
'(gnus-summary-normal-ticked ((t (:foreground "#cf6a4c" :weight bold))))
|
||||
'(gnus-summary-normal-ancient ((t (:foreground "#404040" :weight normal))))
|
||||
'(gnus-summary-normal-undownloaded ((t (:foreground "#8fbfdc" :slant italic))))
|
||||
'(gnus-summary-high-unread ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(gnus-summary-high-read ((t (:foreground "#99ad6a" :weight normal))))
|
||||
'(gnus-summary-high-ticked ((t (:foreground "#cf6a4c" :weight bold))))
|
||||
'(gnus-summary-high-ancient ((t (:foreground "#767676" :weight normal))))
|
||||
'(gnus-summary-low-unread ((t (:foreground "#8fbfdc" :slant italic :weight bold))))
|
||||
'(gnus-summary-low-read ((t (:foreground "#404040" :slant italic :weight normal))))
|
||||
'(gnus-summary-low-ticked ((t (:foreground "#cf6a4c" :slant italic))))
|
||||
'(gnus-summary-low-ancient ((t (:foreground "#404040" :slant italic))))
|
||||
'(gnus-summary-selected ((t (:background "#404040" :foreground "#e8e8d3" :weight bold))))
|
||||
'(gnus-summary-cancelled ((t (:foreground "#cf6a4c" :strike-through t))))
|
||||
|
||||
;;;; gnus: article headers, citations, misc
|
||||
'(gnus-header-name ((t (:foreground "#8fbfdc" :weight bold))))
|
||||
'(gnus-header-content ((t (:foreground "#fad07a" :slant italic))))
|
||||
'(gnus-header-from ((t (:foreground "#e8e8d3" :weight bold))))
|
||||
'(gnus-header-subject ((t (:foreground "#ffb17a"))))
|
||||
'(gnus-header-newsgroups ((t (:foreground "#fad07a" :slant italic))))
|
||||
'(gnus-cite-1 ((t (:foreground "#8fbfdc"))))
|
||||
'(gnus-cite-2 ((t (:foreground "#99ad6a"))))
|
||||
'(gnus-cite-3 ((t (:foreground "#fad07a"))))
|
||||
'(gnus-cite-4 ((t (:foreground "#cf6a4c"))))
|
||||
'(gnus-cite-5 ((t (:foreground "#c6b5ed"))))
|
||||
'(gnus-cite-6 ((t (:foreground "#ffb17a"))))
|
||||
'(gnus-cite-7 ((t (:foreground "#8fbfdc"))))
|
||||
'(gnus-cite-8 ((t (:foreground "#99ad6a"))))
|
||||
'(gnus-cite-9 ((t (:foreground "#fad07a"))))
|
||||
'(gnus-cite-10 ((t (:foreground "#767676"))))
|
||||
'(gnus-cite-11 ((t (:foreground "#404040"))))
|
||||
'(gnus-signature ((t (:foreground "#767676" :slant italic))))
|
||||
'(gnus-button ((t (:inherit link))))
|
||||
'(gnus-splash ((t (:foreground "#767676"))))
|
||||
'(gnus-emphasis-bold ((t (:weight bold))))
|
||||
'(gnus-emphasis-italic ((t (:slant italic))))
|
||||
'(gnus-emphasis-underline ((t (:underline t))))
|
||||
'(gnus-emphasis-bold-italic ((t (:weight bold :slant italic))))
|
||||
'(gnus-server-opened ((t (:foreground "#99ad6a" :weight bold))))
|
||||
'(gnus-server-closed ((t (:foreground "#767676" :slant italic))))
|
||||
'(gnus-server-denied ((t (:foreground "#cf6a4c" :weight bold))))
|
||||
'(gnus-server-offline ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(gnus-server-agent ((t (:foreground "#8fbfdc" :weight bold))))
|
||||
|
||||
;;;; message (gnus composition buffers)
|
||||
'(message-header-name ((t (:foreground "#8fbfdc" :weight bold))))
|
||||
'(message-header-to ((t (:foreground "#e8e8d3" :weight bold))))
|
||||
'(message-header-cc ((t (:foreground "#ffb17a"))))
|
||||
'(message-header-subject ((t (:foreground "#e8e8d3" :weight bold))))
|
||||
'(message-header-newsgroups ((t (:foreground "#fad07a" :slant italic))))
|
||||
'(message-header-other ((t (:foreground "#fad07a"))))
|
||||
'(message-header-xheader ((t (:foreground "#767676"))))
|
||||
'(message-separator ((t (:foreground "#404040"))))
|
||||
'(message-mml ((t (:foreground "#99ad6a"))))
|
||||
'(message-cited-text-1 ((t (:foreground "#8fbfdc"))))
|
||||
'(message-cited-text-2 ((t (:foreground "#99ad6a"))))
|
||||
'(message-cited-text-3 ((t (:foreground "#fad07a"))))
|
||||
'(message-cited-text-4 ((t (:foreground "#cf6a4c"))))
|
||||
|
||||
;;;; magit: sections
|
||||
'(magit-section-heading ((t (:foreground "#fad07a" :weight bold :extend t))))
|
||||
'(magit-section-secondary-heading ((t (:foreground "#c6b5ed" :weight bold :extend t))))
|
||||
'(magit-section-heading-selection ((t (:foreground "#99ad6a" :weight bold :extend t))))
|
||||
'(magit-section-highlight ((t (:background "#1b1b1b" :extend t))))
|
||||
'(magit-section-child-count ((t (:foreground "#767676"))))
|
||||
|
||||
;;;; magit: refs, hashes, log
|
||||
'(magit-branch-local ((t (:foreground "#8fbfdc"))))
|
||||
'(magit-branch-remote ((t (:foreground "#99ad6a"))))
|
||||
'(magit-branch-current ((t (:foreground "#8fbfdc" :weight bold :box (:line-width -1 :color "#767676")))))
|
||||
'(magit-branch-remote-head ((t (:foreground "#99ad6a" :weight bold :box (:line-width -1 :color "#767676")))))
|
||||
'(magit-branch-upstream ((t (:slant italic))))
|
||||
'(magit-tag ((t (:foreground "#fad07a"))))
|
||||
'(magit-hash ((t (:foreground "#767676"))))
|
||||
'(magit-dimmed ((t (:foreground "#404040"))))
|
||||
'(magit-filename ((t (:foreground "#e8e8d3"))))
|
||||
'(magit-refname ((t (:foreground "#767676"))))
|
||||
'(magit-refname-stash ((t (:foreground "#767676"))))
|
||||
'(magit-refname-wip ((t (:foreground "#767676"))))
|
||||
'(magit-log-author ((t (:foreground "#fad07a"))))
|
||||
'(magit-log-date ((t (:foreground "#767676"))))
|
||||
'(magit-log-graph ((t (:foreground "#404040"))))
|
||||
'(magit-keyword ((t (:foreground "#fad07a"))))
|
||||
'(magit-keyword-squash ((t (:foreground "#fad07a"))))
|
||||
'(magit-cherry-equivalent ((t (:foreground "#e8e8d3"))))
|
||||
'(magit-cherry-unmatched ((t (:foreground "#8fbfdc"))))
|
||||
|
||||
;;;; magit: diffs
|
||||
'(magit-diff-file-heading ((t (:foreground "#e8e8d3" :weight bold :extend t))))
|
||||
'(magit-diff-file-heading-highlight ((t (:inherit magit-diff-file-heading :background "#1b1b1b"))))
|
||||
'(magit-diff-file-heading-selection ((t (:inherit magit-diff-file-heading :foreground "#fad07a" :background "#404040"))))
|
||||
'(magit-diff-hunk-heading ((t (:foreground "#c6b5ed" :background "#222222" :extend t))))
|
||||
'(magit-diff-hunk-heading-highlight ((t (:foreground "#e8e8d3" :background "#404040" :extend t))))
|
||||
'(magit-diff-hunk-heading-selection ((t (:foreground "#fad07a" :background "#404040" :extend t))))
|
||||
'(magit-diff-lines-heading ((t (:foreground "#151515" :background "#fad07a" :extend t))))
|
||||
'(magit-diff-context ((t (:foreground "#767676" :extend t))))
|
||||
'(magit-diff-context-highlight ((t (:foreground "#c6b5ed" :background "#1b1b1b" :extend t))))
|
||||
'(magit-diff-added ((t (:foreground "#99ad6a" :background "#1a261a" :extend t))))
|
||||
'(magit-diff-added-highlight ((t (:foreground "#99ad6a" :background "#223322" :extend t))))
|
||||
'(magit-diff-removed ((t (:foreground "#cf6a4c" :background "#261a1a" :extend t))))
|
||||
'(magit-diff-removed-highlight ((t (:foreground "#cf6a4c" :background "#332222" :extend t))))
|
||||
'(magit-diffstat-added ((t (:foreground "#99ad6a"))))
|
||||
'(magit-diffstat-removed ((t (:foreground "#cf6a4c"))))
|
||||
'(magit-diff-whitespace-warning ((t (:background "#cf6a4c"))))
|
||||
|
||||
;;;; magit: process, signatures, sequences, blame, header line
|
||||
'(magit-process-ok ((t (:foreground "#99ad6a" :weight bold))))
|
||||
'(magit-process-ng ((t (:foreground "#cf6a4c" :weight bold))))
|
||||
'(magit-mode-line-process ((t (:foreground "#fad07a"))))
|
||||
'(magit-mode-line-process-error ((t (:foreground "#cf6a4c"))))
|
||||
'(magit-signature-good ((t (:foreground "#99ad6a"))))
|
||||
'(magit-signature-bad ((t (:foreground "#cf6a4c" :weight bold))))
|
||||
'(magit-signature-untrusted ((t (:foreground "#8fbfdc"))))
|
||||
'(magit-signature-expired ((t (:foreground "#fad07a"))))
|
||||
'(magit-signature-expired-key ((t (:foreground "#fad07a"))))
|
||||
'(magit-signature-revoked ((t (:foreground "#cf6a4c"))))
|
||||
'(magit-signature-error ((t (:foreground "#cf6a4c"))))
|
||||
'(magit-sequence-head ((t (:foreground "#8fbfdc"))))
|
||||
'(magit-sequence-stop ((t (:foreground "#99ad6a"))))
|
||||
'(magit-sequence-part ((t (:foreground "#fad07a"))))
|
||||
'(magit-sequence-done ((t (:foreground "#767676"))))
|
||||
'(magit-sequence-onto ((t (:foreground "#767676"))))
|
||||
'(magit-bisect-good ((t (:foreground "#99ad6a"))))
|
||||
'(magit-bisect-skip ((t (:foreground "#fad07a"))))
|
||||
'(magit-bisect-bad ((t (:foreground "#cf6a4c"))))
|
||||
'(magit-blame-heading ((t (:foreground "#c6b5ed" :background "#222222" :extend t))))
|
||||
'(magit-header-line ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(magit-header-line-key ((t (:foreground "#fad07a"))))
|
||||
'(magit-header-line-log-select ((t (:foreground "#e8e8d3" :weight bold))))
|
||||
|
||||
;;;; transient (magit popups)
|
||||
'(transient-heading ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(transient-key ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(transient-key-exit ((t (:foreground "#cf6a4c" :weight bold))))
|
||||
'(transient-key-return ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(transient-key-stay ((t (:foreground "#99ad6a" :weight bold))))
|
||||
'(transient-argument ((t (:foreground "#99ad6a" :weight bold))))
|
||||
'(transient-value ((t (:foreground "#99ad6a"))))
|
||||
'(transient-inactive-argument ((t (:foreground "#767676"))))
|
||||
'(transient-inactive-value ((t (:foreground "#767676"))))
|
||||
'(transient-unreachable ((t (:foreground "#404040"))))
|
||||
'(transient-unreachable-key ((t (:foreground "#404040"))))
|
||||
'(transient-disabled-suffix ((t (:foreground "#151515" :background "#cf6a4c" :weight bold))))
|
||||
'(transient-enabled-suffix ((t (:foreground "#151515" :background "#99ad6a" :weight bold))))
|
||||
'(transient-delimiter ((t (:foreground "#767676"))))
|
||||
'(transient-separator ((t (:background "#1c1c1c"))))
|
||||
'(transient-active-infix ((t (:foreground "#e8e8d3" :background "#404040"))))
|
||||
'(transient-mismatched-key ((t (:underline t))))
|
||||
'(transient-nonstandard-key ((t (:underline t))))
|
||||
|
||||
;;;; git-commit (magit commit message buffer)
|
||||
'(git-commit-summary ((t (:foreground "#e8e8d3" :weight bold))))
|
||||
'(git-commit-overlong-summary ((t (:foreground "#cf6a4c" :weight bold))))
|
||||
'(git-commit-nonempty-second-line ((t (:foreground "#cf6a4c"))))
|
||||
'(git-commit-keyword ((t (:foreground "#8fbfdc"))))
|
||||
'(git-commit-comment-heading ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(git-commit-comment-branch-local ((t (:foreground "#8fbfdc"))))
|
||||
'(git-commit-comment-branch-remote ((t (:foreground "#99ad6a"))))
|
||||
'(git-commit-comment-detached ((t (:foreground "#fad07a"))))
|
||||
'(git-commit-comment-file ((t (:foreground "#fad07a"))))
|
||||
'(git-commit-comment-action ((t (:foreground "#99ad6a"))))
|
||||
|
||||
;;;; erc: buffer text
|
||||
'(erc-default-face ((t (:foreground "#e8e8d3"))))
|
||||
'(erc-input-face ((t (:foreground "#99ad6a"))))
|
||||
'(erc-my-nick-face ((t (:foreground "#99ad6a" :weight bold))))
|
||||
'(erc-my-nick-prefix-face ((t (:foreground "#99ad6a" :weight bold))))
|
||||
'(erc-nick-default-face ((t (:foreground "#e8e8d3" :weight bold))))
|
||||
'(erc-nick-prefix-face ((t (:foreground "#fad07a"))))
|
||||
'(erc-notice-face ((t (:foreground "#767676" :weight normal))))
|
||||
'(erc-information ((t (:foreground "#c6b5ed"))))
|
||||
'(erc-timestamp-face ((t (:foreground "#404040" :weight normal))))
|
||||
'(erc-action-face ((t (:foreground "#ffb17a" :weight bold))))
|
||||
'(erc-prompt-face ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(erc-command-indicator-face ((t (:foreground "#c6b5ed" :weight bold))))
|
||||
'(erc-error-face ((t (:foreground "#cf6a4c"))))
|
||||
'(erc-button ((t (:inherit link :foreground "#e8e8d3"))))
|
||||
'(erc-button-nick-default-face ((t (:foreground "#e8e8d3" :weight bold))))
|
||||
'(erc-bold-face ((t (:weight bold))))
|
||||
'(erc-italic-face ((t (:slant italic))))
|
||||
'(erc-underline-face ((t (:underline t))))
|
||||
'(erc-inverse-face ((t (:foreground "#151515" :background "#e8e8d3"))))
|
||||
'(erc-keep-place-indicator-line ((t (:underline (:color "#404040" :style line)))))
|
||||
'(erc-keep-place-indicator-arrow ((t (:foreground "#cf6a4c"))))
|
||||
'(erc-header-line ((t (:foreground "#c6b5ed" :background "#1c1c1c"))))
|
||||
'(erc-header-line-disconnected ((t (:foreground "#cf6a4c" :background "#1c1c1c"))))
|
||||
|
||||
;;;; erc: highlighting rules
|
||||
'(erc-current-nick-face ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(erc-keyword-face ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(erc-nick-msg-face ((t (:foreground "#fad07a" :weight bold))))
|
||||
'(erc-direct-msg-face ((t (:foreground "#cf6a4c"))))
|
||||
'(erc-pal-face ((t (:foreground "#99ad6a" :weight bold))))
|
||||
'(erc-fool-face ((t (:foreground "#404040"))))
|
||||
'(erc-dangerous-host-face ((t (:foreground "#cf6a4c"))))
|
||||
|
||||
;;;; css-mode / scss-mode
|
||||
'(css-proprietary-property ((t (:foreground "#fad07a"))))
|
||||
'(css-property ((t (:foreground "#e8e8d3"))))
|
||||
'(css-selector ((t (:foreground "#cf6a4c"))))
|
||||
|
||||
;;;; markdown-mode
|
||||
'(markdown-markup-face ((t (:foreground "#404040"))))
|
||||
'(markdown-header-face ((t (:inherit bold :foreground "#cf6a4c"))))
|
||||
'(markdown-code-face ((t (:background "#1c1c1c"))))
|
||||
|
||||
;;;; outline
|
||||
'(outline-1 ((t (:foreground "#e8e8d3" :weight ultra-bold))))
|
||||
'(outline-2 ((t (:foreground "#8fbfdc"))))
|
||||
'(outline-3 ((t (:foreground "#99ad6a"))))
|
||||
'(outline-4 ((t (:foreground "#c6b5ed"))))
|
||||
'(outline-5 ((t (:foreground "#ffb17a"))))
|
||||
'(outline-6 ((t (:foreground "#fad07a"))))
|
||||
'(outline-7 ((t (:foreground "#cf6a4c"))))
|
||||
'(outline-8 ((t (:foreground "#e8e8d3"))))
|
||||
|
||||
;;;; org
|
||||
'(org-block ((t (:background "#1b1b1b"))))
|
||||
'(org-block-begin-line ((t (:foreground "#404040" :slant italic :background "#121212"))))
|
||||
'(org-ellipsis ((t (:underline nil :background "#151515" :foreground "#cf6a4c"))))
|
||||
'(org-quote ((t (:background "#1c1c1c"))))
|
||||
'(org-hide ((t (:foreground "#151515"))))
|
||||
|
||||
;;;; solaire-mode
|
||||
'(solaire-mode-line-face ((t (:inherit mode-line :background "#1c1c1c"))))
|
||||
'(solaire-mode-line-inactive-face ((t (:inherit mode-line-inactive :background "#1c1c1c")))))
|
||||
|
||||
;;;###autoload
|
||||
(when load-file-name
|
||||
(add-to-list 'custom-theme-load-path
|
||||
(file-name-as-directory (file-name-directory load-file-name))))
|
||||
|
||||
(provide-theme 'minimal)
|
||||
|
||||
;;; minimal-theme.el ends here
|
||||
@@ -21,7 +21,6 @@ set -gx COLORTERM "truecolor"
|
||||
set -gx DEBUG 1
|
||||
set -gx GOPATH "$HOME/.go"
|
||||
set -gx GOCACHE "$HOME/.go/cache"
|
||||
set -gx GOROOT /usr/local/go
|
||||
set -gx OLS_BUILTIN_FOLDER "/home/jason/ThirdParty/ols/builtin"
|
||||
|
||||
# Direnv
|
||||
@@ -82,6 +81,10 @@ alias bat 'bat --theme="ansi" --paging=never'
|
||||
alias :q 'exit'
|
||||
alias files 'thunar .'
|
||||
alias fetch 'pfetch'
|
||||
# Map 'php' directly to FrankenPHP's bundled PHP CLI runtime
|
||||
alias php="frankenphp php-cli"
|
||||
# Optional: A shorthand to spin up your local dev server instantly using your Caddyfile
|
||||
alias phpserve="frankenphp php-server --config Caddyfile"
|
||||
|
||||
# Custom shortcuts
|
||||
alias reload 'source ~/.config/fish/config.fish'
|
||||
|
||||
+4
-3
@@ -150,10 +150,11 @@ if [ "$DO_INSTALL" = true ]; then
|
||||
wget curl ca-certificates gnupg rsync
|
||||
# core utilities & CLI tools
|
||||
git fd jq fzf ripgrep tree direnv make
|
||||
bat unzip 7zip tar gzip bzip2 xz ark
|
||||
bat unzip 7zip tar gzip bzip2 xz ark
|
||||
mpv xfce4-screenshooter xkill xwininfo
|
||||
xdotool wmctrl
|
||||
# build & dev tools
|
||||
emacs-x11 alacritty base-devel valgrind
|
||||
xfce4-screenshooter xkill xdotool wmctrl
|
||||
emacs-x11 alacritty base-devel valgrind go
|
||||
)
|
||||
|
||||
MISSING_PACKAGES=()
|
||||
|
||||
Executable
+281
@@ -0,0 +1,281 @@
|
||||
#!/usr/bin/env bash
|
||||
# focus - small window helpers for xfwm4
|
||||
# focus next|prev move focus right/left through windows (stops at the ends)
|
||||
# focus up|down focus the nearest window directly above/below, if any
|
||||
# focus tile master/stack tiling: active window left, the rest stacked right
|
||||
# (a single window is simply maximized)
|
||||
# Deps: wmctrl xdotool xprop xwininfo
|
||||
set -u
|
||||
|
||||
# ---- config -----------------------------------------------------------------
|
||||
MASTER_RATIO=50 # master width as % of the usable width
|
||||
GAP=0 # px between windows and around the screen edge
|
||||
USE_WORKAREA=1 # 1 = ask xfwm4 for the usable area (already excludes panels)
|
||||
PANEL_TOP=0 # extra px to keep free on each side; if USE_WORKAREA=0,
|
||||
PANEL_BOTTOM=0 # put your panel sizes here instead
|
||||
PANEL_LEFT=0
|
||||
PANEL_RIGHT=0
|
||||
SETTLE=0.05 # seconds to let xfwm4 finish un-maximizing before moving
|
||||
VERIFY=1 # 1 = measure each window afterwards and fix pixel offsets
|
||||
VERIFY_TRIES=2 # correction passes per window
|
||||
|
||||
# ---- generic helpers --------------------------------------------------------
|
||||
die() { echo "${0##*/}: $*" >&2; exit 1; }
|
||||
usage() { echo "usage: ${0##*/} next|prev|up|down|tile" >&2; exit 1; }
|
||||
|
||||
# window geometry from wmctrl, keyed by id (filled by collect_windows)
|
||||
declare -A GX GY GW GH
|
||||
|
||||
need() {
|
||||
local c
|
||||
for c in "$@"; do command -v "$c" >/dev/null || die "missing dependency: $c"; done
|
||||
}
|
||||
|
||||
# Active window id in wmctrl's 0x%08x format (0x00000000 if none)
|
||||
active_window() {
|
||||
local d
|
||||
d=$(xdotool getactivewindow 2>/dev/null) || d=0
|
||||
printf '0x%08x' "$d"
|
||||
}
|
||||
|
||||
# index_of ID -> prints index in WINS, or -1
|
||||
index_of() {
|
||||
local i
|
||||
for i in "${!WINS[@]}"; do
|
||||
[[ ${WINS[i]} == "$1" ]] && { echo "$i"; return; }
|
||||
done
|
||||
echo -1
|
||||
}
|
||||
|
||||
# collect_windows focus|tile -> fills WINS, ordered left to right on screen
|
||||
# (then top to bottom), so "next" moves right and "prev" moves left.
|
||||
# focus: normal windows + dialogs, minimized included (focusing restores them)
|
||||
# vert: normal windows + dialogs, minimized skipped (they have no real position)
|
||||
# tile: normal windows only, minimized skipped
|
||||
collect_windows() {
|
||||
local mode=$1 cur id desk x y w h props
|
||||
local -a found=()
|
||||
cur=$(xdotool get_desktop) || die "cannot read current desktop"
|
||||
WINS=()
|
||||
while read -r id desk x y w h _; do
|
||||
[[ $desk == "$cur" || $desk == -1 ]] || continue # this desktop or sticky
|
||||
props=$(xprop -id "$id" _NET_WM_WINDOW_TYPE _NET_WM_STATE 2>/dev/null) || continue
|
||||
|
||||
if [[ $props == *"_NET_WM_WINDOW_TYPE(ATOM)"* ]]; then
|
||||
if [[ $mode == tile ]]; then
|
||||
[[ $props == *_NET_WM_WINDOW_TYPE_NORMAL* ]] || continue
|
||||
else
|
||||
[[ $props == *_NET_WM_WINDOW_TYPE_NORMAL* || $props == *_NET_WM_WINDOW_TYPE_DIALOG* ]] || continue
|
||||
fi
|
||||
fi
|
||||
[[ $props == *_NET_WM_STATE_SKIP_TASKBAR* ]] && continue # panels, desktop, notifyd
|
||||
[[ $mode != focus && $props == *_NET_WM_STATE_HIDDEN* ]] && continue
|
||||
|
||||
GX[$id]=$x GY[$id]=$y GW[$id]=$w GH[$id]=$h
|
||||
|
||||
found+=("$x $y $id")
|
||||
done < <(wmctrl -lG)
|
||||
|
||||
(( ${#found[@]} )) || return 0
|
||||
while read -r _ _ id; do WINS+=("$id"); done < <(printf '%s\n' "${found[@]}" | sort -n -k1,1 -k2,2)
|
||||
}
|
||||
|
||||
# ---- focus ------------------------------------------------------------------
|
||||
focus_cycle() {
|
||||
local dir=$1 n idx
|
||||
collect_windows focus
|
||||
n=${#WINS[@]}
|
||||
(( n > 0 )) || return 0
|
||||
|
||||
idx=$(index_of "$(active_window)")
|
||||
if (( idx < 0 )); then
|
||||
# nothing of ours focused (desktop/panel): enter at the matching end
|
||||
[[ $dir == next ]] && idx=0 || idx=$(( n - 1 ))
|
||||
elif [[ $dir == next ]]; then
|
||||
(( idx < n - 1 )) || return 0 # already rightmost: stop, no wrap
|
||||
(( idx += 1 ))
|
||||
else
|
||||
(( idx > 0 )) || return 0 # already leftmost: stop, no wrap
|
||||
(( idx -= 1 ))
|
||||
fi
|
||||
wmctrl -ia "${WINS[idx]}"
|
||||
}
|
||||
|
||||
# focus_vertical up|down -- nearest window straight above/below the active one.
|
||||
# "Straight above/below" = shares some horizontal span with it. No match: do nothing.
|
||||
focus_vertical() {
|
||||
local dir=$1 act id ax1 ax2 acy cy dy best="" best_dy=-1
|
||||
collect_windows vert
|
||||
act=$(active_window)
|
||||
[[ -n ${GX[$act]+x} ]] || return 0
|
||||
|
||||
ax1=${GX[$act]}; ax2=$(( ax1 + GW[$act] ))
|
||||
acy=$(( GY[$act] + GH[$act] / 2 ))
|
||||
|
||||
for id in "${WINS[@]}"; do
|
||||
[[ $id == "$act" ]] && continue
|
||||
(( GX[$id] < ax2 && GX[$id] + GW[$id] > ax1 )) || continue # no horizontal overlap
|
||||
cy=$(( GY[$id] + GH[$id] / 2 ))
|
||||
if [[ $dir == up ]]; then dy=$(( acy - cy )); else dy=$(( cy - acy )); fi
|
||||
(( dy > 0 )) || continue # wrong side
|
||||
if (( best_dy < 0 || dy < best_dy )); then best=$id best_dy=$dy; fi
|
||||
done
|
||||
|
||||
[[ -n $best ]] && wmctrl -ia "$best"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ---- geometry helpers -------------------------------------------------------
|
||||
# workarea -> WA_X WA_Y WA_W WA_H (usable rectangle on this desktop)
|
||||
workarea() {
|
||||
local cur raw i
|
||||
local -a a
|
||||
cur=$(xdotool get_desktop)
|
||||
raw=$(xprop -root _NET_WORKAREA 2>/dev/null)
|
||||
if (( USE_WORKAREA )) && [[ $raw == *=* ]]; then
|
||||
IFS=', ' read -r -a a <<< "${raw#*= }"
|
||||
i=$(( cur * 4 ))
|
||||
(( i + 3 < ${#a[@]} )) || i=0
|
||||
WA_X=${a[i]} WA_Y=${a[i+1]} WA_W=${a[i+2]} WA_H=${a[i+3]}
|
||||
else
|
||||
read -r WA_W WA_H < <(xdotool getdisplaygeometry)
|
||||
WA_X=0 WA_Y=0
|
||||
fi
|
||||
(( WA_X += PANEL_LEFT, WA_Y += PANEL_TOP,
|
||||
WA_W -= PANEL_LEFT + PANEL_RIGHT, WA_H -= PANEL_TOP + PANEL_BOTTOM ))
|
||||
}
|
||||
|
||||
# frame_extents ID -> FL FR FT FB (decoration size; 0 if not reported)
|
||||
frame_extents() {
|
||||
local raw
|
||||
FL=0 FR=0 FT=0 FB=0
|
||||
raw=$(xprop -id "$1" _NET_FRAME_EXTENTS 2>/dev/null) || return 0
|
||||
[[ $raw == *=* ]] && IFS=', ' read -r FL FR FT FB <<< "${raw#*= }"
|
||||
}
|
||||
|
||||
# client_position ID -> CX CY (real on-screen top-left of the client area)
|
||||
client_position() {
|
||||
read -r CX CY < <(xwininfo -id "$1" 2>/dev/null | awk '
|
||||
/Absolute upper-left X/ {x=$NF} /Absolute upper-left Y/ {y=$NF}
|
||||
END {print x+0, y+0}')
|
||||
}
|
||||
|
||||
# ---- window actions ---------------------------------------------------------
|
||||
# Drop states that make xfwm4 ignore move/resize (maximized, xfwm4 edge-tiling, fullscreen, shaded)
|
||||
reset_state() {
|
||||
wmctrl -ir "$1" -b remove,maximized_vert,maximized_horz
|
||||
wmctrl -ir "$1" -b remove,fullscreen,shaded
|
||||
}
|
||||
|
||||
# maximize ID -- clear fullscreen/shaded, then set the WM's maximized state
|
||||
maximize() {
|
||||
wmctrl -ir "$1" -b remove,fullscreen,shaded
|
||||
wmctrl -ir "$1" -b add,maximized_vert,maximized_horz
|
||||
wmctrl -ia "$1"
|
||||
}
|
||||
|
||||
# place ID X Y W H -- X Y W H is the OUTER rectangle including decorations
|
||||
place() {
|
||||
local id=$1 x=$2 y=$3 w=$4 h=$5 cw ch
|
||||
frame_extents "$id"
|
||||
cw=$(( w - FL - FR )); (( cw < 1 )) && cw=1
|
||||
ch=$(( h - FT - FB )); (( ch < 1 )) && ch=1
|
||||
# gravity 1 (NorthWest): x,y = top-left of the frame, w,h = client size
|
||||
wmctrl -ir "$id" -e "1,$x,$y,$cw,$ch"
|
||||
}
|
||||
|
||||
# verify ID X Y W H -- measure where the window really landed and nudge it if off
|
||||
verify() {
|
||||
local id=$1 x=$2 y=$3 w=$4 h=$5 try dx dy
|
||||
for (( try = 0; try < VERIFY_TRIES; try++ )); do
|
||||
frame_extents "$id"
|
||||
client_position "$id"
|
||||
dx=$(( CX - (x + FL) ))
|
||||
dy=$(( CY - (y + FT) ))
|
||||
(( dx == 0 && dy == 0 )) && return 0
|
||||
place "$id" $(( x - dx )) $(( y - dy )) "$w" "$h"
|
||||
sleep "$SETTLE"
|
||||
done
|
||||
}
|
||||
|
||||
# ---- layout -----------------------------------------------------------------
|
||||
# layout_master_stack N -> fills RECTS with "x y w h" outer rectangles, index 0 = master
|
||||
# Integer remainders are handed out so the tiles cover the area exactly, no 1px gaps.
|
||||
layout_master_stack() {
|
||||
local n=$1 x0 y0 w0 h0 mw sw sx avail base rem i y hh
|
||||
RECTS=()
|
||||
x0=$(( WA_X + GAP )); y0=$(( WA_Y + GAP ))
|
||||
w0=$(( WA_W - 2 * GAP )); h0=$(( WA_H - 2 * GAP ))
|
||||
|
||||
if (( n == 1 )); then
|
||||
RECTS+=("$x0 $y0 $w0 $h0")
|
||||
return
|
||||
fi
|
||||
|
||||
mw=$(( (w0 - GAP) * MASTER_RATIO / 100 ))
|
||||
sw=$(( w0 - GAP - mw ))
|
||||
sx=$(( x0 + mw + GAP ))
|
||||
RECTS+=("$x0 $y0 $mw $h0")
|
||||
|
||||
(( n -= 1 ))
|
||||
avail=$(( h0 - (n - 1) * GAP ))
|
||||
base=$(( avail / n )); rem=$(( avail % n ))
|
||||
y=$y0
|
||||
for (( i = 0; i < n; i++ )); do
|
||||
hh=$(( base + (i < rem ? 1 : 0) ))
|
||||
RECTS+=("$sx $y $sw $hh")
|
||||
(( y += hh + GAP ))
|
||||
done
|
||||
}
|
||||
|
||||
# ---- tile -------------------------------------------------------------------
|
||||
tile() {
|
||||
local n idx master i
|
||||
(( VERIFY )) && need xwininfo
|
||||
collect_windows tile
|
||||
n=${#WINS[@]}
|
||||
(( n > 0 )) || return 0
|
||||
|
||||
# only one window: let xfwm4 maximize it (real maximized state, not fullscreen)
|
||||
if (( n == 1 )); then
|
||||
maximize "${WINS[0]}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# active window becomes master, the rest keep their order in the stack
|
||||
idx=$(index_of "$(active_window)")
|
||||
if (( idx > 0 )); then
|
||||
master=${WINS[idx]}
|
||||
WINS=("$master" "${WINS[@]:0:idx}" "${WINS[@]:idx+1}")
|
||||
fi
|
||||
|
||||
workarea
|
||||
layout_master_stack "$n"
|
||||
|
||||
for i in "${!WINS[@]}"; do reset_state "${WINS[i]}"; done
|
||||
sleep "$SETTLE"
|
||||
|
||||
for i in "${!WINS[@]}"; do
|
||||
# shellcheck disable=SC2086
|
||||
place "${WINS[i]}" ${RECTS[i]}
|
||||
done
|
||||
|
||||
if (( VERIFY )); then
|
||||
sleep "$SETTLE"
|
||||
for i in "${!WINS[@]}"; do
|
||||
# shellcheck disable=SC2086
|
||||
verify "${WINS[i]}" ${RECTS[i]}
|
||||
done
|
||||
fi
|
||||
|
||||
wmctrl -ia "${WINS[0]}"
|
||||
}
|
||||
|
||||
# ---- main -------------------------------------------------------------------
|
||||
need wmctrl xdotool xprop
|
||||
case ${1:-next} in
|
||||
next|prev) focus_cycle "${1:-next}" ;;
|
||||
up|down) focus_vertical "$1" ;;
|
||||
tile) tile ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
# ---------------------------------------------------------------------------------
|
||||
# Steam install recipe
|
||||
# Target: Void Linux (x86_64 glibc only)
|
||||
# Enables nonfree + multilib repos, installs Steam, 32-bit runtime libs, GPU drivers
|
||||
# Usage: GPU=amd|nvidia|intel ./steam.sh (default: amd)
|
||||
# ---------------------------------------------------------------------------------
|
||||
set -e
|
||||
|
||||
GPU="${GPU:-amd}"
|
||||
|
||||
if [ "$(xbps-uhelper arch)" != "x86_64" ]; then
|
||||
echo "Steam requires x86_64 glibc. Aborting." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Enabling nonfree and multilib repositories..."
|
||||
sudo xbps-install -Sy void-repo-nonfree void-repo-multilib void-repo-multilib-nonfree
|
||||
sudo xbps-install -Sy # sync the newly added repos
|
||||
|
||||
echo "Installing Steam and 32-bit runtime libraries..."
|
||||
sudo xbps-install -y \
|
||||
steam \
|
||||
steam-udev-rules \
|
||||
libgcc-32bit \
|
||||
libstdc++-32bit \
|
||||
libdrm-32bit \
|
||||
libglvnd-32bit \
|
||||
mesa-dri \
|
||||
mesa-dri-32bit \
|
||||
vulkan-loader \
|
||||
vulkan-loader-32bit \
|
||||
alsa-lib-32bit \
|
||||
libpulseaudio-32bit
|
||||
|
||||
echo "Installing GPU drivers ($GPU)..."
|
||||
case "$GPU" in
|
||||
amd)
|
||||
sudo xbps-install -y \
|
||||
mesa-vulkan-radeon mesa-vulkan-radeon-32bit \
|
||||
mesa-vaapi
|
||||
;;
|
||||
nvidia)
|
||||
sudo xbps-install -y nvidia nvidia-libs nvidia-libs-32bit
|
||||
;;
|
||||
intel)
|
||||
sudo xbps-install -y \
|
||||
mesa-vulkan-intel mesa-vulkan-intel-32bit \
|
||||
intel-video-accel
|
||||
;;
|
||||
*)
|
||||
echo "Unknown GPU '$GPU' (amd|nvidia|intel)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Reloading udev rules..."
|
||||
sudo udevadm control --reload
|
||||
sudo udevadm trigger
|
||||
|
||||
echo ""
|
||||
echo "✓ Steam installed. Log out/in (or reboot) before first launch."
|
||||
echo ""
|
||||
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
#!/bin/sh
|
||||
# square-xfwm4-corners.sh (v2)
|
||||
# Makes ~/.themes/Default-Square: an exact copy of the xfwm4 "Default" theme
|
||||
# with square top corners, keeping the thin dark outline and highlight.
|
||||
# Usage: ./square-xfwm4-corners.sh [ACTIVE_TITLE_COLOR]
|
||||
# e.g. ./square-xfwm4-corners.sh '#ff9900' (or a name like orange)
|
||||
# no argument = keep the theme's normal title colour
|
||||
set -eu
|
||||
|
||||
ACTIVE_TITLE_COLOR="${1:-}"
|
||||
case "$ACTIVE_TITLE_COLOR" in
|
||||
''|\#[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]|\#[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]) ;;
|
||||
*[!a-zA-Z]*) echo "Colour must be #rgb, #rrggbb or a plain name like orange"; exit 1 ;;
|
||||
esac
|
||||
|
||||
SRC=/usr/share/themes/Default/xfwm4
|
||||
DST_THEME="$HOME/.themes/Default-Square"
|
||||
DST="$DST_THEME/xfwm4"
|
||||
[ -d "$SRC" ] || { echo "Missing $SRC"; exit 1; }
|
||||
|
||||
# Warn if the installed theme differs from the version these overlays were made from
|
||||
want=349096e386ab06feddff55aa404bed0a
|
||||
have=$(md5sum "$SRC/top-left-active.png" 2>/dev/null | cut -d' ' -f1 || true)
|
||||
[ "$have" = "$want" ] || echo "Warning: your Default theme differs from the expected version; result may be slightly off."
|
||||
|
||||
# Fresh copy (also cleans up the result of the first version of this script)
|
||||
rm -rf "$DST_THEME"
|
||||
mkdir -p "$DST_THEME"
|
||||
cp -r "$SRC" "$DST"
|
||||
|
||||
# 1) Base layer (XPM): make the transparent corner pixels use the frame colour
|
||||
for f in "$DST"/top-left-*.xpm "$DST"/top-right-*.xpm; do
|
||||
awk '
|
||||
/"[^"]*"/ && !hdr { hdr = 1; split(substr($0, index($0,"\"")+1), a, /[ \t"]+/); nc = a[3]; cpp = a[4]; print; next }
|
||||
hdr && seen < nc && /"/ {
|
||||
seen++; s = substr($0, index($0,"\"")+1); s = substr(s, 1, index(s,"\"")-1)
|
||||
key[seen] = substr(s, 1, cpp); spec[seen] = substr(s, cpp+1); pre[seen] = substr($0, 1, index($0,"\"")-1)
|
||||
isnone[seen] = (tolower(spec[seen]) ~ /c[ \t]+none/)
|
||||
if (!isnone[seen] && fill == "") fill = spec[seen]
|
||||
if (seen == nc) for (i = 1; i <= nc; i++) print pre[i] "\"" key[i] (isnone[i] ? fill : spec[i]) "\","
|
||||
next }
|
||||
{ print }' "$f" > "$f.tmp" && mv "$f.tmp" "$f"
|
||||
done
|
||||
|
||||
# 2) Overlay (PNG): square versions of the outline/highlight images
|
||||
write_png() { printf '%s' "$2" | base64 -d > "$DST/$1"; }
|
||||
write_png top-left-active.png 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAdCAYAAACXFC2jAAAASklEQVR42mNkYGBoYMADWLi5udm+fPnShlPB/////zMwMPzHqQBK41TAxEAAsPz79+8/ZSYQcgMdrBj1JpIbGBkZ/5FtwqgCCAAAJ9onK5/spQ0AAAAASUVORK5CYII='
|
||||
write_png top-left-inactive.png 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAdCAYAAACXFC2jAAAASklEQVR42mNkYGBoYMADWLi5udm+fPnShlPB/////zMwMPzHqQBK41TAxEAAsPz79+8/ZSYQcgMdrBj1JpIbGBkZ/5FtwqgCCAAAJ9onK5/spQ0AAAAASUVORK5CYII='
|
||||
write_png top-right-active.png 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAdCAYAAACXFC2jAAAAR0lEQVR42u2PMQ7AIAwDz6hjXszEy+MOZSUMlZi41dY5ETAokO1YhRHRH8Crgm2XBYDGhtKQmf5nODRx35wGSVnk+xtu4eMFmCwkTAAQh0MAAAAASUVORK5CYII='
|
||||
write_png top-right-inactive.png 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAdCAYAAACXFC2jAAAAR0lEQVR42u2PMQ7AIAwDz6hjXszEy+MOZSUMlZi41dY5ETAokO1YhRHRH8Crgm2XBYDGhtKQmf5nODRx35wGSVnk+xtu4eMFmCwkTAAQh0MAAAAASUVORK5CYII='
|
||||
|
||||
# 3) Optional: colour of the focused window's title text
|
||||
if [ -n "$ACTIVE_TITLE_COLOR" ]; then
|
||||
rc="$DST/themerc"
|
||||
if grep -q '^active_text_color=' "$rc"; then
|
||||
sed -i "s|^active_text_color=.*|active_text_color=$ACTIVE_TITLE_COLOR|" "$rc"
|
||||
else
|
||||
echo "active_text_color=$ACTIVE_TITLE_COLOR" >> "$rc"
|
||||
fi
|
||||
echo "Active title colour: $ACTIVE_TITLE_COLOR"
|
||||
fi
|
||||
|
||||
echo "Created $DST_THEME"
|
||||
xfconf-query -c xfwm4 -p /general/theme -s Default 2>/dev/null || true
|
||||
xfconf-query -c xfwm4 -p /general/theme -s Default-Square 2>/dev/null \
|
||||
&& echo "Applied theme 'Default-Square'." \
|
||||
|| echo "Select 'Default-Square' in Settings > Window Manager > Style."
|
||||
Reference in New Issue
Block a user