diff options
80 files changed, 3902 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b3d54b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.~*~
\ No newline at end of file diff --git a/home/bashrc b/home/bashrc new file mode 100644 index 0000000..9a3a2cf --- /dev/null +++ b/home/bashrc @@ -0,0 +1,42 @@ +export SHELL + +if [[ $- != *i* ]] +then + # We are being invoked from a non-interactive shell. If this + # is an SSH session (as in "ssh host command"), source + # /etc/profile so we get PATH and other essential variables. + [[ -n "$SSH_CLIENT" ]] && source /etc/profile + + # Don't do anything else. + return +fi + +# Source the system-wide file. +[ -f /etc/bashrc ] && source /etc/bashrc + +alias rm='rm -i' +alias grep="ugrep --exclude-dir=node-modules --exclude-dir=_build" +alias e="$EDITOR" +alias g="git" +alias grep="ugrep" +alias logdate='date +"%Y-%m-%d"' + +optimizeimg() { + magick -strip -quality 85% $1 $2 +} + +refs() { + recsel -q $1 ~/personal-db/refs.rec +} + +cleartrail() { + cat $1 | tr -d '\n' +} + +alias a='pwd' + +eval "$(zoxide init posix --hook prompt)" + +if [ "$(tty)" = "/dev/tty1" ]; then + exec startx +fi diff --git a/home/config.scm b/home/config.scm new file mode 100644 index 0000000..4b2820a --- /dev/null +++ b/home/config.scm @@ -0,0 +1,121 @@ +;; This is a sample Guix Home configuration which can help setup your +;; home directory in the same declarative manner as Guix System. +;; For more information, see the Home Configuration section of the manual. +(define-module (guix-home-config) + #:use-module (gnu home) + #:use-module (gnu home services) + #:use-module (gnu home services shells) + #:use-module (gnu services) + #:use-module (gnu packages) + #:use-module (gnu packages admin) + #:use-module (gnu packages emacs) + #:use-module (gnu packages fonts) + #:use-module (gnu packages mail) + #:use-module (gnu packages rust-apps) + #:use-module (gnu packages search) + #:use-module (gnu packages imagemagick) + #:use-module (gnu packages password-utils) + #:use-module (gnu packages image-viewers) + #:use-module (gnu packages xfce) + #:use-module (gnu packages sync) + #:use-module (gnu packages xorg) + #:use-module (gnu packages xdisorg) + #:use-module (gnu packages gnome) + #:use-module (gnu packages librewolf) + #:use-module (gnu packages emacs-xyz) + #:use-module (gnu packages text-editors) + #:use-module (gnu packages golang) + #:use-module (gnu packages gnupg) + #:use-module (gnu packages aspell) + #:use-module (gnu packages sqlite) + #:use-module (gnu packages databases) + #:use-module (gnu packages compression) + #:use-module (gnu system shadow) + #:use-module (gnu home services fontutils) + #:use-module (gnu home services dotfiles) + #:use-module (gnu home services gnupg) + #:use-module (gnu packages ssh) + #:use-module (guix gexp) + #:use-module (guix packages) + #:use-module (guix download) + #:use-module (guix build-system go) + #:use-module (gnu home services pm)) + + +(define home-config + (home-environment + (packages (list + font-iosevka + font-iosevka-aile + font-iosevka-etoile + + isync + + zoxide + ugrep + imagemagick + password-store + fd + recutils + unzip + + go + sqlite + + mg + + imv + thunar + thunar-volman + + emacs-geiser + emacs-geiser-guile + emacs-pinentry + mu + msmtp + emacs + + aspell + aspell-dict-en + + gnupg + pinentry + openssh + + librewolf + + xsetroot + xset + xrdb + autocutsel + gsettings-desktop-schemas + setxkbmap)) + (services + (list + (service home-bash-service-type + (home-bash-configuration + (guix-defaults? #f) + (bash-profile (list (local-file "./profile"))) + (bashrc (list (local-file "./bashrc"))))) + (service home-gpg-agent-service-type + (home-gpg-agent-configuration + (pinentry-program + (file-append pinentry-emacs "/bin/pinentry-emacs")) + (ssh-support? #t))) + + (service home-files-service-type + `((".guile" ,%default-dotguile) + (".Xdefaults" ,%default-xdefaults))) + + (service home-dotfiles-service-type + (home-dotfiles-configuration + (directories '("./dots")))) + + (simple-service 'extend-home + home-environment-variables-service-type + `(("PATH" . "${PATH}:~/home/go/bin"))) + + (service home-xdg-configuration-files-service-type + `(("gdb/gdbinit" ,%default-gdbinit))))))) + +home-config diff --git a/home/dots/.Xresources b/home/dots/.Xresources new file mode 100644 index 0000000..5985b2c --- /dev/null +++ b/home/dots/.Xresources @@ -0,0 +1,37 @@ +Xcursor*theme: Adwaita +Xcursor*size: 32 +XTerm*faceSize: 6 +XTerm*selectToClipboard: true +XTerm*faceName: Iosevka SS13 Extended:style=regular:antialias=true:hinting=false +xterm*scrollBar: false +xterm*rightScrollbar: false +XTerm.termName: xterm-256color +XTerm*Background: #FFFFFF +XTerm*Foreground: #000000 +XTerm*HiBackColor: #FFFFFF +XTerm*scaleHeight: 1.2 + +urxvt*selectToClipboard: true +urxvt*font: xft:Iosevka SS13 Extended:size=14:style=Regular:antialias=true:hinting=false +urxvt*scrollBar: false +urxvt*rightScrollbar: false +urxvt.termName: xterm-256color +urxvt*Background: #FFFFFF +urxvt*Foreground: #000000 +urxvt*HiBackColor: #FFFFFF +urxvt*internalBorder: 8 +urxvt*lineSpace: 4 +URxvt.perl-ext-common: default,matcher +URxvt.url-launcher: /usr/bin/xdg-open +URxvt.matcher.button: 1 + +Emacs.font: Iosevka SS13 Extended-15 + +! yellow +*.color3: #ffb319 +*.color11: #ffb319 + +! cyan +*.color6: #0000FF +*.color12: #0000FF +*.color14: #0000FF diff --git a/home/dots/.emacs b/home/dots/.emacs new file mode 100644 index 0000000..9a931a1 --- /dev/null +++ b/home/dots/.emacs @@ -0,0 +1,863 @@ +;; -*- lexical-binding: t; -*- +(add-to-list 'load-path "~/.emacs.d/elisp") +(fset 'yes-or-no-p 'y-or-n-p) +(setq + inhibit-startup-screen t + default-frame-alist '((font . "Iosevka SS13 Extended") + (height . 170) + (line-spacing . 0.5)) + ;; undo + undo-limit 10000000 + undo-outer-limit 20000000 + + ;; Package list + package-list '( + magit + nix-mode + go-mode + devdocs + rec-mode + almost-mono-themes + eldoc-box + markdown-mode + nov + yasnippet + yasnippet-snippets + pinentry + geiser + geiser-guile + guix + avy + tldr + elfeed + elfeed-protocol + exwm + emms + mastodon + pass + lem + expand-region) + + package-archives '(("elpa" . "https://elpa.gnu.org") + ("gnu" . "http://elpa.gnu.org/packages/") + ("melpa" . "https://melpa.org/packages/") + ("non-gnu" . "https://elpa.nongnu.org/nongnu/") + ("melpa-stable" . "https://stable.melpa.org/packages/"))) + + +;; UI +(menu-bar-mode -1) +(tool-bar-mode -1) + +(setq-default fill-column 80 + frame-title-format '("%b")) + +(package-initialize) + + +(unless package-archive-contents + (package-refresh-contents)) + +;; install the missing packages +(dolist (package package-list) + (unless (package-installed-p package) + (package-install package))) + +(use-package tab-bar + :init + (tab-bar-mode)) + +(use-package project + :ensure t + :init + (add-to-list 'project-switch-commands '(project-shell "Shell"))) + +(use-package exwm + :init + (setq exwm-workspace-number 1 + exwm-input-global-keys + `(([?\s-r] . exwm-reset) ;; s-r: Reset (to line-mode). + ;; s-N: Switch to certain workspace. + ,@(mapcar (lambda (i) + `(,(kbd (format "s-%d" i)) . + (lambda () + (interactive) + (tab-bar-select-tab ,i)))) + (number-sequence 0 9)))) + (exwm-input-set-key (kbd "s-f") + (lambda () (interactive) + (shell-command "firefox"))) + (exwm-input-set-key (kbd "<print>") + (lambda () (interactive) + (shell-command "scrot -F '/home/mccd/screenshots/%Y-%m-%d_$wx$h.png'"))) + (exwm-input-set-key (kbd "C-<print>") + (lambda () (interactive) + (shell-command "scrot -s -F '/home/mccd/screenshots/%Y-%m-%d_$wx$h.png'"))) + (exwm-input-set-key (kbd "s-<SPC>") + (lambda (cmd) ;; s-&: Launch application. + (interactive (list (read-shell-command "$ "))) + (start-process-shell-command cmd nil cmd))) + (exwm-enable) + (exwm-xim-mode) + (push ?\C-\\ exwm-input-prefix-keys) + :config + (setq + ring-bell-function 'ignore + default-directory "/home/mccd/" + focus-follows-mouse t + mouse-autoselect-window t) + :hook + (;; Make sure titles match X window + (server-after-make-frame . (lambda () + (set-window-margins (selected-window) 2 2))) + (exwm-update-title . (lambda () + (exwm-workspace-rename-buffer + (concat exwm-class-name ":" + (if (<= (length exwm-title) 50) exwm-title + (concat (substring exwm-title 0 49) "...")))))) + (exwm-update-class . (lambda () + (exwm-workspace-rename-buffer + (concat exwm-class-name ":" + (if (<= (length exwm-title) 50) exwm-title + (concat (substring exwm-title 0 49) "...")))))))) + +(use-package time + :init + (display-time-mode) + :config + (setq display-time-format "%a, %d/%m/%Y %H:%M")) + +(use-package geiser + :ensure t) + +(use-package pixel-scroll + :init + (pixel-scroll-precision-mode)) + +(use-package scroll-bar + :init + (scroll-bar-mode -1)) + +(use-package frame + :init + (window-divider-mode)) + +(use-package delsel + :init + (delete-selection-mode)) + +(use-package files + :config + (setq delete-old-versions t + kept-new-versions 6 + kept-old-versions 2 + version-control t + auto-save-default nil)) + +(use-package minibuffer + :defer t + :config + (setq completion-cycle-threshold 5 + completion-ignore-case t)) + +(use-package pass + :defer t + :ensure t) + +(use-package select + :config + (setq x-select-enable-clipboard t + x-select-enable-primary t)) + +(use-package imenu + :defer t + :config + (setq imenu-auto-rescan t)) + +(defun sudo-shell-command (command) + (interactive "MShell command (root): ") + (with-temp-buffer + (cd "/sudo::/") + (async-shell-command command))) + + +(use-package guix + :ensure t + :bind + (("C-c C-g g" . guix) + ("C-c C-g o" . (lambda () + (interactive) + (sudo-shell-command "guix system reconfigure /home/mccd/system/os/config.scm"))) + ("C-c C-g h" . (lambda () + (interactive) + (async-shell-command "guix home reconfigure ~/system/home/config.scm"))))) + + +(use-package nov + :defer t + :ensure t + :init + (add-to-list 'auto-mode-alist '("\\.epub'" . nov-mode))) + +(use-package battery + :init + (display-battery-mode t)) + +(use-package comint + :bind + ((:repeat-map + repeat-hist-line-map + ("n" . comint-next-input) + ("p" . comint-previous-input)))) + +(use-package repeat + :demand t + :bind + ((:repeat-map + repeat-normal-movement-map + ("n" . next-line) + ("b" . backward-char) + ("f" . forward-char) + ("e" . move-end-of-line) + ("F" . forward-word) + ("B" . backward-word) + ("v" . scroll-up-command) + ("V" . scroll-down-command) + ("o" . avy-goto-char-timer) + ("g" . goto-line) + ("a" . move-beginning-of-line) + ("k" . kill-line) + ("d" . delete-char) + ("D" . kill-word) + ("." . er/expand-region) + ("-" . er/contract-region) + ("p" . previous-line)) + (:repeat-map + repeat-movement-map + ("e" . end-of-defun) + ("f" . forward-sexp) + ("n" . forward-list) + ("p" . backward-list) + ("d" . down-list) + ("u" . up-list) + ("b" . backward-sexp) + ("a" . beginning-of-defun))) + :config + (setq repeat-on-final-keystroke t + set-mark-command-repeat-pop t + repeat-exit-key (kbd "<TAB>")) + (repeat-mode 1)) + +(use-package org-crypt + :ensure nil + :init + (setenv "GPG_AGENT_INFO" nil) + (setq auth-source-debug t + epg-gpg-program "gpg2") + (org-crypt-use-before-save-magic)) + +(use-package grep + :config + (setq-default + grep-template (string-join + '("ugrep" + "--color=never" + "--ignore-binary" + "--ignore-case" + "--include=<F>" + "--line-number" + "--null" + "--recursive" + "--regexp=<R>") + " "))) + +(use-package pinentry + :ensure t + :init + (pinentry-start)) + + +(use-package epa-file + :init + (epa-file-enable) + (setq + epa-pinentry-mode 'loopback)) + +(use-package exwm-mff + :demand t + :load-path "elisp" + :hook + ((server-after-make-frame . exwm-mff-mode))) + +(use-package avy + :ensure t + :config + (setq + avy-timeout-seconds 0.2) + (global-set-key (kbd "M-o") 'avy-goto-char-timer) + (set-face-attribute 'avy-lead-face nil :inherit 'fixed-pitch) + (set-face-attribute 'avy-lead-face-0 nil :inherit 'fixed-pitch) + (set-face-attribute 'avy-lead-face-1 nil :inherit 'fixed-pitch) + (set-face-attribute 'avy-lead-face-2 nil :inherit 'fixed-pitch) + (setf (alist-get ? avy-dispatch-alist) 'avy-action-mark-to-char) + (define-key isearch-mode-map (kbd "M-o") 'avy-isearch) + (defun avy-action-kill-whole-line (pt) + (save-excursion + (goto-char pt) + (kill-whole-line)) + (select-window + (cdr + (ring-ref avy-ring 0))) + t) + (setf (alist-get ?k avy-dispatch-alist) 'avy-action-kill-stay + (alist-get ?K avy-dispatch-alist) 'avy-action-kill-whole-line) + (defun avy-action-copy-whole-line (pt) + (save-excursion + (goto-char pt) + (cl-destructuring-bind (start . end) + (bounds-of-thing-at-point 'line) + (copy-region-as-kill start end))) + (select-window + (cdr + (ring-ref avy-ring 0))) + t) + (defun avy-action-yank-whole-line (pt) + (avy-action-copy-whole-line pt) + (save-excursion (yank)) + t) + + (setf (alist-get ?y avy-dispatch-alist) 'avy-action-yank + (alist-get ?w avy-dispatch-alist) 'avy-action-copy + (alist-get ?W avy-dispatch-alist) 'avy-action-copy-whole-line + (alist-get ?Y avy-dispatch-alist) 'avy-action-yank-whole-line) + (defun avy-action-copy-whole-line (pt) + (save-excursion + (goto-char pt) + (cl-destructuring-bind (start . end) + (bounds-of-thing-at-point 'line) + (copy-region-as-kill start end))) + (select-window + (cdr + (ring-ref avy-ring 0))) + t) + + (defun avy-action-yank-whole-line (pt) + (avy-action-copy-whole-line pt) + (save-excursion (yank)) + t) + + (setf (alist-get ?y avy-dispatch-alist) 'avy-action-yank + (alist-get ?w avy-dispatch-alist) 'avy-action-copy + (alist-get ?W avy-dispatch-alist) 'avy-action-copy-whole-line + (alist-get ?Y avy-dispatch-alist) 'avy-action-yank-whole-line) + + (defun avy-action-teleport-whole-line (pt) + (avy-action-kill-whole-line pt) + (save-excursion (yank)) t) + + (setf (alist-get ?t avy-dispatch-alist) 'avy-action-teleport + (alist-get ?T avy-dispatch-alist) 'avy-action-teleport-whole-line) + + (defun avy-action-mark-to-char (pt) + (activate-mark) + (goto-char pt)) + + (setf (alist-get ? avy-dispatch-alist) 'avy-action-mark-to-char)) + +(use-package flymake + :defer t + :bind + (:repeat-map flymake-repeat-map + ("]" . flymake-goto-next-error) + ("[" . flymake-goto-prev-error)) + :hook + ((flymake-mode . + (lambda () + (define-key flymake-mode-map (kbd "C-c ]") 'flymake-goto-next-error) + (define-key flymake-mode-map (kbd "C-c [") 'flymake-goto-prev-error))))) + +(use-package expand-region + :ensure t + :init + (global-set-key (kbd "C-c .") 'er/expand-region)) + +(use-package devdocs + :ensure t + :init + (global-set-key (kbd "C-h D") 'devdocs-lookup)) + +(use-package sgml-mode + :init + (add-to-list 'auto-mode-alist '("\\.njk\\'" . html-mode)) + (add-to-list 'auto-mode-alist '("\\.tmpl\\'" . html-mode)) + :hook + ;; TODO fix + ((html-mode . (lambda () + (keymap-local-set (kbd "M-o") 'avy-goto-char-timer))) + (html-mode . (lambda () + (setq sgml-basic-offset 8 + indent-tabs-mode t))))) + +(use-package eldoc + :ensure t + :demand t + :diminish "" + :config + (setq eldoc-print-after-edit t + echo-area-display-truncation-message nil + eldoc-echo-area-prefer-doc-buffer 'maybe + eldoc-echo-area-use-multiline-p nil) + :hook (prog-mode . eldoc-mode)) + +(use-package eldoc-box + :ensure t + :demand t + :hook + (eglot-managed-mode . #'eldoc-box-hover-mode) + :config + (global-set-key (kbd "C-h .") #'eldoc-box-help-at-point)) + +(use-package markdown-mode + :ensure t + :config + (set-face-attribute 'markdown-code-face nil :inherit 'fixed-pitch) + :hook + ((markdown-mode . variable-pitch-mode) + (markdown-mode . markdown-toggle-url-hiding) + (markdown-mode . markdown-toggle-markup-hiding) + (markdown-mode . visual-line-mode))) + +(use-package elec-pair + :init + (electric-pair-mode 1) + :config + (global-set-key (kbd "M-{") 'insert-pair) + (global-set-key (kbd "M-\"") 'insert-pair) + (global-set-key (kbd "M-\'") 'insert-pair) + (global-set-key (kbd "M-<") 'insert-pair) + (global-set-key (kbd "M-[") 'insert-pair)) + +(use-package ido + :init + (ido-mode t)) + +(use-package org-link-minor-mode + :load-path "elisp" + :defer t) + +(use-package calendar + :defer t + :init + (add-to-list 'auto-mode-alist '("~/personal-db/log" . diary-mode)) + :hook + ((diary-mode . variable-pitch-mode) + ; (diary-mode . org-link-minor-mode) + ; (diary-fancy-display-mode . org-link-minor-mode) + (diary-fancy-display-mode . variable-pitch-mode) + (diary-mode . (lambda () + (add-hook 'after-save-hook 'sync-org nil t))) + (diary-mode . flyspell-mode)) + :config + (global-set-key (kbd "C-c d") 'calendar) + (calendar-set-date-style 'european) + (set-face-attribute 'diary nil :inherit 'fixed-pitch) + (setq diary-file "~/personal-db/log" + calendar-mark-diary-entries-flag t + calendar-week-start-day 1)) + +(use-package nix-mode + :ensure t + :defer t + :hook + ((nix-mode . (lambda () + (add-hook 'before-save-hook #'nix-format-buffer nil t))) + (nix-mode . nix-prettify-mode))) + +(use-package eglot + :config + ;; Ensure `nil` is in your PATH. + (add-to-list 'eglot-server-programs '(nix-mode . ("nil"))) + (define-key eglot-mode-map (kbd "C-c r") 'eglot-rename) + (define-key eglot-mode-map (kbd "C-c o") 'eglot-code-actions) + :hook + (nix-mode . eglot-ensure) + (go-mode . eglot-ensure)) + +(use-package go-mode + :ensure t + :defer t + :hook + ((go-mode . (lambda () + (add-hook + 'before-save-hook 'eglot-format-buffer nil t))) + (go-mode . (lambda () + (setq-local compile-command "go build ."))))) + +(use-package rec-mode + :ensure nil + :defer t + :mode "\\.rec\\'" + :hook + ((rec-mode . flymake-mode) + (rec-mode . eldoc-mode))) + +(use-package erc + :ensure t + :config + (setq erc-autojoin-channels-alist + '(("Libera.Chat" + "#emacs" + "#permacomputing" + "#oldcomputerchallenge" + "#go-nuts" + "#netbsd" + "#nonguix" + "#guix"))) + :init + (global-set-key + "\C-cef" + (lambda () + (interactive) + (erc + :server "irc.libera.chat" + :port "6667" + :nick "mccd" + :password (shell-command-to-string "pass show libera.chat"))))) + +(use-package ob-rec + :ensure nil) + +(defun sync-org () + (interactive) + (async-shell-command "org-sync")) + +(add-to-list 'display-buffer-alist '("*Async Shell Command*" display-buffer-no-window (nil))) + +;; Org +(use-package org + :ensure t + :init + (add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode)) + (org-babel-do-load-languages + 'org-babel-load-languages + '((shell . t) + (rec .t))) + + :config + (setq org-refile-targets + '((nil :maxlevel . 4) + (org-agenda-files :maxlevel . 4)) + org-default-notes-file "~/personal-db/notes/todo.org" + org-hide-emphasis-markers t + org-agenda-include-diary t + org-agenda-remove-tags t + org-startup-folded 'content + org-agenda-inhibit-startup nil + ;; Add /New Heading at the end for use + org-refile-allow-creating-parent-nodes 'confirm + org-outline-path-complete-in-steps nil + org-refile-use-outline-path 'file + ;; Otherwise looks weird in variable-pitch-mode + org-log-done 'time + org-capture-templates + '(("t" "Todo" + entry (file "~/personal-db/notes/todo.org") + "* TODO %?\n%i\n%a\n " + :empty-lines 0) + ("l" "Log" plain (file "~/personal-db/log") + "%<%d %b %Y %H:%M> %?" + :prepend t) + ("n" "Inbox" + entry (file "~/personal-db/notes/inbox.org") + "** %?\n%T" + :empty-lines 0))) + (set-face-attribute 'org-block nil :inherit 'fixed-pitch) + (set-face-attribute 'org-code nil :inherit 'fixed-pitch) + (set-face-attribute 'org-table nil :inherit 'fixed-pitch) + (set-face-attribute 'org-date nil :inherit 'fixed-pitch) + (set-face-attribute 'org-tag nil :inherit 'fixed-pitch) + (global-set-key (kbd "C-c l") #'org-store-link) + (global-set-key (kbd "C-c a") #'org-agenda) + (global-set-key (kbd "C-c c") #'org-capture) + (global-set-key (kbd "C-c j") #'org-goto) + (global-set-key (kbd "C-c s") #'project-find-regexp) + (global-set-key (kbd "C-c C-o") #'org-open-at-point-global) + (global-set-key (kbd "C-c C-s") #'sync-org) + ;; Something errors out with capture logs and non-org files + (add-to-list 'warning-suppress-log-types '(org-element)) + (add-to-list 'warning-suppress-types '(org-element)) + :hook + ((org-mode . auto-save-visited-mode) + (org-mode . org-indent-mode) + (org-mode . flyspell-mode) + (org-mode . visual-line-mode) + (org-mode . (lambda () + (add-hook 'after-save-hook 'sync-org nil t))) + (org-mode . variable-pitch-mode))) + +(use-package rec-mode + :ensure t) + +(use-package magit + :ensure t + :demand t) + +(use-package magit-extras + :ensure nil) + +(use-package yasnippet + :diminish t + :ensure t + :init + (yas-global-mode 1)) + +(use-package register + :bind + (("C-z" . 'point-to-register))) + +(defun marc/set-msmtp-account () + (if (message-mail-p) + (save-excursion + (let* + ((from (save-restriction + (message-narrow-to-headers) + (message-fetch-field "from"))) + (account + (cond + ((string-match "marcc@fastmail.fr" from) "home") + ((string-match "marc.coquand@sustainably.app" from) "work") + ((string-match "marc@mccd.space" from) "home")))) + (setq message-sendmail-extra-arguments (list '"-a" account)))))) + +;(use-package message +; :defer t +; :hook +; ((message-send-mail . marc/set-msmtp-account) +; (message-mode-hook flyspell-mode))) + +(add-hook 'message-send-mail-hook #'marc/set-msmtp-account) +(add-hook 'message-mode-hook #'flyspell-mode) + +(use-package flyspell + :defer t) + +(use-package mu4e + :ensure nil + :config + ;; This is set to 't' to avoid mail syncing issues when using mbsync + (setq mu4e-change-filenames-when-moving t) + + ;; don't keep message compose buffers around after sending: + (setq message-kill-buffer-on-exit t) + + ;; send function: + (setq send-mail-function 'sendmail-send-it + message-send-mail-function 'sendmail-send-it) + + ;; send program: + ;; this is exeranal. remember we installed it before. + (setq sendmail-program (executable-find "msmtp")) + + ;; select the right sender email from the context. + (setq message-sendmail-envelope-from 'header) + + ;; Refresh mail using isync every 10 minutes + (setq mu4e-update-interval (* 10 60) + mu4e-get-mail-command "mbsync -a" + mu4e-view-show-images t + mu4e-view-show-addresses t + mu4e-attachment-dir "~/Downloads" + mu4e-view-prefer-html t + mu4e-maildir "~/mail") + + (setq mu4e-contexts + (list + ;; Home + (make-mu4e-context + :name "home" + :enter-func (lambda () (mu4e-message "Entering personal context")) + :leave-func (lambda () (mu4e-message "Leaving personal context")) + :match-func + (lambda (msg) + (when msg + (string-prefix-p "/home" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "marc@mccd.space") + (user-full-name . "Marc Coquand") + (mu4e-drafts-folder . "/home/Drafts") + (mu4e-sent-folder . "/home/Sent") + (mu4e-refile-folder . "/home/Archive") + (mu4e-trash-folder . "/home/Trash") + (mu4e-sent-messages-behavior . sent) + + (mu4e-maildir-shortcuts . + (("/home/INBOX" . ?i) + ("/home/Archive/Done" . ?d) + ("/home/Archive" . ?a) + ("/home/Archive/Todo" . ?t))))) + ;; Work account + (make-mu4e-context + :name "work" + :enter-func (lambda () (mu4e-message "Entering work context")) + :leave-func (lambda () (mu4e-message "Leaving work context")) + :match-func + (lambda (msg) + (when msg + (string-prefix-p "/work" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "marc.coquand@sustainably.app") + (user-full-name . "Marc Coquand") + (mu4e-drafts-folder . "/work/[Gmail]/Drafts") + (mu4e-sent-folder . "/work/[Gmail]/Sent Mail") + (mu4e-refile-folder . "/work/[Gmail]/All Mail") + (mu4e-sent-messages-behavior . delete) + (mu4e-trash-folder . "/work/[Gmail]/Trash") + (mu4e-maildir-shortcuts . + (("/work/[Gmail]/All Mail" . ?a) + ("/work/INBOX" . ?i)))))))) + + +(use-package lem + :ensure t + :config + (setq lem-instance-url "https://lemmy.sdf.org")) + +(use-package elfeed-protocol + :ensure t + :init + (elfeed-protocol-enable)) + +(use-package elfeed + :ensure t + :config + (setq elfeed-use-curl t + ;; setup feeds + elfeed-protocol-fever-update-unread-only t + elfeed-protocol-fever-fetch-category-as-tag t + elfeed-protocol-feeds '(("fever+https://freshrss@rss.mccd.space" + :api-url "https://rss.mccd.space/api/fever.php" + :password (shell-command-to-string "pass show mccd/freshrss"))) + ;; enable elfeed-protocol + elfeed-protocol-enabled-protocols '(fever) + elfeed-curl-extra-arguments '("--insecure")) ;necessary for https without a trust certificate + (elfeed-set-timeout 36000) + (global-set-key (kbd "C-x w") 'elfeed)) + +(use-package mastodon + :defer t + :config + (setq + mastodon-active-user "marcc" + mastodon-instance-url "https://fosstodon.org")) + +(use-package eww + :config + (setq + browse-url-browser-function 'eww-browse-url ; Use eww as the default browser + eww-search-prefix "https://lite.duckduckgo.com/lite/?q=" + shr-max-image-proportion 0.3 + shr-width 70)) + +;; Can play youtube urls and music. +;; Requires mpv +(use-package emms + :ensure t + :init + (add-hook 'emms-player-started-hook 'emms-show) + :config + (setq emms-shop-format "on: %s") + (emms-all) + (emms-default-players)) + +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(default ((t (:inherit nil :extend nil :stipple nil :background "white" :foreground "black" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight regular :height 150 :width expanded :foundry "UKWN" :family "Iosevka SS13 Extended")))) + '(avy-lead-face ((t (:inherit fixed-pitch :background "dark red" :foreground "white")))) + '(calendar-weekend-header ((t (:inherit nil)))) + '(custom-group-subtitle ((t (:weight bold :family "Iosevka Aile")))) + '(diary ((t (:inherit fixed-pitch :foreground "red1")))) + '(eglot-highlight-symbol-face ((t (:weight bold)))) + '(eglot-mode-line ((t (:weight regular)))) + '(erc-timestamp-face ((t (:foreground "blue" :weight bold)))) + '(eshell-prompt ((t (:weight bold)))) + '(eww-valid-certificate ((t (:foreground "black" :weight bold)))) + '(fixed-pitch ((t (:family "Iosevka SS13 Extended")))) + '(font-lock-builtin-face ((t (:weight regular)))) + '(font-lock-comment-face ((t (:foreground "royalblue" :slant normal)))) + '(font-lock-constant-face ((t (:slant italic :weight regular)))) + '(font-lock-function-name-face ((t (:weight regular)))) + '(font-lock-keyword-face ((t (:weight regular)))) + '(font-lock-string-face ((t (:foreground "black" :slant italic)))) + '(font-lock-type-face ((t (:foreground "black")))) + '(font-lock-variable-name-face ((t (:foreground "black")))) + '(fringe ((t (:background "white")))) + '(header-line ((t (:inherit default :foreground "grey20" :box (:line-width (8 . 8) :color "#FFFFFF") :underline (:color "#e0e0e0" :style line :position 0) :family "Iosevka Aile")))) + '(highlight ((t (:background "azure2")))) + '(info-header-xref ((t (:inherit info-xref :underline (:color "RoyalBlue3" :style line :position t))))) + '(info-node ((t (:foreground "brown" :box (:line-width (4 . 4) :color "white") :slant italic :weight bold)))) + '(link ((t (:foreground "royalblue" :underline t)))) + '(magit-branch-remote ((t (:foreground "royalblue")))) + '(markdown-inline-code-face ((t (:inherit markdown-code-face)))) + '(markdown-pre-face ((t (:inherit markdown-code-face)))) + '(mastodon-display-name-face ((t (:inherit nil :weight bold)))) + '(mode-line ((t (:background "gray95" :foreground "black" :box (:line-width (8 . 8) :style flat-button) :overline "#e0e0e0" :underline (:color "#e0e0e0" :style line :position t) :family "Iosevka Aile")))) + '(mode-line-emphasis ((t (:weight regular)))) + '(mode-line-inactive ((t (:inherit mode-line :background "#fbfbfb" :foreground "grey60" :overline "#f9f9f9" :underline (:color "#f9f9f9" :style line :position 0) :weight light)))) + '(mu4e-header-highlight-face ((t (:inherit hl-line :extend t :weight bold)))) + '(mu4e-highlight-face ((t (:inherit highlight)))) + '(org-date ((t (:inherit fixed-pitch :foreground "gray40" :underline t)))) + '(org-headline-done ((t (:foreground "gray40")))) + '(org-level-1 ((t (:inherit outline-1 :extend nil :weight regular)))) + '(org-tag ((t (:inherit fixed-pitch :foreground "gray40" :weight regular)))) + '(org-time-grid ((t (:foreground "gray")))) + '(outline-4 ((t (:inherit outline-2)))) + '(tab-bar ((t (:box (:line-width (12 . 24) :style flat-button) :weight semi-light :family "Iosevka Aile")))) + '(tab-bar-tab ((t (:inherit tab-bar :foreground "black" :box (:line-width (20 . 1) :color "white") :weight semi-bold)))) + '(tab-bar-tab-inactive ((t (:inherit tab-bar-tab :background "white" :foreground "#999999" :weight semi-light)))) + '(tldr-code-block ((t (:background "cornsilk" :foreground "black")))) + '(tldr-command-argument ((t (:background "cornsilk" :foreground "black")))) + '(tldr-command-itself ((t (:background "khaki" :foreground "black" :weight bold)))) + '(tldr-introduction ((t (:foreground "black" :slant italic)))) + '(tldr-title ((t (:inherit variable-pitch :foreground "black" :weight bold :height 1.2)))) + '(variable-pitch ((t (:family "Iosevka Aile")))) + '(window-divider ((t (:foreground "gray90"))))) +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(custom-safe-themes + '("cbd85ab34afb47003fa7f814a462c24affb1de81ebf172b78cb4e65186ba59d2" default)) + '(erc-mode-line-format "") + '(erc-modules + '(autojoin button completion fill irccontrols list match menu move-to-prompt netsplit networks noncommands notifications readonly ring services stamp spelling)) + '(magit-section-visibility-indicator '("..." . t)) + '(markdown-list-item-bullets '("-")) + '(mastodon-tl--enable-proportional-fonts t) + '(mastodon-use-emojify t) + '(mode-line-compact 'long) + '(mode-line-format + '("%e" mode-line-front-space + (:propertize + ("" mode-line-modified " ")) + mode-line-buffer-identification " " mode-line-modes)) + '(mode-line-percent-position nil) + '(mode-line-position-line-format '(" ")) + '(mu4e-bookmarks + '((:name "Last 7 days" :query "date:7d..now" :hide-unread t :key 119) + (:name "Messages with images" :query "mime:image/*" :key 112))) + '(org-agenda-files + '("~/personal-db/notes/sustainable-software.org" "/home/mccd/personal-db/notes/thoughts.org" "/home/mccd/personal-db/notes/cal-ios.org" "/home/mccd/personal-db/notes/ethics-and-software.org" "/home/mccd/personal-db/notes/reminders.org" "/home/mccd/builds/sustainably/piva.org" "/home/mccd/personal-db/notes/programming.org" "/home/mccd/personal-db/notes/unix.org" "/home/mccd/personal-db/notes/agency-and-tech.org" "/home/mccd/personal-db/notes/emacs-teaches.org" "/home/mccd/personal-db/notes/emacs.org" "/home/mccd/personal-db/notes/inbox.org" "/home/mccd/personal-db/notes/todo.org")) + '(org-fold-core-style 'overlays) + '(package-selected-packages + '(nov eldoc-box hide-mode-line exwm-mff eat pinentry exwm emms company orglink web-mode flycheck nix-mode nix-ts-mode avy pdf-tools elfeed-protocol lem yasnippet-snippets elfeed yasnippet smartparens markdown-mode mastodon tldr almost-mono-themes rec-mode magit go-mode expand-region devdocs)) + '(tab-bar-auto-width t) + '(tab-bar-close-button-show nil) + '(tab-bar-format + '(tab-bar-format-tabs tab-bar-format-align-right tab-bar-format-global)) + '(tab-bar-position nil) + '(tab-bar-tab-hints t) + '(window-divider-default-right-width 2) + '(yank-from-kill-ring-rotate t)) +(put 'secrets-mode 'disabled nil) diff --git a/home/dots/.emacs.d/elisp/almost-mono-themes.el b/home/dots/.emacs.d/elisp/almost-mono-themes.el new file mode 100644 index 0000000..4b7769e --- /dev/null +++ b/home/dots/.emacs.d/elisp/almost-mono-themes.el @@ -0,0 +1,205 @@ +;;; almost-mono-themes.el --- Almost monochromatic color themes -*- lexical-binding: t; -*- + +;; Copyright (C) 2019 - 2022 John Olsson + +;; Author: John Olsson <john@cryon.se> +;; Maintainer: John Olsson <john@cryon.se> +;; URL: https://github.com/cryon/almost-mono-themes +;; Created: 9th May 2019 +;; Version: 1.0.0 +;; Keywords: faces +;; Package-Requires: ((emacs "24")) + +;; This file is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published +;; by the Free Software Foundation, either version 3 of the License, +;; or (at your option) any later version. + +;; This file is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this file. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; A suite of almost monochrome Emacs themes + +;;; Code: + +(defconst almost-mono-themes-colors + '((white . ((background . "#ffffff") + (foreground . "#000000") + (weak . "#888888") + (weaker . "#dddddd") + (weakest . "#efefef") + (highlight . "#fda50f") + (warning . "#ff0000") + (success . "#00ff00") + (string . "#3c5e2b"))) + + (black . ((background . "#000000") + (foreground . "#ffffff") + (weak . "#aaaaaa") + (weaker . "#666666") + (weakest . "#222222") + (highlight . "#fda50f") + (warning . "#ff0000") + (success . "#00ff00") + (string . "#a7bca4"))) + + (gray . ((background . "#2b2b2b") + (foreground . "#ffffff") + (weak . "#aaaaaa") + (weaker . "#666666") + (weakest . "#222222") + (highlight . "#fda50f") + (warning . "#ff0000") + (success . "#00ff00") + (string . "#a7bca4"))) + + (cream . ((background . "#f0e5da") + (foreground . "#000000") + (weak . "#7d7165") + (weaker . "#c4baaf") + (weakest . "#dbd0c5") + (highlight . "#fda50f") + (warning . "#ff0000") + (success . "#00ff00") + (string . "#3c5e2b"))))) + +(defmacro almost-mono-themes--variant-with-colors (variant &rest body) + "Execute BODY in a scope where the different colors for given VARIANT is bound." + `(let* ((colors (or (cdr (assoc ,variant almost-mono-themes-colors)) + (error "No such theme variant"))) + (background (cdr (assoc 'background colors))) + (foreground (cdr (assoc 'foreground colors))) + (weak (cdr (assoc 'weak colors))) + (weaker (cdr (assoc 'weaker colors))) + (weakest (cdr (assoc 'weakest colors))) + (highlight (cdr (assoc 'highlight colors))) + (warning (cdr (assoc 'warning colors))) + (success (cdr (assoc 'success colors))) + (string (cdr (assoc 'string colors)))) + ,@body)) + +(defmacro almost-mono-themes--faces-spec () + "Provide the faces specification." + (quote + (mapcar + (lambda (entry) (list (car entry) `((t ,@(cdr entry))))) + `( + + ;; default + (default (:background ,background :foreground ,foreground)) + (fringe (:background ,background)) + (region (:background ,highlight :foreground ,foreground)) + (show-paren-match (:background ,background :foreground ,success :bold t)) + (show-paren-mismatch (:background ,background :foreground ,warning :bold t)) + (minibuffer-prompt (:weight bold :foreground ,foreground)) + (isearch (:background ,weak :foreground ,foreground :bold t)) + (lazy-highlight (:background ,weaker :foreground ,foreground)) + (link (:underline t)) + + ;; mode line + (mode-line (:box (:line-width -1 :color ,weaker) + :background ,weakest :foreground ,foreground)) + + (mode-line-inactive (:box (:line-width -1 :color ,weaker) + :background ,background :foreground ,weaker)) + + ;; font lock + (font-lock-keyword-face (:bold t)) + (font-lock-function-name-face (:bold t)) + (font-lock-variable-name-face (:foreground ,foreground)) + (font-lock-warning-face (:foreground ,foreground :underline (:color ,warning :style wave))) + (font-lock-builtin-face (:bold t)) + (font-lock-variable-name-face (:foreground ,foreground :italic t)) + (font-lock-constant-face (:bold t :italic t)) + (font-lock-type-face (:italic t)) + (font-lock-preprocessor-face (:italic t)) + (font-lock-comment-face (:foreground ,weak :italic t)) + (font-lock-string-face (:foreground ,string)) + (font-lock-doc-face (:inherit font-lock-comment-face)) + (line-number (:foreground ,weaker)) + (linum (:inherit line-number)) + (vertical-border (:foreground ,weaker)) + + ;; eshell + (eshell-prompt (:foreground ,foreground :bold t)) + (eshell-ls-directory (:foreground ,foreground :bold t)) + (eshell-ls-archive (:inherit eshell-ls-unreadable)) + (eshell-ls-backup (:inherit eshell-ls-unreadable)) + (eshell-ls-clutter (:inherit eshell-ls-unreadable)) + (eshell-ls-executable (:inherit eshell-ls-unreadable)) + (eshell-ls-missing (:inherit eshell-ls-unreadable)) + (eshell-ls-product (:inherit eshell-ls-unreadable)) + (eshell-ls-readonly (:inherit eshell-ls-unreadable)) + (eshell-ls-special (:inherit eshell-ls-unreadable)) + (eshell-ls-symlink (:inherit eshell-ls-unreadable)) + + ;; company mode + (company-tooltip (:background ,weakest :foreground ,foreground)) + (company-tooltip-selection (:background ,weaker :foreground ,foreground)) + ;;(company-tooltip-search (:background "#ff0000" :foreground "#00ff00")) + (company-tooltip-common (:bold t)) + (company-tooltip-common-selection (:bold t)) + (company-scrollbar-bg (:background ,weaker)) + (company-scrollbar-fg (:background ,weak)) + (company-tooltip-annotation-selection (:background ,weaker :foreground ,foreground :italic t)) + (company-tooltip-annotation (:background ,weakest :foreground ,weak :italic t)) + + ;; git gutter + (git-gutter:modified (:background ,highlight :foreground ,highlight)) + (git-gutter:added (:background ,success :foreground ,success)) + (git-gutter:deleted (:background ,warning :foreground ,warning)) + + ;; diff hl + (diff-hl-change (:background ,highlight :foreground ,highlight)) + (diff-hl-insert (:background ,success :foreground ,success)) + (diff-hl-delete (:background ,warning :foreground ,warning)) + + ;; hl line + (hl-line (:background ,weakest)) + (highlight-current-line-face (:inherit hl-line)) + + ;; ido + (ido-first-match (:bold t)) + (ido-only-match (:bold t)) + (ido-subdir (:italic t)) + (ido-virtual (:foreground ,weak)) + (ido-vertical-match-face (:bold t :italic nil)) + + ;; org mode + (org-table (:foreground ,weak)) + + )))) + + +(defun almost-mono-themes--variant-name (variant) + "Create symbol for color theme variant VARIANT." + (intern (format "almost-mono-%s" (symbol-name variant)))) + +(defmacro almost-mono-themes--define-theme (variant) + "Define a theme for the almost-mono variant VARIANT." + (let ((name (almost-mono-themes--variant-name variant)) + (doc (format "almost mono theme (%s version)" variant))) + `(progn + (deftheme ,name ,doc) + (put ',name 'theme-immediate t) + (almost-mono-themes--variant-with-colors + ',variant + (apply 'custom-theme-set-faces ',name + (almost-mono-themes--faces-spec))) + (provide-theme ',name)))) + +;;;###autoload +(when (and (boundp 'custom-theme-load-path) load-file-name) + (add-to-list 'custom-theme-load-path + (file-name-as-directory (file-name-directory load-file-name)))) + +(provide 'almost-mono-themes) + +;;; almost-mono-themes.el ends here diff --git a/home/dots/.emacs.d/elisp/exwm-mff.el b/home/dots/.emacs.d/elisp/exwm-mff.el new file mode 100644 index 0000000..6b1ef87 --- /dev/null +++ b/home/dots/.emacs.d/elisp/exwm-mff.el @@ -0,0 +1,191 @@ +;;; exwm-mff.el --- Mouse Follows Focus -*- lexical-binding: t; -*- + +;; Copyright (C) 2019, 2020, 2021 Ian Eure + +;; Author: Ian Eure <public@lowbar.fyi> +;; URL: https://github.com/ieure/exwm-mff +;; Version: 1.2.1 +;; Package-Requires: ((emacs "25.1")) +;; Keywords: unix + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Mouse Follows Focus +;; =================== +;; +;; Traditional window managers are mouse-centric: the window to receive +;; input is usually selected with the pointing device. +;; +;; Emacs is keybord-centric: the window to receive key input is usually +;; selected with the keyboard. When you use the keyboard to focus a +;; window, the spatial relationship between pointer and active window is +;; broken -- the pointer can be anywhere on the screen, instead of over +;; the active window, which can make it hard to find. +;; +;; The same problem also exists in traditional windowing systems when +;; you use the keyboard to switch windows, e.g. with Alt-Tab. +;; +;; Because Emacsโ model is inverted, this suggests that the correct +;; behavior is also the inverse -- instead of using the mouse to +;; select a window to receive keyboard input, the keyboard should be +;; used to select the window to receive mouse input. +;; +;; `EXWM-MFF-MODE' is a global minor mode which does exactly this. +;; When the selected window in Emacs changes, the mouse pointer is +;; moved to its center, unless the pointer is already somewhere inside +;; the windowโs bounds. While it's especially helpful for for EXWM +;; users, it works for any Emacs window in a graphical session. +;; +;; This package also offers the `EXWM-MFF-WARP-TO-SELECTED' command, +;; which allows you to summon the pointer with a hotkey. Unlike the +;; minor mode, summoning is unconditional, and will place the pointer in +;; the center of the window even if it already resides within its bounds +;; -- a handy feature if youโve lost your pointer, even if youโre using +;; the minor mode. +;; +;; +;; Limitations +;; ~~~~~~~~~~~ +;; +;; None known at this time. + +;;; Code: + +(require 'subr-x) +(require 'cl-macs) + +(defcustom exwm-mff-ignore-if nil + "List of predicate functions for windows to ignore. + +Predicates accept one argument, WINDOW, and return non-NIL if +automatic pointer warping should be suppressed." + :type 'hook + :group 'exwm-mff) + +(defconst exwm-mff--debug-buffer " *exwm-mff-debug*" + "Name of the buffer exwm-mff will write debug messages into.") + +(defvar exwm-mff--debug 0 + "Whether (and how) to debug exwm-mff. +0 = don't debug. +1 = log messages to *exwm-mff-debug*. +2 = log messages to *exwm-mff-debug* and the echo area.") + +(defvar exwm-mff--last-window nil + "The last selected window.") + +(defun exwm-mff--guard () + "Raise an error unless this is a graphic session with mouse support." + (unless (and (display-graphic-p) (display-mouse-p)) + (error "EXWM-MFF-MODE doesn't work on non-graphic or non-mouse sessions"))) + +(defun exwm-mff--contains-pointer? (window) + "Return non-NIL when the mouse pointer is within FRAME and WINDOW." + (cl-destructuring-bind ((mouse-x . mouse-y) (left top right bottom)) + (list (mouse-absolute-pixel-position) + (window-absolute-pixel-edges window)) + (and (<= left mouse-x right) + (<= top mouse-y bottom)))) + +(defun exwm-mff--debug (string &rest objects) + "Log debug message STRING, using OBJECTS to format it." + (let ((debug-level (or exwm-mff--debug 0))) + (when (> debug-level 0) + (let ((str (apply #'format (concat "[%s] " string) + (cons (current-time-string) objects)))) + (when (>= debug-level 1) + (with-current-buffer (get-buffer-create exwm-mff--debug-buffer) + (goto-char (point-max)) + (insert (concat str "\n"))) + (when (>= debug-level 2) + (message str))))))) + +(defun exwm-mff-show-debug () + "Enable exwm-mff debugging, and show the buffer with debug logs." + (interactive) + (setq exwm-mff--debug 1) + (pop-to-buffer (get-buffer-create exwm-mff--debug-buffer))) + +(defun exwm-mff--window-center (window) + "Return a list of (x y) coordinates of the center of WINDOW in FRAME." + (cl-destructuring-bind (left top right bottom) (window-pixel-edges window) + (list (+ left (/ (- right left) 2)) + (+ top (/ (- bottom top) 2))))) + +(defun exwm-mff-warp-to (frame window) + "Place the pointer in the center of WINDOW in FRAME." + (apply #'set-mouse-pixel-position frame + (exwm-mff--window-center window))) + +;;;###autoload +(defun exwm-mff-warp-to-selected () + "Place the pointer in the center of the selected window." + (interactive) + (exwm-mff--guard) + (exwm-mff-warp-to (selected-frame) (selected-window))) + +(defun exwm-mff--explain (selected-window same-window? contains-pointer? mini? ignored?) + "Use SELECTED-WINDOW, SAME-WINDOW?, CONTAINS-POINTER?, MINI? +and IGNORED? to return an explanation of focusing behavior." + (cond + (same-window? "selected window hasn't changed") + (contains-pointer? "already contains pointer") + (mini? "is minibuffer") + (ignored? "one or more functions in `exwm-mff-ignore-if' matches") + (t (format "doesn't contain pointer (in %s)" selected-window)))) + +(defun exwm-mff-hook (sw &optional norecord) + "EXWM-MFF-MODE hook. + +This is after-advice placed on SELECT-WINDOW. It moves the +pointer to SW (the currently selected window), if NORECORD is +nil, and if it's not already in it." + (unless norecord + (if-let ((same-window? (eq sw exwm-mff--last-window))) + ;; The selected window is unchanged, we don't need to check + ;; anything else. + (exwm-mff--debug + "nop-> %s" (exwm-mff--explain sw same-window? nil nil nil)) + + (let* ((sf (window-frame sw)) + (contains-pointer? (exwm-mff--contains-pointer? sw)) + (mini? (minibufferp (window-buffer sw))) + (ignore? (run-hook-with-args-until-success 'exwm-mff-ignore-if sw))) + (if (or same-window? contains-pointer? mini? ignore?) + (exwm-mff--debug + "nop-> %s::%s (%s)" sf sw (exwm-mff--explain sw nil contains-pointer? mini? ignore?)) + (exwm-mff--debug + "warp-> %s::%s (%s)" sf sw (exwm-mff--explain sw nil contains-pointer? mini? ignore?)) + (exwm-mff-warp-to sf (setq exwm-mff--last-window sw))))))) + +(defgroup exwm-mff nil + "Mouse-Follows-Focus mode for EXWM." + :group 'exwm) + +;;;###autoload +(define-minor-mode exwm-mff-mode + "Mouse follows focus mode for EXWM." + :global t + :require 'exwm-mff + :group 'exwm-mff + (exwm-mff--guard) + (if exwm-mff-mode + (advice-add 'select-window :after #'exwm-mff-hook) + (advice-remove 'select-window #'exwm-mff-hook))) + +(provide 'exwm-mff) + +;;; exwm-mff.el ends here diff --git a/home/dots/.emacs.d/elisp/org-link-minor-mode.el b/home/dots/.emacs.d/elisp/org-link-minor-mode.el new file mode 100644 index 0000000..7f1faaa --- /dev/null +++ b/home/dots/.emacs.d/elisp/org-link-minor-mode.el @@ -0,0 +1,137 @@ +;;; org-link-minor-mode.el --- Enable org-mode links in non-org modes -*- lexical-binding: t; -*- +;; +;; Copyright (C) 2012-2020 +;; +;; Author: Sean O'Halpin <sean.ohalpin@gmail.com> +;; Maintainer: Sean O'Halpin <sean.ohalpin@gmail.com> +;; Created: 20120825 +;; Modified: 20200129 +;; Version: 0.0.3 +;; Package-Requires: ((emacs "24.3")) +;; Package-Version: 20200129.0141 +;; Keywords: hypermedia +;; Url: https://github.com/seanohalpin/org-link-minor-mode +;; +;; Changes for org v9: Stefan-W. Hahn <stefan dot hahn at s-hahn dot de> +;; +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;; +;;; Commentary: +;; +;; Enables org-mode links of the form: +;; +;; http://www.bbc.co.uk +;; man:emacs +;; info:emacs +;; <http://www.bbc.co.uk> +;; [[http://www.bbc.co.uk][BBC]] +;; [[org-link-minor-mode]] +;; [2012-08-18] +;; <2012-08-18> +;; +;; Note that `org-toggle-link-display' will also work when this mode +;; is enabled. +;; +;;; Code: + +(require 'org-element) + +;; Following declarations are necessary to make the byte compiler happy. + +;; For org v8 compatibility (if used with org v9) +(declare-function org-activate-plain-links "org" (limit)) +(declare-function org-activate-angle-links "org" (limit)) +(declare-function org-activate-bracket-links "org" (limit)) +(declare-function org-decompose-region "org-compat" (beg end)) + +;; For org v9 compatibility (if used with org v8) +(declare-function org-activate-links "org" (limit)) +(declare-function org-activate-dates "org" (limit)) + +(defun org-link-minor-mode--unfontify-region (beg end) + "Remove org-link fontification between BEG and END." + (font-lock-default-unfontify-region beg end) + (let* ((buffer-undo-list t) + (inhibit-read-only t) (inhibit-point-motion-hooks t) + (inhibit-modification-hooks t) + deactivate-mark buffer-file-name buffer-file-truename) + (if (fboundp 'org-decompose-region) + (org-decompose-region beg end) + (decompose-region beg end)) + (remove-text-properties beg end + '(mouse-face t keymap t org-linked-text t + invisible t intangible t + help-echo t rear-nonsticky t + htmlize-link t + org-no-flyspell t org-emphasis t)) + (org-remove-font-lock-display-properties beg end))) + +(defvar org-link-minor-mode-map (make-sparse-keymap) + "Local keymap.") +(make-variable-buffer-local 'org-link-minor-mode-map) + +;;;###autoload +(define-minor-mode org-link-minor-mode + "Toggle display of org-mode style links in non-org-mode buffers." + :lighter " org-link" + :keymap org-link-minor-mode-map + (let ((lk org-highlight-links) + org-link-minor-mode-keywords) + (if (fboundp 'org-activate-links) + ;; from Org v9.2 + (setq org-link-minor-mode-keywords + (list + '(org-activate-links) + (when (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend))) + (when (memq 'radio lk) '(org-activate-target-links (1 'org-link t))) + (when (memq 'date lk) '(org-activate-dates (0 'org-date t))) + (when (memq 'footnote lk) '(org-activate-footnote-links)))) + (setq org-link-minor-mode-keywords + (list + (when (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend))) + (when (memq 'angle lk) '(org-activate-angle-links (0 'org-link t))) + (when (memq 'plain lk) '(org-activate-plain-links (0 'org-link t))) + (when (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t))) + (when (memq 'radio lk) '(org-activate-target-links (0 'org-link t))) + (when (memq 'date lk) '(org-activate-dates (0 'org-date t))) + (when (memq 'footnote lk) '(org-activate-footnote-links))))) + (if org-link-minor-mode + (if (derived-mode-p 'org-mode) + (progn + (message "org-mode doesn't need org-link-minor-mode") + (org-link-minor-mode -1)) + (font-lock-add-keywords nil org-link-minor-mode-keywords t) + (kill-local-variable 'org-mouse-map) + (setq-local org-mouse-map + (let ((map (make-sparse-keymap))) + (define-key map [return] 'org-open-at-point) + (define-key map [tab] 'org-next-link) + (define-key map [backtab] 'org-previous-link) + (define-key map [mouse-2] 'org-open-at-point) + (define-key map [follow-link] 'mouse-face) + map)) + (setq-local font-lock-unfontify-region-function + 'org-link-minor-mode--unfontify-region) + (setq-local org-descriptive-links nil) + (org-toggle-link-display)) + (unless (derived-mode-p 'org-mode) + (font-lock-remove-keywords nil org-link-minor-mode-keywords) + (setq org-descriptive-links t) + (org-toggle-link-display) + (kill-local-variable 'org-descriptive-links) + (kill-local-variable 'org-mouse-map) + (kill-local-variable 'font-lock-unfontify-region-function))))) + +(provide 'org-link-minor-mode) +;;; org-link-minor-mode.el ends here diff --git a/home/dots/.emacs.d/snippets/go-mode/errnotnil b/home/dots/.emacs.d/snippets/go-mode/errnotnil new file mode 100644 index 0000000..0122e56 --- /dev/null +++ b/home/dots/.emacs.d/snippets/go-mode/errnotnil @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: err not nil +# key: ; +# -- +; err != nil
\ No newline at end of file diff --git a/home/dots/.emacs.d/snippets/go-mode/error b/home/dots/.emacs.d/snippets/go-mode/error new file mode 100644 index 0000000..799e9f8 --- /dev/null +++ b/home/dots/.emacs.d/snippets/go-mode/error @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: error +# key: err@ +# -- +if err != nil { + $0 +} diff --git a/home/dots/.emacs.d/snippets/mhtml-mode/<div>..</div>~ b/home/dots/.emacs.d/snippets/mhtml-mode/<div>..</div>~ new file mode 100644 index 0000000..028d782 --- /dev/null +++ b/home/dots/.emacs.d/snippets/mhtml-mode/<div>..</div>~ @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: <div>..</div> +# key: <div +# -- +<div> + $1 +</div> diff --git a/home/dots/.gitconfig b/home/dots/.gitconfig new file mode 100644 index 0000000..99a675c --- /dev/null +++ b/home/dots/.gitconfig @@ -0,0 +1,49 @@ +[alias] + pr = "!gh pr" + issue = "!gh issue" + bug = "!git-bug" +[user] + email = marc@mccd.space + name = Marc Coquand +[credential "https://github.com"] + helper = !gh auth git-credential +[credential "https://gist.github.com"] + helper = !gh auth git-credential +[credential "smtp://marcc%40fastmail.fr@smtp.fastmail.com%3a465"] + helper = + helper = !pass 'fastmail/git' +[color] + ui = false +[merge] + tool = meld +[mergetool] + layout = LOCAL,MERGED,REMOTE +[sendemail] + smtpserver = smtp.fastmail.com + smtpuser = marcc@fastmail.fr + smtpencryption = ssl + smtpserverport = 465 +[pull] + rebase = true +[color "diff"] + meta = blue + old = red + new = green +[log] + date = relative +[format] + pretty = oneline + signoff = true +[credential] + helper = store +[push] + autoSetupRemote = true +[commit] + gpgsign = true + verbose = true +[init] + defaultBranch = main +[grep] + lineNumber = true +[help] + autocorrect = prompt diff --git a/home/dots/.local/bin/capture b/home/dots/.local/bin/capture new file mode 100755 index 0000000..c4cd844 --- /dev/null +++ b/home/dots/.local/bin/capture @@ -0,0 +1,16 @@ +#!/bin/sh + +DATE=$(date +'%y-%m-%d.%H:%M.%S') +CAPTURE_FILE="/tmp/capture-$DATE" +echo $DATE +JRNL="$STITCH_DIRECTORY/$DATE.org" +echo '* ' > $CAPTURE_FILE +$EDITOR $CAPTURE_FILE +1 +if grep -q '^\*\s*$' $CAPTURE_FILE +then + echo "Empty capture; ignoring" +else + echo "Storing capture in $JRNL" + cat $CAPTURE_FILE > $JRNL +fi + diff --git a/home/dots/.local/bin/convert-website b/home/dots/.local/bin/convert-website new file mode 100755 index 0000000..2b951d7 --- /dev/null +++ b/home/dots/.local/bin/convert-website @@ -0,0 +1,5 @@ +#!/bin/env sh +for file in $* +do + pandoc $file --from html --to markdown_strict | NO_COLOR=true lowdown -tterm -o "$file.md" +done diff --git a/home/dots/.local/bin/logdate b/home/dots/.local/bin/logdate new file mode 100755 index 0000000..337552a --- /dev/null +++ b/home/dots/.local/bin/logdate @@ -0,0 +1,2 @@ +#!/bin/env sh +date +"%Y-%m-%d" diff --git a/home/dots/.local/bin/nextcloud-sync b/home/dots/.local/bin/nextcloud-sync new file mode 100755 index 0000000..cb7901a --- /dev/null +++ b/home/dots/.local/bin/nextcloud-sync @@ -0,0 +1,5 @@ +#!/bin/env sh + +/usr/bin/rclone bisync storage.mccd.space:personal-db ~/personal-db +/usr/bin/rclone bisync storage.mccd.space:Articles ~/docs +/usr/bin/rclone bisync storage.mccd.space:Shared ~/shared diff --git a/home/dots/.local/bin/org-sync b/home/dots/.local/bin/org-sync new file mode 100755 index 0000000..47474e6 --- /dev/null +++ b/home/dots/.local/bin/org-sync @@ -0,0 +1,11 @@ +#!/usr/bin/env sh + +IS_CONNECTED=$(nmcli | grep -e ^wlp610s0) + +if $(echo $IS_CONNECTED | grep -q "disconnected") +then + echo "System is not connected to Wifi. Will not sync"; +else + /usr/bin/env rclone bisync storage:personal-db ~/personal-db; + echo "Sync complete"; +fi diff --git a/home/dots/.local/bin/pfetch b/home/dots/.local/bin/pfetch new file mode 100755 index 0000000..bfc58b6 --- /dev/null +++ b/home/dots/.local/bin/pfetch @@ -0,0 +1,1956 @@ +#!/bin/sh +# +# pfetch - Simple POSIX sh fetch script. + +# Wrapper around all escape sequences used by pfetch to allow for +# greater control over which sequences are used (if any at all). +esc() { + case $1 in + CUU) e="${esc_c}[${2}A" ;; # cursor up + CUD) e="${esc_c}[${2}B" ;; # cursor down + CUF) e="${esc_c}[${2}C" ;; # cursor right + CUB) e="${esc_c}[${2}D" ;; # cursor left + + # text formatting + SGR) + case ${PF_COLOR:=1} in + (1) + e="${esc_c}[${2}m" + ;; + + (0) + # colors disabled + e= + ;; + esac + ;; + + # line wrap + DECAWM) + case $TERM in + (dumb | minix | cons25) + # not supported + e= + ;; + + (*) + e="${esc_c}[?7${2}" + ;; + esac + ;; + esac +} + +# Print a sequence to the terminal. +esc_p() { + esc "$@" + printf '%s' "$e" +} + +# This is just a simple wrapper around 'command -v' to avoid +# spamming '>/dev/null' throughout this function. This also guards +# against aliases and functions. +has() { + _cmd=$(command -v "$1") 2>/dev/null || return 1 + [ -x "$_cmd" ] || return 1 +} + +log() { + # The 'log()' function handles the printing of information. + # In 'pfetch' (and 'neofetch'!) the printing of the ascii art and info + # happen independently of each other. + # + # The size of the ascii art is stored and the ascii is printed first. + # Once the ascii is printed, the cursor is located right below the art + # (See marker $[1]). + # + # Using the stored ascii size, the cursor is then moved to marker $[2]. + # This is simply a cursor up escape sequence using the "height" of the + # ascii art. + # + # 'log()' then moves the cursor to the right the "width" of the ascii art + # with an additional amount of padding to add a gap between the art and + # the information (See marker $[3]). + # + # When 'log()' has executed, the cursor is then located at marker $[4]. + # When 'log()' is run a second time, the next line of information is + # printed, moving the cursor to marker $[5]. + # + # Markers $[4] and $[5] repeat all the way down through the ascii art + # until there is no more information left to print. + # + # Every time 'log()' is called the script keeps track of how many lines + # were printed. When printing is complete the cursor is then manually + # placed below the information and the art according to the "heights" + # of both. + # + # The math is simple: move cursor down $((ascii_height - info_height)). + # If the aim is to move the cursor from marker $[5] to marker $[6], + # plus the ascii height is 8 while the info height is 2 it'd be a move + # of 6 lines downwards. + # + # However, if the information printed is "taller" (takes up more lines) + # than the ascii art, the cursor isn't moved at all! + # + # Once the cursor is at marker $[6], the script exits. This is the gist + # of how this "dynamic" printing and layout works. + # + # This method allows ascii art to be stored without markers for info + # and it allows for easy swapping of info order and amount. + # + # $[2] ___ $[3] goldie@KISS + # $[4](.ยท | $[5] os KISS Linux + # (<> | + # / __ \ + # ( / \ /| + # _/\ __)/_) + # \/-____\/ + # $[1] + # + # $[6] /home/goldie $ + + # End here if no data was found. + [ "$2" ] || return + + # Store the values of '$1' and '$3' as we reset the argument list below. + name=$1 + use_seperator=$3 + + # Use 'set --' as a means of stripping all leading and trailing + # white-space from the info string. This also normalizes all + # white-space inside of the string. + # + # Disable the shellcheck warning for word-splitting + # as it's safe and intended ('set -f' disables globbing). + # shellcheck disable=2046,2086 + { + set -f + set +f -- $2 + info=$* + } + + # Move the cursor to the right, the width of the ascii art with an + # additional gap for text spacing. + esc_p CUF "$ascii_width" + + # Print the info name and color the text. + esc_p SGR "3${PF_COL1-4}"; + esc_p SGR 1 + printf '%s' "$name" + esc_p SGR 0 + + # Print the info name and info data separator, if applicable. + [ "$use_seperator" ] || printf %s "$PF_SEP" + + # Move the cursor backward the length of the *current* info name and + # then move it forwards the length of the *longest* info name. This + # aligns each info data line. + esc_p CUB "${#name}" + esc_p CUF "${PF_ALIGN:-$info_length}" + + # Print the info data, color it and strip all leading whitespace + # from the string. + esc_p SGR "3${PF_COL2-9}" + printf '%s' "$info" + esc_p SGR 0 + printf '\n' + + # Keep track of the number of times 'log()' has been run. + info_height=$((${info_height:-0} + 1)) +} + +get_title() { + # Username is retrieved by first checking '$USER' with a fallback + # to the 'id -un' command. + user=${USER:-$(id -un)} + + # Hostname is retrieved by first checking '$HOSTNAME' with a fallback + # to the 'hostname' command. + # + # Disable the warning about '$HOSTNAME' being undefined in POSIX sh as + # the intention for using it is allowing the user to overwrite the + # value on invocation. + # shellcheck disable=3028,2039 + hostname=${HOSTNAME:-${hostname:-$(hostname)}} + + # If the hostname is still not found, fallback to the contents of the + # /etc/hostname file. + [ "$hostname" ] || read -r hostname < /etc/hostname + + # Add escape sequences for coloring to user and host name. As we embed + # them directly in the arguments passed to log(), we cannot use esc_p(). + esc SGR 1 + user=$e$user + esc SGR "3${PF_COL3:-1}" + user=$e$user + esc SGR 1 + user=$user$e + esc SGR 1 + hostname=$e$hostname + esc SGR "3${PF_COL3:-1}" + hostname=$e$hostname + + log "${user}@${hostname}" " " " " >&6 +} + +get_os() { + # This function is called twice, once to detect the distribution name + # for the purposes of picking an ascii art early and secondly to display + # the distribution name in the info output (if enabled). + # + # On first run, this function displays _nothing_, only on the second + # invocation is 'log()' called. + [ "$distro" ] && { + log os "$distro" >&6 + return + } + + case $os in + (Linux*) + # Some Linux distributions (which are based on others) + # fail to identify as they **do not** change the upstream + # distribution's identification packages or files. + # + # It is senseless to add a special case in the code for + # each and every distribution (which _is_ technically no + # different from what it is based on) as they're either too + # lazy to modify upstream's identification files or they + # don't have the know-how (or means) to ship their own + # lsb-release package. + # + # This causes users to think there's a bug in system detection + # tools like neofetch or pfetch when they technically *do* + # function correctly. + # + # Exceptions are made for distributions which are independent, + # not based on another distribution or follow different + # standards. + # + # This applies only to distributions which follow the standard + # by shipping unmodified identification files and packages + # from their respective upstreams. + if has lsb_release; then + distro=$(lsb_release -sd) + + # Android detection works by checking for the existence of + # the follow two directories. I don't think there's a simpler + # method than this. + elif [ -d /system/app ] && [ -d /system/priv-app ]; then + distro="Android $(getprop ro.build.version.release)" + + elif [ -f /etc/os-release ]; then + # This used to be a simple '. /etc/os-release' but I believe + # this is insecure as we blindly executed whatever was in the + # file. This parser instead simply handles 'key=val', treating + # the file contents as plain-text. + while IFS='=' read -r key val; do + case $key in + (NAME) + distro="$(echo $val | tr '[:upper:]' '[:lower:]')" + ;; + esac + done < /etc/os-release + + else + # Special cases for (independent) distributions which + # don't follow any os-release/lsb standards whatsoever. + has crux && distro=$(crux) + has guix && distro='Guix System' + fi + + # 'os-release' and 'lsb_release' sometimes add quotes + # around the distribution name, strip them. + distro=${distro##[\"\']} + distro=${distro%%[\"\']} + + # Check to see if we're running Bedrock Linux which is + # very unique. This simply checks to see if the user's + # PATH contains a Bedrock specific value. + case $PATH in + (*/bedrock/cross/*) + distro='Bedrock Linux' + ;; + esac + + # Check to see if Linux is running in Windows 10 under + # WSL1 (Windows subsystem for Linux [version 1]) and + # append a string accordingly. + # + # If the kernel version string ends in "-Microsoft", + # we're very likely running under Windows 10 in WSL1. + if [ "$WSLENV" ]; then + distro="${distro}${WSLENV+ on Windows 10 [WSL2]}" + + # Check to see if Linux is running in Windows 10 under + # WSL2 (Windows subsystem for Linux [version 2]) and + # append a string accordingly. + # + # This checks to see if '$WSLENV' is defined. This + # appends the Windows 10 string even if '$WSLENV' is + # empty. We only need to check that is has been _exported_. + elif [ -z "${kernel%%*-Microsoft}" ]; then + distro="$distro on Windows 10 [WSL1]" + fi + ;; + + (Darwin*) + # Parse the SystemVersion.plist file to grab the macOS + # version. The file is in the following format: + # + # <key>ProductVersion</key> + # <string>10.14.6</string> + # + # 'IFS' is set to '<>' to enable splitting between the + # keys and a second 'read' is used to operate on the + # next line directly after a match. + # + # '_' is used to nullify a field. '_ _ line _' basically + # says "populate $line with the third field's contents". + while IFS='<>' read -r _ _ line _; do + case $line in + # Match 'ProductVersion' and read the next line + # directly as it contains the key's value. + ProductVersion) + IFS='<>' read -r _ _ mac_version _ + continue + ;; + + ProductName) + IFS='<>' read -r _ _ mac_product _ + continue + ;; + esac + done < /System/Library/CoreServices/SystemVersion.plist + + # Use the ProductVersion to determine which macOS/OS X codename + # the system has. As far as I'm aware there's no "dynamic" way + # of grabbing this information. + case $mac_version in + (10.4*) distro='Mac OS X Tiger' ;; + (10.5*) distro='Mac OS X Leopard' ;; + (10.6*) distro='Mac OS X Snow Leopard' ;; + (10.7*) distro='Mac OS X Lion' ;; + (10.8*) distro='OS X Mountain Lion' ;; + (10.9*) distro='OS X Mavericks' ;; + (10.10*) distro='OS X Yosemite' ;; + (10.11*) distro='OS X El Capitan' ;; + (10.12*) distro='macOS Sierra' ;; + (10.13*) distro='macOS High Sierra' ;; + (10.14*) distro='macOS Mojave' ;; + (10.15*) distro='macOS Catalina' ;; + (11*) distro='macOS Big Sur' ;; + (12*) distro='macOS Monterey' ;; + (*) distro='macOS' ;; + esac + + # Use the ProductName to determine if we're running in iOS. + case $mac_product in + (iP*) distro='iOS' ;; + esac + + distro="$distro $mac_version" + ;; + + (Haiku) + # Haiku uses 'uname -v' for version information + # instead of 'uname -r' which only prints '1'. + distro=$(uname -sv) + ;; + + (Minix|DragonFly) + distro="$os $kernel" + + # Minix and DragonFly don't support the escape + # sequences used, clear the exit trap. + trap '' EXIT + ;; + + (SunOS) + # Grab the first line of the '/etc/release' file + # discarding everything after '('. + IFS='(' read -r distro _ < /etc/release + ;; + + (OpenBSD*) + # Show the OpenBSD version type (current if present). + # kern.version=OpenBSD 6.6-current (GENERIC.MP) ... + IFS=' =' read -r _ distro openbsd_ver _ <<-EOF + $(sysctl kern.version) + EOF + + distro="$distro $openbsd_ver" + ;; + + (FreeBSD) + distro="$(echo $os | tr '[:upper:]' '[:lower:]')" + ;; + + (*) + # Catch all to ensure '$distro' is never blank. + # This also handles the BSDs. + distro="$os $kernel" + ;; + esac +} + +get_kernel() { + case $os in + # Don't print kernel output on some systems as the + # OS name includes it. + (*BSD*|Haiku|Minix) + return + ;; + esac + + # '$kernel' is the cached output of 'uname -r'. + log kernel "$kernel" >&6 +} + +get_host() { + case $os in + (Linux*) + # Despite what these files are called, version doesn't + # always contain the version nor does name always contain + # the name. + read -r name < /sys/devices/virtual/dmi/id/product_name + read -r version < /sys/devices/virtual/dmi/id/product_version + read -r model < /sys/firmware/devicetree/base/model + + host="$name $version $model" + ;; + + (Darwin* | FreeBSD* | DragonFly*) + host=$(sysctl -n hw.model) + ;; + + (NetBSD*) + host=$(sysctl -n machdep.dmi.system-vendor \ + machdep.dmi.system-product) + ;; + + (OpenBSD*) + host=$(sysctl -n hw.version) + ;; + + (*BSD* | Minix) + host=$(sysctl -n hw.vendor hw.product) + ;; + esac + + # Turn the host string into an argument list so we can iterate + # over it and remove OEM strings and other information which + # shouldn't be displayed. + # + # Disable the shellcheck warning for word-splitting + # as it's safe and intended ('set -f' disables globbing). + # shellcheck disable=2046,2086 + { + set -f + set +f -- $host + host= + } + + # Iterate over the host string word by word as a means of stripping + # unwanted and OEM information from the string as a whole. + # + # This could have been implemented using a long 'sed' command with + # a list of word replacements, however I want to show that something + # like this is possible in pure sh. + # + # This string reconstruction is needed as some OEMs either leave the + # identification information as "To be filled by OEM", "Default", + # "undefined" etc and we shouldn't print this to the screen. + for word do + # This works by reconstructing the string by excluding words + # found in the "blacklist" below. Only non-matches are appended + # to the final host string. + case $word in + (To | [Bb]e | [Ff]illed | [Bb]y | O.E.M. | OEM |\ + Not | Applicable | Specified | System | Product | Name |\ + Version | Undefined | Default | string | INVALID | ๏ฟฝ | os |\ + Type1ProductConfigId ) + continue + ;; + esac + + host="$host$word " + done + + # '$arch' is the cached output from 'uname -m'. + log host "${host:-$arch}" >&6 +} + +get_uptime() { + # Uptime works by retrieving the data in total seconds and then + # converting that data into days, hours and minutes using simple + # math. + case $os in + (Linux* | Minix* | SerenityOS*) + IFS=. read -r s _ < /proc/uptime + ;; + + (Darwin* | *BSD* | DragonFly*) + s=$(sysctl -n kern.boottime) + + # Extract the uptime in seconds from the following output: + # [...] { sec = 1271934886, usec = 667779 } Thu Apr 22 12:14:46 2010 + s=${s#*=} + s=${s%,*} + + # The uptime format from 'sysctl' needs to be subtracted from + # the current time in seconds. + s=$(($(date +%s) - s)) + ;; + + (Haiku) + # The boot time is returned in microseconds, convert it to + # regular seconds. + s=$(($(system_time) / 1000000)) + ;; + + (SunOS) + # Split the output of 'kstat' on '.' and any white-space + # which exists in the command output. + # + # The output is as follows: + # unix:0:system_misc:snaptime 14809.906993005 + # + # The parser extracts: ^^^^^ + IFS=' .' read -r _ s _ <<-EOF + $(kstat -p unix:0:system_misc:snaptime) + EOF + ;; + + (IRIX) + # Grab the uptime in a pretty format. Usually, + # 00:00:00 from the 'ps' command. + t=$(LC_ALL=POSIX ps -o etime= -p 1) + + # Split the pretty output into days or hours + # based on the uptime. + case $t in + (*-*) d=${t%%-*} t=${t#*-} ;; + (*:*:*) h=${t%%:*} t=${t#*:} ;; + esac + + h=${h#0} t=${t#0} + + # Convert the split pretty fields back into + # seconds so we may re-convert them to our format. + s=$((${d:-0}*86400 + ${h:-0}*3600 + ${t%%:*}*60 + ${t#*:})) + ;; + esac + + # Convert the uptime from seconds into days, hours and minutes. + d=$((s / 60 / 60 / 24)) + h=$((s / 60 / 60 % 24)) + m=$((s / 60 % 60)) + + # Only append days, hours and minutes if they're non-zero. + case "$d" in ([!0]*) uptime="${uptime}${d}d "; esac + case "$h" in ([!0]*) uptime="${uptime}${h}h "; esac + case "$m" in ([!0]*) uptime="${uptime}${m}m "; esac + + log uptime "${uptime:-0m}" >&6 +} + +get_pkgs() { + # This works by first checking for which package managers are + # installed and finally by printing each package manager's + # package list with each package one per line. + # + # The output from this is then piped to 'wc -l' to count each + # line, giving us the total package count of whatever package + # managers are installed. + packages=$( + case $os in + (Linux*) + # Commands which print packages one per line. + has bonsai && bonsai list + has crux && pkginfo -i + has pacman-key && pacman -Qq + has dpkg && dpkg-query -f '.\n' -W + has rpm && rpm -qa + has xbps-query && xbps-query -l + has apk && apk info + has guix && guix package --list-installed + has opkg && opkg list-installed + + # Directories containing packages. + has kiss && printf '%s\n' /var/db/kiss/installed/*/ + has cpt-list && printf '%s\n' /var/db/cpt/installed/*/ + has brew && printf '%s\n' "$(brew --cellar)/"* + has emerge && printf '%s\n' /var/db/pkg/*/*/ + has pkgtool && printf '%s\n' /var/log/packages/* + has eopkg && printf '%s\n' /var/lib/eopkg/package/* + + # 'nix' requires two commands. + has nix-store && { + nix-store -q --requisites /run/current-system/sw + nix-store -q --requisites ~/.nix-profile + } + ;; + + (Darwin*) + # Commands which print packages one per line. + has pkgin && pkgin list + has dpkg && dpkg-query -f '.\n' -W + + # Directories containing packages. + has brew && printf '%s\n' /usr/local/Cellar/* + + # 'port' prints a single line of output to 'stdout' + # when no packages are installed and exits with + # success causing a false-positive of 1 package + # installed. + # + # 'port' should really exit with a non-zero code + # in this case to allow scripts to cleanly handle + # this behavior. + has port && { + pkg_list=$(port installed) + + case "$pkg_list" in + ("No ports are installed.") + # do nothing + ;; + + (*) + printf '%s\n' "$pkg_list" + ;; + esac + } + ;; + + (FreeBSD*|DragonFly*) + pkg info + ;; + + (OpenBSD*) + printf '%s\n' /var/db/pkg/*/ + ;; + + (NetBSD*) + pkg_info + ;; + + (Haiku) + printf '%s\n' /boot/system/package-links/* + ;; + + (Minix) + printf '%s\n' /usr/pkg/var/db/pkg/*/ + ;; + + (SunOS) + has pkginfo && pkginfo -i + has pkg && pkg list + ;; + + (IRIX) + versions -b + ;; + + (SerenityOS) + while IFS=" " read -r type _; do + [ "$type" != dependency ] && + printf "\n" + done < /usr/Ports/packages.db + ;; + esac | wc -l + ) + + # 'wc -l' can have leading and/or trailing whitespace + # depending on the implementation, so strip them. + # Procedure explained at https://github.com/dylanaraps/pure-sh-bible + # (trim-leading-and-trailing-white-space-from-string) + packages=${packages#"${packages%%[![:space:]]*}"} + packages=${packages%"${packages##*[![:space:]]}"} + + case $os in + # IRIX's package manager adds 3 lines of extra + # output which we must account for here. + (IRIX) + packages=$((packages - 3)) + ;; + + # OpenBSD's wc prints whitespace before the output + # which needs to be stripped. + (OpenBSD) + packages=$((packages)) + ;; + esac + + case $packages in + (1?*|[2-9]*) + log pkgs "$packages" >&6 + ;; + esac +} + +get_memory() { + case $os in + # Used memory is calculated using the following "formula": + # MemUsed = MemTotal + Shmem - MemFree - Buffers - Cached - SReclaimable + # Source: https://github.com/KittyKatt/screenFetch/issues/386 + (Linux*) + # Parse the '/proc/meminfo' file splitting on ':' and 'k'. + # The format of the file is 'key: 000kB' and an additional + # split is used on 'k' to filter out 'kB'. + while IFS=':k ' read -r key val _; do + case $key in + (MemTotal) + mem_used=$((mem_used + val)) + mem_full=$val + ;; + + (Shmem) + mem_used=$((mem_used + val)) + ;; + + (MemFree | Buffers | Cached | SReclaimable) + mem_used=$((mem_used - val)) + ;; + + # If detected this will be used over the above calculation + # for mem_used. Available since Linux 3.14rc. + # See kernel commit 34e431b0ae398fc54ea69ff85ec700722c9da773 + (MemAvailable) + mem_avail=$val + ;; + esac + done < /proc/meminfo + + case $mem_avail in + (*[0-9]*) + mem_used=$(((mem_full - mem_avail) / 1024)) + ;; + + *) + mem_used=$((mem_used / 1024)) + ;; + esac + + mem_full=$((mem_full / 1024)) + ;; + + # Used memory is calculated using the following "formula": + # (wired + active + occupied) * 4 / 1024 + (Darwin*) + mem_full=$(($(sysctl -n hw.memsize) / 1024 / 1024)) + + # Parse the 'vmstat' file splitting on ':' and '.'. + # The format of the file is 'key: 000.' and an additional + # split is used on '.' to filter it out. + while IFS=:. read -r key val; do + case $key in + (*' wired'*|*' active'*|*' occupied'*) + mem_used=$((mem_used + ${val:-0})) + ;; + esac + + # Using '<<-EOF' is the only way to loop over a command's + # output without the use of a pipe ('|'). + # This ensures that any variables defined in the while loop + # are still accessible in the script. + done <<-EOF + $(vm_stat) + EOF + + mem_used=$((mem_used * 4 / 1024)) + ;; + + (OpenBSD*) + mem_full=$(($(sysctl -n hw.physmem) / 1024 / 1024)) + + # This is a really simpler parser for 'vmstat' which grabs + # the used memory amount in a lazy way. 'vmstat' prints 3 + # lines of output with the needed value being stored in the + # final line. + # + # This loop simply grabs the 3rd element of each line until + # the EOF is reached. Each line overwrites the value of the + # previous one so we're left with what we wanted. This isn't + # slow as only 3 lines are parsed. + while read -r _ _ line _; do + mem_used=${line%%M} + + # Using '<<-EOF' is the only way to loop over a command's + # output without the use of a pipe ('|'). + # This ensures that any variables defined in the while loop + # are still accessible in the script. + done <<-EOF + $(vmstat) + EOF + ;; + + # Used memory is calculated using the following "formula": + # mem_full - ((inactive + free + cache) * page_size / 1024) + (FreeBSD*|DragonFly*) + mem_full=$(($(sysctl -n hw.physmem) / 1024 / 1024)) + + # Use 'set --' to store the output of the command in the + # argument list. POSIX sh has no arrays but this is close enough. + # + # Disable the shellcheck warning for word-splitting + # as it's safe and intended ('set -f' disables globbing). + # shellcheck disable=2046 + { + set -f + set +f -- $(sysctl -n hw.pagesize \ + vm.stats.vm.v_inactive_count \ + vm.stats.vm.v_free_count \ + vm.stats.vm.v_cache_count) + } + + # Calculate the amount of used memory. + # $1: hw.pagesize + # $2: vm.stats.vm.v_inactive_count + # $3: vm.stats.vm.v_free_count + # $4: vm.stats.vm.v_cache_count + mem_used=$((mem_full - (($2 + $3 + $4) * $1 / 1024 / 1024))) + ;; + + (NetBSD*) + mem_full=$(($(sysctl -n hw.physmem64) / 1024 / 1024)) + + # NetBSD implements a lot of the Linux '/proc' filesystem, + # this uses the same parser as the Linux memory detection. + while IFS=':k ' read -r key val _; do + case $key in + (MemFree) + mem_free=$((val / 1024)) + break + ;; + esac + done < /proc/meminfo + + mem_used=$((mem_full - mem_free)) + ;; + + (Haiku) + # Read the first line of 'sysinfo -mem' splitting on + # '(', ' ', and ')'. The needed information is then + # stored in the 5th and 7th elements. Using '_' "consumes" + # an element allowing us to proceed to the next one. + # + # The parsed format is as follows: + # 3501142016 bytes free (used/max 792645632 / 4293787648) + IFS='( )' read -r _ _ _ _ mem_used _ mem_full <<-EOF + $(sysinfo -mem) + EOF + + mem_used=$((mem_used / 1024 / 1024)) + mem_full=$((mem_full / 1024 / 1024)) + ;; + + (Minix) + # Minix includes the '/proc' filesystem though the format + # differs from Linux. The '/proc/meminfo' file is only a + # single line with space separated elements and elements + # 2 and 3 contain the total and free memory numbers. + read -r _ mem_full mem_free _ < /proc/meminfo + + mem_used=$(((mem_full - mem_free) / 1024)) + mem_full=$(( mem_full / 1024)) + ;; + + (SunOS) + hw_pagesize=$(pagesize) + + # 'kstat' outputs memory in the following format: + # unix:0:system_pages:pagestotal 1046397 + # unix:0:system_pages:pagesfree 885018 + # + # This simply uses the first "element" (white-space + # separated) as the key and the second element as the + # value. + # + # A variable is then assigned based on the key. + while read -r key val; do + case $key in + (*total) + pages_full=$val + ;; + + (*free) + pages_free=$val + ;; + esac + done <<-EOF + $(kstat -p unix:0:system_pages:pagestotal \ + unix:0:system_pages:pagesfree) + EOF + + mem_full=$((pages_full * hw_pagesize / 1024 / 1024)) + mem_free=$((pages_free * hw_pagesize / 1024 / 1024)) + mem_used=$((mem_full - mem_free)) + ;; + + (IRIX) + # Read the memory information from the 'top' command. Parse + # and split each line until we reach the line starting with + # "Memory". + # + # Example output: Memory: 160M max, 147M avail, ..... + while IFS=' :' read -r label mem_full _ mem_free _; do + case $label in + (Memory) + mem_full=${mem_full%M} + mem_free=${mem_free%M} + break + ;; + esac + done <<-EOF + $(top -n) + EOF + + mem_used=$((mem_full - mem_free)) + ;; + + (SerenityOS) + IFS='{}' read -r _ memstat _ < /proc/memstat + + set -f -- "$IFS" + IFS=, + + for pair in $memstat; do + case $pair in + (*user_physical_allocated*) + mem_used=${pair##*:} + ;; + + (*user_physical_available*) + mem_free=${pair##*:} + ;; + esac + done + + IFS=$1 + set +f -- + + mem_used=$((mem_used * 4096 / 1024 / 1024)) + mem_free=$((mem_free * 4096 / 1024 / 1024)) + + mem_full=$((mem_used + mem_free)) + ;; + esac + + log memory "${mem_used:-?}M / ${mem_full:-?}M" >&6 +} + +get_wm() { + case $os in + (Darwin*) + # Don't display window manager on macOS. + ;; + + (*) + # xprop can be used to grab the window manager's properties + # which contains the window manager's name under '_NET_WM_NAME'. + # + # The upside to using 'xprop' is that you don't need to hardcode + # a list of known window manager names. The downside is that + # not all window managers conform to setting the '_NET_WM_NAME' + # atom.. + # + # List of window managers which fail to set the name atom: + # catwm, fvwm, dwm, 2bwm, monster, wmaker and sowm [mine! ;)]. + # + # The final downside to this approach is that it does _not_ + # support Wayland environments. The only solution which supports + # Wayland is the 'ps' parsing mentioned below. + # + # A more naive implementation is to parse the last line of + # '~/.xinitrc' to extract the second white-space separated + # element. + # + # The issue with an approach like this is that this line data + # does not always equate to the name of the window manager and + # could in theory be _anything_. + # + # This also fails when the user launches xorg through a display + # manager or other means. + # + # + # Another naive solution is to parse 'ps' with a hardcoded list + # of window managers to detect the current window manager (based + # on what is running). + # + # The issue with this approach is the need to hardcode and + # maintain a list of known window managers. + # + # Another issue is that process names do not always equate to + # the name of the window manager. False-positives can happen too. + # + # This is the only solution which supports Wayland based + # environments sadly. It'd be nice if some kind of standard were + # established to identify Wayland environments. + # + # pfetch's goal is to remain _simple_, if you'd like a "full" + # implementation of window manager detection use 'neofetch'. + # + # Neofetch use a combination of 'xprop' and 'ps' parsing to + # support all window managers (including non-conforming and + # Wayland) though it's a lot more complicated! + + # Don't display window manager if X isn't running. + [ "$DISPLAY" ] || return + + # This is a two pass call to xprop. One call to get the window + # manager's ID and another to print its properties. + has xprop && { + # The output of the ID command is as follows: + # _NET_SUPPORTING_WM_CHECK: window id # 0x400000 + # + # To extract the ID, everything before the last space + # is removed. + id=$(xprop -root -notype _NET_SUPPORTING_WM_CHECK) + id=${id##* } + + # The output of the property command is as follows: + # _NAME 8t + # _NET_WM_PID = 252 + # _NET_WM_NAME = "bspwm" + # _NET_SUPPORTING_WM_CHECK: window id # 0x400000 + # WM_CLASS = "wm", "Bspwm" + # + # To extract the name, everything before '_NET_WM_NAME = \"' + # is removed and everything after the next '"' is removed. + wm=$(xprop -id "$id" -notype -len 7 -f _NET_WM_NAME 8t) + } + + # Handle cases of a window manager _not_ populating the + # '_NET_WM_NAME' atom. Display nothing in this case. + case $wm in + (*'_NET_WM_NAME = '*) + wm=${wm##*_NET_WM_NAME = \"} + wm=${wm%%\"*} + ;; + + (*) + # Fallback to checking the process list + # for the select few window managers which + # don't set '_NET_WM_NAME'. + while read -r ps_line; do + case $ps_line in + (*catwm*) wm=catwm ;; + (*fvwm*) wm=fvwm ;; + (*dwm*) wm=dwm ;; + (*2bwm*) wm=2bwm ;; + (*monsterwm*) wm=monsterwm ;; + (*wmaker*) wm='Window Maker' ;; + (*sowm*) wm=sowm ;; + (*penrose*) wm=penrose ;; + esac + done <<-EOF + $(ps x) + EOF + ;; + esac + ;; + esac + + log wm "cwm" >&6 +} + + +get_de() { + # This only supports Xorg related desktop environments though + # this is fine as knowing the desktop environment on Windows, + # macOS etc is useless (they'll always report the same value). + # + # Display the value of '$XDG_CURRENT_DESKTOP', if it's empty, + # display the value of '$DESKTOP_SESSION'. + log de "${XDG_CURRENT_DESKTOP:-$DESKTOP_SESSION}" >&6 +} + +get_shell() { + # Display the basename of the '$SHELL' environment variable. + log sh "${SHELL##*/}" >&6 +} + +get_editor() { + # Display the value of '$VISUAL', if it's empty, display the + # value of '$EDITOR'. + editor=${VISUAL:-"$EDITOR"} + + log ed "${editor##*/}" >&6 +} + +get_palette() { + # Print the first 8 terminal colors. This uses the existing + # sequences to change text color with a sequence prepended + # to reverse the foreground and background colors. + # + # This allows us to save hardcoding a second set of sequences + # for background colors. + # + # False positive. + # shellcheck disable=2154 + { + esc SGR 7 + palette="$e$c1 $c1 $c2 $c2 $c3 $c3 $c4 $c4 $c5 $c5 $c6 $c6 " + esc SGR 0 + palette="$palette$e" + } + + # Print the palette with a new-line before and afterwards but no seperator. + printf '\n' >&6 + log "$palette + " " " " " >&6 +} + +get_ascii() { + # This is a simple function to read the contents of + # an ascii file from 'stdin'. It allows for the use + # of '<<-EOF' to prevent the break in indentation in + # this source code. + # + # This function also sets the text colors according + # to the ascii color. + read_ascii() { + # 'PF_COL1': Set the info name color according to ascii color. + # 'PF_COL3': Set the title color to some other color. ยฏ\_(ใ)_/ยฏ + PF_COL1=${PF_COL1:-${1:-7}} + PF_COL3=${PF_COL3:-$((${1:-7}%8+1))} + + # POSIX sh has no 'var+=' so 'var=${var}append' is used. What's + # interesting is that 'var+=' _is_ supported inside '$(())' + # (arithmetic) though there's no support for 'var++/var--'. + # + # There is also no $'\n' to add a "literal"(?) newline to the + # string. The simplest workaround being to break the line inside + # the string (though this has the caveat of breaking indentation). + while IFS= read -r line; do + ascii="$ascii$line +" + done + } + + # This checks for ascii art in the following order: + # '$1': Argument given to 'get_ascii()' directly. + # '$PF_ASCII': Environment variable set by user. + # '$distro': The detected distribution name. + # '$os': The name of the operating system/kernel. + # + # NOTE: Each ascii art below is indented using tabs, this + # allows indentation to continue naturally despite + # the use of '<<-EOF'. + # + # False positive. + # shellcheck disable=2154 + case ${1:-${PF_ASCII:-${distro:-$os}}} in + ([Aa]lpine*) + read_ascii 4 <<-EOF + ${c4} /\\ /\\ + /${c7}/ ${c4}\\ \\ + /${c7}/ ${c4}\\ \\ + /${c7}// ${c4}\\ \\ + ${c7}// ${c4}\\ \\ + ${c4}\\ + EOF + ;; + + ([Aa]ndroid*) + read_ascii 2 <<-EOF + ${c2} ;, ,; + ${c2} ';,.-----.,;' + ${c2} ,' ', + ${c2} / O O \\ + ${c2}| | + ${c2}'-----------------' + EOF + ;; + + ([Aa]rch*) + read_ascii 4 <<-EOF + ${c6} /\\ + ${c6} / \\ + ${c6} /\\ \\ + ${c4} / \\ + ${c4} / ,, \\ + ${c4} / | | -\\ + ${c4} /_-'' ''-_\\ + EOF + ;; + + ([Aa]rco*) + read_ascii 4 <<-EOF + ${c4} /\\ + ${c4} / \\ + ${c4} / /\\ \\ + ${c4} / / \\ \\ + ${c4} / / \\ \\ + ${c4} / / _____\\ \\ + ${c4}/_/ \`----.\\_\\ + EOF + ;; + + ([Aa]rtix*) + read_ascii 6 <<-EOF + ${c4} /\\ + ${c4} / \\ + ${c4} /\`'.,\\ + ${c4} / ', + ${c4} / ,\`\\ + ${c4} / ,.'\`. \\ + ${c4}/.,'\` \`'.\\ + EOF + ;; + + ([Bb]edrock*) + read_ascii 4 <<-EOF + ${c7}__ + ${c7}\\ \\___ + ${c7} \\ _ \\ + ${c7} \\___/ + EOF + ;; + + ([Bb]uildroot*) + read_ascii 3 <<-EOF + ${c3} ___ + ${c3} / \` \\ + ${c3}| : :| + ${c3}-. _:__.- + ${c3} \` ---- \` + EOF + ;; + + ([Cc]el[Oo][Ss]*) + read_ascii 5 0 <<-EOF + ${c5} .////\\\\\//\\. + ${c5} //_ \\\\ + ${c5} /_ ${c7}############## + ${c5} // *\\ + ${c7}############### ${c5}|# + ${c5} \/ */ + ${c5} \* ${c7}############## + ${c5} */, .// + ${c5} '_///\\\\\//_' + EOF + ;; + + ([Cc]ent[Oo][Ss]*) + read_ascii 5 <<-EOF + ${c2} ____${c3}^${c5}____ + ${c2} |\\ ${c3}|${c5} /| + ${c2} | \\ ${c3}|${c5} / | + ${c5}<---- ${c4}----> + ${c4} | / ${c2}|${c3} \\ | + ${c4} |/__${c2}|${c3}__\\| + ${c2} v + EOF + ;; + + ([Cc]rystal*[Ll]inux) + read_ascii 5 5 <<-EOF + ${c5} -//. + ${c5} -//. + ${c5} -//. . + ${c5} -//. '//- + ${c5} /+: :+/ + ${c5} .//' .//. + ${c5} . .//. + ${c5} .//. + ${c5} .//. + EOF + ;; + + ([Dd]ahlia*) + read_ascii 1 <<-EOF + ${c1} _ + ${c1} ___/ \\___ + ${c1} | _-_ | + ${c1} | / \ | + ${c1}/ | | \\ + ${c1}\\ | | / + ${c1} | \ _ _ / | + ${c1} |___ - ___| + ${c1} \\_/ + EOF + ;; + + ([Dd]ebian*) + read_ascii 1 <<-EOF + ${c1} _____ + ${c1} / __ \\ + ${c1}| / | + ${c1}| \\___- + ${c1}-_ + ${c1} --_ + EOF + ;; + + ([Dd]evuan*) + read_ascii 6 <<-EOF + ${c4} ..:::. + ${c4} ..-==- + ${c4} .+#: + ${c4} =@@ + ${c4} :+%@#: + ${c4}.:=+#@@%*: + ${c4}#@@@#=: + EOF + ;; + + ([Dd]ragon[Ff]ly*) + read_ascii 1 <<-EOF + ,${c1}_${c7}, + ('-_${c1}|${c7}_-') + >--${c1}|${c7}--< + (_-'${c1}|${c7}'-_) + ${c1}| + ${c1}| + ${c1}| + EOF + ;; + + ([Ee]lementary*) + read_ascii <<-EOF + ${c7} _______ + ${c7} / ____ \\ + ${c7}/ | / /\\ + ${c7}|__\\ / / | + ${c7}\\ /__/ / + ${c7}\\_______/ + EOF + ;; + + ([Ee]ndeavour*) + read_ascii 4 <<-EOF + ${c1}/${c4}\\ + ${c1}/${c4}/ \\${c6}\\ + ${c1}/${c4}/ \\ ${c6}\\ + ${c1}/ ${c4}/ _) ${c6}) + ${c1}/_${c4}/___-- ${c6}__- + ${c6}/____-- + EOF + ;; + + ([Ff]edora*) + read_ascii 4 <<-EOF + ${c4},'''''. + ${c4}| ,. | + ${c4}| | '_' + ${c4} ,....| |.. + ${c4}.' ,_;| ..' + ${c4}| | | | + ${c4}| ',_,' | + ${c4} '. ,' + ${c4}''''' + EOF + ;; + + ([Ff]ree[Bb][Ss][Dd]*) + read_ascii 1 <<-EOF + ${c1}/\\,-'''''-,/\\ + ${c1}\\_) (_/ + ${c1}| | + ${c1}| | + ${c1}; ; + ${c1}'-_____-' + EOF + ;; + + ([Gg]aruda*) + read_ascii 4 <<-EOF + ${c3} _______ + ${c3} __/ \\_ + ${c3} _/ / \\_ + ${c7} _/ /_________\\ + ${c7}_/ | + ${c2}\\ ____________ + ${c2} \\_ __/ + ${c2} \\__________/ + EOF + ;; + + ([Gg]entoo*) + read_ascii 5 <<-EOF + ${c5} _-----_ + ${c5}( \\ + ${c5}\\ 0 \\ + ${c7} \\ ) + ${c7} / _/ + ${c7}( _- + ${c7}\\____- + EOF + ;; + + ([Gg][Nn][Uu]*) + read_ascii 3 <<-EOF + ${c2} _-\`\`-, ,-\`\`-_ + ${c2} .' _-_| |_-_ '. + ${c2}./ /_._ _._\\ \\. + ${c2}: _/_._\`:'_._\\_ : + ${c2}\\:._/ ,\` \\ \\ \\_.:/ + ${c2} ,-';'.@) \\ @) \\ + ${c2} ,'/' ..- .\\,-.| + ${c2} /'/' \\(( \\\` ./ ) + ${c2} '/'' \\_,----' + ${c2} '/'' ,;/'' + ${c2} \`\`;' + EOF + ;; + + ([Gg]uix[Ss][Dd]*|[Gg]uix*) + read_ascii 3 <<-EOF + ${c3}|.__ __.| + ${c3}|__ \\ / __| + ${c3}\\ \\ / / + ${c3}\\ \\ / / + ${c3}\\ \\ / / + ${c3}\\ \\/ / + ${c3}\\__/ + EOF + ;; + + ([Hh]aiku*) + read_ascii 3 <<-EOF + ${c3} ,^, + ${c3} / \\ + ${c3}*--_ ; ; _--* + ${c3}\\ '" "' / + ${c3}'. .' + ${c3}.-'" "'-. + ${c3}'-.__. .__.-' + ${c3}|_| + EOF + ;; + + ([Hh]ydroOS*) + read_ascii 4 <<-EOF + ${c1}โโโโโโโโโโโโโโฆโโโ + ${c1}โโโโ โฆโฆโโ โฆโฆโโฃโโโโโฃ + ${c1}โโโโโโโฌโโโฃโฌโโโ โโโ + ${c1}โโโโฌโโ โโฉโโโโฉโโฉโโโ + ${c1}โโโโโโ + EOF + ;; + + ([Hh]yperbola*) + read_ascii <<-EOF + ${c7} |\`__.\`/ + ${c7} \____/ + ${c7} .--. + ${c7} / \\ + ${c7} / ___ \\ + ${c7}/ .\` \`.\\ + ${c7}/.\` \`.\\ + EOF + ;; + + ([Ii]glunix*) + read_ascii <<-EOF + ${c0} | + ${c0} | | + ${c0} | + ${c0} | ________ + ${c0} | /\\ | \\ + ${c0} / \\ | \\ | + ${c0} / \\ \\ | + ${c0} / \\________\\ + ${c0} \\ / / + ${c0} \\ / / + ${c0} \\ / / + ${c0} \\/________/ + EOF + ;; + + ([Ii]nstant[Oo][Ss]*) + read_ascii <<-EOF + ${c0} ,-''-, + ${c0}: .''. : + ${c0}: ',,' : + ${c0} '-____:__ + ${c0} : \`. + ${c0} \`._.' + EOF + ;; + + ([Ii][Rr][Ii][Xx]*) + read_ascii 1 <<-EOF + ${c1} __ + ${c1} \\ \\ __ + ${c1} \\ \\ / / + ${c1} \\ v / + ${c1} / . \\ + ${c1} /_/ \\ \\ + ${c1} \\_\\ + EOF + ;; + + ([Kk][Dd][Ee]*[Nn]eon*) + read_ascii 6 <<-EOF + ${c7} .${c6}__${c7}.${c6}__${c7}. + ${c6} / _${c7}.${c6}_ \\ + ${c6} / / \\ \\ + ${c7} . ${c6}| ${c7}O${c6} | ${c7}. + ${c6} \\ \\_${c7}.${c6}_/ / + ${c6} \\${c7}.${c6}__${c7}.${c6}__${c7}.${c6}/ + EOF + ;; + + ([Ll]inux*[Ll]ite*|[Ll]ite*) + read_ascii 3 <<-EOF + ${c3} /\\ + ${c3} / \\ + ${c3} / ${c7}/ ${c3}/ + ${c3}> ${c7}/ ${c3}/ + ${c3}\\ ${c7}\\ ${c3}\\ + ${c3}\\_${c7}\\${c3}_\\ + ${c7} \\ + EOF + ;; + + ([Ll]inux*[Mm]int*|[Mm]int) + read_ascii 2 <<-EOF + ${c2} ___________ + ${c2}|_ \\ + ${c2}| ${c7}| _____ ${c2}| + ${c2}| ${c7}| | | | ${c2}| + ${c2}| ${c7}| | | | ${c2}| + ${c2}| ${c7}\\__${c7}___/ ${c2}| + ${c2}\\_________/ + EOF + ;; + + + ([Ll]inux*) + read_ascii 4 <<-EOF + ${c4} ___ + ${c4}(${c7}.. ${c4}| + ${c4}(${c5}<> ${c4}| + ${c4}/ ${c7}__ ${c4}\\ + ${c4}( ${c7}/ \\ ${c4}/| + ${c5}_${c4}/\\ ${c7}__)${c4}/${c5}_${c4}) + ${c5}\/${c4}-____${c5}\/ + EOF + ;; + + ([Mm]ac[Oo][Ss]*|[Dd]arwin*) + read_ascii 1 <<-EOF + ${c2} .:' + ${c2} _ :'_ + ${c3} .'\`_\`-'_\`\`. + ${c1}:________.-' + ${c1}:_______: + ${c4} :_______\`-; + ${c5} \`._.-._.' + EOF + ;; + + ([Mm]ageia*) + read_ascii 2 <<-EOF + ${c6} * + ${c6} * + ${c6} ** + ${c7} /\\__/\\ + ${c7}/ \\ + ${c7}\\ / + ${c7} \\____/ + EOF + ;; + + ([Mm]anjaro*) + read_ascii 2 <<-EOF + ${c2}||||||||| |||| + ${c2}||||||||| |||| + ${c2}|||| |||| + ${c2}|||| |||| |||| + ${c2}|||| |||| |||| + ${c2}|||| |||| |||| + ${c2}|||| |||| |||| + EOF + ;; + + ([Mm]inix*) + read_ascii 4 <<-EOF + ${c4} ,, ,, + ${c4};${c7},${c4} ', ,' ${c7},${c4}; + ${c4}; ${c7}',${c4} ',,' ${c7},'${c4} ; + ${c4}; ${c7}',${c4} ${c7},'${c4} ; + ${c4}; ${c7};, '' ,;${c4} ; + ${c4}; ${c7};${c4};${c7}',,'${c4};${c7};${c4} ; + ${c4}', ${c7};${c4};; ;;${c7};${c4} ,' + ${c4} '${c7};${c4}' '${c7};${c4}' + EOF + ;; + + ([Mm][Xx]*) + read_ascii <<-EOF + ${c7} \\\\ / + ${c7} \\\\/ + ${c7} \\\\ + ${c7} /\\/ \\\\ + ${c7} / \\ /\\ + ${c7} / \\/ \\ + ${c7}/__________\\ + EOF + ;; + + ([Nn]et[Bb][Ss][Dd]*) + read_ascii 3 <<-EOF + ${c7}\\${c3}\`-__,----__ + ${c7} \\ ${c3}__\`_ + ${c7} \\${c3}-__,----\`- + ${c7} \\ + ${c7} \\ + EOF + ;; + + ([Nn]ix[Oo][Ss]*) + read_ascii 4 <<-EOF + ${c4} \\\\ \\\\ // + ${c4} ==\\\\__\\\\/ // + ${c4} // \\\\// + ${c4}==// //== + ${c4} //\\\\___// + ${c4}// /\\\\ \\\\== + ${c4} // \\\\ \\\\ + EOF + ;; + + ([Oo]pen[Bb][Ss][Dd]*) + read_ascii 3 <<-EOF + ${c3} _____ + ${c3} \\- -/ + ${c3} \\_/ \\ + ${c3} | ${c7}O O${c3} | + ${c3} |_ < ) 3 ) + ${c3} / \\ / + ${c3} /-_____-\\ + EOF + ;; + + ([Oo]pen[Ss][Uu][Ss][Ee]*[Tt]umbleweed*) + read_ascii 2 <<-EOF + ${c2} _____ ______ + ${c2} / ____\\ / ____ \\ + ${c2}/ / \`/ / \\ \\ + ${c2}\\ \\____/ /,____/ / + ${c2} \\______/ \\_____/ + EOF + ;; + + ([Oo]pen[Ss][Uu][Ss][Ee]*|[Oo]pen*SUSE*|SUSE*|suse*) + read_ascii 2 <<-EOF + ${c2} _______ + ${c2}__| __ \\ + ${c2} / .\\ \\ + ${c2} \\__/ | + ${c2} _______| + ${c2} \\_______ + ${c2}__________/ + EOF + ;; + + ([Oo]pen[Ww]rt*) + read_ascii 1 <<-EOF + ${c1} _______ + ${c1}| |.-----.-----.-----. + ${c1}| - || _ | -__| | + ${c1}|_______|| __|_____|__|__| + ${c1} ________|__| __ + ${c1}| | | |.----.| |_ + ${c1}| | | || _|| _| + ${c1}|________||__| |____| + EOF + ;; + + ([Pp]arabola*) + read_ascii 5 <<-EOF + ${c5} __ __ __ _ + ${c5}.\`_//_//_/ / \`. + ${c5} / .\` + ${c5} / .\` + ${c5} /.\` + ${c5} /\` + EOF + ;; + + ([Pp]op!_[Oo][Ss]*) + read_ascii 6 <<-EOF + ${c6}______ + ${c6}\\ _ \\ __ + ${c6}\\ \\ \\ \\ / / + ${c6}\\ \\_\\ \\ / / + ${c6}\\ ___\\ /_/ + ${c6} \\ \\ _ + ${c6} __\\_\\__(_)_ + ${c6}(___________) + EOF + ;; + + ([Pp]ure[Oo][Ss]*) + read_ascii <<-EOF + ${c7} _____________ + ${c7}| _________ | + ${c7}| | | | + ${c7}| | | | + ${c7}| |_________| | + ${c7}|_____________| + EOF + ;; + + ([Rr]aspbian*) + read_ascii 1 <<-EOF + ${c2} __ __ + ${c2} (_\\)(/_) + ${c1} (_(__)_) + ${c1}(_(_)(_)_) + ${c1} (_(__)_) + ${c1} (__) + EOF + ;; + + ([Ss]erenity[Oo][Ss]*) + read_ascii 4 <<-EOF + ${c7} _____ + ${c1} ,-${c7} -, + ${c1} ;${c7} ( ; + ${c1}| ${c7}. \_${c1}.,${c7} | + ${c1}| ${c7}o _${c1} ',${c7} | + ${c1} ; ${c7}(_)${c1} )${c7} ; + ${c1} '-_____-${c7}' + EOF + ;; + + ([Ss]lackware*) + read_ascii 4 <<-EOF + ${c4} ________ + ${c4} / ______| + ${c4} | |______ + ${c4} \\______ \\ + ${c4} ______| | + ${c4}| |________/ + ${c4}|____________ + EOF + ;; + + ([Ss]olus*) + read_ascii 4 <<-EOF + ${c6} + ${c6} /| + ${c6} / |\\ + ${c6} / | \\ _ + ${c6} /___|__\\_\\ + ${c6} \\ / + ${c6} \`-------ยด + EOF + ;; + + ([Ss]un[Oo][Ss]|[Ss]olaris*) + read_ascii 3 <<-EOF + ${c3} . .; . + ${c3} . :; :: ;: . + ${c3} .;. .. .. .;. + ${c3}.. .. .. .. + ${c3} .;, ,;. + EOF + ;; + + ([Uu]buntu*) + read_ascii 3 <<-EOF + ${c3} _ + ${c3} ---(_) + ${c3} _/ --- \\ + ${c3}(_) | | + ${c3} \\ --- _/ + ${c3} ---(_) + EOF + ;; + + ([Vv]oid*) + read_ascii 2 <<-EOF + ${c2} _______ + ${c2} _ \\______ - + ${c2}| \\ ___ \\ | + ${c2}| | / \ | | + ${c2}| | \___/ | | + ${c2}| \\______ \\_| + ${c2} -_______\\ + EOF + ;; + + ([Xx]eonix*) + read_ascii 2 <<-EOF + ${c2} ___ ___ + ${c2}___ \ \/ / ___ + ${c2}\ \ \ / / / + ${c2} \ \/ \/ / + ${c2} \ /\ / + ${c2} \__/ \__/ + EOF + ;; + + (*) + # On no match of a distribution ascii art, this function calls + # itself again, this time to look for a more generic OS related + # ascii art (KISS Linux -> Linux). + [ "$1" ] || { + get_ascii "$os" + return + } + + printf 'error: %s is not currently supported.\n' "$os" >&6 + printf 'error: Open an issue for support to be added.\n' >&6 + exit 1 + ;; + esac + + # Store the "width" (longest line) and "height" (number of lines) + # of the ascii art for positioning. This script prints to the screen + # *almost* like a TUI does. It uses escape sequences to allow dynamic + # printing of the information through user configuration. + # + # Iterate over each line of the ascii art to retrieve the above + # information. The 'sed' is used to strip '\033[3Xm' color codes from + # the ascii art so they don't affect the width variable. + while read -r line; do + ascii_height=$((${ascii_height:-0} + 1)) + + # This was a ternary operation but they aren't supported in + # Minix's shell. + [ "${#line}" -gt "${ascii_width:-0}" ] && + ascii_width=${#line} + + # Using '<<-EOF' is the only way to loop over a command's + # output without the use of a pipe ('|'). + # This ensures that any variables defined in the while loop + # are still accessible in the script. + done <<-EOF + $(printf %s "$ascii" | sed 's/\[3.m//g') + EOF + + # Add a gap between the ascii art and the information. + ascii_width=$((ascii_width + 4)) + + # Print the ascii art and position the cursor back where we + # started prior to printing it. + { + esc_p SGR 1 + printf '%s' "$ascii" + esc_p SGR 0 + esc_p CUU "$ascii_height" + } >&6 +} + +main() { + case $* in + -v) + printf '%s 0.7.0\n' "${0##*/}" + return 0 + ;; + + -d) + # Below exec is not run, stderr is shown. + ;; + + '') + exec 2>/dev/null + ;; + + *) + cat <<EOF +${0##*/} show system information +${0##*/} -d show stderr (debug mode) +${0##*/} -v show version information +EOF + return 0 + ;; + esac + + # Hide 'stdout' and selectively print to it using '>&6'. + # This gives full control over what it displayed on the screen. + exec 6>&1 >/dev/null + + # Store raw escape sequence character for later reuse. + esc_c=$(printf '\033') + + # Allow the user to execute their own script and modify or + # extend pfetch's behavior. + # shellcheck source=/dev/null + ! [ -f "$PF_SOURCE" ] || . "$PF_SOURCE" + + # Ensure that the 'TMPDIR' is writable as heredocs use it and + # fail without the write permission. This was found to be the + # case on Android where the temporary directory requires root. + [ -w "${TMPDIR:-/tmp}" ] || export TMPDIR=~ + + # Generic color list. + # Disable warning about unused variables. + # shellcheck disable=2034 + for _c in c1 c2 c3 c4 c5 c6 c7 c8; do + esc SGR "3${_c#?}" 0 + export "$_c=$e" + done + + # Disable line wrapping and catch the EXIT signal to enable it again + # on exit. Ideally you'd somehow query the current value and retain + # it but I'm yet to see this irk anyone. + esc_p DECAWM l >&6 + trap 'esc_p DECAWM h >&6' EXIT + + # Store the output of 'uname' to avoid calling it multiple times + # throughout the script. 'read <<EOF' is the simplest way of reading + # a command into a list of variables. + read -r os kernel arch <<-EOF + $(uname -srm) + EOF + + # Always run 'get_os' for the purposes of detecting which ascii + # art to display. + get_os + + # Allow the user to specify the order and inclusion of information + # functions through the 'PF_INFO' environment variable. + # shellcheck disable=2086 + { + # Disable globbing and set the positional parameters to the + # contents of 'PF_INFO'. + set -f + set +f -- ${PF_INFO-ascii title os host kernel uptime pkgs memory} + + # Iterate over the info functions to determine the lengths of the + # "info names" for output alignment. The option names and subtitles + # match 1:1 so this is thankfully simple. + for info do + command -v "get_$info" >/dev/null || continue + + # This was a ternary operation but they aren't supported in + # Minix's shell. + [ "${#info}" -gt "${info_length:-0}" ] && + info_length=${#info} + done + + # Add an additional space of length to act as a gap. + info_length=$((info_length + 1)) + + # Iterate over the above list and run any existing "get_" functions. + for info do + "get_$info" + done + } + + # Position the cursor below both the ascii art and information lines + # according to the height of both. If the information exceeds the ascii + # art in height, don't touch the cursor (0/unset), else move it down + # N lines. + # + # This was a ternary operation but they aren't supported in Minix's shell. + [ "${info_height:-0}" -lt "${ascii_height:-0}" ] && + cursor_pos=$((ascii_height - info_height)) + + # Print '$cursor_pos' amount of newlines to correctly position the + # cursor. This used to be a 'printf $(seq X X)' however 'seq' is only + # typically available (by default) on GNU based systems! + while [ "${i:=0}" -le "${cursor_pos:-0}" ]; do + printf '\n' + i=$((i + 1)) + done >&6 +} + +main "$@" diff --git a/home/dots/.local/bin/todo b/home/dots/.local/bin/todo new file mode 100755 index 0000000..f0a02b8 --- /dev/null +++ b/home/dots/.local/bin/todo @@ -0,0 +1,14 @@ +#!/bin/sh + +TODO_BASE='* TODO ' +JRNL="$STITCH_DIRECTORY/$(date +'%y-%m-%d.%H:%M.%S').org" +echo '* TODO ' > /tmp/capture +$EDITOR /tmp/capture +1 +if grep -q '^\* TODO\s*$' /tmp/capture +then + echo "Empty capture" +else + echo "Storing capture in $JRNL" + cat /tmp/capture > $JRNL +fi + diff --git a/home/dots/.local/share/fonts/IosevkaSS13-Bold.ttf b/home/dots/.local/share/fonts/IosevkaSS13-Bold.ttf Binary files differnew file mode 100644 index 0000000..5adc20b --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-Bold.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-BoldItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-BoldItalic.ttf Binary files differnew file mode 100644 index 0000000..65e4275 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-BoldItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-BoldOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-BoldOblique.ttf Binary files differnew file mode 100644 index 0000000..58750b2 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-BoldOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-Extended.ttf b/home/dots/.local/share/fonts/IosevkaSS13-Extended.ttf Binary files differnew file mode 100644 index 0000000..8bf150f --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-Extended.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedBold.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedBold.ttf Binary files differnew file mode 100644 index 0000000..f23643d --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedBold.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedBoldItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedBoldItalic.ttf Binary files differnew file mode 100644 index 0000000..61b9973 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedBoldItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedBoldOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedBoldOblique.ttf Binary files differnew file mode 100644 index 0000000..8657c09 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedBoldOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraBold.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraBold.ttf Binary files differnew file mode 100644 index 0000000..80d2dc7 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraBold.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraBoldItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraBoldItalic.ttf Binary files differnew file mode 100644 index 0000000..b6645bf --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraBoldItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraBoldOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraBoldOblique.ttf Binary files differnew file mode 100644 index 0000000..88f9585 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraBoldOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraLight.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraLight.ttf Binary files differnew file mode 100644 index 0000000..22a7abe --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraLight.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraLightItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraLightItalic.ttf Binary files differnew file mode 100644 index 0000000..8fb491e --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraLightItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraLightOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraLightOblique.ttf Binary files differnew file mode 100644 index 0000000..bd84354 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedExtraLightOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedHeavy.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedHeavy.ttf Binary files differnew file mode 100644 index 0000000..8cc72d2 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedHeavy.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedHeavyItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedHeavyItalic.ttf Binary files differnew file mode 100644 index 0000000..137df73 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedHeavyItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedHeavyOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedHeavyOblique.ttf Binary files differnew file mode 100644 index 0000000..e6a0cbc --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedHeavyOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedItalic.ttf Binary files differnew file mode 100644 index 0000000..f15527d --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedLight.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedLight.ttf Binary files differnew file mode 100644 index 0000000..8694293 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedLight.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedLightItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedLightItalic.ttf Binary files differnew file mode 100644 index 0000000..ac366b5 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedLightItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedLightOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedLightOblique.ttf Binary files differnew file mode 100644 index 0000000..5a90087 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedLightOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedMedium.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedMedium.ttf Binary files differnew file mode 100644 index 0000000..903fca8 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedMedium.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedMediumItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedMediumItalic.ttf Binary files differnew file mode 100644 index 0000000..48208ea --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedMediumItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedMediumOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedMediumOblique.ttf Binary files differnew file mode 100644 index 0000000..a1e0f00 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedMediumOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedOblique.ttf Binary files differnew file mode 100644 index 0000000..b92a407 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedSemiBold.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedSemiBold.ttf Binary files differnew file mode 100644 index 0000000..02c954f --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedSemiBold.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedSemiBoldItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedSemiBoldItalic.ttf Binary files differnew file mode 100644 index 0000000..d3a8451 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedSemiBoldItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedSemiBoldOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedSemiBoldOblique.ttf Binary files differnew file mode 100644 index 0000000..1a1d2de --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedSemiBoldOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedThin.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedThin.ttf Binary files differnew file mode 100644 index 0000000..9b294a9 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedThin.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedThinItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedThinItalic.ttf Binary files differnew file mode 100644 index 0000000..e2a0c10 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedThinItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtendedThinOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedThinOblique.ttf Binary files differnew file mode 100644 index 0000000..b9f5ee2 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtendedThinOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtraBold.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtraBold.ttf Binary files differnew file mode 100644 index 0000000..91bdf22 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtraBold.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtraBoldItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtraBoldItalic.ttf Binary files differnew file mode 100644 index 0000000..df36e15 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtraBoldItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtraBoldOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtraBoldOblique.ttf Binary files differnew file mode 100644 index 0000000..4e6fa98 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtraBoldOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtraLight.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtraLight.ttf Binary files differnew file mode 100644 index 0000000..d26599e --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtraLight.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtraLightItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtraLightItalic.ttf Binary files differnew file mode 100644 index 0000000..d9856c1 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtraLightItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ExtraLightOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ExtraLightOblique.ttf Binary files differnew file mode 100644 index 0000000..1accf09 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ExtraLightOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-Heavy.ttf b/home/dots/.local/share/fonts/IosevkaSS13-Heavy.ttf Binary files differnew file mode 100644 index 0000000..24ae757 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-Heavy.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-HeavyItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-HeavyItalic.ttf Binary files differnew file mode 100644 index 0000000..4bdb262 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-HeavyItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-HeavyOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-HeavyOblique.ttf Binary files differnew file mode 100644 index 0000000..f31bb9b --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-HeavyOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-Italic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-Italic.ttf Binary files differnew file mode 100644 index 0000000..b83c3ad --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-Italic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-Light.ttf b/home/dots/.local/share/fonts/IosevkaSS13-Light.ttf Binary files differnew file mode 100644 index 0000000..34d4918 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-Light.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-LightItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-LightItalic.ttf Binary files differnew file mode 100644 index 0000000..1d034fa --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-LightItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-LightOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-LightOblique.ttf Binary files differnew file mode 100644 index 0000000..2c2f1aa --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-LightOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-Medium.ttf b/home/dots/.local/share/fonts/IosevkaSS13-Medium.ttf Binary files differnew file mode 100644 index 0000000..25fa6e1 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-Medium.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-MediumItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-MediumItalic.ttf Binary files differnew file mode 100644 index 0000000..851ac47 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-MediumItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-MediumOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-MediumOblique.ttf Binary files differnew file mode 100644 index 0000000..6fb550d --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-MediumOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-Oblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-Oblique.ttf Binary files differnew file mode 100644 index 0000000..fbc37e1 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-Oblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-Regular.ttf b/home/dots/.local/share/fonts/IosevkaSS13-Regular.ttf Binary files differnew file mode 100644 index 0000000..88baaeb --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-Regular.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-SemiBold.ttf b/home/dots/.local/share/fonts/IosevkaSS13-SemiBold.ttf Binary files differnew file mode 100644 index 0000000..6f22260 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-SemiBold.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-SemiBoldItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-SemiBoldItalic.ttf Binary files differnew file mode 100644 index 0000000..c321a3d --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-SemiBoldItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-SemiBoldOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-SemiBoldOblique.ttf Binary files differnew file mode 100644 index 0000000..7c43381 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-SemiBoldOblique.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-Thin.ttf b/home/dots/.local/share/fonts/IosevkaSS13-Thin.ttf Binary files differnew file mode 100644 index 0000000..d9d0c5f --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-Thin.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ThinItalic.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ThinItalic.ttf Binary files differnew file mode 100644 index 0000000..1c1b60c --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ThinItalic.ttf diff --git a/home/dots/.local/share/fonts/IosevkaSS13-ThinOblique.ttf b/home/dots/.local/share/fonts/IosevkaSS13-ThinOblique.ttf Binary files differnew file mode 100644 index 0000000..3460e86 --- /dev/null +++ b/home/dots/.local/share/fonts/IosevkaSS13-ThinOblique.ttf diff --git a/home/dots/.mbsyncrc b/home/dots/.mbsyncrc new file mode 100644 index 0000000..ca00992 --- /dev/null +++ b/home/dots/.mbsyncrc @@ -0,0 +1,60 @@ +CopyArrivalDate yes # Don't mess up message timestamps when moving them between folders. +Create Near # Automatically create new folders in the local copy. +Remove Near # Automatically remove deleted folders from the local copy. +Expunge Near # Expunge deleted messages from the local copy. + +# First section: remote IMAP account +IMAPAccount Home +Host imap.fastmail.com +Port 993 +User marcc@fastmail.fr +# For simplicity, this is how to read the password from another file. +# For better security you should use GPG https://gnupg.org/ +PassCmd "pass fastmail/marcc" +TLSType IMAPS +TLSVersions +1.2 + +IMAPStore Home-remote +Account Home + +# This section describes the local storage +MaildirStore Home-local +Path ~/mail/home/ +Inbox ~/mail/home/INBOX +SubFolders Verbatim + +# This section a "channel", a connection between remote and local +Channel Home +Far :Home-remote: +Near :Home-local: +Patterns * +Expunge None +CopyArrivalDate yes +Sync All +Create Both +SyncState * + + +# WORK +IMAPAccount Work +Host imap.gmail.com +User marc.coquand@sustainably.app +PassCmd "pass sustainably/gmail" +TLSType IMAPS +Timeout 60 + +IMAPStore Work-remote +Account Work + +MaildirStore Work-local +Path ~/mail/work/ +Inbox ~/mail/work/INBOX +SubFolders Verbatim + +Channel Work +Far :Work-remote: +Near :Work-local: +Expunge Both +Create Both +Patterns * +SyncState * diff --git a/home/dots/.mozilla/firefox/p8ada7a1.default/chrome/userChrome.css b/home/dots/.mozilla/firefox/p8ada7a1.default/chrome/userChrome.css new file mode 100644 index 0000000..ae8a6dd --- /dev/null +++ b/home/dots/.mozilla/firefox/p8ada7a1.default/chrome/userChrome.css @@ -0,0 +1,10 @@ +#TabsToolbar { + visibility: collapse; +} + +menubar, toolbar, nav-bar, #TabsToolbar > * { + background-color: white !important; + font-family: "Iosevka Aile"; +} + + diff --git a/home/dots/.msmtprc b/home/dots/.msmtprc new file mode 100644 index 0000000..170f86e --- /dev/null +++ b/home/dots/.msmtprc @@ -0,0 +1,25 @@ +# Set default values for all following accounts. +defaults +auth on +tls on +tls_trust_file /etc/ssl/certs/ca-certificates.crt +logfile ~/.msmtp.log + +# Work +account work +host smtp.gmail.com +port 587 +from marc@baemingo.com +user marc@baemingo.com +passwordeval "pass baemingo/gmail" + +# Home +account home +host smtp.fastmail.com +port 465 +tls_starttls off +from marcc@fastmail.fr +user marcc@fastmail.fr +passwordeval "pass fastmail/marcc" + +account default : home diff --git a/home/dots/.xsession.bak b/home/dots/.xsession.bak new file mode 100755 index 0000000..5823726 --- /dev/null +++ b/home/dots/.xsession.bak @@ -0,0 +1,18 @@ + +#!/usr/bin/env sh +export _JAVA_AWT_WM_NONREPARENTING=1 +export VISUAL=emacsclient +export EDITOR="$VISUAL" +#autocutsel & +xsetroot -solid '#FFFFFF' & +#ulimit -c 0 & +#xclock -digital -geometry +5+1402 -face "Iosevka Aile:pixelsize=18:style=regular" -bg \#282C34 -fg \#B8BCC4 -strftime "Bogo (%Y/%m/%d) %H:%M" & +gsettings set org.gnome.desktop.interface document-font-name 'Iosevka Aile' & +gsettings set org.gnome.desktop.interface font-name 'Iosevka Aile' & +gsettings set org.gnome.desktop.interface cursor-size 32 & +gsettings set org.gnome.desktop.interface cursor-theme Adwaita & +# xkbcomp $HOME/.config/keymap_locked_modifier.xkb $DISPLAY & +#xsetroot -cursor_name left_ptr & +xset r rate 200 60 & +emacs --daemon --eval "(require 'exwm)" -f exwm-enable +exec dbus-launch emacsclient -c diff --git a/home/profile b/home/profile new file mode 100644 index 0000000..b8fa27f --- /dev/null +++ b/home/profile @@ -0,0 +1,18 @@ +PATH=${PATH}:/home/mccd/go/bin:/home/mccd/.cargo/bin:/home/mccd/.local/bin + +export EDITOR="mg -n" +export GDK_DPI_SCALE="1.5" +export GDK_SCALE="1.5" +export XCURSOR_SIZE="32" +# So when you hover the desktop, it still uses Adwaita +export XCURSOR_THEME="Adwaita" +export PF_INFO="ascii title os editor shell wm" +export PF_ALIGN="5" +export PF_COLOR="0" +export MOZ_ACCELERATED=1 +export HISTSIZE=65535 +export HISTFILE=$HOME/.history +export STITCH_DIRECTORY=/home/mccd/notes +export STITCH_GREP_CMD=ugrep + + diff --git a/os/config.scm b/os/config.scm new file mode 100644 index 0000000..95086a5 --- /dev/null +++ b/os/config.scm @@ -0,0 +1,91 @@ +;; This is an operating system configuration generated +;; by the graphical installer. +;; +;; Once installation is complete, you can learn and modify +;; this file to tweak the system configuration, and pass it +;; to the 'guix system reconfigure' command to effect your +;; changes. + + +;; Indicate which modules to import to access the variables +;; used in this configuration. +(use-modules (gnu) + (nongnu packages linux) + (nongnu system linux-initrd)) +(use-service-modules cups desktop networking ssh xorg) + +(operating-system + (kernel linux) + (initrd microcode-initrd) + (firmware (list linux-firmware)) + (locale "en_US.utf8") + (timezone "Asia/Nicosia") + (keyboard-layout (keyboard-layout "us" "colemak" #:options '("ctrl:nocaps"))) + (host-name "guix") + + ;; The list of user accounts ('root' is implicit). + (users (cons* (user-account + (name "mccd") + (comment "Marc") + (group "users") + (home-directory "/home/mccd") + (supplementary-groups '("wheel" "netdev" "audio" "video"))) + %base-user-accounts)) + + ;; Packages installed system-wide. Users can also install packages + ;; under their own account: use 'guix search KEYWORD' to search + ;; for packages and 'guix install PACKAGE' to install a package. + (packages (append (list (specification->package "emacs") + (specification->package "emacs-exwm") + (specification->package "mu") + (specification->package "guile") + (specification->package + "emacs-desktop-environment")) %base-packages)) + + ;; Below is the list of system services. To search for available + ;; services, run 'guix system search KEYWORD' in a terminal. + (services + (append (list (service cups-service-type) + (set-xorg-configuration + (xorg-configuration (keyboard-layout keyboard-layout)))) + (modify-services %desktop-services + (guix-service-type config => (guix-configuration + (inherit config) + (substitute-urls + (append (list "https://substitutes.nonguix.org") + %default-substitute-urls)) + (authorized-keys + (append (list (local-file "./signing-key.pub")) + %default-authorized-guix-keys))))))) + + ;; This is the default list of services we + ;; are appending to. + + (bootloader (bootloader-configuration + (bootloader grub-efi-bootloader) + (targets (list "/boot/efi")) + (keyboard-layout keyboard-layout))) + (swap-devices (list (swap-space + (target (uuid + "6ee329b8-9475-4675-9c46-b2f68ec97f08"))))) + + ;; The list of file systems that get "mounted". The unique + ;; file system identifiers there ("UUIDs") can be obtained + ;; by running 'blkid' in a terminal. + (file-systems (cons* (file-system + (mount-point "/boot/efi") + (device (uuid "132A-1FDF" + 'fat32)) + (type "vfat")) + (file-system + (mount-point "/") + (device (uuid + "96a8d2d0-d991-4dc2-b50e-be8884887961" + 'ext4)) + (type "ext4")) + (file-system + (mount-point "/home") + (device (uuid + "b90ebc14-5472-4dbe-98e4-0b6e72f48199" + 'ext4)) + (type "ext4")) %base-file-systems))) diff --git a/os/signing-key.pub b/os/signing-key.pub new file mode 100644 index 0000000..56ee811 --- /dev/null +++ b/os/signing-key.pub @@ -0,0 +1,6 @@ +(public-key + (ecc + (curve Ed25519) + (q #C1FD53E5D4CE971933EC50C9F307AE2171A2D3B52C804642A7A35F84F3A4EA98#) + ) + ) |