├── .gitignore ├── Emacs.org ├── Makefile ├── README.md ├── Workstation-Desktop-Felix.org ├── Workstation-Desktop.org ├── Workstation.org ├── manifests ├── browsers.scm ├── code.scm ├── communication.scm ├── desktop.scm ├── emacs.scm ├── encryption.scm ├── files.scm ├── games.scm ├── multimedia-system.scm ├── multimedia.scm ├── themes.scm └── tools.scm └── res └── Desktop.png /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.swp 3 | -------------------------------------------------------------------------------- /Emacs.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Emacs 2 | #+STARTUP: content 3 | #+CONSTANTS: code_dir_path="/data/dustin/Projects/Code" 4 | 5 | * Configuration :emacs: 6 | ** About Emacs 7 | This is my emacs config file. Yes, in emacs you can write configuration like a Google Doc and get away with it. It's called [[https://en.wikipedia.org/wiki/Literate_programming]["literate programming"]]. 8 | 9 | Emacs is more than an editor, it's a whole damn operating system. This file is evidence of that. This configuration drives how I interact with my journal, complete and organize tasks, develop and write blog posts, write code and ship new stuff, etc. etc. etc. list goes o. I've yet to jump into EXWM, but if one is so inclined, Emacs can expand beyond an application into all software. 10 | 11 | ** Personal Information 12 | Just me! 13 | 14 | #+NAME: personal-info 15 | #+BEGIN_SRC emacs-lisp 16 | (setq user-full-name "Dustin Lyons" 17 | user-mail-address "hello@dustinlyons.co") 18 | #+END_SRC 19 | 20 | ** Initialization 21 | *** Booting up 22 | Mainly splash screen settings. In the future we may look to optimize performance here. 23 | #+NAME: startup 24 | #+BEGIN_SRC emacs-lisp 25 | ;; Turn off the splash screen 26 | (setq inhibit-startup-screen t) 27 | ;; Turn off the splash screen 28 | (setq initial-scratch-message nil) 29 | #+END_SRC 30 | 31 | *** Add package sources 32 | This associates our package manager with the right source (MELPA). 33 | 34 | #+NAME: package-sources 35 | #+BEGIN_SRC emacs-lisp 36 | (unless (assoc-default "melpa" package-archives) 37 | (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)) 38 | (unless (assoc-default "org" package-archives) 39 | (add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t)) 40 | (unless (assoc-default "nongnu" package-archives) 41 | (add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/") t)) 42 | #+END_SRC 43 | 44 | *** Package managers 45 | Using straight.el under the hood of use-package enables us to download packages using git. This is preferred for easier hacking. 46 | 47 | **** Straight.el 48 | Straight.el fetchs packages over git via use-package. 49 | 50 | #+NAME: straight-el 51 | #+BEGIN_SRC emacs-lisp 52 | ;; use-package package provides common package import functions 53 | (unless (package-installed-p 'use-package) 54 | (package-initialize) 55 | (package-install 'use-package)) 56 | (setq use-package-verbose t) 57 | (setq use-package-always-ensure t) 58 | (require 'use-package) 59 | 60 | ;; This sets up straight.el, a git package manager 61 | (defvar bootstrap-version) 62 | (let ((bootstrap-file 63 | (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) 64 | (bootstrap-version 5)) 65 | (unless (file-exists-p bootstrap-file) 66 | (with-current-buffer 67 | (url-retrieve-synchronously 68 | "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el" 69 | 'silent 'inhibit-cookies) 70 | (goto-char (point-max)) 71 | (eval-print-last-sexp))) 72 | (load bootstrap-file nil 'nomessage)) 73 | 74 | ;; Tells (use-package) to use straight.el to download packages 75 | ;; straight.el uses git packages, instead of the default bin files, which we like 76 | ;; as it's much easier to open it up and hack it 77 | (setq straight-use-package-by-default t) 78 | #+END_SRC 79 | 80 | ** Keybindings 81 | *** Leader keys 82 | I use general.el to define groups of keybindings under my 'leader' definition. You will see these definitions sprinkled throughout this file; my own private collection of fast shit. For more info, [[https://medium.com/usevim/vim-101-what-is-the-leader-key-f2f5c1fa610f][here]] is a good explanation on leader keys. 83 | 84 | #+NAME: keybindings 85 | #+BEGIN_SRC emacs-lisp 86 | ;; ESC will also cancel/quit/etc. 87 | (global-set-key (kbd "") 'keyboard-escape-quit) 88 | (use-package general 89 | :config 90 | (general-evil-setup t) 91 | (general-create-definer dl/leader-keys 92 | :keymaps '(normal visual emacs) 93 | :prefix ",")) 94 | #+END_SRC 95 | 96 | *** Hydra 97 | Hydra enables me drop into quick keybinding modes. See [[https://github.com/abo-abo/hydra][here]]. 98 | 99 | #+NAME: hydra 100 | #+BEGIN_SRC emacs-lisp 101 | (use-package hydra) 102 | #+END_SRC 103 | 104 | *** Buffers 105 | #+NAME: next-buffer 106 | #+BEGIN_SRC emacs-lisp 107 | (global-set-key (kbd "") 'next-buffer) 108 | #+END_SRC 109 | 110 | ** Display Options 111 | *** Themes 112 | Some my own, some from others. 113 | 114 | #+NAME: themes-autothemer 115 | #+BEGIN_SRC emacs-lisp 116 | (use-package autothemer 117 | :init (load-theme 'zeroed t)) 118 | #+END_SRC 119 | 120 | *** Windows 121 | **** Defaults 122 | Sets some reasonable defaults. 123 | 124 | #+NAME: windows-reasonable-defaults 125 | #+BEGIN_SRC emacs-lisp 126 | ;; Maximize window on initialize 127 | ;; (add-hook 'window-setup-hook 'toggle-frame-maximized t) 128 | (when window-system (set-frame-size (selected-frame) 120 60)) 129 | (setq use-dialog-box nil 130 | use-file-dialog nil 131 | cursor-type 'bar) 132 | #+END_SRC 133 | 134 | **** Display configuration 135 | Turns off the various menu bars, they're quite ugly. 136 | 137 | ***** Fonts 138 | [[https://sourcefoundry.org/hack/][Hack]] is a code-friendly typeface. I really like it. 139 | 140 | #+NAME: fonts 141 | #+BEGIN_SRC emacs-lisp 142 | ;; Set the default pitch face 143 | (set-face-attribute 'default nil :font "Hack" :height 100) 144 | 145 | ;; Set the fixed pitch face 146 | (set-face-attribute 'fixed-pitch nil 147 | :font "Hack" 148 | :weight 'light 149 | :height 100) 150 | 151 | ;; Set the variable pitch face 152 | (set-face-attribute 'variable-pitch nil 153 | :font "Helvetica LT Std" 154 | :height 120) 155 | #+END_SRC 156 | 157 | ***** Line numbers 158 | These functions define vim-style relative line numbers. 159 | 160 | #+NAME: line-numbers 161 | #+BEGIN_SRC emacs-lisp 162 | (global-linum-mode 1) 163 | (defvar my-linum-current-line-number 0) 164 | (setq linum-format 'my-linum-relative-line-numbers) 165 | 166 | ;; This fancy function handles the math behind relative line numbers 167 | (defun my-linum-relative-line-numbers (line-number) 168 | (let ((y (1+ (- line-number my-linum-current-line-number)))) 169 | (propertize 170 | (number-to-string 171 | (cond ((<= y 0) (abs (- y 2))) ((> y 0) y))) 172 | 'face 'linum))) 173 | 174 | (defadvice linum-update (around my-linum-update) 175 | (let ((my-linum-current-line-number (line-number-at-pos))) 176 | ad-do-it)) 177 | 178 | ;; Turn it on 179 | (ad-activate 'linum-update) 180 | 181 | ;; Disable line numbers for some modes 182 | (dolist (mode '(org-mode-hook 183 | term-mode-hook 184 | shell-mode-hook 185 | eshell-mode-hook)) 186 | (add-hook mode (lambda () (linum-mode 0)))) 187 | #+END_SRC 188 | 189 | ***** Toggles 190 | Turn UI things on and off, scale things up and down. 191 | 192 | #+NAME: ui-toggles 193 | #+BEGIN_SRC emacs-lisp 194 | (defhydra hydra-text-scale (:timeout 4) 195 | "scale text" 196 | ("j" text-scale-increase "big") 197 | ("k" text-scale-decrease "small") 198 | ("q" nil "quit" :exit t)) 199 | 200 | (dl/leader-keys 201 | "t" '(:ignore t :which-key "toggles") 202 | "tt" '(counsel-load-theme :which-key "choose theme") 203 | "ts" '(hydra-text-scale/body :which-key "scale text")) 204 | #+END_SRC 205 | 206 | ***** Window minor modes 207 | I like these window related minor modes. 208 | 209 | #+NAME: windows-ui-settings 210 | #+BEGIN_SRC emacs-lisp 211 | ;; Turn off UI junk 212 | ;; Note to future self: If you have problems with these later, 213 | ;; move these into custom file and set variable custom-file 214 | (column-number-mode) 215 | (scroll-bar-mode -1) 216 | (menu-bar-mode -1) 217 | (tool-bar-mode -1) 218 | (winner-mode 1) ;; ctrl-c left, ctrl-c right for window undo/redo 219 | #+END_SRC 220 | 221 | ***** Rainbow delimiters 222 | Makes my lisp parens pretty, and easy to spot. 223 | 224 | #+NAME: rainbow-delmiters 225 | #+BEGIN_SRC emacs-lisp 226 | (use-package rainbow-delimiters 227 | :hook (prog-mode . rainbow-delimiters-mode)) 228 | #+END_SRC 229 | 230 | ***** Color definitions 231 | Define a global set of colors to be used everywhere in Emacs. 232 | 233 | #+NAME: color-definitions 234 | #+BEGIN_SRC emacs-lisp 235 | (defvar dl/black-color "#1F2528") 236 | (defvar dl/red-color "#EC5F67") 237 | (defvar dl/yellow-color "#FAC863") 238 | (defvar dl/blue-color "#6699CC") 239 | (defvar dl/green-color "#99C794") 240 | (defvar dl/purple-color "#C594C5") 241 | (defvar dl/teal-color "#5FB3B3") 242 | (defvar dl/light-grey-color "#C0C5CE") 243 | (defvar dl/dark-grey-color "#65737E") 244 | #+END_SRC 245 | 246 | **** Set mode margins 247 | This is used primarily to center org mode text. 248 | 249 | #+NAME: mode-margins 250 | #+BEGIN_SRC emacs-lisp 251 | (defun dl/org-mode-visual-fill () 252 | (setq visual-fill-column-width 110 253 | visual-fill-column-center-text t) 254 | (visual-fill-column-mode 1)) 255 | 256 | (use-package visual-fill-column 257 | :defer t 258 | :hook (org-mode . dl/org-mode-visual-fill)) 259 | #+END_SRC 260 | 261 | **** Easy window motions with ace-window 262 | Predefine windows with hotkeys and jump to them. 263 | 264 | #+BEGIN_SRC emacs-lisp 265 | (use-package ace-window 266 | :bind (("M-o" . ace-window)) 267 | :custom 268 | (aw-scope 'frame) 269 | (aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)) 270 | (aw-minibuffer-flag t) 271 | :config 272 | (ace-window-display-mode 1)) 273 | #+END_SRC 274 | 275 | **** "Powerline" 276 | Keeps info at my fingertips. Modeline is much better than Vim's Powerline (sorry Vim). 277 | 278 | #+NAME: modeline 279 | #+BEGIN_SRC emacs-lisp 280 | ;; Run M-x all-the-icons-install-fonts to install 281 | (use-package all-the-icons) 282 | (use-package doom-modeline 283 | :ensure t 284 | :init (doom-modeline-mode 1)) 285 | #+END_SRC 286 | 287 | **** Rotate windows 288 | Various helpers and packages I find useful for window management. 289 | 290 | #+BEGIN_SRC emacs-lisp 291 | 292 | ;; Rotates windows and layouts 293 | (use-package rotate 294 | :config) 295 | 296 | (dl/leader-keys 297 | "r" '(:ignore t :which-key "rotate") 298 | "rw" '(rotate-window :which-key "rotate window") 299 | "rl" '(rotate-layout :which-key "rotate layout")) 300 | 301 | #+END_SRC 302 | ** Global Settings and Config 303 | *** Global modes 304 | I like these modes, what can I say. 305 | 306 | #+NAME: global-modes 307 | #+BEGIN_SRC emacs-lisp 308 | (defalias 'yes-or-no-p 'y-or-n-p) ;; Use Y or N in prompts, instead of full Yes or No 309 | 310 | (global-visual-line-mode t) ;; Wraps lines everywhere 311 | (line-number-mode t) ;; Line numbers in the gutter 312 | (show-paren-mode t) ;; Highlights parans for me 313 | #+END_SRC 314 | 315 | ** Org mode 316 | *** Install package 317 | If you haven't heard of org mode, go watch [[https://www.youtube.com/watch?v=SzA2YODtgK4][this]] talk and come back when you are finished. 318 | 319 | #+NAME::org-mode 320 | #+BEGIN_SRC emacs-lisp 321 | (defun dl/org-mode-setup () 322 | (org-indent-mode) 323 | (variable-pitch-mode 1) 324 | (auto-fill-mode 0) 325 | (visual-line-mode 1) 326 | (setq evil-auto-indent nil)) 327 | 328 | (use-package org 329 | :defer t 330 | :hook (org-mode . dl/org-mode-setup) 331 | :config 332 | (setq org-edit-src-content-indentation 2 ;; Indent code blocks by 2 333 | org-ellipsis " ▾" ;; Prettify the fold indicator 334 | org-hide-emphasis-markers t ;; Hide special characters 335 | org-hide-block-startup nil) ;; Don't start org mode with blocks folded 336 | :bind 337 | (("C-c a" . org-agenda))) 338 | 339 | (setq org-todo-keywords 340 | '((sequence "TODO(t)" 341 | "NEXT(n)" 342 | "WAITING(w)" 343 | "SOMEDAY(s)" 344 | "|" 345 | "CANCELED(c)" 346 | "DONE(d)"))) 347 | 348 | ;; Fast access to tag common contexts I use 349 | (setq org-tag-persistent-alist 350 | '(("Inbox" . ?i) ("@Home" . ?h) ("@Amanda" . ?a)("@Justin" . ?j) 351 | ("@Car" . ?c) ("@Office" . ?o) ("#Phone" . ?p) ("#Computer" . ?u))) 352 | 353 | (setq org-todo-keyword-faces 354 | `(("NEXT" . ,dl/yellow-color) 355 | ("WAITING" . ,dl/light-grey-color) 356 | ("SOMEDAY" . ,dl/dark-grey-color))) 357 | 358 | (setq org-tag-faces 359 | `(("@Home" . ,dl/green-color) 360 | ("@Car" . ,dl/purple-color) 361 | ("@Office" . ,dl/teal-color) 362 | ("Inbox" . ,dl/blue-color))) 363 | #+END_SRC 364 | 365 | **** Quick Snippets 366 | 367 | Simple snippets using leader keys. I'll convert to yas-snippets when this needs an upgrade. 368 | #+NAME::org-mode-quick-entry 369 | #+BEGIN_SRC emacs-lisp 370 | 371 | (defvar current-time-format "%H:%M:%S" 372 | "Format of date to insert with `insert-current-time' func. 373 | Note the weekly scope of the command's precision.") 374 | 375 | (defun dl/insert-current-time () 376 | "insert the current time (1-week scope) into the current buffer." 377 | (interactive) 378 | (insert "* ") 379 | (insert (format-time-string current-time-format (current-time))) 380 | (insert "\n")) 381 | 382 | (dl/leader-keys 383 | "c" '(:ignore t :which-key "compilation") 384 | "cc" '(compile :which-key "compile") 385 | "cr" '(compile :which-key "recompile") 386 | "," '(dl/insert-current-time :which-key "current time")) 387 | 388 | #+END_SRC 389 | 390 | ***** Roam capture templates 391 | These are templates used to create new notes. 392 | 393 | #+NAME::roam-templates 394 | #+BEGIN_SRC emacs-lisp 395 | (setq org-roam-capture-templates 396 | '(("d" "default" plain 397 | "%?" 398 | :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n\n") 399 | :unnarrowed t) 400 | ("a" "area" plain 401 | "#+filetags: Area\n\n* Goals\n\n%^{Goals}\n\n* Tasks\n\n** TODO %?" 402 | :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}") 403 | :unnarrowed t) 404 | ("j" "project" plain 405 | "#+filetags: Project\n\n* Goals\n\n%^{Goals}\n\n* Tasks\n\n** TODO %?" 406 | :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}") 407 | :unnarrowed t) 408 | ("p" "people" plain 409 | "#+filetags: People CRM\n\n* Contacts\n\nRelationship: %^{Relationship}\nPhone:\nAddress:\nBirthday:\n\n* Notes\n\n %?" 410 | :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}") 411 | :unnarrowed t) 412 | ("i" "institution" plain 413 | "#+filetags: Institution CRM\n\n* Contacts\n\nRelationship: %^{Relationship}\nPhone:\nAddress:\n\n* Notes\n\n %?" 414 | :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}") 415 | :unnarrowed t))) 416 | #+END_SRC 417 | **** Org Roam 418 | ***** Install package 419 | #+NAME::org-roam-package 420 | #+BEGIN_SRC emacs-lisp 421 | (use-package org-roam 422 | :straight (:host github :repo "org-roam/org-roam" 423 | :files (:defaults "extensions/*")) 424 | :init 425 | (setq org-roam-v2-ack t) ;; Turn off v2 warning 426 | (add-to-list 'display-buffer-alist 427 | '("\\*org-roam\\*" 428 | (display-buffer-in-direction) 429 | (direction . right) 430 | (window-width . 0.33) 431 | (window-height . fit-window-to-buffer))) 432 | (org-roam-db-autosync-mode) 433 | :custom 434 | (org-roam-directory (file-truename "~/Notebook")) 435 | (org-roam-dailies-directory "daily/") 436 | (org-roam-completion-everywhere t) 437 | :bind 438 | (("C-c r b" . org-roam-buffer-toggle) 439 | ("C-c r t" . org-roam-dailies-goto-today) 440 | ("C-c r y" . org-roam-dailies-goto-yesterday) 441 | ("C-M-n" . org-roam-node-insert) 442 | :map org-mode-map 443 | ("C-M-i" . completion-at-point) 444 | ("C-M-f" . org-roam-node-find) 445 | ("C-M-c" . dl/org-roam-create-id) 446 | ("C-" . org-roam-dailies-goto-previous-note) 447 | ("C-`" . org-roam-buffer-toggle) 448 | ("C-" . org-roam-dailies-goto-next-note))) 449 | 450 | #+END_SRC 451 | 452 | ***** Configure templates 453 | #+NAME::org-roam-templates 454 | #+BEGIN_SRC emacs-lisp 455 | (setq org-roam-dailies-capture-templates 456 | '(("d" "default" entry 457 | "* %?" 458 | :if-new (file+head "%<%Y-%m-%d>.org" 459 | "#+TITLE: %<%Y-%m-%d>\n#+filetags: Daily\n\n")))) 460 | #+END_SRC 461 | 462 | ***** Extending Roam 463 | Here we add additional function to org-roam to either do something specific for more workflow, or otherwise make ~org-roam~ more full featured. 464 | 465 | ****** Set CREATED and LAST_MODIFIED filetags on save 466 | Sets timestamps in the Properties drawer of files. I intend to use this one day when rendering these notes as HTML, to quickly see files last touched. 467 | 468 | #+NAME::org-roam-set-timestamps-on-save 469 | #+BEGIN_SRC emacs-lisp 470 | (defvar dl/org-created-property-name "CREATED") 471 | 472 | (defun dl/org-set-created-property (&optional active name) 473 | (interactive) 474 | (let* ((created (or name dl/org-created-property-name)) 475 | (fmt (if active "<%s>" "[%s]")) 476 | (now (format fmt (format-time-string "%Y-%m-%d %a %H:%M")))) 477 | (unless (org-entry-get (point) created nil) 478 | (org-set-property created now) 479 | now))) 480 | 481 | (defun dl/org-find-time-file-property (property &optional anywhere) 482 | (save-excursion 483 | (goto-char (point-min)) 484 | (let ((first-heading 485 | (save-excursion 486 | (re-search-forward org-outline-regexp-bol nil t)))) 487 | (when (re-search-forward (format "^#\\+%s:" property) 488 | (if anywhere nil first-heading) t) 489 | (point))))) 490 | 491 | (defun dl/org-has-time-file-property-p (property &optional anywhere) 492 | (when-let ((pos (dl/org-find-time-file-property property anywhere))) 493 | (save-excursion 494 | (goto-char pos) 495 | (if (and (looking-at-p " ") 496 | (progn (forward-char) 497 | (org-at-timestamp-p 'lax))) 498 | pos -1)))) 499 | 500 | (defun dl/org-set-time-file-property (property &optional anywhere pos) 501 | (when-let ((pos (or pos 502 | (dl/org-find-time-file-property property)))) 503 | (save-excursion 504 | (goto-char pos) 505 | (if (looking-at-p " ") 506 | (forward-char) 507 | (insert " ")) 508 | (delete-region (point) (line-end-position)) 509 | (let* ((now (format-time-string "[%Y-%m-%d %a %H:%M]"))) 510 | (insert now))))) 511 | 512 | (defun dl/org-set-last-modified () 513 | "Update the LAST_MODIFIED file property in the preamble." 514 | (when (derived-mode-p 'org-mode) 515 | (dl/org-set-time-file-property "LAST_MODIFIED"))) 516 | #+END_SRC 517 | 518 | ****** Set CREATED on node creation 519 | #+NAME::org-roam-set-timestamps-on-save 520 | #+BEGIN_SRC emacs-lisp 521 | (defun dl/org-roam-create-id () 522 | (interactive) 523 | (org-id-get-create) 524 | (dl/org-set-created-property)) 525 | #+END_SRC 526 | 527 | *** Agenda 528 | **** Filter out files that don't include tasks in org-agenda 529 | I use org-roam to take notes, which keeps many small files in the style of Zettelkasten. However, org-agenda doesn't perform well in this scenario. To fix this, we filter out all files from org-agenda that don't contain a ~TODO~. 530 | 531 | #+NAME::org-mode 532 | #+BEGIN_SRC emacs-lisp 533 | (defun dl/define-agenda-files () 534 | (interactive) 535 | "Return a list of note files containing 'HasTodo' tag. 536 | I use this to denote files with tasks for org-agenda" ; 537 | (seq-uniq 538 | (seq-map 539 | #'car 540 | (org-roam-db-query 541 | [:select [nodes:file] 542 | :from tags 543 | :left-join nodes 544 | :on (= tags:node-id nodes:id) 545 | :where (in tag $v1)] '(["Project" "Area" "Daily"]))))) 546 | 547 | ;; Roam Daily Log and Project Files only 548 | (setq org-agenda-files (dl/define-agenda-files)) 549 | 550 | (dl/leader-keys 551 | "a" '(dl/define-agenda-files :which-key "refresh agenda db")) 552 | 553 | #+END_SRC 554 | 555 | **** Remove noise from org-agenda views 556 | This block sets the ~org-agenda-prefix-format~ in an friendly way for org-roam (credit to [[https://d12frosted.io/posts/2020-06-24-task-management-with-roam-vol2.html][this post)]]. It truncates long filenames and removes the org-roam timestamp slug. 557 | 558 | #+NAME::remove-noise-from-org-agenda 559 | #+BEGIN_SRC emacs-lisp 560 | (defun dl/buffer-prop-get (name) 561 | "Get a buffer property called NAME as a string." 562 | (org-with-point-at 1 563 | (when (re-search-forward (concat "^#\\+" name ": \\(.*\\)") 564 | (point-max) t) 565 | (buffer-substring-no-properties 566 | (match-beginning 1) 567 | (match-end 1))))) 568 | 569 | (defun dl/agenda-category (&optional len) 570 | "Get category of item at point for agenda." 571 | (let* ((file-name (when buffer-file-name 572 | (file-name-sans-extension 573 | (file-name-nondirectory buffer-file-name)))) 574 | (title (dl/buffer-prop-get "title")) 575 | (category (org-get-category)) 576 | (result 577 | (or (if (and 578 | title 579 | (string-equal category file-name)) 580 | title 581 | category) 582 | ""))) 583 | (if (numberp len) 584 | (s-truncate len (s-pad-right len " " result)) 585 | result))) 586 | 587 | (setq org-agenda-prefix-format 588 | '((agenda . " %i %(dl/agenda-category 32)%?-32t% s") 589 | (todo . " %i %(dl/agenda-category 32) ") 590 | (tags . " %i %(dl/agenda-category 32) ") 591 | (search . " %i %(dl/agenda-category 32) "))) 592 | #+END_SRC 593 | 594 | **** org-super-agenda views 595 | Setup for org-super-agenda and org-ql. 596 | 597 | #+NAME::org-super-agenda 598 | #+BEGIN_SRC emacs-lisp 599 | (use-package org-super-agenda 600 | :after org-agenda 601 | :init 602 | (setq org-agenda-dim-blocked-tasks nil)) 603 | 604 | ;; Dashboard View 605 | (setq org-super-agenda-groups 606 | '((:name "Priority" 607 | :priority "A") 608 | (:name "Inbox" 609 | :tag ("Inbox" "Daily")) 610 | (:name "Next Actions at Office" 611 | :and ( 612 | :todo ("NEXT") 613 | :tag ("Active") 614 | :tag ("@Office"))) 615 | (:name "Next Actions at Home" 616 | :and ( 617 | :todo ("NEXT") 618 | :tag ("Active") 619 | :tag ("@Home"))) 620 | (:name "Waiting" 621 | :todo "WAITING") 622 | (:name "Maintenance" 623 | :todo "MAINTAIN") 624 | (:name "Home" 625 | :tag "@Home") 626 | (:name "Office" 627 | :tag "@Office") 628 | (:name "Braeview" 629 | :tag "Braeview") 630 | (:name "Productivity" 631 | :tag "Productivity") 632 | (:name "Someday" 633 | :todo "SOMEDAY"))) 634 | 635 | (org-super-agenda-mode) 636 | #+END_SRC 637 | 638 | *** UI improvements 639 | Anything related to making org mode pretty. 640 | 641 | **** Change default bullets to be pretty 642 | 643 | Replaces the standard org-mode header asterisks with dots. 644 | #+NAME::org-mode-visuals 645 | #+BEGIN_SRC emacs-lisp 646 | (use-package org-superstar 647 | :after org 648 | :hook (org-mode . org-superstar-mode) 649 | :custom 650 | (org-superstar-remove-leading-stars t) 651 | (org-superstar-headline-bullets-list '("•" "•" "•" "◦" "◦" "◦" "◦"))) 652 | #+END_SRC 653 | 654 | **** Fonts 655 | #+NAME::org-mode-variable-width-fonts 656 | #+BEGIN_SRC emacs-lisp 657 | ;; Not sure why this is needed, but the org-indent face "requires" it (pun) 658 | (require 'org-indent) 659 | 660 | (set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch) 661 | (set-face-attribute 'org-table nil :inherit 'fixed-pitch) 662 | (set-face-attribute 'org-formula nil :inherit 'fixed-pitch) 663 | (set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch)) 664 | (set-face-attribute 'org-indent nil :inherit '(org-hide fixed-pitch)) 665 | (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch)) 666 | (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch)) 667 | (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch)) 668 | (set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch) 669 | 670 | (set-face-attribute 'org-document-title nil :font "Helvetica LT Std" :weight 'bold :height 1.2) 671 | (dolist (face '((org-level-1 . 1.2) 672 | (org-level-2 . 1.15) 673 | (org-level-3 . 1.1) 674 | (org-level-4 . 1.05) 675 | (org-level-5 . 1.05) 676 | (org-level-6 . 1.0) 677 | (org-level-7 . 1.0) 678 | (org-level-8 . 1.0))) 679 | (set-face-attribute (car face) nil :font "Helvetica LT Std" :weight 'medium :height (cdr face))) 680 | #+END_SRC 681 | 682 | ** Evil mode (Vim) 683 | *** Install package 684 | This is what makes emacs possible for me. All evil mode packages and related configuration. 685 | 686 | #+NAME: evil-packages 687 | #+BEGIN_SRC emacs-lisp 688 | 689 | (defun dl/evil-hook () 690 | (dolist (mode '(eshell-mode 691 | git-rebase-mode 692 | term-mode)) 693 | (add-to-list 'evil-emacs-state-modes mode))) ;; no evil mode for these modes 694 | 695 | (use-package evil 696 | :init 697 | (setq evil-want-integration t) ;; TODO: research what this does 698 | (setq evil-want-keybinding nil) 699 | (setq evil-want-fine-undo 'fine) ;; undo/redo each motion 700 | (setq evil-want-Y-yank-to-eol t) ;; Y copies to end of line like vim 701 | (setq evil-want-C-u-scroll t) ;; vim like scroll up 702 | :hook (evil-mode . dl/evil-hook) 703 | :config 704 | (evil-mode 1) 705 | 706 | ;; Emacs "cancel" == vim "cancel" 707 | (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state) 708 | ;; Ctrl-h deletes in vim insert mode 709 | (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join) 710 | ;; When we wrap lines, jump visually, not to the "actual" next line 711 | (evil-global-set-key 'motion "j" 'evil-next-visual-line) 712 | (evil-global-set-key 'motion "k" 'evil-previous-visual-line) 713 | 714 | (evil-set-initial-state 'message-buffer-mode 'normal) 715 | (evil-set-initial-state 'dashboard-mode 'normal)) 716 | 717 | ;; Gives me vim bindings elsewhere in emacs 718 | (use-package evil-collection 719 | :after evil 720 | :config 721 | (evil-collection-init)) 722 | 723 | ;; Keybindings in org mode 724 | (use-package evil-org 725 | :after org 726 | :hook 727 | (org-mode . (lambda () evil-org-mode)) 728 | :config 729 | (require 'evil-org-agenda) 730 | (evil-org-agenda-set-keys)) 731 | 732 | ;; Branching undo system 733 | (use-package undo-tree 734 | :after evil 735 | :diminish 736 | :config 737 | (evil-set-undo-system 'undo-tree) 738 | (global-undo-tree-mode 1)) 739 | 740 | #+END_SRC 741 | 742 | ** Managing Projects 743 | *** Projectile 744 | Projectile enables me organize projects with a killer grep interface. 745 | 746 | #+NAME: projectile 747 | #+BEGIN_SRC emacs-lisp :var code_dir_path=(org-table-get-constant "code_dir_path") 748 | (use-package projectile 749 | :diminish projectile-mode 750 | :config (projectile-mode) 751 | :custom 752 | ((projectile-completion-system 'ivy)) 753 | :bind-keymap 754 | ("C-c p" . projectile-command-map) 755 | :init 756 | (when (file-directory-p code_dir_path) 757 | (setq projectile-project-search-path '(code_dir_path))) 758 | (setq projectile-switch-project-action #'projectile-dired)) 759 | 760 | ;; Gives me Ivy options in the Projectile menus 761 | (use-package counsel-projectile 762 | :after projectile 763 | :config (counsel-projectile-mode)) 764 | #+END_SRC 765 | 766 | ** Managing Files 767 | Configuration related to filesystem, either basic IO and interaction from emacs or directly moving files around where it makes sense. 768 | 769 | *** Backups and auto-save 770 | These settings keep emacs from littering the filesystem with buffer backups. These files look like ~~yourfilename.txt~ or ~#yourfilename.txt#~ and would otherwise be dropped in your working directory. 771 | 772 | #+NAME: backup-files 773 | #+BEGIN_SRC emacs-lisp 774 | (setq backup-directory-alist 775 | `(("." . ,(concat user-emacs-directory "backup"))) 776 | backup-by-copying t ; Don't delink hardlinks 777 | version-control t ; Use version numbers on backups 778 | delete-old-versions t ; Automatically delete excess backups 779 | kept-new-versions 20 ; how many of the newest versions to keep 780 | kept-old-versions 5 ; and how many of the old 781 | ) 782 | #+END_SRC 783 | 784 | *** Fuzzy file finder 785 | File finder and associated helpers that uses the minibuffer (the info window at the bottom). 786 | 787 | #+NAME: file-finder 788 | #+BEGIN_SRC emacs-lisp 789 | (use-package ivy 790 | :diminish 791 | :bind (("C-s" . swiper) 792 | :map ivy-minibuffer-map 793 | ("TAB" . ivy-alt-done) 794 | ("C-f" . ivy-alt-done) 795 | ("C-l" . ivy-alt-done) 796 | ("C-j" . ivy-next-line) 797 | ("C-k" . ivy-previous-line) 798 | :map ivy-switch-buffer-map 799 | ("C-k" . ivy-previous-line) 800 | ("C-l" . ivy-done) 801 | ("C-d" . ivy-switch-buffer-kill) 802 | :map ivy-reverse-i-search-map 803 | ("C-k" . ivy-previous-line) 804 | ("C-d" . ivy-reverse-i-search-kill)) 805 | :init 806 | (ivy-mode 1) 807 | :config 808 | (setq ivy-use-virtual-buffers t) 809 | (setq ivy-wrap t) 810 | (setq ivy-count-format "(%d/%d) ") 811 | (setq enable-recursive-minibuffers t)) 812 | 813 | (use-package ivy-rich 814 | :init 815 | (ivy-rich-mode 1)) 816 | 817 | (use-package counsel 818 | :demand t 819 | :bind (("M-x" . counsel-M-x) 820 | ("C-x b" . counsel-ibuffer) 821 | ("C-x C-f" . counsel-find-file) 822 | ("C-M-j" . counsel-switch-buffer) 823 | :map minibuffer-local-map 824 | ("C-r" . 'counsel-minibuffer-history)) 825 | :custom 826 | (counsel-linux-app-format-function #'counsel-linux-app-format-function-name-only) 827 | :config 828 | (setq ivy-initial-inputs-alist nil)) ;; Don't start searches with ^ 829 | #+END_SRC 830 | 831 | ** Writing 832 | *** Spell Check / Flycheck Mode 833 | Everything related to spell and grammar checking. 834 | 835 | #+NAME: spell-check 836 | #+BEGIN_SRC emacs-lisp 837 | 838 | (use-package flycheck-grammarly) 839 | (require 'flycheck-grammarly) 840 | (defun spell() (interactive) (flyspell-mode 1)) 841 | 842 | ;; Add spell check for git commits 843 | (add-hook 'git-commit-mode-hook 'turn-on-flyspell) 844 | 845 | #+END_SRC 846 | 847 | ** Coding 848 | *** Compile Buffers 849 | 850 | Everything related to M-x compile. 851 | 852 | #+NAME: compilation-buffer 853 | #+BEGIN_SRC emacs-lisp 854 | ;; Auto scroll the buffer as we compile 855 | (setq compilation-scroll-output t) 856 | 857 | ;; By default, eshell doesn't support ANSI colors. Enable them for compilation. 858 | (require 'ansi-color) 859 | (defun colorize-compilation-buffer () 860 | (let ((inhibit-read-only t)) 861 | (ansi-color-apply-on-region (point-min) (point-max)))) 862 | (add-hook 'compilation-filter-hook 'colorize-compilation-buffer) 863 | #+END_SRC 864 | 865 | *** Languages 866 | **** HTML 867 | Emmet mode gives autocompletion for HTML tags using short hand notations. 868 | #+NAME: html-auto-completion 869 | #+BEGIN_SRC emacs-lisp 870 | ;; Auto complete HTML and CSS tags 871 | (use-package emmet-mode) 872 | (add-hook 'sgml-mode-hook 'emmet-mode) ;; Auto-start on any markup modes 873 | (add-hook 'css-mode-hook 'emmet-mode) ;; enable Emmet's css abbreviation. 874 | #+END_SRC 875 | 876 | Rainbow mode is an Emacs minor mode to highlight the color shown by a RGB hex triplet (example #FFFFFF). 877 | #+NAME: rainbow-mode 878 | #+BEGIN_SRC emacs-lisp 879 | ;; Minor mode to show HTML hex colors 880 | (use-package rainbow-mode) 881 | #+END_SRC 882 | 883 | **** Javascript 884 | #+NAME: javascript 885 | #+BEGIN_SRC emacs-lisp 886 | (use-package lsp-mode 887 | :commands lsp lsp-deferred 888 | :init 889 | (setq lsp-keymap-prefix "C-c l") 890 | (setq lsp-enable-which-key-integration t)) 891 | 892 | (use-package lsp-ui 893 | :hook (lsp-mode . lsp-ui-mode) 894 | :custom 895 | (lsp-ui-doc-position 'bottom)) 896 | 897 | (use-package company 898 | :after lsp-mode 899 | :hook (lsp-mode . company-mode) 900 | :bind (:map company-active-map 901 | ("" . company-complete-selection)) 902 | (:map lsp-mode-map 903 | ("" . company-indent-or-complete-common)) 904 | :custom 905 | (company-minimum-prefix-length 1) 906 | (company-idle-delay 0.0)) 907 | 908 | (use-package company-box 909 | :hook (company-mode . company-box-mode)) 910 | 911 | (use-package typescript-mode 912 | :mode "\\.ts\\'" 913 | :hook (typescript-mode . lsp-deferred) 914 | :config 915 | (setq typescript-indent-level 2)) 916 | 917 | ;; Fixes flycheck in vue-mode (Vue.js) 918 | ;; https://emacs-lsp.github.io/lsp-mode/page/faq/ 919 | (with-eval-after-load 'lsp-mode 920 | (mapc #'lsp-flycheck-add-mode '(typescript-mode js-mode css-mode vue-html-mode))) 921 | 922 | ;; Using flycheck with Grammarly for now, turning this off 923 | ;;(add-to-list 'lsp-language-id-configuration '(org-mode . "plaintext")) 924 | #+END_SRC 925 | 926 | *** Git 927 | #+NAME: magit-git 928 | #+BEGIN_SRC emacs-lisp 929 | (use-package magit 930 | :commands (magit-status magit-get-current-branch)) 931 | #+END_SRC 932 | 933 | **** File types 934 | ***** Markdown mode 935 | #+NAME: markdown-mode 936 | #+BEGIN_SRC emacs-lisp 937 | ;; This uses Github Flavored Markdown for README files 938 | (use-package markdown-mode 939 | :commands (markdown-mode gfm-mode) 940 | :mode (("README\\.md\\'" . gfm-mode) 941 | ("\\.md\\'" . markdown-mode) 942 | ("\\.markdown\\'" . markdown-mode)) 943 | :init (setq markdown-command "pandoc")) 944 | #+END_SRC 945 | 946 | *** Quality of Life 947 | 948 | Delete trailing whitespace on save. 949 | 950 | #+NAME: trailing-whitespace-on-save 951 | #+BEGIN_SRC emacs-lisp 952 | (add-hook 'before-save-hook 'delete-trailing-whitespace) 953 | #+END_SRC 954 | 955 | ** Writing 956 | 957 | *** Update Table of Contents on Save 958 | 959 | I use =org-make-toc= to automatically update the Table of Contents in any header with a property named =TOC=. 960 | 961 | #+begin_src emacs-lisp 962 | (use-package org-make-toc) 963 | (add-hook 'org-mode-hook #'org-make-toc-mode) 964 | #+end_src 965 | 966 | ** Learning Emacs 967 | These packages may come and go, but ultimately aid in my understanding of emacs and emacs lisp. 968 | 969 | *** Indent org-babel source blocks 970 | #+BEGIN_SRC emacs-lisp 971 | (setq org-src-tab-acts-natively nil) 972 | #+END_SRC 973 | 974 | *** Show real-time key bindings in a separate buffer 975 | #+NAME: command-log 976 | #+BEGIN_SRC emacs-lisp 977 | ;; Gives me a fancy list of commands I run 978 | (use-package command-log-mode) 979 | (setq global-command-log-mode t) 980 | ;; TODO Install package that lets you define help screens for keymaps 981 | #+END_SRC 982 | 983 | *** Panel popup to show key bindings 984 | #+NAME: which-key 985 | #+BEGIN_SRC emacs-lisp 986 | ;; Gives me a fancy list of commands I run 987 | (use-package which-key 988 | :init (which-key-mode) 989 | :diminish which-key-mode 990 | :config 991 | (setq which-key-idle-delay 0.3)) 992 | #+END_SRC 993 | 994 | *** Helpful documentation strings for common functions 995 | #+NAME: ivy-rich 996 | #+BEGIN_SRC emacs-lisp 997 | (use-package ivy-rich 998 | :init 999 | (ivy-rich-mode 1)) 1000 | #+END_SRC 1001 | 1002 | #+NAME: helpful 1003 | #+BEGIN_SRC emacs-lisp 1004 | (use-package helpful 1005 | :custom 1006 | ;; Remap Counsel help functions 1007 | (counsel-describe-function-function #'helpful-callable) 1008 | (counsel-describe-variable-function #'helpful-variable) 1009 | :bind 1010 | ;; Remap default help functions 1011 | ([remap describe-function] . helpful-function) 1012 | ([remap describe-symbol] . helpful-symbol) 1013 | ([remap describe-variable] . helpful-variable) 1014 | ([remap describe-command] . helpful-command) 1015 | ([remap describe-key] . helpful-key)) 1016 | #+END_SRC 1017 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile, tangles all configs and builds a new guix generation 2 | # Dustin Lyons 3 | 4 | SHELL = /bin/sh 5 | CYAN_TERMINAL_OUTPUT = \033[1;36m 6 | GREEN_TERMINAL_OUTPUT = \033[1;32m 7 | RED_TERMINAL_OUTPUT = \033[1;31m 8 | CLEAR = \033[0m 9 | 10 | ## Config Targets - Tangle literate config into real conf and shell files 11 | ## ============================================================================= 12 | .ONESHELL: 13 | --config-felix: --config-desktop 14 | @{ \ 15 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Makefile] Building Felix...${CLEAR}" 16 | emacs --batch --eval "(require 'org)" --eval '(org-babel-tangle-file "Workstation-Desktop-Felix.org")' 17 | } 18 | 19 | .ONESHELL: 20 | --config-desktop: --config-workstation 21 | @{ \ 22 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Makefile] Building Desktop Workstation...${CLEAR}" 23 | emacs --batch --eval "(require 'org)" --eval '(org-babel-tangle-file "Workstation-Desktop.org")' 24 | } 25 | 26 | .ONESHELL: 27 | --config-workstation: --config-emacs 28 | @{ \ 29 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Makefile] Building Base Workstation...${CLEAR}" 30 | emacs --batch --eval "(require 'org)" --eval '(org-babel-tangle-file "Workstation.org")' 31 | } 32 | 33 | .ONESHELL: 34 | --config-emacs: 35 | @{ \ 36 | mkdir -p ./build/emacs 37 | cp Emacs.org ./build/emacs/config.org && \ 38 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Makefile] Copied Emacs.org in preparation for Guix Home daemon...${CLEAR}" 39 | } 40 | 41 | 42 | ## Deployment Targets - runs guix reconfigure to install new OS generation 43 | ## ============================================================================= 44 | .ONESHELL: 45 | --deploy-felix-system: 46 | @{ \ 47 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Makefile] Deploying Guix System...${CLEAR}" 48 | if sudo -E guix system --cores=12 --load-path=./build reconfigure ./build/felix-os.scm; then 49 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Makefile] Finished deploying Guix System.${CLEAR}" 50 | fi 51 | } 52 | 53 | .ONESHELL: 54 | --deploy-felix-home: 55 | @{ \ 56 | echo -e "${GREEN_TERMINAL_OUTPUT}--> Deploying Guix Home...${CLEAR}" 57 | if guix home --load-path=./build reconfigure ./build/felix-home.scm; then 58 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Makefile] Finished deploying Guix Home.${CLEAR}" 59 | fi 60 | } 61 | 62 | ## Activation & Initalize Targets - shell scripts, etc. 63 | ## ============================================================================= 64 | .ONESHELL: 65 | --activate-felix: 66 | @{ \ 67 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Makefile] Activating Guix Home...${CLEAR}" 68 | ./build/scripts/activate-workstation.sh && \ 69 | ./build/scripts/activate-desktop.sh && \ 70 | ./build/scripts/activate-felix.sh && \ 71 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Makefile] Finished activating Guix Home.${CLEAR}" 72 | } 73 | 74 | .ONESHELL: 75 | --initalize-felix: 76 | @{ \ 77 | echo -e "${GREEN_TERMINAL_OUTPUT}--> Initializing Guix System...${CLEAR}" 78 | ./build/scripts/initialize-workstation.sh && \ 79 | ./build/scripts/initialize-desktop.sh && \ 80 | ./build/scripts/initialize-felix.sh && \ 81 | echo -e "${CYAN_TERMINAL_OUTPUT}--> [Makefile] Successfully initialized Guix System. Hooray!${CLEAR}" 82 | } 83 | 84 | ## Install Targets - Dry run targets, or the real deal 85 | ## ============================================================================= 86 | 87 | install: install-system install-home 88 | install-home: --install-felix-home 89 | install-system: --install-felix 90 | 91 | --install-felix: --deploy-felix --activate-felix 92 | 93 | .ONESHELL: 94 | --install-felix-dry-run: 95 | @{ \ 96 | echo -e "${RED_TERMINAL_OUTPUT}[DRY RUN]${CLEAR}${GREEN_TERMINAL_OUTPUT}--> [Makefile] Installing Guix System...${CLEAR}" 97 | if sudo -E guix system --cores=12 --dry-run --load-path=./build reconfigure ./build/felix-os.scm; then 98 | echo -e "${RED_TERMINAL_OUTPUT}[DRY RUN]${CLEAR}${GREEN_TERMINAL_OUTPUT}--> [Makefile] Finished installing Guix System. Hooray!${CLEAR}" 99 | else 100 | echo -e "${RED_TERMINAL_OUTPUT}[DRY RUN]${CLEAR}${GREEN_TERMINAL_OUTPUT} x [Makefile] Failed to install Guix System.${CLEAR}" 101 | fi 102 | } 103 | 104 | .ONESHELL: 105 | --install-felix-home: --deploy-felix-home --activate-felix 106 | @echo -e "${CYAN_TERMINAL_OUTPUT}--> [Makefile] Finished installing Guix Home. Hooray!${CLEAR}" 107 | 108 | .ONESHELL: 109 | --install-felix-home-dry-run: 110 | @{ \ 111 | echo -e "${RED_TERMINAL_OUTPUT}[DRY RUN]${CLEAR}${GREEN_TERMINAL_OUTPUT} Installing Guix System Home...${CLEAR}" 112 | if guix home --dry-run --load-path=./build reconfigure ./build/felix-home.scm; then 113 | echo -e "${RED_TERMINAL_OUTPUT}[DRY RUN]${CLEAR}${GREEN_TERMINAL_OUTPUT}--> [Makefile] Finished installing Guix Home.${CLEAR}" 114 | else 115 | echo -e "${RED_TERMINAL_OUTPUT}[DRY RUN]${CLEAR}${GREEN_TERMINAL_OUTPUT} x [Makefile] Failed to install Guix Home.${CLEAR}" 116 | fi 117 | } 118 | 119 | clean: 120 | @echo "Removing build artifacts..." 121 | @rm -rf build 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # guix-config 2 | ## Screenshot 3 | 4 | ![Desktop in October, 2021](res/Desktop.png) 5 | 6 | ## What is this? 7 | #### _tl;dr The "functional programming" equivalent of operating systems_ 8 | The configuration of my operating system, Guix Linux, and day-to-day software (who are we kidding, emacs) defined in literate configuration style. 9 | 10 | 1. The .org files represent the code itself. 11 | 2. Makefile is used to [tangle](https://orgmode.org/worg/org-contrib/babel/intro.html) the code into seperate files of which are primarily Scheme, ELisp, and shell scripts. 12 | 3. Finally, the Guix daemon interprets these files to generate everything from my desktop and laptop, to servers running in a rack or VMs inside of a hypervisor. _(coming soon)_ 13 | 14 | No more traditional dotfiles. Hello Scheme and literate configuration. 15 | 16 | > [!IMPORTANT] 17 | > I moved to [Nix](https://github.com/dustinlyons/nixos-config) at the end of 2021, so this repository is no longer being maintained. However, I hope it still serves as an example to others exploring literate configuration and Guix. 18 | 19 | ## Why? 20 | With everything defined in this way I can treat my system as one program. It's 100% reproducible, bit by bit. My environments across laptop 21 | and desktop are exactly the same, staying in sync without headache. This is the way. 22 | 23 | Every change to my system is now deployed from the [Guix Store](https://guix.gnu.org/manual/en/html_node/The-Store.html) thanks to [Guix Home](https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html). This means I get rollbacks, transcational upgrades, fine-grained profiles, and other guix goodness with even my dotfiles. 24 | 25 | Other advantages: 26 | - theming now becomes easier. It's all here, I can define one set of colors, fonts, or margins to be used everywhere. Technically possible before but again, don't want to pull my hair out. 27 | - no more "polutting" my system with experiments. I can try different blockchain projects, work with a client that needs .NET, or do anything I want without feeling like I need to clean it up later. 28 | - Scheme is fun to hack on, and I hack on my home-lab for fun 29 | 30 | Learn more about Guix [here](https://guix.gnu.org/). 31 | 32 | ## Installation 33 | This project isn't intended for outside use yet; please just use as an example. I use Makefile to tangle org files into their own configs and then ```guix system reconfigure``` to inject those config files into ```.config```, create symlinks, set environment variables, etc. 34 | 35 | #### Generate a ```build``` directory that contains all guix and dotfile configuration 36 | 37 | ```sh 38 | $ make 39 | ``` 40 | 41 | #### Install new configuration and move system to next generation 42 | ```sh 43 | $ make install 44 | ``` 45 | 46 | ## Files and Organization 47 | I use inheritance to share configuration between my machines where it makes sense. This is subject to change as I make progress, acquire new machines, setup new VMS, etc. 48 | 49 | ### Workstation.org 50 | ###### Base File 51 | Base definition of machines I'll work on day-to-day. Includes core system functions like the kernel, libinput, X Window System, etc. This is to seperate configuration concerns from machines I have running in my home-lab, but keep things shared between my Desktop and Laptop. 52 | 53 | ### Workstation-Desktop.org 54 | ###### Inherits from `Workstation` 55 | Sensible definitions for my Desktop machine that are likely to never change. Includes Openbox configuration, users and filesystems for Desktops, more dotfiles and package configuration. 56 | 57 | ### Workstation-Desktop-Felix.org 58 | ###### Inherits from `Desktop` 59 | Felix is my Desktop computer sitting in my office at home. This file contains a lightweight Operating System definition and an extensive Guix Home definition, as well as some associated dotfiles, initialization scripts, etc. I don't store anything meaningful in my Home directory (it's all kept in /data), so this script manages 100% of my it. 60 | 61 | ### Emacs.org 62 | ###### Editor Configuration 63 | Emacs is my editor and primary interface for using my computer day-to-day. This config is large, also defined in literate style, but does not get built beforehand like the rest of this repo. Changes are still deployed via the Guix Store but it is interpreted as Elisp at runtime. 64 | 65 | ### Get in touch 66 | - Feedback or questions? Find me on [Twitter](https://twitter.com/dustinhlyons). 67 | -------------------------------------------------------------------------------- /Workstation-Desktop-Felix.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Workstation - Desktop - Felix Definition 2 | #+STARTUP: content 3 | #+PROPERTY: header-args :mkdirp yes 4 | #+PROPERTY: header-args:sh :tangle-mode (identity #o555) 5 | #+PROPERTY: header-args:conf :tangle-mode (identity #o555) 6 | 7 | * Table of Contents 8 | :PROPERTIES: 9 | :TOC: :include all :ignore this 10 | :CONTENTS: 11 | - [[#operating-system][Operating System]] 12 | - [[#home-environment][Home Environment]] 13 | - [[#dependencies--setup][Dependencies & Setup]] 14 | - [[#initialize][Initialize]] 15 | - [[#initialize][Initialize]] 16 | - [[#activate][Activate]] 17 | - [[#services][Services]] 18 | - [[#bash][Bash]] 19 | - [[#initialize][Initialize]] 20 | - [[#bash-profile][Bash Profile]] 21 | - [[#keyboard][Keyboard]] 22 | - [[#dotfiles-manifest][Dotfiles Manifest]] 23 | - [[#dotfiles][Dotfiles]] 24 | - [[#xmodmap][.Xmodmap]] 25 | - [[#home-environment][Home Environment]] 26 | - [[#definition][Definition]] 27 | - [[#export][Export]] 28 | :END: 29 | 30 | * Operating System 31 | 32 | This machine sits on my desk at home, so define and name a new Desktop Operating System. 33 | 34 | #+NAME: desktop-operating-system 35 | #+BEGIN_SRC scheme :tangle build/felix-os.scm 36 | (define-module (felix-os) 37 | #:use-module (desktop) 38 | #:use-module (gnu services) 39 | #:use-module (gnu system) 40 | #:use-module (gnu packages)) 41 | 42 | (operating-system 43 | (inherit desktop-operating-system) 44 | (host-name "felix")) 45 | #+END_SRC 46 | 47 | * Home Environment 48 | 49 | Here we load most of the software and it's respective configuration I use day-to-day. The list of packages is compiled from the various 'guix-packages' sections found throughout this file and others. 50 | 51 | Dotfiles (i.e configuration files) are installed by Guix Home. 52 | 53 | Please note: Guix Home defines "services" below, not as Shepherd services, like Guix Linux does, but as plugins to perform a build action on your home environment. Do not get them confused. 54 | 55 | ** Dependencies & Setup 56 | 57 | #+NAME: dependencies 58 | #+BEGIN_SRC scheme :tangle build/felix-home.scm 59 | (define-module (felix-home) 60 | #:use-module (gnu home) 61 | #:use-module (desktop) 62 | #:use-module (dl utils) 63 | #:use-module (gnu home services) 64 | #:use-module (gnu home services shells) 65 | #:use-module (gnu services) 66 | #:use-module (gnu system) 67 | #:use-module (gnu packages) 68 | #:use-module (guix build utils) 69 | #:use-module (gnu packages admin) 70 | #:use-module (guix gexp)) 71 | #+END_SRC 72 | 73 | We setup some scripts to be used throughout this file that are woven together as part of Makefile. 74 | 75 | *** Initialize 76 | **** Initialize 77 | 78 | Initialize our bash script that runs as part of each first install. 79 | 80 | #+BEGIN_SRC sh :noweb-ref initialize-shell-script :noweb-sep "" 81 | # This script created from Workstation-Desktop-Felix.org 82 | GREEN_TERMINAL_OUTPUT='\033[1;32m' 83 | CLEAR='\033[0m' 84 | 85 | #+END_SRC 86 | 87 | **** Activate 88 | 89 | Initialize our bash script that runs as part of each activation. 90 | 91 | #+BEGIN_SRC sh :noweb-ref activate-shell-script :noweb-sep "" 92 | # This script created from Workstation-Desktop-Felix.org 93 | GREEN_TERMINAL_OUTPUT='\033[1;32m' 94 | CLEAR='\033[0m' 95 | 96 | #+END_SRC 97 | 98 | ** Services 99 | 100 | *** Bash 101 | 102 | **** Initialize 103 | 104 | This runs after bash is installed for the first time. I use Oh-My-Bash! for terminal colors, no plugins or other aliases. 105 | 106 | #+BEGIN_SRC sh :noweb-ref initialize-shell-script :noweb-sep "" 107 | # Clone Oh-My-Bash! for the themes 108 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Bash] Downloading oh-my-bash...${CLEAR}" 109 | git clone https://github.com/ohmybash/oh-my-bash.git ~/.config/oh-my-bash && \ 110 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Bash] Download successful.${CLEAR}" 111 | 112 | #+END_SRC 113 | 114 | **** Bash Profile 115 | 116 | #+NAME: home-services-bash 117 | #+BEGIN_SRC sh :tangle build/bash/bashrc.sh 118 | # Export 'SHELL' to child processes. 119 | # Programs such as 'screen' honor it and otherwise use /bin/sh. 120 | export SHELL 121 | export LANG=en_US.UTF-8 122 | export OSH="$HOME/.config/oh-my-bash" 123 | export OSH_THEME="agnoster" 124 | export PATH=$PATH:/home/dustin/bin 125 | export LIBGL_ALWAYS_INDIRECT=1 126 | export GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles 127 | alias ls='ls --color' 128 | alias open='thunar' 129 | 130 | # We are being invoked from a non-interactive shell. If this 131 | # is an SSH session (as in \"ssh host command\"), source 132 | # /etc/profile so we get PATH and other essential variables. 133 | if [[ $- != *i* ]] 134 | then 135 | [[ -n "$SSH_CLIENT" ]] && source "$GUIX_PROFILE/etc/profile" 136 | 137 | # Don't do anything else. 138 | return 139 | fi 140 | 141 | # Load all Guix profiles 142 | for i in $GUIX_EXTRA_PROFILES/*; do 143 | profile=$i/$(basename "$i") 144 | if [ -f "$profile"/etc/profile ]; then 145 | GUIX_PROFILE="$profile" 146 | . "$GUIX_PROFILE"/etc/profile 147 | fi 148 | unset profile 149 | done 150 | 151 | # System wide configuration and oh-my-BASH! 152 | source /etc/bashrc 153 | source $OSH/oh-my-bash.sh 154 | #+END_SRC 155 | 156 | *** Keyboard 157 | 158 | Map CAPS LOCK to Control key. 159 | 160 | ***** Dotfiles Manifest 161 | 162 | #+NAME: keyboard-dotfiles-manifest 163 | #+BEGIN_SRC scheme :noweb-ref dotfiles-manifest :noweb-sep "" 164 | ".Xmodmap" 165 | #+END_SRC 166 | 167 | ***** Dotfiles 168 | ****** .Xmodmap 169 | 170 | #+NAME: home-services-keyboard 171 | #+BEGIN_SRC conf :tangle build/.Xmodmap 172 | clear lock 173 | clear control 174 | keycode 66 = Control_L 175 | add control = Control_L Control_R 176 | #+END_SRC 177 | 178 | ** Home Environment 179 | 180 | The function below takes the various dotfiles manifests I have defined in my literate configuration and maps them to real files managed by guix home. 181 | 182 | *** Definition 183 | 184 | #+NAME: home-environment-definition 185 | #+BEGIN_SRC scheme :tangle build/felix-home.scm :noweb yes 186 | ;; Returns a list of home-file-service structs for each dotfile 187 | (define (generate-dotfiles-services dotfiles) 188 | (if (null? dotfiles) 189 | '() 190 | (let ((config-file (string-append "config/" (car dotfiles))) 191 | (build-file (string-append "build/" (car dotfiles)))) 192 | (cons 193 | (simple-service 'load-build-files 194 | home-files-service-type 195 | (list ;; pair of destination path and source path 196 | `(,config-file 197 | ,(local-file build-file "config")))) 198 | (generate-dotfiles-services (cdr dotfiles)))))) 199 | 200 | (home-environment 201 | (packages (map specification->package+output %dl-packages)) 202 | (services 203 | (append (list 204 | (service home-bash-service-type 205 | (home-bash-configuration 206 | (guix-defaults? #t) 207 | (bashrc (list 208 | (local-file "bash/bashrc.sh")))))) 209 | (generate-dotfiles-services (append '(<>) %dl-dotfiles))))) 210 | #+END_SRC 211 | 212 | *** Export 213 | These are activation and initialization scripts, built from tangled sections in this file. Check out the Makefile to see how they are used. 214 | 215 | #+BEGIN_SRC sh :tangle build/scripts/activate-felix.sh :noweb yes 216 | #!/bin/bash 217 | <> 218 | #+END_SRC 219 | 220 | #+BEGIN_SRC sh :tangle build/scripts/initialize-felix.sh :noweb yes 221 | #!/bin/bash 222 | <> 223 | #+END_SRC 224 | -------------------------------------------------------------------------------- /Workstation-Desktop.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Workstation - Desktop Definition 2 | #+STARTUP: content 3 | #+PROPERTY: header-args :mkdirp yes 4 | #+PROPERTY: header-args:sh :tangle-mode (identity #o555) 5 | #+PROPERTY: header-args:conf :tangle-mode (identity #o555) 6 | 7 | * Table of Contents 8 | :PROPERTIES: 9 | :TOC: :include all :ignore this 10 | :CONTENTS: 11 | - [[#operating-system][Operating System]] 12 | - [[#dependencies][Dependencies]] 13 | - [[#initialize][Initialize]] 14 | - [[#activate][Activate]] 15 | - [[#keyboard-and-mouse][Keyboard and Mouse]] 16 | - [[#libinput][libinput]] 17 | - [[#base-definition][Base Definition]] 18 | - [[#kernel][Kernel]] 19 | - [[#network][Network]] 20 | - [[#file-systems][File Systems]] 21 | - [[#btrfs][btrfs]] 22 | - [[#uefi][UEFI]] 23 | - [[#users][Users]] 24 | - [[#packages][Packages]] 25 | - [[#services][Services]] 26 | - [[#shepherd][Shepherd]] 27 | - [[#x-window-system-components][X Window System Components]] 28 | - [[#window-manager][Window Manager]] 29 | - [[#openbox][Openbox]] 30 | - [[#initialize][Initialize]] 31 | - [[#guix-packages][Guix Packages]] 32 | - [[#dotfiles-manifest][Dotfiles Manifest]] 33 | - [[#dotfiles][Dotfiles]] 34 | - [[#openboxautostart][openbox/autostart]] 35 | - [[#openboxrcxml][openbox/rc.xml]] 36 | - [[#launcher][Launcher]] 37 | - [[#rofi][Rofi]] 38 | - [[#guix-packages][Guix Packages]] 39 | - [[#dotfiles-manifest][Dotfiles Manifest]] 40 | - [[#dotfile][Dotfile]] 41 | - [[#rofilaunchersh][rofi/launcher.sh]] 42 | - [[#rofithemerasi][rofi/theme.rasi]] 43 | - [[#export][Export]] 44 | :END: 45 | 46 | * Operating System 47 | 48 | This base definition outlines reasonable choices for using Linux as a Desktop environment in 2021. This is not likely to change anytime soon; I leave more user specific configuration up to implementations of this. 49 | 50 | Note we inherit this definition from the base [[#System][System]] definition. 51 | 52 | ** Dependencies 53 | Define all dependencies we need to to build the base definition. 54 | #+NAME: base-definition 55 | #+BEGIN_SRC scheme :tangle build/desktop.scm 56 | (define-module (desktop) 57 | #:use-module (workstation) 58 | #:use-module (srfi srfi-1) ;; for the remove function 59 | #:use-module (guix transformations) 60 | #:use-module (guix channels) 61 | #:use-module (gnu packages bash) 62 | #:use-module (gnu packages linux) 63 | #:use-module (gnu services cups) 64 | #:use-module (gnu packages cups) 65 | #:use-module (gnu services xorg) 66 | #:use-module (gnu packages xorg) 67 | #:use-module (gnu services linux) 68 | #:use-module (gnu services desktop) 69 | #:use-module (nongnu packages nvidia) 70 | #:use-module (dl utils) ;; for the dotfiles functions 71 | #:use-module (gnu)) 72 | 73 | (define transform 74 | (options->transformation 75 | '((with-graft . "mesa=nvda")))) 76 | #+END_SRC 77 | 78 | **** Initialize 79 | 80 | Initialize our bash script that runs as part of each first install. 81 | 82 | #+BEGIN_SRC sh :noweb-ref initialize-shell-script :noweb-sep "" 83 | # This script created from Workstation-Desktop.org 84 | GREEN_TERMINAL_OUTPUT='\033[1;32m' 85 | CLEAR='\033[0m' 86 | 87 | #+END_SRC 88 | 89 | **** Activate 90 | 91 | Initialize our bash script that runs as part of each generation activation. 92 | 93 | #+BEGIN_SRC sh :noweb-ref activate-shell-script :noweb-sep "" 94 | # This script created from Workstation-Desktop.org 95 | GREEN_TERMINAL_OUTPUT='\033[1;32m' 96 | CLEAR='\033[0m' 97 | 98 | #+END_SRC 99 | 100 | ** Keyboard and Mouse 101 | 102 | Prepare some rules, config to be used in base operating system definition. This is common across all machines, so I keep this here. All changes get propogated everywhere. 103 | 104 | *** libinput 105 | 106 | Use =libinput= driver for all input devices as it provides more optionality. 107 | 108 | #+NAME: keyboard-mouse-config 109 | #+BEGIN_SRC scheme :tangle build/desktop.scm 110 | ;; @todo: Move this to where it is used in slim-service-type 111 | (define %xorg-libinput-config 112 | "Section \"InputClass\" 113 | Identifier \"Touchpads\" 114 | Driver \"libinput\" 115 | MatchDevicePath \"/dev/input/event*\" 116 | MatchIsTouchpad \"on\" 117 | 118 | Option \"Tapping\" \"on\" 119 | Option \"TappingDrag\" \"on\" 120 | Option \"DisableWhileTyping\" \"on\" 121 | Option \"MiddleEmulation\" \"on\" 122 | Option \"ScrollMethod\" \"twofinger\" 123 | EndSection 124 | 125 | Section \"InputClass\" 126 | Identifier \"Keyboards\" 127 | Driver \"libinput\" 128 | MatchDevicePath \"/dev/input/event*\" 129 | MatchIsKeyboard \"on\" 130 | EndSection") 131 | #+end_src 132 | 133 | ** Base Definition 134 | #+NAME: desktop-operating-system 135 | #+BEGIN_SRC scheme :tangle build/desktop.scm 136 | (define-public desktop-operating-system 137 | (operating-system 138 | (inherit base-operating-system) 139 | (host-name "desktop") 140 | #+END_SRC 141 | 142 | ** Kernel 143 | Kernel modules and associated configuration. We remove the community nvidia-driver (nouveau) and use the offficial (non-free) one instead. 144 | #+NAME: kernel 145 | #+BEGIN_SRC scheme :tangle build/desktop.scm 146 | (kernel-arguments 147 | (append 148 | '("modprobe.blacklist=nouveau") ;; Use nvidia-driver instead 149 | %default-kernel-arguments)) 150 | 151 | (kernel-loadable-modules (list nvidia-driver)) 152 | #+END_SRC 153 | 154 | ** Network 155 | #+NAME: network 156 | #+BEGIN_SRC scheme :tangle build/desktop.scm 157 | ;; Allow resolution of '.local' host names with mDNS 158 | (name-service-switch %mdns-host-lookup-nss) 159 | #+END_SRC 160 | 161 | ** File Systems 162 | 163 | *** btrfs 164 | We use btrfs on all Systems. btrfs is great for the following reasons: 165 | 166 | - Copy on Write: Although each computer has their own Home directory and associated dotfiles, I share my user state across machines. CoW supports shipping data back to my home-lab hypervisor. 167 | 168 | - Snapshots: btrfs' writeable snapshots allow us to rollback state 169 | 170 | #+NAME: file-systems-btrfs 171 | #+BEGIN_SRC scheme :tangle build/desktop.scm 172 | ;; File partitions, filesystems 173 | (file-systems 174 | (cons* (file-system ;; One big fat btrfs partition for our stuff 175 | (mount-point "/") 176 | (device (uuid "3fdd9ded-2779-4401-8b3f-b5a9179a5a6f" 'btrfs)) 177 | (type "btrfs")) 178 | 179 | #+END_SRC 180 | 181 | *** UEFI 182 | Guix needs to reference the filesystem on disk, we use an UUID to identify it. 183 | #+NAME: file-systems-uefi 184 | #+BEGIN_SRC scheme :tangle build/desktop.scm 185 | (file-system ;; UEFI boot partition 186 | (mount-point "/boot/efi") 187 | (device (uuid "1F00-ED40" 'fat32)) 188 | (type "vfat")) 189 | %base-file-systems)) 190 | #+END_SRC 191 | 192 | ** Users 193 | Setup the one user, me, and establish a core set of groups. 194 | #+NAME: users 195 | #+BEGIN_SRC scheme :tangle build/desktop.scm 196 | ;; @todo: Move to guix-home, move packages to profile manifests 197 | ;; Users, home directories, groups, etc. 198 | (users (cons* (user-account 199 | (name "dustin") ;; It me 200 | (comment "Dustin") 201 | (group "users") 202 | (home-directory "/home/dustin") 203 | (supplementary-groups 204 | '("wheel" "netdev" "audio" "video" "lp"))) 205 | %base-user-accounts)) 206 | #+END_SRC 207 | 208 | ** Packages 209 | We save most of the package loading for our independent machine definitions. However, here is a base set of packages for my Desktop that shouldn't change that often. 210 | 211 | #+NAME: packages 212 | #+BEGIN_SRC scheme :tangle build/desktop.scm 213 | ;; Install a base set of Desktop packages 214 | ;; @todo: Decide what to do with these packages 215 | (packages (append (map specification->package 216 | '("openbox" "nss-certs" "xf86-input-libinput")) %base-packages)) 217 | 218 | #+END_SRC 219 | 220 | *** Services 221 | 222 | **** Shepherd 223 | #+NAME: services-shepherd 224 | #+BEGIN_SRC scheme :tangle build/desktop.scm 225 | (services (cons* (service special-files-service-type 226 | `(("/bin/sh" ,(file-append bash "/bin/bash")) 227 | ("/bin/bash" ,(file-append bash "/bin/bash")) 228 | ("/usr/bin/env" ,(file-append coreutils "/bin/env")))) 229 | 230 | (simple-service 'custom-udev-rules udev-service-type 231 | (list nvidia-driver)) 232 | 233 | (service kernel-module-loader-service-type 234 | '("ipmi_devintf" 235 | "nvidia" 236 | "nvidia_modeset" 237 | "nvidia_uvm")) 238 | 239 | (service cups-service-type 240 | (cups-configuration 241 | (web-interface? #t) 242 | (extensions 243 | (list cups-filters brlaser)))) 244 | 245 | (service slim-service-type (slim-configuration 246 | (display ":0") 247 | (vt "vt8") 248 | (xorg-configuration (xorg-configuration 249 | (keyboard-layout (keyboard-layout "us" 250 | #:options '("ctrl:nocaps")) 251 | (extra-config (list %xorg-libinput-config)) 252 | (modules (cons* nvidia-driver %default-xorg-modules)) 253 | (server (transform xorg-server)) 254 | (drivers '("nvidia")))))) 255 | 256 | (remove (lambda (service) 257 | (eq? (service-kind service) gdm-service-type)) 258 | %desktop-services))))) 259 | #+END_SRC 260 | 261 | * X Window System Components 262 | ** Window Manager 263 | 264 | *** Openbox 265 | 266 | I use Openbox primarily on my Desktop, as I find window managers to be too restrictive to free thought. I'm all for winning at vim golf but the mouse does have a place for a little bit of meandering. I meander on my Desktop. 267 | 268 | Openbox is great on a big monitor, so it's primarily used on my Desktop. The dotfiles configure boot scripts and visual styles. 269 | 270 | **** Initialize 271 | 272 | This runs after openbox is installed for the first time. 273 | 274 | #+BEGIN_SRC sh :noweb-ref initialize-shell-script :noweb-sep "" 275 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Openbox] Looking for openbox theme...${CLEAR}" 276 | if [[ -d "$HOME/.themes/Kaunas" ]]; then 277 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Openbox] Found Kaunas.${CLEAR}" 278 | else 279 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Openbox] None found. Cloning Kaunas...${CLEAR}" 280 | git clone git@github.com:Dovias/Kaunas.git ~/.themes/Kaunas && \ 281 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [Openbox] Download successful.${CLEAR}" 282 | fi 283 | 284 | #+END_SRC 285 | 286 | **** Guix Packages 287 | 288 | #+BEGIN_SRC scheme :noweb-ref packages-manifest :noweb-sep "" 289 | "openbox" 290 | #+END_SRC 291 | 292 | **** Dotfiles Manifest 293 | #+BEGIN_SRC scheme :noweb-ref dotfiles-manifest :noweb-sep "" 294 | "openbox/autostart" 295 | "openbox/rc.xml" 296 | #+END_SRC 297 | **** Dotfiles 298 | ****** openbox/autostart 299 | autostart is a simple shell script that runs after Openbox initializes. 300 | #+BEGIN_SRC shell :tangle build/openbox/autostart 301 | # Set wallpaper 302 | # @todo: Fix this dependency, or at the very least activate it 303 | feh --no-fehbg --bg-scale $(shuf -n1 -e "/data/dustin/Resources/Wallpaper/active/*") 304 | 305 | # Launch the bar 306 | polybar -q main -c "$HOME/.config/polybar/config.ini" & 307 | 308 | # Fix tearing issues 309 | nvidia-settings --assign CurrentMetaMode="nvidia-auto-select +0+0 { ForceFullCompositionPipeline = On }" 310 | 311 | # Thunar Daemon 312 | exec thunar --daemon & 313 | 314 | # Notification Daemon 315 | exec dunst & 316 | 317 | # Turn on le screensaver 318 | xscreensaver -no-splash & 319 | 320 | # Start Compositing Manager (i.e thing that draws windows efficently) 321 | picom --xrender-sync-fence --backend xrender --config="$HOME/.config/picom/picom.conf" 322 | #+END_SRC 323 | 324 | ****** openbox/rc.xml 325 | rc.xml holds the desktop menu, keyboard shortucts, workspaces, window placement, and display settings. 326 | 327 | #+BEGIN_SRC xml :visiblity folded :tangle build/openbox/rc.xml 328 | 329 | 330 | 331 | 10 332 | 20 333 | 334 | 335 | yes 336 | no 337 | yes 338 | no 339 | 200 340 | no 341 | 342 | 343 | Smart 344 |
yes
345 | Mouse 346 | Mouse 347 |
348 | 349 | Kaunas 350 | LSC 351 | yes 352 | yes 353 | 354 | Arial Narrow Condensed 355 | 9 356 | Normal 357 | Normal 358 | 359 | 360 | Arial Narrow Condensed 361 | 9 362 | Normal 363 | Normal 364 | 365 | 366 | Arial Narrow Condensed 367 | 9 368 | Normal 369 | Normal 370 | 371 | 372 | Arial Narrow Condensed 373 | 9 374 | Normal 375 | Normal 376 | 377 | 378 | Arial Narrow Condensed 379 | 9 380 | Normal 381 | Normal 382 | 383 | 384 | Arial Narrow Condensed 385 | 9 386 | Normal 387 | Normal 388 | 389 | 390 | 391 | 3 392 | 0 393 | 394 | A 395 | B 396 | C 397 | 398 | 0 399 | 400 | 401 | yes 402 | NonPixel 403 | Center 404 | 405 | 10 406 | 10 407 | 408 | 409 | 410 | 60 411 | 35 412 | 35 413 | 35 414 | 415 | 416 | Bottom 417 | 0 418 | 0 419 | no 420 | Above 421 | Vertical 422 | no 423 | 300 424 | 300 425 | Middle 426 | 427 | 428 | 429 | C-g 430 | 431 | 432 | 1 433 | 434 | 435 | 436 | 437 | 2 438 | 439 | 440 | 441 | 442 | left 443 | no 444 | 445 | 446 | 447 | 448 | right 449 | no 450 | 451 | 452 | 453 | 454 | left 455 | no 456 | 457 | 458 | 459 | 460 | right 461 | no 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | client-menu 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | +395 504 | +90 505 | 45/100 506 | 75/100 507 | 508 | 509 | 510 | 511 | 512 | +70 513 | +45 514 | 90/100 515 | 85/100 516 | 517 | 518 | 519 | 520 | 521 | 75/100 522 | 75/100 523 | 524 | 525 | 526 | 527 | 528 | 529 | 51/100 530 | 50/100 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | true 539 | polybar 540 | 541 | launch-polybar 542 | 543 | 544 | 545 | 546 | xscreensaver-command -activate 547 | 548 | 549 | 550 | 551 | 552 | false 553 | rofi 554 | 555 | rofi -no-lazy-grab -show drun -theme ~/.config/rofi/theme.rasi 556 | 557 | 558 | 559 | 560 | 561 | false 562 | catfish 563 | 564 | catfish 565 | 566 | 567 | 568 | 569 | 570 | false 571 | alacritty 572 | 573 | alacritty --working-directory /data/dustin 574 | 575 | 576 | 577 | 578 | 579 | false 580 | File Manager 581 | 582 | thunar 583 | 584 | 585 | 586 | 587 | 588 | true 589 | Volume 590 | 591 | pavucontrol 592 | 593 | 594 | 595 | 596 | 597 | true 598 | OBconf 599 | 600 | obconf 601 | 602 | 603 | 604 | 605 | scrot -q 100 'Screenshot_%Y-%m-%d-%S_$wx$h.png' -e 'notify-send " Capture Screenshot!  " ; mv $f /data/dustin/Inbox/Screenshots ; feh /data/dustin/Inbox/Screenshots/$f' 606 | 607 | 608 | 609 | 610 | scrot -u -q 100 'Screenshot_%Y-%m-%d-%S_$wx$h.png' -e 'notify-send " Capture Screenshot!  " ; mv $f /home/dustin/Inbox/screenshots ; feh /home/dustin/Inbox/screenshots/$f' 611 | 612 | 613 | 614 | 615 | scrot -se 'xclip -selection clipboard -t image/png -i $f' 616 | 617 | 618 | 619 | 620 | 621 | client-list-combined-menu 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 1 634 | 635 | 500 636 | 637 | 400 638 | 641 | false 642 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | previous 671 | 672 | 673 | 674 | 675 | next 676 | 677 | 678 | 679 | 680 | previous 681 | 682 | 683 | 684 | 685 | next 686 | 687 | 688 | 689 | 690 | previous 691 | 692 | 693 | 694 | 695 | next 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | no 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | yes 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | client-menu 743 | 744 | 745 | 746 | 747 | 748 | 749 | top 750 | 751 | 752 | 753 | 754 | 755 | 756 | left 757 | 758 | 759 | 760 | 761 | 762 | 763 | right 764 | 765 | 766 | 767 | 768 | 769 | 770 | bottom 771 | 772 | 773 | 774 | 775 | 776 | 777 | client-menu 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | client-menu 812 | 813 | 814 | 815 | 816 | 817 | 818 | client-menu 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | vertical 872 | 873 | 874 | 875 | 876 | horizontal 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | previous 894 | 895 | 896 | 897 | 898 | next 899 | 900 | 901 | 902 | 903 | previous 904 | 905 | 906 | 907 | 908 | next 909 | 910 | 911 | 912 | 913 | previous 914 | 915 | 916 | 917 | 918 | next 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | client-list-combined-menu 935 | 936 | 937 | 938 | 939 | root-menu 940 | 941 | 942 | 943 | 944 | 945 | 946 | previous 947 | 948 | 949 | 950 | 951 | next 952 | 953 | 954 | 955 | 956 | previous 957 | 958 | 959 | 960 | 961 | next 962 | 963 | 964 | 965 | 966 | 967 | menu.xml 968 | 400 969 | no 970 | 100 971 | 200 972 | yes 973 | yes 974 | yes 975 | 976 | 977 | 978 | 979 | 1 980 | 981 | yes 982 | 983 | 984 | 985 | 0% 986 | 0% 987 | 1 988 | 989 | 990 | 50% 991 | 50% 992 | 993 | 994 | 995 | yes 996 | 997 | 998 |
999 | 1000 | #+END_SRC 1001 | 1002 | ** Launcher 1003 | 1004 | *** Rofi 1005 | 1006 | Rofi is a quick launcher and how I primarily interface with applications in Openbox. 1007 | 1008 | **** Guix Packages 1009 | 1010 | #+BEGIN_SRC scheme :noweb-ref packages-manifest :noweb-sep "" 1011 | "rofi" 1012 | #+END_SRC 1013 | 1014 | **** Dotfiles Manifest 1015 | #+BEGIN_SRC scheme :noweb-ref dotfiles-manifest :noweb-sep "" 1016 | "rofi/launcher.sh" 1017 | "rofi/theme.rasi" 1018 | #+END_SRC 1019 | **** Dotfile 1020 | ****** rofi/launcher.sh 1021 | 1022 | Launches the display defined in theme.rasi. 1023 | 1024 | #+BEGIN_SRC shell :tangle build/rofi/launcher.sh 1025 | #!/usr/bin/env bash 1026 | rofi -no-lazy-grab -show drun -theme theme.rasi 1027 | 1028 | #+END_SRC 1029 | 1030 | ****** rofi/theme.rasi 1031 | #+BEGIN_SRC conf :tangle build/rofi/theme.rasi 1032 | configuration { 1033 | drun-display-format: "{icon} {name}"; 1034 | display-drun: "run"; 1035 | show-icons: true; 1036 | icon-theme: "Moka"; 1037 | location: 0; 1038 | yoffset: 0; 1039 | xoffset: 0; 1040 | columns: 1; 1041 | fake-transparency: false; 1042 | hide-scrollbar: true; 1043 | bw: 0; 1044 | fullscreen: false; 1045 | show-icons: true; 1046 | terminal: "alacritty"; 1047 | sidebar-mode: false; 1048 | } 1049 | 1050 | ,* { 1051 | background: #1f2528; 1052 | background-alt: #414c51ff; 1053 | foreground: #A2A4A6cc; 1054 | border: #394F55ff; 1055 | border-alt: #88c0d0ff; 1056 | selected: #394F55; 1057 | urgent: #b48eadFF; 1058 | } 1059 | 1060 | ,* { 1061 | text-font: "Arial"; 1062 | 1063 | inputbar-margin: 3px 3px; 1064 | prompt-padding: 5px 5px; 1065 | entry-padding: 10px 0px 10px 0px; 1066 | list-element-padding: 5px; 1067 | list-element-margin: @inputbar-margin; 1068 | list-element-border: 0px 0px 0px 4px; 1069 | 1070 | apps-textbox-prompt-colon-padding: 10px -5px 0px 0px; 1071 | } 1072 | 1073 | ,* { 1074 | background-color: #1F2528; 1075 | border-color: #2e343f; 1076 | text-color: #C0C5CE; 1077 | spacing: 0; 1078 | width: 512px; 1079 | } 1080 | 1081 | inputbar { 1082 | border: 0 0 1px 0; 1083 | children: [prompt,entry]; 1084 | } 1085 | 1086 | prompt { 1087 | padding: 16px; 1088 | border: 0 1px 0 0; 1089 | } 1090 | 1091 | textbox { 1092 | background-color: #2e343f; 1093 | border: 0 0 1px 0; 1094 | border-color: #282C33; 1095 | padding: 8px 16px; 1096 | } 1097 | 1098 | entry { 1099 | padding: 12px; 1100 | } 1101 | 1102 | listview { 1103 | cycle: false; 1104 | margin: 0 0 -1px 0; 1105 | scrollbar: false; 1106 | } 1107 | 1108 | element { 1109 | border: 0 0 1px 0; 1110 | padding: 12px; 1111 | } 1112 | 1113 | element selected { 1114 | border: 1px 1px 1px 1px; 1115 | border-color: #FAC863; 1116 | } 1117 | #+END_SRC 1118 | 1119 | * Export 1120 | 1121 | We export the various dotfiles and package definitions described throughout this file. They are later appended to the global list and interpreted by the Guix Daemon. 1122 | 1123 | #+begin_src scheme :tangle build/dl/desktop.scm :noweb yes 1124 | (define-module (dl desktop) 1125 | #:export (%dl-packages-desktop) 1126 | #:export (%dl-dotfiles-desktop)) 1127 | 1128 | (define %dl-packages-desktop 1129 | (list 1130 | <> 1131 | )) 1132 | 1133 | (define %dl-dotfiles-desktop 1134 | (list 1135 | <> 1136 | )) 1137 | #+end_src 1138 | 1139 | #+begin_src scheme :tangle build/dl/utils.scm :noweb yes 1140 | (define-module (dl utils) 1141 | #:export (%dl-packages) 1142 | #:export (%dl-dotfiles)) 1143 | 1144 | (use-modules (dl workstation) 1145 | (dl desktop)) 1146 | 1147 | (define %dl-packages 1148 | (append %dl-packages-workstation %dl-packages-desktop)) 1149 | 1150 | (define %dl-dotfiles 1151 | (append %dl-dotfiles-workstation %dl-dotfiles-desktop)) 1152 | 1153 | #+end_src 1154 | 1155 | Activation and Initialization scripts. Check out the Makefile for more info on how they are used. 1156 | 1157 | #+BEGIN_SRC sh :tangle build/scripts/activate-desktop.sh :noweb yes 1158 | #!/bin/bash 1159 | <> 1160 | #+END_SRC 1161 | 1162 | #+BEGIN_SRC sh :tangle build/scripts/initialize-desktop.sh :noweb yes 1163 | #!/bin/bash 1164 | <> 1165 | #+END_SRC 1166 | -------------------------------------------------------------------------------- /Workstation.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Workstation Definition 2 | #+STARTUP: content 3 | #+PROPERTY: header-args :mkdirp yes 4 | #+PROPERTY: header-args:sh :tangle-mode (identity #o555) 5 | #+PROPERTY: header-args:conf :tangle-mode (identity #o555) 6 | 7 | * Table of Contents 8 | :PROPERTIES: 9 | :TOC: :include all :ignore this :depth 5 10 | :CONTENTS: 11 | - [[#channels][Channels]] 12 | - [[#operating-system][Operating System]] 13 | - [[#dependencies][Dependencies]] 14 | - [[#initialize][Initialize]] 15 | - [[#activate][Activate]] 16 | - [[#helpers][Helpers]] 17 | - [[#scripts][Scripts]] 18 | - [[#activate-profiles][activate-profiles]] 19 | - [[#update-profiles][update-profiles]] 20 | - [[#operating-system-definition][Operating System Definition]] 21 | - [[#kernel][Kernel]] 22 | - [[#file-systems][File Systems]] 23 | - [[#boot-loader][Boot Loader]] 24 | - [[#empty-stub][Empty Stub]] 25 | - [[#x-window-systems][X Window Systems]] 26 | - [[#compositor---picom][Compositor - Picom]] 27 | - [[#guix-packages][Guix Packages]] 28 | - [[#manifest][Manifest]] 29 | - [[#files][Files]] 30 | - [[#picompicomconf][picom/picom.conf]] 31 | - [[#color-theme-and-fonts][Color Theme and Fonts]] 32 | - [[#activate][Activate]] 33 | - [[#guix-packages][Guix Packages]] 34 | - [[#dotfiles-manifest][Dotfiles Manifest]] 35 | - [[#dotfiles][Dotfiles]] 36 | - [[#xresources][.Xresources]] 37 | - [[#status-bar---polybar][Status Bar - Polybar]] 38 | - [[#guix-packages][Guix Packages]] 39 | - [[#dotfiles-manifest][Dotfiles Manifest]] 40 | - [[#dotfiles][Dotfiles]] 41 | - [[#polybarcolorsini][polybar/colors.ini]] 42 | - [[#polybarbarsini][polybar/bars.ini]] 43 | - [[#polybarmodulesini][polybar/modules.ini]] 44 | - [[#polybarconfigini][polybar/config.ini]] 45 | - [[#file-manager---thunar][File Manager - Thunar]] 46 | - [[#guix-packages][Guix Packages]] 47 | - [[#dotfiles-manifest][Dotfiles Manifest]] 48 | - [[#dotfiles][Dotfiles]] 49 | - [[#thunarucaxml][Thunar/uca.xml]] 50 | - [[#notifications---dunst][Notifications - Dunst]] 51 | - [[#guix-packages][Guix Packages]] 52 | - [[#dotfiles-manifest][Dotfiles Manifest]] 53 | - [[#dotfiles][Dotfiles]] 54 | - [[#dunstdunstrc][dunst/dunstrc]] 55 | - [[#printers][Printers]] 56 | - [[#brother-dl-2170w][Brother DL-2170W]] 57 | - [[#initialize][Initialize]] 58 | - [[#guix-packages][Guix Packages]] 59 | - [[#dotfiles-manifest][Dotfiles Manifest]] 60 | - [[#dotfiles][Dotfiles]] 61 | - [[#printersconf][printers.conf]] 62 | - [[#terminal][Terminal]] 63 | - [[#alacritty][Alacritty]] 64 | - [[#guix-packages][Guix Packages]] 65 | - [[#dotfiles-manifest][Dotfiles Manifest]] 66 | - [[#dotfiles][Dotfiles]] 67 | - [[#alacrittyyml][alacritty.yml]] 68 | - [[#git][Git]] 69 | - [[#config][Config]] 70 | - [[#initialize][Initialize]] 71 | - [[#guix-packages][Guix Packages]] 72 | - [[#dotfiles-manifest][Dotfiles Manifest]] 73 | - [[#dotfiles][Dotfiles]] 74 | - [[#gitconfig][.gitconfig]] 75 | - [[#editors][Editors]] 76 | - [[#vim][Vim]] 77 | - [[#initialize][Initialize]] 78 | - [[#activate][Activate]] 79 | - [[#guix-packages][Guix Packages]] 80 | - [[#dotfiles-manifest][Dotfiles Manifest]] 81 | - [[#dotfiles][Dotfiles]] 82 | - [[#colorsthemevim][colors/theme.vim]] 83 | - [[#vimrc][.vimrc]] 84 | - [[#emacs][Emacs]] 85 | - [[#activate][Activate]] 86 | - [[#guix-packages][Guix Packages]] 87 | - [[#dotfiles-manifest][Dotfiles Manifest]] 88 | - [[#dotfiles][Dotfiles]] 89 | - [[#emacsconfigorg][emacs/config.org]] 90 | - [[#emacszeroed-themeel][emacs/zeroed-theme.el]] 91 | - [[#export][Export]] 92 | :END: 93 | 94 | * Channels 95 | 96 | Guix manages package definitions through [[https://guix.gnu.org/manual/en/html_node/Channels.html#Channels][channels]]. As Guix strongly respects the [[https://www.gnu.org/distros/free-system-distribution-guidelines.html][freedom of computer users]], to download non-free software one must include non-free channels. I include one of these below (~nongnu)~, in addition to the default Guix channel definition. 97 | 98 | #+NAME: channels 99 | #+BEGIN_SRC scheme :tangle build/channels.scm 100 | (list (channel 101 | (name 'guix) 102 | (url "https://git.savannah.gnu.org/git/guix.git") 103 | (introduction 104 | (make-channel-introduction 105 | "9edb3f66fd807b096b48283debdcddccfea34bad" 106 | (openpgp-fingerprint 107 | "BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA")))) 108 | (channel 109 | (name 'nonguix) 110 | (url "https://gitlab.com/nonguix/nonguix") 111 | (introduction 112 | (make-channel-introduction 113 | "897c1a470da759236cc11798f4e0a5f7d4d59fbc" 114 | (openpgp-fingerprint 115 | "2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5"))))) 116 | #+END_SRC 117 | 118 | * Operating System 119 | 120 | I build up my system configurations using [[https://orgmode.org/manual/Extracting-Source-Code.html][noweb]] style syntax. This enables us to write a base operating system available to be inherited by concrete system definitions (laptops, desktops, servers). 121 | 122 | ** Dependencies 123 | 124 | Define all dependencies we need to build the base definition. 125 | 126 | #+NAME: base-definition 127 | #+BEGIN_SRC scheme :tangle build/workstation.scm 128 | (define-module (workstation) 129 | #:use-module (gnu) 130 | #:use-module (guix) 131 | #:use-module (gnu packages) 132 | #:use-module (gnu system) 133 | #:use-module (gnu system nss) 134 | #:use-module (nongnu system linux-initrd) 135 | #:use-module (nongnu packages linux) 136 | #:use-module (guix transformations) 137 | #:use-module (gnu packages base) 138 | #:use-module (gnu packages xorg) 139 | #:use-module (gnu services xorg) 140 | #:use-module (gnu packages file-systems) 141 | #:use-module (gnu packages shells) 142 | #:use-module (gnu packages certs) 143 | #:use-module (gnu services networking) 144 | #:use-module (gnu services desktop) 145 | #:use-module (gnu services ssh)) 146 | #+END_SRC 147 | 148 | **** Initialize 149 | 150 | Initialize our bash script that runs as part of each first install. 151 | 152 | #+BEGIN_SRC sh :noweb-ref initialize-shell-script :noweb-sep "" 153 | # This script created from Workstation.org 154 | WORKING_DIR=$(dirname $(readlink -f $0)) 155 | GREEN_TERMINAL_OUTPUT='\033[1;32m' 156 | CLEAR='\033[0m' 157 | 158 | #+END_SRC 159 | 160 | **** Activate 161 | 162 | Initialize our bash script that runs as part of each generation activation. 163 | 164 | #+BEGIN_SRC sh :noweb-ref activate-shell-script :noweb-sep "" 165 | GREEN_TERMINAL_OUTPUT='\033[1;32m' 166 | CLEAR='\033[0m' 167 | 168 | #+END_SRC 169 | 170 | ** Helpers 171 | 172 | I define small groups of packages in manifest files that enable me to build up to a larger package list of software to install. These helper scripts turn on and or update individual manifests (profiles) without forcing me to update everything. Thanks to David Wilson for these. 173 | 174 | #+BEGIN_SRC sh :noweb-ref initialize-shell-script :noweb-sep "" 175 | # Create bin if it doesn't already exist 176 | mkdir -p ~/bin 177 | 178 | # activate-profiles and update-profiles, scripts for Guix profiles 179 | mv $WORKING_DIR/activate-profiles ~/bin/activate-profiles 180 | mv $WORKING_DIR/update-profiles ~/bin/update-profiles 181 | chmod +x ~/bin/activate-profiles 182 | chmod +x ~/bin/update-profiles 183 | 184 | #+END_SRC 185 | 186 | **** Scripts 187 | ***** activate-profiles 188 | 189 | #+NAME: activate-profiles-script 190 | #+BEGIN_SRC sh :tangle build/scripts/activate-profiles 191 | #!/bin/sh 192 | 193 | GREEN='\033[1;32m' 194 | RED='\033[1;30m' 195 | NC='\033[0m' 196 | GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles 197 | 198 | profiles=$* 199 | if [[ $# -eq 0 ]]; then 200 | profiles="$HOME/.config/guix/manifests/*.scm"; 201 | fi 202 | 203 | for profile in $profiles; do 204 | 205 | # Remove the path and file extension, if any 206 | profileName=$(basename $profile) 207 | profileName="${profileName%.*}" 208 | profilePath="$GUIX_EXTRA_PROFILES/$profileName" 209 | manifestPath=$HOME/.config/guix/manifests/$profileName.scm 210 | 211 | if [ -f $manifestPath ]; then 212 | echo -e "${GREEN}Activating profile:" $manifestPath "${NC}" 213 | echo 214 | 215 | mkdir -p $profilePath 216 | guix package --manifest=$manifestPath --profile="$profilePath/$profileName" 217 | 218 | # Source the new profile 219 | GUIX_PROFILE="$profilePath/$profileName" 220 | if [ -f $GUIX_PROFILE/etc/profile ]; then 221 | . "$GUIX_PROFILE"/etc/profile 222 | else 223 | echo -e "${RED}Couldn't find profile:" $GUIX_PROFILE/etc/profile "${NC}" 224 | fi 225 | else 226 | echo "No profile found at path" $profilePath 227 | fi 228 | done 229 | #+END_SRC 230 | 231 | ***** update-profiles 232 | 233 | #+NAME: update-profiles-script 234 | #+BEGIN_SRC sh :tangle build/scripts/update-profiles 235 | #!/bin/sh 236 | 237 | GREEN='\033[1;32m' 238 | NC='\033[0m' 239 | GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles 240 | 241 | profiles=$* 242 | if [[ $# -eq 0 ]]; then 243 | profiles="$GUIX_EXTRA_PROFILES/*"; 244 | fi 245 | 246 | for profile in $profiles; do 247 | profileName=$(basename $profile) 248 | profilePath=$GUIX_EXTRA_PROFILES/$profileName 249 | 250 | echo -e "${GREEN}Updating profile:" $profilePath "${NC}" 251 | echo 252 | 253 | guix package --profile="$profilePath/$profileName" --manifest="$HOME/.config/guix/manifests/$profileName.scm" 254 | done 255 | #+END_SRC 256 | 257 | ** Operating System Definition 258 | 259 | Now that we've prepped module definitions and labeled values to be used in our base operating system, let's define it. All systems inherit from this defintion, both servers and computers. 260 | 261 | #+NAME: base-definition 262 | #+BEGIN_SRC scheme :tangle build/workstation.scm 263 | ;; Base Operating System 264 | (define-public base-operating-system 265 | (operating-system 266 | (host-name "workstation") 267 | (hosts-file 268 | (plain-file "hosts" 269 | (string-append (local-host-aliases host-name) 270 | (string-append 271 | "---------- This file is generated by guix-config (Workstation.org) ----------\n" 272 | "192.168.0.67 BRN008077D92A06.local")))) ;; Add office printer 273 | (locale "en_US.utf8") 274 | (timezone "America/Kentucky/Louisville") 275 | (keyboard-layout (keyboard-layout "us")) 276 | 277 | #+END_SRC 278 | 279 | *** Kernel 280 | 281 | Linux-lts kernel is chosen as the nvidia-driver in the nonfree channel was compiled against it. In the future I'd like to move away from lts to get more frequent patches. 282 | 283 | #+NAME: kernel 284 | #+BEGIN_SRC scheme :tangle build/workstation.scm 285 | (kernel linux-lts) 286 | (firmware (list linux-firmware)) 287 | 288 | #+END_SRC 289 | 290 | *** File Systems 291 | **** Boot Loader 292 | 293 | Define GRUB as the bootloader for all machines and insert an empty filesystem to be overridden by derivative machines. 294 | 295 | #+NAME: file-systems-boot-loader 296 | #+BEGIN_SRC scheme :tangle build/workstation.scm 297 | ;; Boot settings (UEFI) 298 | (bootloader 299 | (bootloader-configuration 300 | (bootloader grub-efi-bootloader) 301 | (targets (list "/boot/efi")) 302 | (keyboard-layout keyboard-layout))) 303 | 304 | #+END_SRC 305 | 306 | **** Empty Stub 307 | 308 | Stub out an empty filesystem to be overriden later. Guix complains otherwise. 309 | 310 | #+NAME: file-systems-stub 311 | #+BEGIN_SRC scheme :tangle build/workstation.scm 312 | (file-systems (cons* 313 | (file-system 314 | (mount-point "/tmp") 315 | (device "none") 316 | (type "tmpfs") 317 | (check? #f)) 318 | %base-file-systems)))) 319 | #+END_SRC 320 | 321 | ** X Window Systems 322 | 323 | These components and their respective dotfiles are shared across all computers. 324 | 325 | *** Compositor - Picom 326 | 327 | Compositing is the process of combining visual elements from separate sources into single images, i.e building the window image. Also provides shaders for drop shadows and other effects. 328 | 329 | **** Guix Packages 330 | 331 | #+BEGIN_SRC scheme :noweb-ref packages-manifest :noweb-sep "" 332 | "picom" 333 | #+END_SRC 334 | 335 | **** Manifest 336 | 337 | #+BEGIN_SRC scheme :noweb-ref dotfiles-manifest :noweb-sep "" 338 | "picom/picom.conf" 339 | #+END_SRC 340 | 341 | **** Files 342 | ***** picom/picom.conf 343 | #+NAME: home-services-xresources 344 | #+BEGIN_SRC conf :visiblity :tangle build/picom/picom.conf 345 | ################################# 346 | # Shadows 347 | ################################# 348 | shadow = true; 349 | shadow-radius = 15; 350 | shadow-offset-x = -15; 351 | shadow-offset-y = -15; 352 | shadow-opacity = 0.6; 353 | shadow-ignore-shaped = false; 354 | shadow-exclude = [ 355 | "class_g = 'firefox' && window_type = 'utility'", 356 | "_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'", 357 | "_GTK_FRAME_EXTENTS@:c" 358 | ]; 359 | 360 | ################################# 361 | # Opacity 362 | ################################# 363 | inactive-opacity = 1; 364 | active-opacity = 1; 365 | frame-opacity = 0.9; 366 | inactive-opacity-override = false; 367 | blur-background = true; 368 | blur-background-frame = true; 369 | blur-background-fixed = true; 370 | blur-background-exclude = [ 371 | "window_type = 'dock'", 372 | "window_type = 'desktop'" 373 | ]; 374 | 375 | ################################# 376 | # Fading 377 | ################################# 378 | fading = true; 379 | fade-delta = 10; # 30; 380 | fade-in-step = 0.1; 381 | fade-out-step = 0.1; 382 | fade-exclude = [ ]; 383 | 384 | wintypes: 385 | { 386 | dock = { shadow = false; } 387 | dnd = { shadow = false; } 388 | popup_menu = { opacity = 1.0; } 389 | dropdown_menu = { opacity = 1.0; } 390 | } 391 | 392 | ################################# 393 | # Rendering 394 | ################################# 395 | vsync = false; 396 | unredir-if-possible = false; 397 | #+END_SRC 398 | 399 | *** Color Theme and Fonts 400 | 401 | I use my own theme throughout my terminal, emacs, and status bars. 402 | 403 | **** Activate 404 | 405 | Link the .Xresources file defined below. 406 | 407 | #+BEGIN_SRC sh :noweb-ref activate-shell-script :noweb-sep "" 408 | # Link configuration and theme from Guix Store to final location 409 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [X11] Linking Xresources...${CLEAR}" 410 | mv ~/.config/.Xresources ~/.Xresources && \ 411 | echo -e "${GREEN_TERMINAL_OUTPUT}--> [X11] Linked.${CLEAR}" 412 | 413 | #+END_SRC 414 | 415 | **** Guix Packages 416 | 417 | #+BEGIN_SRC scheme :noweb-ref packages-manifest :noweb-sep "" 418 | "font-hack" 419 | "font-awesome" 420 | "font-google-roboto" 421 | "font-google-material-design-icons" 422 | #+END_SRC 423 | 424 | **** Dotfiles Manifest 425 | 426 | #+BEGIN_SRC scheme :noweb-ref dotfiles-manifest :noweb-sep "" 427 | ".Xresources" 428 | #+END_SRC 429 | 430 | **** Dotfiles 431 | ****** .Xresources 432 | #+NAME: home-services-xresources 433 | #+BEGIN_SRC conf :visiblity :tangle build/.Xresources 434 | ! Color palette 435 | #define RED #EC5F67 436 | #define GREEN #99C794 437 | #define YELLOW #FAC863 438 | #define BLUE #6699CC 439 | #define PURPLE #C594C5 440 | #define TEAL #5FB3B3 441 | #define BLACK #1F2528 442 | #define LIGHT_GREY #C0C5CE 443 | #define DARK_GREY #65737E 444 | 445 | ! Colors 0-15. 446 | *.color0: BLACK 447 | *color0: BLACK 448 | *.color1: RED 449 | *color1: RED 450 | *.color2: GREEN 451 | *color2: GREEN 452 | *.color3: YELLOW 453 | *color3: YELLOW 454 | *.color4: BLUE 455 | *color4: BLUE 456 | *.color5: PURPLE 457 | *color5: PURPLE 458 | *.color6: TEAL 459 | *color6: TEAL 460 | *.color7: LIGHT_GREY 461 | *color7: LIGHT_GREY 462 | *.color8: DARK_GREY 463 | *color8: DARK_GREY 464 | *.color9: RED 465 | *color9: RED 466 | *.color10: GREEN 467 | *color10: GREEN 468 | *.color11: YELLOW 469 | *color11: YELLOW 470 | *.color12: BLUE 471 | *color12: BLUE 472 | *.color13: PURPLE 473 | *color13: PURPLE 474 | *.color14: TEAL 475 | *color14: TEAL 476 | *.color15: LIGHT_GREY 477 | *color15: LIGHT_GREY 478 | 479 | ! Black color that will not be affected by bold highlighting. 480 | *.color66: BLACK 481 | *color66: BLACK 482 | 483 | ! Xclock colors. 484 | XClock*foreground: LIGHT_GREY 485 | XClock*background: BLACK 486 | XClock*majorColor: rgba:d8/de/e9/ff 487 | XClock*minorColor: rgba:d8/de/e9/ff 488 | XClock*hourColor: rgba:d8/de/e9/ff 489 | XClock*minuteColor: rgba:d8/de/e9/ff 490 | XClock*secondColor: rgba:d8/de/e9/ff 491 | 492 | Xft.dpi: 96 493 | Xft.antialias: true 494 | Xft.hinting: true 495 | Xft.rgba: rgb 496 | Xft.autohint: false 497 | Xft.hintstyle: hintslight 498 | Xft.lcdfilter: lcddefault 499 | #+END_SRC 500 | 501 | *** Status Bar - Polybar 502 | 503 | I use polybar to provide a minimal amount of data in a status bar. Date, time, and a watch over CPU, RAM, and Network. 504 | 505 | **** Guix Packages 506 | 507 | #+BEGIN_SRC scheme :noweb-ref packages-manifest :noweb-sep "" 508 | "polybar" 509 | #+END_SRC 510 | 511 | **** Dotfiles Manifest 512 | 513 | #+BEGIN_SRC scheme :noweb-ref dotfiles-manifest :noweb-sep "" 514 | 515 | "polybar/colors.ini" 516 | "polybar/bars.ini" 517 | "polybar/modules.ini" 518 | "polybar/config.ini" 519 | 520 | #+END_SRC 521 | 522 | **** Dotfiles 523 | ****** polybar/colors.ini 524 | 525 | Color definitions for various modules. @todo: pull this from my global color definition. 526 | #+NAME: polybar-colors 527 | #+BEGIN_SRC conf :visiblity folded :tangle build/polybar/colors.ini 528 | ;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ 529 | [color] 530 | background = #1F2528 531 | background-alt = #000000 532 | foreground = #FFFFFF 533 | foreground-alt = #FDF6E3 534 | primary = #FAC863 535 | white = #FFFFFF 536 | black = #000000 537 | red = #EC5F67 538 | purple = #C594C5 539 | blue = #6699CC 540 | cyan = #5FB3B3 541 | teal = #5FB3B3 542 | green = #99C794 543 | yellow = #FAC863 544 | pink = #EC6798 545 | lime = #B9C244 546 | amber = #EDB83F 547 | orange = #E57C46 548 | brown = #AC8476 549 | gray = #1F2528 550 | indigo = #6C77BB 551 | blue-gray = #5FB3B3 552 | ;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ 553 | 554 | #+END_SRC 555 | 556 | ****** polybar/bars.ini 557 | Define bars and visual elements. 558 | #+NAME: polybar-bars 559 | #+BEGIN_SRC conf :visiblity folded :tangle build/polybar/bars.ini 560 | ;; Bar settings 561 | 562 | [bar] 563 | fill = ⏽ 564 | empty = ⏽ 565 | indicator = ⏽ 566 | 567 | ;; Module settings 568 | 569 | [module/volume] 570 | type = internal/alsa 571 | 572 | ; Soundcard to be used 573 | ; Usually in the format hw:# where # is the card number 574 | ; You can find the different card numbers in `/proc/asound/cards` 575 | master-soundcard = default 576 | speaker-soundcard = default 577 | headphone-soundcard = default 578 | 579 | ; Name of the master, speaker and headphone mixers 580 | ; Use the following command to list available mixer controls: 581 | ; $ amixer scontrols | sed -nr "s/.*'([[:alnum:]]+)'.*/\1/p" 582 | ; If master, speaker or headphone-soundcard isn't the default, 583 | ; use `amixer -c # scontrols` instead where # is the number 584 | ; of the master, speaker or headphone soundcard respectively 585 | ; 586 | ; Default: Master 587 | master-mixer = Master 588 | 589 | ; Optionally define speaker and headphone mixers 590 | ; Default: none 591 | ;;speaker-mixer = Speaker 592 | ; Default: none 593 | ;;headphone-mixer = Headphone 594 | 595 | ; NOTE: This is required if headphone_mixer is defined 596 | ; Default: none 597 | ;;headphone-id = 9 598 | 599 | ; Use volume mapping (similar to amixer -M and alsamixer), where the increase in volume is linear to the ear 600 | ; Default: false 601 | ;;mapped = true 602 | 603 | ; Interval for volume increase/decrease (in percent points) 604 | interval = 5 605 | format-volume = 606 | format-volume-prefix =  607 | format-volume-prefix-padding = 1 608 | format-volume-prefix-background = ${color.blue} 609 | format-volume-prefix-foreground = ${color.foreground} 610 | format-volume-background = ${color.background-alt} 611 | format-volume-foreground = ${color.foreground} 612 | format-volume-overline = ${color.background} 613 | format-volume-underline = ${color.background} 614 | format-muted = 615 | format-muted-prefix =  616 | format-muted-prefix-padding = 1 617 | format-muted-prefix-background = ${color.red} 618 | format-muted-overline = ${color.background} 619 | format-muted-underline = ${color.background} 620 | label-volume = %percentage%% 621 | label-volume-background = ${color.background-alt} 622 | label-volume-padding = 1 623 | label-muted = "Off" 624 | label-muted-foreground = ${color.foreground} 625 | label-muted-background = ${color.background-alt} 626 | label-muted-padding = 1 627 | 628 | ; Only applies if is used 629 | bar-volume-format = " %fill%%indicator%%empty% " 630 | bar-volume-width = 10 631 | bar-volume-gradient = false 632 | bar-volume-indicator = ${bar.indicator} 633 | bar-volume-indicator-foreground = ${color.foreground} 634 | bar-volume-fill = ${bar.fill} 635 | bar-volume-foreground-0 = ${color.foreground} 636 | bar-volume-foreground-1 = ${color.foreground} 637 | bar-volume-foreground-2 = ${color.foreground} 638 | bar-volume-empty = ${bar.empty} 639 | bar-volume-empty-foreground = ${color.gray} 640 | ;; _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ 641 | 642 | [module/cpu_bar] 643 | type = internal/cpu 644 | 645 | ; Seconds to sleep between updates 646 | ; Default: 1 647 | interval = 0.5 648 | format =