Skip to content

Latest commit

 

History

History
6706 lines (5666 loc) · 199 KB

freebsd-dotfiles-mac.org

File metadata and controls

6706 lines (5666 loc) · 199 KB

Freebsd Dotfiles mac

tangle dotfiles

tangle document

C-c C-v t

tangle only one code block

C-u C-c C-v t

tangle from the command line

emacs --batch -l org --eval '(org-babel-tangle-file "~/git/freebsd-dotfiles/freebsd-dotfiles.org")'

freebsd dotfiles

emacs

emacs config

init.el

;; ----------------------------------------------------------------------------------
;; emacs init.el - also using early-init.el
;; ----------------------------------------------------------------------------------

;; Use a hook so the message doesn't get clobbered by other messages.
(add-hook 'emacs-startup-hook
          (lambda ()
            (message "Emacs ready in %s with %d garbage collections."
                     (format "%.2f seconds"
                             (float-time
                              (time-subtract after-init-time before-init-time)))
                     gcs-done)))


;; ----------------------------------------------------------------------------------
;; melpa packages
;; ----------------------------------------------------------------------------------

;; package-selected-packages
(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.
 '(auth-source-save-behavior nil)
 '(custom-safe-themes
   '("ffafb0e9f63935183713b204c11d22225008559fa62133a69848835f4f4a758c"
     "636b135e4b7c86ac41375da39ade929e2bd6439de8901f53f88fde7dd5ac3561"
     "" default))
 '(package-selected-packages
   '(async consult doom-modeline doom-modeline-now-playing doom-themes
           ednc elfeed elfeed-org elfeed-tube elfeed-tube-mpv embark
           embark-consult emmet-mode evil evil-collection evil-leader
           fd-dired git-auto-commit-mode google-translate hydra iedit
           marginalia mpv nerd-icons nix-mode ob-async orderless
           org-tree-slide rg s shrink-path undo-tree vertico wgrep
           which-key yaml-mode))
 '(warning-suppress-types '((comp))))

;; require package
(require 'package)

;; package archive
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
                         ("elpa" . "https://elpa.gnu.org/packages/")))

;; package initialize
(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))
(package-install-selected-packages)

;; emacs aysnc - asynchronous compilation of your (M)elpa packages
(async-bytecomp-package-mode 1)
(setq async-bytecomp-allowed-packages '(all))

;;(setq native-comp-deferred-compilation nil
;;comp-enable-subr-trampolines nil)


;; ----------------------------------------------------------------------------------
;; general settings
;; ----------------------------------------------------------------------------------

;; Save all tempfiles in $TMPDIR/emacs$UID/                                                        
(defconst emacs-tmp-dir (expand-file-name (format "emacs%d" (user-uid)) temporary-file-directory))
(setq backup-directory-alist
    `((".*" . ,emacs-tmp-dir)))
(setq auto-save-file-name-transforms
    `((".*" ,emacs-tmp-dir t)))
(setq auto-save-list-file-prefix
    emacs-tmp-dir)


;; dont backup files opened by sudo or doas
(setq backup-enable-predicate
      (lambda (name)
        (and (normal-backup-enable-predicate name)
             (not
              (let ((method (file-remote-p name 'method)))
                (when (stringp method)
                  (member method '("su" "sudo" "doas"))))))))


;; save
(save-place-mode 1)         ;; save cursor position
(desktop-save-mode 0)       ;; dont save the desktop session
(savehist-mode 1)           ;; save history
(global-auto-revert-mode 1) ;; revert buffers when the underlying file has changed

;; scrolling
(pixel-scroll-precision-mode 1)


;; ----------------------------------------------------------------------------------
;; fonts
;; ----------------------------------------------------------------------------------

(defvar efs/default-font-size 180)
(defvar efs/default-variable-font-size 180)


;; ----------------------------------------------------------------------------------
;; set-face-attribute
;; ----------------------------------------------------------------------------------

;; Set the default pitch face
(set-face-attribute 'default nil :font "Fira Code" :height efs/default-font-size)

;; Set the fixed pitch face
(set-face-attribute 'fixed-pitch nil :font "Fira Code" :height efs/default-font-size)

;; Set the variable pitch face
(set-face-attribute 'variable-pitch nil :font "Iosevka Aile" :height efs/default-variable-font-size :weight 'regular)

;; tab bar background
(set-face-attribute 'tab-bar nil
                    :foreground "#93a1a1")

;; active tab
(set-face-attribute 'tab-bar-tab nil
                    :foreground "#51AFEF")

;; inactive tab
(set-face-attribute 'tab-bar-tab-inactive nil
                    :foreground "grey50")


;; ----------------------------------------------------------------------------------
;; doom-modeline 
;; ----------------------------------------------------------------------------------

(require 'doom-modeline)
(doom-modeline-mode 1)

;; M-x nerd-icons-install-fonts
(setq doom-modeline-icon t)

;; doom modeline truncate text
(setq doom-modeline-buffer-file-name-style 'truncate-except-project)

;; hide the time icon
(setq doom-modeline-time-icon nil)

;; dont display the buffer encoding.
(setq doom-modeline-buffer-encoding nil)


;; ----------------------------------------------------------------------------------
;; doom modeline now playing
;; ----------------------------------------------------------------------------------

;; now playing
(require 'doom-modeline-now-playing)

;; max length
(setq doom-modeline-now-playing-max-length 35)

;; update interval 1 second
(setq doom-modeline-now-playing-interval 1)

;; ignored players
(setq doom-modeline-now-playing-ignored-players '("firefox"))

;; playerctl format
(setq doom-modeline-now-playing-format "[{{duration(position)}}/{{duration(mpris:length)}}] {{title}}")

(doom-modeline-def-modeline 'main
'(bar matches buffer-info remote-host buffer-position parrot selection-info now-playing)
'(misc-info minor-modes input-method buffer-encoding major-mode process vcs check time))

;; modeline
(with-eval-after-load 'doom-modeline-now-playing
(doom-modeline-def-segment now-playing
  "Current status of playerctl. Configurable via
variables for update interval, output format, etc."
  (when (and doom-modeline-now-playing
             (doom-modeline--active)
             doom-modeline-now-playing-status
             (not (string= (now-playing-status-player doom-modeline-now-playing-status) "No players found")))
    (let ((player (now-playing-status-player doom-modeline-now-playing-status))
          (status (now-playing-status-status doom-modeline-now-playing-status))
          (text   (now-playing-status-text   doom-modeline-now-playing-status)))
      (concat
       (propertize (if (equal status "playing")
                       (doom-modeline-icon 'faicon "nf-fa-circle_play" "" ">"
                                           :v-adjust -0)
                     (doom-modeline-icon 'faicon "nf-fa-circle_pause" "" "||"
                                         :v-adjust -0))
                   'mouse-face 'mode-line-highlight
                   'help-echo "mouse-1: Toggle player status"
                   'local-map (let ((map (make-sparse-keymap)))
                                (define-key map [mode-line mouse-1] 'doom-modeline-now-playing-toggle-status)
                                map))
       (doom-modeline-spc)
       (propertize
        (truncate-string-to-width text doom-modeline-now-playing-max-length nil nil "...")
        'face 'doom-modeline-now-playing-text))))))

;; doom-modeline-now-playing-timer - keep at bottom
(doom-modeline-now-playing-timer)


;; ----------------------------------------------------------------------------------
;; TAB bar mode 
;; ----------------------------------------------------------------------------------

(setq tab-bar-show 1)                     ;; hide bar if <= 1 tabs open
(setq tab-bar-close-button-show nil)      ;; hide close tab button
(setq tab-bar-new-button-show nil)        ;; hide new tab button
(setq tab-bar-new-tab-choice "*scratch*") ;; default tab scratch
(setq tab-bar-close-last-tab-choice 'tab-bar-mode-disable) 
(setq tab-bar-close-tab-select 'recent)
(setq tab-bar-new-tab-to 'right)
(setq tab-bar-tab-hints nil)
(setq tab-bar-separator " ")
(setq tab-bar-auto-width-max '((100) 20))
(setq tab-bar-auto-width t)

;; Customize the tab bar format to add the global mode line string
(setq tab-bar-format '(tab-bar-format-tabs tab-bar-separator tab-bar-format-align-right tab-bar-format-global))

;; menubar in tab bar
(add-to-list 'tab-bar-format #'tab-bar-format-menu-bar)

;; Turn on tab bar mode after startup
(tab-bar-mode 1)

;; tab bar menu bar button
(setq tab-bar-menu-bar-button "👿")

;; ----------------------------------------------------------------------------------
;; evil
;; ----------------------------------------------------------------------------------

;; evil
(setq evil-want-keybinding nil)

;; fix tab in evil for org mode
(setq evil-want-C-i-jump nil)

;; evil
(require 'evil)
(evil-collection-init)
(evil-mode 1)

;; dired use h and l
(evil-collection-define-key 'normal 'dired-mode-map
    "e" 'dired-find-file
    "h" 'dired-up-directory
    "l" 'dired-find-file-mpv)


;; ----------------------------------------------------------------------------------
;; require
;; ----------------------------------------------------------------------------------

;; tree-sitter
(require 'treesit)

;; ob-async
(require 'ob-async)

;; which key
(require 'which-key)
(which-key-mode)

;; undo tree
(require 'undo-tree)
(global-undo-tree-mode 1)
(setq undo-tree-visualizer-timestamps t)
(setq undo-tree-visualizer-diff t)


;; ----------------------------------------------------------------------------------
;; tree-sitter
;; ----------------------------------------------------------------------------------

;; M-x treesit-install-language-grammar bash
(add-to-list
 'treesit-language-source-alist
 '(bash "https://github.com/tree-sitter/tree-sitter-bash.git"))

;; sh-mode use bash-ts-mode
(add-to-list 'major-mode-remap-alist
             '(sh-mode . bash-ts-mode))


;; treesitter explore open in side window
(add-to-list 'display-buffer-alist
   '("^*tree-sitter explorer *" display-buffer-in-side-window
     (side . right)
     (window-width . 0.40)))


;; ----------------------------------------------------------------------------------
;; buffer list
;; ----------------------------------------------------------------------------------

;; display Buffer List in same window
(add-to-list 'display-buffer-alist
   '("^*Buffer List*" display-buffer-same-window))


;; ----------------------------------------------------------------------------------
;; setq
;; ----------------------------------------------------------------------------------

;; general
(setq version-control t)
(setq vc-make-backup-files t)
(setq backup-by-copying t)
(setq delete-old-versions t)
(setq kept-new-versions 6)
(setq kept-old-versions 2)
(setq create-lockfiles nil)
(setq undo-tree-auto-save-history nil)

;; pinentry
(defvar epa-pinentry-mode)
(setq epa-pinentry-mode 'loopback)

;; display time in mode line, hide load average
(setq display-time-format "%H:%M")
(setq display-time-default-load-average nil)
(display-time-mode 1)       ;; display time

;; change prompt from yes or no, to y or n
(setq use-short-answers t)

;; turn off blinking cursor
(setq blink-cursor-mode nil)

;; suppress large file prompt
(setq large-file-warning-threshold nil)

;; always follow symlinks
(setq vc-follow-symlinks t)

;; case insensitive search
(setq read-file-name-completion-ignore-case t)
(setq completion-ignore-case t)

;; M-n, M-p recall previous mini buffer commands
(setq history-length 25)

;; Use spaces instead of tabs
(setq-default indent-tabs-mode nil)

;; Use spaces instead of tabs
(setq-default indent-tabs-mode nil)

;; revert dired and other buffers
(setq global-auto-revert-non-file-buffers t)

;; eww browser text width
(setq shr-width 80)

;; company auto complete
(setq company-idle-delay 0)
(setq company-minimum-prefix-length 3)

;; ediff
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
(setq ediff-split-window-function 'split-window-horizontally)

;; disable ring bell
(setq ring-bell-function 'ignore)

;; side windows
(setq switch-to-buffer-obey-display-actions t)

;; hippie expand
(setq hippie-expand-try-functions-list
      '(try-expand-all-abbrevs
        try-complete-file-name-partially
        try-complete-file-name
        try-expand-dabbrev
        try-expand-dabbrev-from-kill
        try-expand-dabbrev-all-buffers
        try-expand-list
        try-expand-line
        try-complete-lisp-symbol-partially
        try-complete-lisp-symbol))

;; ----------------------------------------------------------------------------------
;; emacs 28 - dictionary server
;; ----------------------------------------------------------------------------------

(setq dictionary-server "dict.org")

;; mandatory, as the dictionary misbehaves!
(add-to-list 'display-buffer-alist
   '("^\\*Dictionary\\*" display-buffer-in-side-window
     (side . right)
     (window-width . 0.50)))


;; ----------------------------------------------------------------------------------
;; functions
;; ----------------------------------------------------------------------------------

;; clear the kill ring
(defun clear-kill-ring ()
  "Clear the results on the kill ring."
  (interactive)
  (setq kill-ring nil))

;; reload init.el
(defun my-reload-init ()
  "reload init.el"
  (interactive)
  (load-file "~/.config/emacs/init.el"))


;; ----------------------------------------------------------------------------------
;; completion
;; ----------------------------------------------------------------------------------

;; Vertico
(require 'vertico)
(require 'vertico-directory)

(with-eval-after-load 'evil
  (define-key vertico-map (kbd "C-j") 'vertico-next)
  (define-key vertico-map (kbd "C-k") 'vertico-previous)
  (define-key vertico-map (kbd "M-h") 'vertico-directory-up))

;; Cycle back to top/bottom result when the edge is reached
(customize-set-variable 'vertico-cycle t)

;; Start Vertico
(vertico-mode 1)

;;; Marginalia
(require 'marginalia)
(customize-set-variable 'marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
(marginalia-mode 1)


;; consult
(global-set-key (kbd "C-s") 'consult-line)
(define-key minibuffer-local-map (kbd "C-r") 'consult-history)

;; remap switch-to-buffer "C-x b" to consult-buffer
(global-set-key [remap switch-to-buffer] 'consult-buffer)

(setq completion-in-region-function #'consult-completion-in-region)

;; consult-yank-pop
(global-set-key (kbd "M-y") 'consult-yank-pop)

;; It lets you use a new minibuffer when you're in the minibuffer
(setq enable-recursive-minibuffers t)

;;; Orderless

;; Set up Orderless for better fuzzy matching
(require 'orderless)
(customize-set-variable 'completion-styles '(orderless basic))
(customize-set-variable 'completion-category-overrides '((file (styles . (partial-completion)))))


;;; Embark
(require 'embark)
(require 'embark-consult)

(global-set-key [remap describe-bindings] #'embark-bindings)
(global-set-key (kbd "C-,") 'embark-act)

;; Use Embark to show bindings in a key prefix with `C-h`
(setq prefix-help-command #'embark-prefix-help-command)

(with-eval-after-load 'embark-consult
  (add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode))


;; ----------------------------------------------------------------------------------
;; keymap-global-set
;; ----------------------------------------------------------------------------------

;; magit
;;(keymap-global-set "C-x g" 'magit-status)

;; org-capture
(keymap-global-set "C-c c" 'org-capture)

;; press M-/ and invoke hippie-expand
(keymap-global-set "M-/" 'hippie-expand)

;; window-toggle-side-windows
(keymap-global-set "C-x x w" 'window-toggle-side-windows)

;; ----------------------------------------------------------------------------------
;; keymap-set
;; ----------------------------------------------------------------------------------

(keymap-set global-map "C-c o" 'iedit-mode)
(keymap-set global-map "C-c l" 'org-store-link)
(keymap-set global-map "C-c a" 'org-agenda)


;; ----------------------------------------------------------------------------------
;; dired 
;; ----------------------------------------------------------------------------------

;; Toggle Hidden Files in Emacs dired with C-x M-o
(require 'dired-x)

;; dired-async
(autoload 'dired-async-mode "dired-async.el" nil t)
(dired-async-mode 1)

;; kill the current buffer when selecting a new directory to display
(setq dired-kill-when-opening-new-dired-buffer t)

;; dired directory listing options for ls
(setq dired-use-ls-dired t)
;; freebsd gls fix
(setq insert-directory-program "/usr/local/bin/gls")
(setq dired-listing-switches "-ahlv")

;; hide dotfiles
(setq dired-omit-mode t)

;; recursive delete and copy
(setq dired-recursive-copies 'always)
(setq dired-recursive-deletes 'always)

;; dired hide free space
(setq dired-free-space nil)

;; dired dwim
(setq dired-dwim-target t)

;; hide dotfiles
(setq dired-omit-files
      (concat dired-omit-files "\\|^\\..+$"))


;; dired hide long listing by default
(defun my-dired-mode-setup ()
  "show less information in dired buffers"
  (dired-hide-details-mode 1))
(add-hook 'dired-mode-hook 'my-dired-mode-setup)

;; dired omit
(add-hook 'dired-mode-hook (lambda () (dired-omit-mode 1)))

;; dired hide aync output buffer
(add-to-list 'display-buffer-alist (cons "\\*Async Shell Command\\*.*" (cons #'display-buffer-no-window nil)))

;; ob-async sentinel fix
(defun no-hide-overlays (orig-fun &rest args)
(setq org-babel-hide-result-overlays nil))
(advice-add 'ob-async-org-babel-execute-src-block :before #'no-hide-overlays)

;; & open pdf's with zatuhra
(setq dired-guess-shell-alist-user
      '(("\\.pdf$" "zathura")))


;; ----------------------------------------------------------------------------------
;; dired-fd
;; ----------------------------------------------------------------------------------

;; switch to buffer results automatically

(defcustom fd-dired-display-in-current-window nil
  "Whether display result"
  :type 'boolean
  :safe #'booleanp
  :group 'fd-dired)


;; ----------------------------------------------------------------------------------
;; rip-grep
;; ----------------------------------------------------------------------------------

;; rip-grep automatically switch to results buffer
;; https://github.com/dajva/rg.el/issues/142

(with-eval-after-load 'rg
  (advice-add 'rg-run :after
              #'(lambda (_pattern _files _dir &optional _literal _confirm _flags) (pop-to-buffer (rg-buffer-name)))))


;; ----------------------------------------------------------------------------------
;; tramp
;; ----------------------------------------------------------------------------------

;; tramp
(require 'tramp)

;; tramp setq
(setq tramp-default-method "ssh")

;; tramp ssh
(tramp-set-completion-function "ssh"
                               '((tramp-parse-sconfig "/etc/ssh_config")
                                 (tramp-parse-sconfig "~/.ssh/config")))

;; set tramp shell to bash to avoid zsh problems
(setenv "SHELL" "/bin/sh")
(setq tramp-allow-unsafe-temporary-files t)

;; tramp backup directory
(add-to-list 'backup-directory-alist (cons tramp-file-name-regexp nil))


;; ----------------------------------------------------------------------------------
;; org mode
;; ----------------------------------------------------------------------------------

;; org mode
(require 'org)
(require 'org-tempo)
(require 'org-protocol)
(require 'org-capture)
(setq org-agenda-files '("~/git/personal/org/"))

;; resize org headings
(require 'org-faces)
(dolist (face '((org-level-1 . 1.2)
                (org-level-2 . 1.1)
                (org-level-3 . 1.05)
                (org-level-4 . 1.0)
                (org-level-5 . 1.1)
                (org-level-6 . 1.1)
                (org-level-7 . 1.1)
                (org-level-8 . 1.1)))
  (set-face-attribute (car face) nil :font "Iosevka Aile" :weight 'medium :height (cdr face)))

;; org babel supress do you want to execute code message
(setq org-confirm-babel-evaluate nil
      org-src-fontify-natively t
      org-src-tab-acts-natively t)

;; org hide markup
(setq org-hide-emphasis-markers t)

;; org column spacing for tags
(setq org-tags-column 0)

;; dont indent src block for export
(setq org-src-preserve-indentation t)

;; org src to use the current window
(setq org-src-window-setup 'current-window)

;; dont show images full size
(setq org-image-actual-width nil)

;; prevent demoting heading also shifting text inside sections
(setq org-adapt-indentation nil)

;; asynchronous tangle
(setq org-export-async-debug t)

(setq org-capture-templates
    '(("w" "web site" entry
      (file+olp "~/git/personal/bookmarks/bookmarks.org" "sites")
      "** [[%c][%^{link-description}]]"
       :empty-lines-after 1)
      ("v" "video url" entry
       (file+olp "~/git/personal/bookmarks/video.org" "links")
       "** [[video:%c][%^{link-description}]]"
        :empty-lines-after 1)))

;; refile
(setq org-refile-targets '((nil :maxlevel . 2)
                                (org-agenda-files :maxlevel . 2)))
(setq org-outline-path-complete-in-steps nil)         ; Refile in a single go
(setq org-refile-use-outline-path t)                  ; Show full paths for refiling

;; ox-pandoc export
(setq org-pandoc-options-for-latex-pdf '((latex-engine . "xelatex")))

;; Prepare stuff for org-export-backends
(setq org-export-backends '(org md html latex icalendar odt ascii))

;; todo keywords
(setq org-todo-keywords
      '((sequence "TODO(t@/!)" "IN-PROGRESS(p/!)" "WAITING(w@/!)" "|" "DONE(d@)")))
(setq org-log-done t)

;; Fast Todo Selection - Changing a task state is done with C-c C-t KEY
(setq org-use-fast-todo-selection t)

;; org todo logbook
(setq org-log-into-drawer t)

;; org open files
(setq org-file-apps
     (quote
     ((auto-mode . emacs)
     ("\\.mm\\'" . default)
     ("\\.x?html?\\'" . default)
     ("\\.mkv\\'" . "mpv %s")
     ("\\.mp4\\'" . "mpv %s")
     ("\\.mov\\'" . "mpv %s")
     ("\\.pdf\\'" . default))))

  
(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.
 '(org-link ((t (:inherit link :underline nil)))))

(defadvice org-capture
    (after make-full-window-frame activate)
  "Advise capture to be the only window when used as a popup"
  (if (equal "emacs-capture" (frame-parameter nil 'name))
      (delete-other-windows)))

(defadvice org-capture-finalize
    (after delete-capture-frame activate)
  "Advise capture-finalize to close the frame"
  (if (equal "emacs-capture" (frame-parameter nil 'name))
      (delete-frame)))

; org-babel shell script
(org-babel-do-load-languages
'org-babel-load-languages
'((shell . t))) 

;; yank-media--registered-handlers org mode
(with-eval-after-load 'org
  (setq yank-media--registered-handlers '(("image/.*" . #'org-mode--image-yank-handler))))

;; org mode image yank handler
(yank-media-handler "image/.*" #'org-mode--image-yank-handler)

;; org-mode insert image as file link from the clipboard
(defun org-mode--image-yank-handler (type image)
  (let ((file (read-file-name (format "Save %s image to: " type))))
    (when (file-directory-p file)
      (user-error "%s is a directory"))
    (when (and (file-exists-p file)
               (not (yes-or-no-p (format "%s exists; overwrite?" file))))
      (user-error "%s exists"))
    (with-temp-buffer
      (set-buffer-multibyte nil)
      (insert image)
      (write-region (point-min) (point-max) file))
    (insert (format "[[file:%s]]\n" (file-relative-name file)))))


;; ----------------------------------------------------------------------------------
;; org tree slide
;; ----------------------------------------------------------------------------------

;; presentation start
(defun my/presentation-setup ()
(setq-local mode-line-format nil) 
(setq-local face-remapping-alist '((default (:height 1.5) variable-pitch)
                                   (header-line (:height 4.0) variable-pitch)
                                   (org-document-title (:height 1.75) org-document-title)
                                   (org-code (:height 1.55) org-code)
                                   (org-verbatim (:height 1.55) org-verbatim)
                                   (org-block (:height 1.25) org-block)
                                   (org-block-begin-line (:height 0.7) org-block))))

;; presentation end
(defun my/presentation-end ()
(doom-modeline-set-modeline 'main)
  (setq-local face-remapping-alist '((default fixed-pitch default)))
  (setq-local face-remapping-alist '((default variable-pitch default))))

;; Make sure certain org faces use the fixed-pitch face when variable-pitch-mode is on
(set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
(set-face-attribute 'org-table nil :inherit 'fixed-pitch)
(set-face-attribute 'org-formula nil :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)

;; presentation hooks
(add-hook 'org-tree-slide-play-hook 'my/presentation-setup)
(add-hook 'org-tree-slide-stop-hook 'my/presentation-end)

;; org tree slide settings
(setq org-tree-slide-header nil)
(setq org-tree-slide-activate-message "Presentation started")
(setq org-tree-slide-deactivate-message "Presentation finished")
(setq org-tree-slide-slide-in-effect t)
(setq org-tree-slide-breakcrumbs " // ")
(setq org-tree-slide-heading-emphasis nil)
(setq org-tree-slide-slide-in-blank-lines 2)
(setq org-tree-slide-indicator nil)

;; make #+ lines invisible during presentation
(with-eval-after-load "org-tree-slide"
  (defvar my-hide-org-meta-line-p nil)
  (defun my-hide-org-meta-line ()
    (interactive)
    (setq my-hide-org-meta-line-p t)
    (set-face-attribute 'org-meta-line nil
			                  :foreground (face-attribute 'default :background)))
  (defun my-show-org-meta-line ()
    (interactive)
    (setq my-hide-org-meta-line-p nil)
    (set-face-attribute 'org-meta-line nil :foreground nil))

  (defun my-toggle-org-meta-line ()
    (interactive)
    (if my-hide-org-meta-line-p
	      (my-show-org-meta-line) (my-hide-org-meta-line)))

  (add-hook 'org-tree-slide-play-hook #'my-hide-org-meta-line)
  (add-hook 'org-tree-slide-stop-hook #'my-show-org-meta-line))


;; ----------------------------------------------------------------------------------
;; mutt
;; ----------------------------------------------------------------------------------

(add-to-list 'auto-mode-alist '("/mutt" . mail-mode))


;; ----------------------------------------------------------------------------------
;; add-hook
;; ----------------------------------------------------------------------------------

;; Make shebang (#!) file executable when saved
(add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)

;; global company mode
;;(add-hook 'after-init-hook 'global-company-mode)

;; visual line mode
(add-hook 'text-mode-hook 'visual-line-mode)

;; h1 line mode
(add-hook 'prog-mode-hook #'hl-line-mode)
(add-hook 'text-mode-hook #'hl-line-mode)

;; flycheck syntax linting
(add-hook 'sh-mode-hook 'flycheck-mode)


;; ----------------------------------------------------------------------------------
;; wayland clipboard
;; ----------------------------------------------------------------------------------

;; credit: yorickvP on Github
(setq wl-copy-process nil)
(defun wl-copy (text)
  (setq wl-copy-process (make-process :name "wl-copy"
                                      :buffer nil
                                      :command '("wl-copy" "-f" "-n")
                                      :connection-type 'pipe
                                      :noquery t))
  (process-send-string wl-copy-process text)
  (process-send-eof wl-copy-process))
(defun wl-paste ()
  (if (and wl-copy-process (process-live-p wl-copy-process))
      nil ; should return nil if we're the current paste owner
      (shell-command-to-string "wl-paste -n | tr -d \r")))
(setq interprogram-cut-function 'wl-copy)
(setq interprogram-paste-function 'wl-paste)


;; ----------------------------------------------------------------------------------
;; mpv.el
;; ----------------------------------------------------------------------------------

;; mpv-default-options play fullscreen on second display
(setq mpv-default-options '("--fs" "--fs-screen=1"))


;; get the youtube title from url on the clipboard
(defun yt-get-title ()
  "get the youtube title from a url on the clipboard"
  (interactive)
  (let ((yt-url (current-kill 0 t)))
    (async-shell-command (concat
                   "yt-dlp --skip-download --no-playlist --print \"%(title)s\" " (shell-quote-argument yt-url)))))


;; yank the async buffer
(defun yank-async ()
  "yank async buffer"
  (interactive)
    (yank (kill-new (with-current-buffer "*Async Shell Command*"
    (buffer-substring-no-properties (point-min) (point-max))))))


;; create a video: link type that opens a url using mpv-play-remote-video
(org-link-set-parameters "video"
                         :follow #'mpv-play-remote-video
                         :store #'org-video-store-link)


;; org video store link
(defun org-video-store-link ()
  "Store a link to a video url."
      (org-link-store-props
       :type "video"
       :link link
       :description description))


;; mpv-play-remote-video
(defun mpv-play-remote-video (url &rest args)
  "Start an mpv process playing the video stream at URL."
  (interactive)
  (unless (mpv--url-p url)
    (user-error "Invalid argument: `%s' (must be a valid URL)" url))
  (if (not mpv--process)
      ;; mpv isnt running play file
      (mpv-start url)
      ;; mpv running append file to playlist
    (mpv--playlist-append url)))


;; mpv-play-clipboard - play url from clipboard
(defun mpv-play-clipboard ()
  "Start an mpv process playing the video stream at URL."
  (interactive)
  (let ((url (current-kill 0 t)))
  (unless (mpv--url-p url)
    (user-error "Invalid argument: `%s' (must be a valid URL)" url))
  (if (not mpv--process)
      ;; mpv isnt running play file
      (mpv-start url)
      ;; mpv running append file to playlist
    (mpv--playlist-append url))))

;; create a mpv: link type that opens a file using mpv-play
(defun org-mpv-complete-link (&optional arg)
  (replace-regexp-in-string
   "file:" "mpv:"
   (org-link-complete-file arg)
   t t))
(org-link-set-parameters "mpv"
  :follow #'mpv-play :complete #'org-mpv-complete-link)

;; M-RET will insert a new item with the timestamp of the current playback position
(defun my:mpv/org-metareturn-insert-playback-position ()
  (when-let ((item-beg (org-in-item-p)))
    (when (and (not org-timer-start-time)
               (mpv-live-p)
               (save-excursion
                 (goto-char item-beg)
                 (and (not (org-invisible-p)) (org-at-item-timer-p))))
      (my/mpv-insert-playback-position t))))
(add-hook 'org-metareturn-hook #'my:mpv/org-metareturn-insert-playback-position)

;; mpv insert playback position
(with-eval-after-load 'mpv
  (defun my/mpv-insert-playback-position (&optional arg)
    "Insert the current playback position at point.

  When called with a non-nil ARG, insert a timer list item like `org-timer-item'."
    (interactive "P")
    (let ((time (mpv-get-playback-position)))
      (funcall
       (if arg #'mpv--position-insert-as-org-item #'insert)
       (my/org-timer-secs-to-hms (float time))))))


;; seek to position
(with-eval-after-load 'mpv
  (defun my/mpv-seek-to-position-at-point ()
    "Jump to playback position as inserted by `mpv-insert-playback-position'.

  This can be used with the `org-open-at-point-functions' hook."
    (interactive)
    (save-excursion
      (skip-chars-backward ":[:digit:]" (point-at-bol))
      (when (looking-at "[0-9]+:[0-9]\\{2\\}:[0-9]\\{2\\}\\([.]?[0-9]\\{0,3\\}\\)"))
        (let ((secs (my/org-timer-hms-to-secs (match-string 0))))
          (when (>= secs 0)
            (mpv-seek secs))))))

;; mpv seek to position at point
(keymap-set global-map "C-x ," 'my/mpv-seek-to-position-at-point)


;; ----------------------------------------------------------------------------------
;; org-timer milliseconds for mpv
;; ----------------------------------------------------------------------------------

;; org-timer covert seconds and milliseconds to hours, minutes, seconds, milliseconds
(with-eval-after-load 'org-timer
  (defun my/org-timer-secs-to-hms (s)
    "Convert integer S into hh:mm:ss.m
  If the integer is negative, the string will start with \"-\"."
    (let (sign m h)
      (setq x (number-to-string s)
            seconds (car (split-string x "[.]"))
            milliseconds (cadr (split-string x "[.]"))
            sec (string-to-number seconds)
            ms (string-to-number milliseconds))
      (setq sign (if (< sec 0) "-" "")
          sec (abs sec)
          m (/ sec 60) sec (- sec (* 60 m))
          h (/ m 60) m (- m (* 60 h)))
      (format "%s%02d:%02d:%02d.%02d" sign h m sec ms))))

;; org-timer covert hours, minutes, seconds, milliseconds to seconds, milliseconds
(with-eval-after-load 'org-timer
  (defun my/org-timer-hms-to-secs (hms)
    "Convert h:mm:ss string to an integer time.
  If the string starts with a minus sign, the integer will be negative."
    (if (not (string-match
            "\\([-+]?[0-9]+\\):\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\([.]?[0-9]\\{0,3\\}\\)"
            hms))
        0
      (let* ((h (string-to-number (match-string 1 hms)))
           (m (string-to-number (match-string 2 hms)))
           (s (string-to-number (match-string 3 hms)))
           (ms (string-to-number (match-string 4 hms)))
           (sign (equal (substring (match-string 1 hms) 0 1) "-")))
        (setq h (abs h))
        (* (if sign -1 1) (+ s (+ ms (* 60 (+ m (* 60 h))))))))))


;; ----------------------------------------------------------------------------------
;; mpv commands
;; ----------------------------------------------------------------------------------

;; frame step forward
(with-eval-after-load 'mpv
  (defun mpv-frame-step ()
    "Step one frame forward."
    (interactive)
    (mpv--enqueue '("frame-step") #'ignore)))


;; frame step backward
(with-eval-after-load 'mpv
  (defun mpv-frame-back-step ()
    "Step one frame backward."
    (interactive)
    (mpv--enqueue '("frame-back-step") #'ignore)))


;; mpv take a screenshot
(with-eval-after-load 'mpv
  (defun mpv-screenshot ()
    "Take a screenshot"
    (interactive)
    (mpv--enqueue '("screenshot") #'ignore)))


;; mpv show osd
(with-eval-after-load 'mpv
  (defun mpv-osd ()
    "Show the osd"
    (interactive)
    (mpv--enqueue '("set_property" "osd-level" "3") #'ignore)))


;; add a newline in the current document
(defun end-of-line-and-indented-new-line ()
  (interactive)
  (end-of-line)
  (newline-and-indent))


;; ----------------------------------------------------------------------------------
;; mpv dired
;; ----------------------------------------------------------------------------------

;; video and audio mime types
(defvar supported-mime-types
  '("video/quicktime"
    "video/x-matroska"
    "video/mp4"
    "video/webm"
    "video/x-m4v"
    "video/x-msvideo"
    "audio/x-wav"
    "audio/mpeg"
    "audio/x-hx-aac-adts"
    "audio/mp4"
    "audio/flac"
    "audio/ogg"))

;; subr-x
(load "subr-x")

;; get files mime type
(defun get-mimetype (filepath)
  (string-trim
   (shell-command-to-string (concat "file -b --mime-type "
                                    (shell-quote-argument filepath)))))

;; dired-find-file-mpv
(defun dired-find-file-mpv ()
  "Start an mpv process playing the file at PATH append subsequent files to the playlist"
  (interactive)
  (let ((file (dired-get-file-for-visit)))
    (if (member (get-mimetype file) supported-mime-types)
        (mpv-play-dired file)
      (dired-find-file))))


;; mpv-play-dired
(with-eval-after-load 'mpv
  (defun mpv-play-dired (path)
  "Start an mpv process playing the file at PATH append subsequent files to the playlist"
    (if (not mpv--process)
        ;; mpv isnt running play file
        (mpv-start (expand-file-name path))
        ;; mpv running append file to playlist
      (mpv--playlist-append (expand-file-name path)))))


;; mpv play dired marked files
(defun mpv-play-marked-files ()
  "Play marked files with mpv"
  (interactive)
  (mapc 'mpv-play-dired (dired-get-marked-files nil nil nil t)))

;; mpv dired embark
(with-eval-after-load 'embark
  (define-key embark-file-map "l" #'mpv-play-marked-files))


;; ----------------------------------------------------------------------------------
;; mpv eww
;; ----------------------------------------------------------------------------------

(defun mpv-play-eww ()
  "Start an mpv process playing the video stream at URL."
  (interactive)
  (let ((url (shr-url-at-point current-prefix-arg)))
  (unless (mpv--url-p url)
    (user-error "Invalid argument: `%s' (must be a valid URL)" url))
  (if (not mpv--process)
      ;; mpv isnt running play file
      (mpv-start url)
      ;; mpv running append file to playlist
    (mpv--playlist-append url))))


(evil-collection-define-key 'normal 'eww-mode-map
    "l" 'mpv-play-eww)


;; ----------------------------------------------------------------------------------
;; eww pinch
;; ----------------------------------------------------------------------------------

(defun eww-pinch ()
  "Send the url under the point to mpd with pinch"
  (interactive)
  (let ((url (shr-url-at-point current-prefix-arg)))
    (async-shell-command (concat
                    "pinch -i " (shell-quote-argument url)))))


(evil-collection-define-key 'normal 'eww-mode-map
    "n" 'eww-pinch)


;; ----------------------------------------------------------------------------------
;; eww taskspooler yt-dlp
;; ----------------------------------------------------------------------------------

(defun eww-yt-dlp ()
  "Send the url under the point to taskspooler and yt-dlp"
  (interactive)
  (let ((url (shr-url-at-point current-prefix-arg)))
    (async-shell-command (concat
                    "ts yt-dlp -o '%(title)s.%(ext)s' -P ~/downloads " (shell-quote-argument url)))))


(evil-collection-define-key 'normal 'eww-mode-map
    "x" 'eww-yt-dlp)


;; ----------------------------------------------------------------------------------
;; eww taskspooler aria2c
;; ----------------------------------------------------------------------------------

(defun eww-aria2c ()
  "Send the url under the point to taskspooler and aria2c"
  (interactive)
  (let ((url (shr-url-at-point current-prefix-arg)))
    (async-shell-command (concat
                    "ts aria2c -d ${HOME}/downloads " (shell-quote-argument url)))))


(evil-collection-define-key 'normal 'eww-mode-map
    "b" 'eww-aria2c)


;; ----------------------------------------------------------------------------------
;; kocontrol - kodi
;; ----------------------------------------------------------------------------------

;; toggle play/pause
(defun kodi-play ()
  "Kodi toggle play/pause"
  (interactive)
  (async-shell-command "kocontrol -p play"))

;; stop playback
(defun kodi-stop ()
  "Kodi stop playback"
  (interactive)
  (async-shell-command "kocontrol -x stop"))

;; seek forward 5 seconds
(defun kodi-seek-forward-5 ()
  "Kodi seek forward 5 seconds"
  (interactive)
  (async-shell-command "kocontrol -s 5"))

;; seek forward 60 seconds
(defun kodi-seek-forward-60 ()
  "Kodi seek forward 60 seconds"
  (interactive)
  (async-shell-command "kocontrol -s 60"))

;; seek backward 5 seconds
(defun kodi-seek-backward-5 ()
  "Kodi seek backward 5 seconds"
  (interactive)
  (async-shell-command "kocontrol -s -5"))

;; seek backward 60 seconds
(defun kodi-seek-backward-60 ()
  "Kodi seek backward 60 seconds"
  (interactive)
  (async-shell-command "kocontrol -s -60"))

;; kodi-forward kodi forward 2x speed
(defun kodi-forward ()
  "Kodi forward 2x speed"
  (interactive)
  (async-shell-command "kocontrol -f 2"))

;; kodi-rewind kodi rewind 2x speed
(defun kodi-rewind ()
  "Kodi rewind 2x speed"
  (interactive)
  (async-shell-command "kocontrol -r 2"))


;; ----------------------------------------------------------------------------------
;; hydra
;; ----------------------------------------------------------------------------------

(defhydra hydra-mpv (global-map "<f2>")
  "
  ^Seek^                    ^Actions^                ^General^                       ^Playlists^
  ^^^^^^^^-----------------------------------------------------------------------------------------------------------
  _h_: seek back -5         _,_: back frame          _i_: insert playback position   _n_: next item in playlist
  _j_: seek back -60        _._: forward frame       _m_: insert a newline           _p_: previous item in playlist
  _k_: seek forward 60      _SPC_: pause             _s_: take a screenshot          _e_: jump to playlist entry
  _l_: seek forward 5       _q_: quit mpv            _o_: show the osd               _r_: remove playlist entry
  ^
  "
  ("h" mpv-seek-backward "-5")
  ("j" mpv-seek-backward "-60")
  ("k" mpv-seek-forward "60")
  ("l" mpv-seek-forward "5")
  ("," mpv-frame-back-step)
  ("." mpv-frame-step)
  ("SPC" mpv-pause)
  ("q" mpv-kill)
  ("i" my/mpv-insert-playback-position)
  ("m" end-of-line-and-indented-new-line)
  ("s" mpv-screenshot)
  ("o" mpv-osd)
  ("n" mpv-playlist-next)
  ("p" mpv-playlist-prev)
  ("e" mpv-jump-to-playlist-entry)
  ("r" mpv-remove-playlist-entry))


;; ----------------------------------------------------------------------------------
;; hydra-kodi
;; ----------------------------------------------------------------------------------

(defhydra hydra-kodi (global-map "<f9>")
  "
  ^Seek^                    ^Actions^          
  ^^^^^^^^----------------------------------------------
  _h_: seek back -5         _SPC_: toggle play pause
  _j_: seek back -60        _x_: stop playback
  _k_: seek forward 60      _f_: forward       
  _l_: seek forward 5       _r_: rewind
  ^
  "
  ("h" kodi-seek-backward-5)
  ("j" kodi-seek-backward-60)
  ("k" kodi-seek-forward-60)
  ("l" kodi-seek-forward-5)
  ("SPC" kodi-play)
  ("x" kodi-stop)
  ("f" kodi-forward)
  ("r" kodi-rewind))


;; ----------------------------------------------------------------------------------
;; emacs desktop notification center
;; ----------------------------------------------------------------------------------

;; start ednc-mode
(ednc-mode 1)

(defun show-notification-in-buffer (old new)
  (let ((name (format "Notification %d" (ednc-notification-id (or old new)))))
    (with-current-buffer (get-buffer-create name)
      (if new (let ((inhibit-read-only t))
                (if old (erase-buffer) (ednc-view-mode))
                (insert (ednc-format-notification new t))
                (pop-to-buffer (current-buffer)))
        (kill-buffer)))))


;; notifications hook
(add-hook 'ednc-notification-presentation-functions
          #'show-notification-in-buffer)

;; open notifications in side window
(add-to-list 'display-buffer-alist
   '("^Notification *" display-buffer-in-side-window
     (side . right)
     (window-width . 0.50)))

;; ednc evil - normal mode
(defun noevil ()
  (evil-define-key 'normal ednc-view-mode-map "d" 'ednc-dismiss-notification)
  (evil-define-key 'normal ednc-view-mode-map (kbd "RET") 'ednc-invoke-action)
)

(add-hook 'ednc-view-mode-hook 'noevil)

; ----------------------------------------------------------------------------------
;; elfeed
;; ----------------------------------------------------------------------------------

; elfeed
(require 'elfeed)
(require 'elfeed-org)
(elfeed-org)
(setq elfeed-db-directory "~/.config/emacs/elfeed") ;; elfeed db location
(setq rmh-elfeed-org-files (list "~/git/personal/feeds/feeds.org"))
(global-set-key (kbd "C-x w") 'elfeed)

(require 'elfeed-tube)
(elfeed-tube-setup)
(define-key elfeed-show-mode-map (kbd "F") 'elfeed-tube-fetch)
(define-key elfeed-show-mode-map [remap save-buffer] 'elfeed-tube-save)
(define-key elfeed-search-mode-map (kbd "F") 'elfeed-tube-fetch)
(define-key elfeed-search-mode-map [remap save-buffer] 'elfeed-tube-save)

(require 'elfeed-tube-mpv)
(define-key elfeed-show-mode-map (kbd "C-c C-f") 'elfeed-tube-mpv-follow-mode)
(define-key elfeed-show-mode-map (kbd "C-c C-w") 'elfeed-tube-mpv-where)

;; play video with mpv
(define-key elfeed-show-mode-map (kbd "C-c C-d") 'elfeed-tube-mpv)

;; mpv play fullscreen on second display
(setq elfeed-tube-mpv-options
  '("--force-window=yes" "--fs" "--fs-screen=1"))

; elfeed evil
(add-to-list 'evil-motion-state-modes 'elfeed-search-mode)
(add-to-list 'evil-motion-state-modes 'elfeed-show-mode)

;; evil elfeed-search-mode-map
(evil-collection-define-key 'normal 'elfeed-search-mode-map
     "l" 'elfeed-search-show-entry        ;; l opens entry
     "s" #'prot-elfeed-search-tag-filter  ;; s prot search tags
     "R" 'elfeed-mark-all-as-read         ;; R mark all as read
     "u" 'elfeed-update                   ;; u elfeed update
     "b" #'elfeed-search-browse-url       ;; b open in browser
     "r" 'elfeed-search-untag-all-unread) ;; r mark as read


;; evil elfeed-show-mode-map
(evil-collection-define-key 'normal 'elfeed-show-mode-map
     "b" #'shr-browse-url)                ;; b open in browser

; elfeed search filter 
(setq-default elfeed-search-filter "@1-week-ago +unread")

; mark all as read
(defun elfeed-mark-all-as-read ()
      (interactive)
      (mark-whole-buffer)
      (elfeed-search-untag-all-unread))

;; elfeed-send-to-kodi
(defun elfeed-send-to-kodi (&optional link)
  "Send the current entry link URL to Kodi."
  (interactive "P")
  (let ((link (elfeed-entry-link elfeed-show-entry)))
    (when link
      (async-shell-command (concat
                      "kyt-send -i " (shell-quote-argument link))))))

;; elfeed-send-to-kodi keymap
(define-key elfeed-show-mode-map (kbd "C-c C-s") 'elfeed-send-to-kodi)



;; ----------------------------------------------------------------------------------
;; prot elfeed - requires ~/.config/emacs/lisp/prot-common.el
;; ----------------------------------------------------------------------------------

(eval-when-compile (require 'subr-x))
;;(require 'elfeed nil t)
(require 'url-util)
(require 'prot-common)

(defgroup prot-elfeed ()
  "Personal extensions for Elfeed."
  :group 'elfeed)

;;;; Utilities
(defvar prot-elfeed--tag-hist '()
  "History of inputs for `prot-elfeed-toggle-tag'.")

(defun prot-elfeed--character-prompt (tags)
  "Helper of `prot-elfeed-toggle-tag' to read TAGS."
  (let ((def (car prot-elfeed--tag-hist)))
    (completing-read
     (format "Toggle tag [%s]: " def)
     tags nil t nil 'prot-elfeed--tag-hist def)))

(defvar elfeed-show-entry)
(declare-function elfeed-tagged-p "elfeed")
(declare-function elfeed-search-toggle-all "elfeed")
(declare-function elfeed-show-tag "elfeed")
(declare-function elfeed-show-untag "elfeed")

;;;###autoload
(defun prot-elfeed-toggle-tag (tag)
  "Toggle TAG for the current item.

When the region is active in the `elfeed-search-mode' buffer, all
entries encompassed by it are affected.  Otherwise the item at
point is the target.  For `elfeed-show-mode', the current entry
is always the target.

The list of tags is provided by `prot-elfeed-search-tags'."
  (interactive
   (list
    (intern
     (prot-elfeed--character-prompt prot-elfeed-search-tags))))
  (if (derived-mode-p 'elfeed-show-mode)
      (if (elfeed-tagged-p tag elfeed-show-entry)
          (elfeed-show-untag tag)
        (elfeed-show-tag tag))
    (elfeed-search-toggle-all tag)))

(defvar elfeed-show-truncate-long-urls)
(declare-function elfeed-entry-title "elfeed")
(declare-function elfeed-show-refresh "elfeed")

;;;; General commands
(defvar elfeed-search-filter-active)
(defvar elfeed-search-filter)
(declare-function elfeed-db-get-all-tags "elfeed")
(declare-function elfeed-search-update "elfeed")
(declare-function elfeed-search-clear-filter "elfeed")

(defun prot-elfeed--format-tags (tags sign)
  "Prefix SIGN to each tag in TAGS."
  (mapcar (lambda (tag)
            (format "%s%s" sign tag))
          tags))

;;;###autoload
(defun prot-elfeed-search-tag-filter ()
  "Filter Elfeed search buffer by tags using completion.

Completion accepts multiple inputs, delimited by `crm-separator'.
Arbitrary input is also possible, but you may have to exit the
minibuffer with something like `exit-minibuffer'."
  (interactive)
  (unwind-protect
      (elfeed-search-clear-filter)
    (let* ((elfeed-search-filter-active :live)
           (db-tags (elfeed-db-get-all-tags))
           (plus-tags (prot-elfeed--format-tags db-tags "+"))
           (minus-tags (prot-elfeed--format-tags db-tags "-"))
           (all-tags (delete-dups (append plus-tags minus-tags)))
           (tags (completing-read-multiple
                  "Apply one or more tags: "
                  all-tags #'prot-common-crm-exclude-selected-p t))
           (input (string-join `(,elfeed-search-filter ,@tags) " ")))
      (setq elfeed-search-filter input))
    (elfeed-search-update :force)))

(provide 'prot-elfeed)

;; ----------------------------------------------------------------------------------
;; mpc
;; ----------------------------------------------------------------------------------

;; mpd host
(setq mpc-host "/home/djwilcox/.config/mpd/socket")


;; ----------------------------------------------------------------------------------
;; garbage collection
;; ----------------------------------------------------------------------------------

;; Make gc pauses faster by decreasing the threshold.
(setq gc-cons-threshold (* 2 1000 1000))

early-init.el

;;; early-init.el -*- lexical-binding: t; -*-

;;; Garbage collection
;; Increase the GC threshold for faster startup
;; The default is 800 kilobytes.  Measured in bytes.
(setq gc-cons-threshold (* 50 1000 1000))

;;; UI configuration
;; Remove some unneeded UI elements (the user can turn back on anything they wish)
(setq inhibit-startup-message t)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)

;; general settings
(setq initial-scratch-message nil)

;; Don’t compact font caches during GC.
(setq inhibit-compacting-font-caches t)

;; load theme
(add-hook 'after-init-hook (lambda () (load-theme 'doom-solarized-dark)))

;; start the initial frame maximized
(add-to-list 'initial-frame-alist '(fullscreen . maximized))

;; start every frame maximized
(add-to-list 'default-frame-alist '(fullscreen . maximized))

;;Tell emacs where is your personal elisp lib dir
(add-to-list 'load-path "~/.config/emacs/lisp/")

;; Make the initial buffer load faster by setting its mode to fundamental-mode
(customize-set-variable 'initial-major-mode 'fundamental-mode)

bookmarks config

;;;; Emacs Bookmark Format Version 1;;;; -*- coding: utf-8-emacs; mode: lisp-data -*-
;;; This format is meant to be slightly human-readable;
;;; nevertheless, you probably don't want to edit it.
;;; -*- End Of Bookmark File Format Version Stamp -*-
(("video" (filename . "~/git/personal/bookmarks/video.org")
 (front-context-string . "#+TITLE: video l") (rear-context-string)
 (position . 1) (last-modified 26366 43436 379270 855000))
("desktop" (filename . "~/desktop/")
 (front-context-string . "  -rw-r--r--  1 ")
 (rear-context-string . "wilcox/desktop:\n") (position . 27)
 (last-modified 26100 23708 303122 580000))
("dotfiles"
 (filename . "~/git/freebsd/freebsd-dotfiles/freebsd-dotfiles-mac.org")
 (front-context-string . "* freebsd dotfil")
 (rear-context-string . "g\")'\n#+END_SRC\n\n") (position . 382)
 (last-modified 26009 27139 884243 798000))
("bookmarks" (filename . "~/git/personal/bookmarks/bookmarks.org")
 (front-context-string . "#+STARTUP: overv") (rear-context-string)
 (position . 1) (last-modified 25703 35089 410375 479000))
("feeds" (filename . "~/git/personal/feeds/feeds.org")
 (front-context-string . "* elfeed :elfeed")
 (rear-context-string . "TARTUP: content\n") (position . 20)
 (last-modified 25692 54791 894815 365000))
("org-refile-last-stored" (filename . "~/git/personal/org/web.org")
 (front-context-string . "** [[https://its")
 (rear-context-string . "lview\" program.\n") (position . 173198))
("root" (filename . "/") (front-context-string . "bin -> usr/bin\n ")
 (rear-context-string . " 7 Oct 30 23:23 ") (position . 197))
("home" (filename . "~/") (front-context-string . "..\n  drwxr-xr-x ")
 (rear-context-string . " 3 Oct 30 23:26 ") (position . 178))
("cerberus" (filename . "~/git/cerberus/")
 (front-context-string . "7zip\n  drwxr-xr-")
 (rear-context-string . "96 Jan  4  2016 ") (position . 249))
)

lisp

prot-common
;;; prot-common.el --- Common functions for my dotemacs -*- lexical-binding: t -*-

;; Copyright (C) 2020-2023  Protesilaos Stavrou

;; Author: Protesilaos Stavrou <[email protected]>
;; URL: https://protesilaos.com/emacs/dotemacs
;; Version: 0.1.0
;; Package-Requires: ((emacs "30.1"))

;; This file is NOT part of GNU Emacs.

;; 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 <https://www.gnu.org/licenses/>.

;;; Commentary:
;;
;; Common functions for my Emacs: <https://protesilaos.com/emacs/dotemacs/>.
;;
;; Remember that every piece of Elisp that I write is for my own
;; educational and recreational purposes.  I am not a programmer and I
;; do not recommend that you copy any of this if you are not certain of
;; what it does.

;;; Code:

(eval-when-compile
  (require 'subr-x))

(defgroup prot-common ()
  "Auxiliary functions for my dotemacs."
  :group 'editing)

;;;###autoload
(defun prot-common-number-even-p (n)
  "Test if N is an even number."
  (if (numberp n)
      (= (% n 2) 0)
    (error "%s is not a number" n)))

;;;###autoload
(defun prot-common-number-integer-p (n)
  "Test if N is an integer."
  (if (integerp n)
      n
    (error "%s is not an integer" n)))

;;;###autoload
(defun prot-common-number-integer-positive-p (n)
  "Test if N is a positive integer."
  (if (prot-common-number-integer-p n)
      (> n 0)
    (error "%s is not a positive integer" n)))

;; Thanks to Gabriel for providing a cleaner version of
;; `prot-common-number-negative': <https://github.com/gabriel376>.
;;;###autoload
(defun prot-common-number-negative (n)
  "Make N negative."
  (if (and (numberp n) (> n 0))
      (* -1 n)
    (error "%s is not a valid positive number" n)))

;;;###autoload
(defun prot-common-reverse-percentage (number percent change-p)
  "Determine the original value of NUMBER given PERCENT.

CHANGE-P should specify the increase or decrease.  For simplicity,
nil means decrease while non-nil stands for an increase.

NUMBER must satisfy `numberp', while PERCENT must be `natnump'."
  (unless (numberp number)
    (user-error "NUMBER must satisfy numberp"))
  (unless (natnump percent)
    (user-error "PERCENT must satisfy natnump"))
  (let* ((pc (/ (float percent) 100))
         (pc-change (if change-p (+ 1 pc) pc))
         (n (if change-p pc-change (float (- 1 pc-change)))))
    ;; FIXME 2021-12-21: If float, round to 4 decimal points.
    (/ number n)))

;;;###autoload
(defun prot-common-percentage-change (n-original n-final)
  "Find percentage change between N-ORIGINAL and N-FINAL numbers.

When the percentage is not an integer, it is rounded to 4
floating points: 16.666666666666664 => 16.667."
  (unless (numberp n-original)
    (user-error "N-ORIGINAL must satisfy numberp"))
  (unless (numberp n-final)
    (user-error "N-FINAL must satisfy numberp"))
  (let* ((difference (float (abs (- n-original n-final))))
         (n (* (/ difference n-original) 100))
         (round (floor n)))
    ;; FIXME 2021-12-21: Any way to avoid the `string-to-number'?
    (if (> n round) (string-to-number (format "%0.4f" n)) round)))

;; REVIEW 2023-04-07 07:43 +0300: I just wrote the conversions from
;; seconds.  Hopefully they are correct, but I need to double check.
(defun prot-common-seconds-to-minutes (seconds)
  "Convert a number representing SECONDS to MM:SS notation."
  (let ((minutes (/ seconds 60))
        (seconds (% seconds 60)))
    (format "%.2d:%.2d" minutes seconds)))

(defun prot-common-seconds-to-hours (seconds)
  "Convert a number representing SECONDS to HH:MM:SS notation."
  (let* ((hours (/ seconds 3600))
         (minutes (/ (% seconds 3600) 60))
         (seconds (% seconds 60)))
    (format "%.2d:%.2d:%.2d" hours minutes seconds)))

;;;###autoload
(defun prot-common-seconds-to-minutes-or-hours (seconds)
  "Convert SECONDS to either minutes or hours, depending on the value."
  (if (> seconds 3599)
      (prot-common-seconds-to-hours seconds)
    (prot-common-seconds-to-minutes seconds)))

;;;###autoload
(defun prot-common-rotate-list-of-symbol (symbol)
  "Rotate list value of SYMBOL by moving its car to the end.
Return the first element before performing the rotation.

This means that if `sample-list' has an initial value of `(one
two three)', this function will first return `one' and update the
value of `sample-list' to `(two three one)'.  Subsequent calls
will continue rotating accordingly."
  (unless (symbolp symbol)
    (user-error "%s is not a symbol" symbol))
  (when-let* ((value (symbol-value symbol))
              (list (and (listp value) value))
              (first (car list)))
    (set symbol (append (cdr list) (list first)))
    first))

;;;###autoload
(defun prot-common-empty-buffer-p ()
  "Test whether the buffer is empty."
  (or (= (point-min) (point-max))
      (save-excursion
        (goto-char (point-min))
        (while (and (looking-at "^\\([a-zA-Z]+: ?\\)?$")
                    (zerop (forward-line 1))))
        (eobp))))

;;;###autoload
(defun prot-common-minor-modes-active ()
  "Return list of active minor modes for the current buffer."
  (let ((active-modes))
    (mapc (lambda (m)
            (when (and (boundp m) (symbol-value m))
              (push m active-modes)))
          minor-mode-list)
    active-modes))

;;;###autoload
(defun prot-common-truncate-lines-silently ()
  "Toggle line truncation without printing messages."
  (let ((inhibit-message t))
    (toggle-truncate-lines t)))

;;;###autoload
(defun prot-common-disable-hl-line ()
  "Disable Hl-Line-Mode (for hooks)."
  (hl-line-mode -1))

;;;###autoload
(defun prot-common-window-bounds ()
  "Determine start and end points in the window."
  (list (window-start) (window-end)))

;;;###autoload
(defun prot-common-page-p ()
  "Return non-nil if there is a `page-delimiter' in the buffer."
  (or (save-excursion (re-search-forward page-delimiter nil t))
      (save-excursion (re-search-backward page-delimiter nil t))))

;;;###autoload
(defun prot-common-read-data (file)
  "Read Elisp data from FILE."
  (with-temp-buffer
    (insert-file-contents file)
    (read (current-buffer))))

;; Thanks to Omar Antolín Camarena for providing this snippet!
;;;###autoload
(defun prot-common-completion-table (category candidates)
  "Pass appropriate metadata CATEGORY to completion CANDIDATES.

This is intended for bespoke functions that need to pass
completion metadata that can then be parsed by other
tools (e.g. `embark')."
  (lambda (string pred action)
    (if (eq action 'metadata)
        `(metadata (category . ,category))
      (complete-with-action action candidates string pred))))

;; Thanks to Igor Lima for the `prot-common-crm-exclude-selected-p':
;; <https://github.com/0x462e41>.
;; This is used as a filter predicate in the relevant prompts.
(defvar crm-separator)

;;;###autoload
(defun prot-common-crm-exclude-selected-p (input)
  "Filter out INPUT from `completing-read-multiple'.
Hide non-destructively the selected entries from the completion
table, thus avoiding the risk of inputting the same match twice.

To be used as the PREDICATE of `completing-read-multiple'."
  (if-let* ((pos (string-match-p crm-separator input))
            (rev-input (reverse input))
            (element (reverse
                      (substring rev-input 0
                                 (string-match-p crm-separator rev-input))))
            (flag t))
      (progn
        (while pos
          (if (string= (substring input 0 pos) element)
              (setq pos nil)
            (setq input (substring input (1+ pos))
                  pos (string-match-p crm-separator input)
                  flag (when pos t))))
        (not flag))
    t))

;; The `prot-common-line-regexp-p' and `prot-common--line-regexp-alist'
;; are contributed by Gabriel: <https://github.com/gabriel376>.  They
;; provide a more elegant approach to using a macro, as shown further
;; below.
(defvar prot-common--line-regexp-alist
  '((empty . "[\s\t]*$")
    (indent . "^[\s\t]+")
    (non-empty . "^.+$")
    (list . "^\\([\s\t#*+]+\\|[0-9]+[^\s]?[).]+\\)")
    (heading . "^[=-]+"))
  "Alist of regexp types used by `prot-common-line-regexp-p'.")

(defun prot-common-line-regexp-p (type &optional n)
  "Test for TYPE on line.
TYPE is the car of a cons cell in
`prot-common--line-regexp-alist'.  It matches a regular
expression.

With optional N, search in the Nth line from point."
  (save-excursion
    (goto-char (line-beginning-position))
    (and (not (bobp))
         (or (beginning-of-line n) t)
         (save-match-data
           (looking-at
            (alist-get type prot-common--line-regexp-alist))))))

;; The `prot-common-shell-command-with-exit-code-and-output' function is
;; courtesy of Harold Carr, who also sent a patch that improved
;; `prot-eww-download-html' (from the `prot-eww.el' library).
;;
;; More about Harold: <http://haroldcarr.com/about/>.
(defun prot-common-shell-command-with-exit-code-and-output (command &rest args)
  "Run COMMAND with ARGS.
Return the exit code and output in a list."
  (with-temp-buffer
    (list (apply 'call-process command nil (current-buffer) nil args)
          (buffer-string))))

(defvar prot-common-url-regexp
  (concat
   "~?\\<\\([-a-zA-Z0-9+&@#/%?=~_|!:,.;]*\\)"
   "[.@]"
   "\\([-a-zA-Z0-9+&@#/%?=~_|!:,.;]+\\)\\>/?")
  "Regular expression to match (most?) URLs or email addresses.")

(autoload 'auth-source-search "auth-source")

;;;###autoload
(defun prot-common-auth-get-field (host prop)
  "Find PROP in `auth-sources' for HOST entry."
  (when-let ((source (auth-source-search :host host)))
    (if (eq prop :secret)
        (funcall (plist-get (car source) prop))
      (plist-get (flatten-list source) prop))))

;;;###autoload
(defun prot-common-parse-file-as-list (file)
  "Return the contents of FILE as a list of strings.
Strings are split at newline characters and are then trimmed for
negative space.

Use this function to provide a list of candidates for
completion (per `completing-read')."
  (split-string
   (with-temp-buffer
     (insert-file-contents file)
     (buffer-substring-no-properties (point-min) (point-max)))
   "\n" :omit-nulls "[\s\f\t\n\r\v]+"))

(provide 'prot-common)
;;; prot-common.el ends here

emacs tangle

init.el

  • home dir
<<init.el>>
  • current dir
<<init.el>>

early-init.el

  • home dir
<<early-init.el>>
  • current dir
<<early-init.el>>

bookmark tangle

  • home dir
<<emacs-bookmarks>>
  • current dir
<<emacs-bookmarks>>

lisp

prot-common
  • home dir
<<prot-common>>
  • current dir
<<prot-common>>

alacritty

alacritty config

[colors.bright]
black = "0x002b36"
blue = "0x839496"
cyan = "0x93a1a1"
green = "0x586e75"
magenta = "0x6c71c4"
red = "0xcb4b16"
white = "0xfdf6e3"
yellow = "0x657b83"

[colors.normal]
black = "0x073642"
blue = "0x268bd2"
cyan = "0x2aa198"
green = "0x859900"
magenta = "0xd33682"
red = "0xdc322f"
white = "0xeee8d5"
yellow = "0xb58900"

[colors.primary]
background = "0x002b36"
foreground = "0x839496"

[env]
TERM = "xterm-256color"

[font]
size = 16.0

[font.bold]
family = "Fira Code"
style = "Bold"

[font.bold_italic]
family = "Fira Code"
style = "Bold Italic"

[font.italic]
family = "Fira Code"
style = "Italic"

[font.normal]
family = "Fira Code"
style = "Regular"

[window]
decorations = "full"
decorations_theme_variant = "Dark"
startup_mode = "Windowed"

[window.class]
general = "Alacritty"
instance = "Alacritty"

[window.padding]
x = 4
y = 4

alacritty tangle

  • home dir
<<alacritty>>
  • current dir
<<alacritty>>

labwc

labwc config

autostart config

# autostart file

swaybg -i "${HOME}/pictures/wallpaper/macosx.png" >/dev/null 2>&1 &
kanshi >/dev/null 2>&1 &

environment config

XKB_DEFAULT_LAYOUT=gb(mac)
XKB_DEFAULT_OPTIONS=custom:alt_win_ctrl,caps:none
XDG_CURRENT_DESKTOP=wlroots

menu.xml config

<?xml version="1.0" encoding="UTF-8"?>

<openbox_menu>
<!-- Note: for localization support of menu items "client-menu" has to be removed here -->
<menu id="client-menu">
  <item label="Always on Top">
    <action name="ToggleAlwaysOnTop" />
  </item>
  <!--
    Any menu with the id "workspaces" will be hidden
    if there is only a single workspace available.
  -->
  <menu id="workspaces" label="Workspace">
    <item label="Move left">
      <action name="SendToDesktop" to="left" />
    </item>
    <item label="Move right">
      <action name="SendToDesktop" to="right" />
    </item>
    <separator />
    <item label="Always on Visible Workspace">
      <action name="ToggleOmnipresent" />
    </item>
  </menu>
</menu>

<menu id="root-menu">
  <item label="Reconfigure">
    <action name="Reconfigure" />
  </item>
  <item label="Terminal">
    <action name="Execute" command="alacritty" />
  </item>
  <item label="Emacs">
    <action name="Execute" command="emacsclient -a= -c" />
  </item>
  <item label="Exit">
    <action name="Exit" />
  </item>
</menu>
</openbox_menu>

rc.xml config

<?xml version="1.0"?>

<labwc_config>

  <!-- window placement -->
  <placement>
    <policy>automatic</policy>
  </placement>

  <!-- theme -->
  <theme>
    <name>Solarized-Dark-Blue</name>
    <cornerRadius>0</cornerRadius>
    <font name="sans" size="10" />
  </theme>

  <!-- window switcher -->
  <windowSwitcher show="yes" preview="yes" outlines="yes">
    <fields>
      <field content="title" width="100%" />
    </fields>
  </windowSwitcher>

  <!-- keyboard -->
  <keyboard>
    <default />
    <!-- terminal, emacs, tofi, wlr-which-key -->
    <keybind key="W-S-Return">
      <action name="Execute" command="alacritty" />
    </keybind>
    <keybind key="W-C-Return">
      <action name="Execute" command="emacsclient -a= -c" />
    </keybind>
    <keybind key="W-a">
      <action name="Execute" command="tofi-drun" />
    </keybind>
    <keybind key="W-s">
      <action name="Execute" command="window-switcher" />
    </keybind>
    <keybind key="W-z">
      <action name="Execute" command="wlr-which-key" />
    </keybind>

    <!-- windows -->
    <keybind key="S-W-c">
      <action name="Close" />
    </keybind>
    <keybind key="W-m">
      <action name="ToggleMaximize" />
    </keybind>
    <keybind key="W-n">
      <action name="ToggleFullscreen" />
    </keybind>

    <!-- GoToDesktop by number -->
    <keybind key="W-1">
      <action name="GoToDesktop"><to>1</to></action>
    </keybind>
    <keybind key="W-2">
      <action name="GoToDesktop"><to>2</to></action>
    </keybind>
    <keybind key="W-3">
      <action name="GoToDesktop"><to>3</to></action>
    </keybind>
    <keybind key="W-4">
      <action name="GoToDesktop"><to>4</to></action>
    </keybind>

    <!-- GoToDesktop with h and l -->
    <keybind key="W-h">
      <action name="GoToDesktop"><to>left</to></action>
    </keybind>
    <keybind key="W-l">
      <action name="GoToDesktop"><to>right</to></action>
    </keybind>

    <!-- SendToDesktop -->
    <keybind key="S-W-1">
      <action name="SendToDesktop"><to>1</to></action>
    </keybind>
    <keybind key="S-W-2">
      <action name="SendToDesktop"><to>2</to></action>
    </keybind>
    <keybind key="S-W-3">
      <action name="SendToDesktop"><to>3</to></action>
    </keybind>
    <keybind key="S-W-4">
      <action name="SendToDesktop"><to>4</to></action>
    </keybind>

    <!-- move window to left monitor -->
    <keybind key="S-W-i">
    <action name="MoveToOutput" direction="left">
    </action>
    </keybind>

    <!-- move window to right monitor -->
    <keybind key="S-W-o">
    <action name="MoveToOutput" direction="right">
    </action>
    </keybind>

    <!-- warp cursor left-->
    <keybind key="W-i">
       <action name="FocusOutput" output="eDP-1" />
    </keybind>

    <!-- warp cursor right-->
    <keybind key="W-o">
       <action name="FocusOutput" output="DP-3" />
    </keybind>

    <!-- audio -->
    <keybind key="XF86_AudioLowerVolume">
      <action name="Execute" command="mixer vol=-5%:-5%" />
    </keybind>
    <keybind key="XF86_AudioRaiseVolume">
      <action name="Execute" command="mixer vol=+5%:+5%" />
    </keybind>
    <keybind key="XF86_AudioMute">
      <action name="Execute" command="mixer vol.mute=^" />
    </keybind>
    <keybind key="A-W-Space">
      <action name="Execute" command="playerctl play-pause" />
    </keybind>

    <keybind key="S-Left">
      <action name="MoveToEdge" direction="left" />
    </keybind>
    <keybind key="S-Right">
      <action name="MoveToEdge" direction="right" />
    </keybind>
    <keybind key="S-Up">
      <action name="MoveToEdge" direction="up" />
    </keybind>
    <keybind key="S-Down">
      <action name="MoveToEdge" direction="down" />
    </keybind>
    <keybind key="S-W-Left">
      <action name="SnapToEdge" direction="left" />
    </keybind>
    <keybind key="S-W-Right">
      <action name="SnapToEdge" direction="right" />
    </keybind>
    <keybind key="S-W-Up">
      <action name="SnapToEdge" direction="up" />
    </keybind>
    <keybind key="S-W-Down">
      <action name="SnapToEdge" direction="down" />
    </keybind>

  </keyboard>

  <!-- mouse -->
  <mouse>
    <default />
    <context name="Root">
      <mousebind button="Right" action="Press">
        <action name="ShowMenu" menu="some-custom-menu" />
      </mousebind>
    </context>
  </mouse>

  <!-- focus -->
  <focus>
    <followMouse>yes</followMouse>
    <followMouseRequiresMovement>no</followMouseRequiresMovement>
    <raiseOnFocus>no</raiseOnFocus>
  </focus>

  <!-- virtual desktops - hide workspace switcher -->
  <desktops number="4">
    <popupTime>0</popupTime>
  </desktops>

  <!-- window rules -->
    <windowRules>

  <!-- chromium -->
      <windowRule identifier="chromium-browser" matchOnce="true">
        <skipTaskbar>no</skipTaskbar>
        <skipWindowSwitcher>no</skipWindowSwitcher>
        <action name="ToggleOmnipresent"/>
      </windowRule>

  <!-- firefox pip -->
      <windowRule identifier="firefox" title="Picture-in-Picture" matchOnce="false">
        <skipTaskbar>no</skipTaskbar>
        <skipWindowSwitcher>no</skipWindowSwitcher>
        <action name="ToggleOmnipresent"/>
      </windowRule>

  <!-- mpv -->
      <windowRule identifier="mpv" matchOnce="true">
        <skipTaskbar>no</skipTaskbar>
        <skipWindowSwitcher>no</skipWindowSwitcher>
        <action name="ToggleOmnipresent"/>
      </windowRule>

    </windowRules>

  <libinput>
    <device category="default">
      <naturalScroll>no</naturalScroll>
      <leftHanded></leftHanded>
      <pointerSpeed></pointerSpeed>
      <accelProfile></accelProfile>
      <tap>yes</tap>
      <tapButtonMap></tapButtonMap>
      <tapAndDrag></tapAndDrag>
      <dragLock></dragLock>
      <middleEmulation></middleEmulation>
      <disableWhileTyping></disableWhileTyping>
      <clickMethod></clickMethod>
      <sendEventsMode></sendEventsMode>
    </device>
  </libinput>

</labwc_config>

themerc-override config

border.width: 0
padding.height: 4
osd.border.width: 1
osd.window-switcher.width: 500
osd.window-switcher.padding: 4
osd.window-switcher.item.padding.x: 2
osd.window-switcher.item.padding.y: 1
osd.window-switcher.item.active.border.width: 1
osd.workspace-switcher.boxes.width: 20
osd.workspace-switcher.boxes.height: 20
window.active.title.bg.color: #073642

labwc tangle

autostart tangle

  • home dir
<<autostart>>
  • current dir
<<autostart>>

environment tangle

  • home dir
<<environment>>
  • current dir
<<environment>>

menu.xml tangle

  • home dir
<<menu.xml>>
  • current dir
<<menu.xml>>

rc.xml tangle

  • home dir
<<rc.xml>>
  • current dir
<<rc.xml>>

themerc-override tangle

  • home dir
<<themerc-override>>
  • current dir
<<themerc-override>>

zsh

zsh config

zshrc

# ~/.zshrc

# ssh zsh fix
[[ $TERM == "dumb" ]] && unsetopt zle && PS1='$ ' && return

# Keep 1000 lines of history within the shell and save it to ~/.zsh_history:
HISTSIZE=1000

# variables for PS3 prompt
newline=$'\n'
yesmaster='Yes Master ? '

# PS3 prompt function
function zle-line-init zle-keymap-select {
    PS1="[%n@%M %~]${newline}${yesmaster}"
    zle reset-prompt
}

# run PS3 prompt function
zle -N zle-line-init
zle -N zle-keymap-select

# set terminal window title to program name
case $TERM in
  (*xterm* | xterm-256color)
    function precmd {
      print -Pn "\e]0;%(1j,%j job%(2j|s|); ,)%~\a"
    }
    function preexec {
      printf "\033]0;%s\a" "$1"
    }
  ;;
esac

# Fix bugs when switching modes
bindkey -v # vi mode
bindkey "^?" backward-delete-char
bindkey "^u" backward-kill-line
bindkey "^a" beginning-of-line
bindkey "^e" end-of-line
bindkey "^k" kill-line

# Use modern completion system
autoload -Uz compinit
compinit

# Set/unset  shell options
setopt notify globdots pushdtohome cdablevars autolist
setopt recexact longlistjobs
setopt autoresume histignoredups pushdsilent noclobber
setopt autopushd pushdminus extendedglob rcquotes mailwarning
setopt histignorealldups sharehistory
#setopt auto_cd
cdpath=($HOME)
unsetopt bgnice autoparamslash

# Completion Styles

# list of completers to use
zstyle ':completion:*::::' completer _expand _complete _ignored _approximate

# allow one error for every three characters typed in approximate completer
zstyle -e ':completion:*:approximate:*' max-errors \
    'reply=( $(( ($#PREFIX+$#SUFFIX)/3 )) numeric )'
    
# insert all expansions for expand completer
zstyle ':completion:*:expand:*' tag-order all-expansions

# formatting and messages
zstyle ':completion:*' verbose yes
zstyle ':completion:*:descriptions' format '%B%d%b'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:warnings' format 'No matches for: %d'
zstyle ':completion:*:corrections' format '%B%d (errors: %e)%b'
zstyle ':completion:*' group-name ''

#eval "$(dircolors -b)"
zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS}
zstyle ':completion:*' list-colors ''

# match uppercase from lowercase
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

# offer indexes before parameters in subscripts
zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters

# Filename suffixes to ignore during completion (except after rm command)
zstyle ':completion:*:*:(^rm):*:*files' ignored-patterns '*?.o' '*?.c~' \
    '*?.old' '*?.pro' '.hidden'

# ignore completion functions (until the _ignored completer)
zstyle ':completion:*:functions' ignored-patterns '_*'

# kill - red, green, blue
zstyle ':completion:*:*:kill:*' list-colors '=(#b) #([0-9]#)*( *[a-z])*=22=31=34'

# list optiones colour, white + cyan
zstyle ':completion:*:options' list-colors '=(#b) #(-[a-zA-Z0-9,]#)*(-- *)=36=37'

# zsh autocompletion for sudo and doas
zstyle ":completion:*:(sudo|su|doas):*" command-path /usr/local/bin /usr/sbin /home/djwilcox/bin

# rehash commands
zstyle ':completion:*' rehash true

# highlighting
source /usr/local/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
ZSH_HIGHLIGHT_STYLES[suffix-alias]=fg=cyan,underline
ZSH_HIGHLIGHT_STYLES[precommand]=fg=cyan,underline
ZSH_HIGHLIGHT_STYLES[arg0]=fg=cyan
ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets pattern)
ZSH_HIGHLIGHT_PATTERNS=('rm -rf *' 'fg=white,bold,bg=red')

# aliases
#========

# keyboard backlight on
alias backlight-on='sysctl dev.asmc.0.light.control:255'

# keyboard backlight off
alias backlight-off='sysctl dev.asmc.0.light.control:0'

zshenv

# ~/.zshenv

# Path
typeset -U PATH path
path=("$HOME/bin" "/usr/local/bin" "$path[@]")
export PATH

# xdg directories
export XDG_CONFIG_HOME="$HOME/.config"
export XDG_CACHE_HOME="$HOME/.cache"
export XDG_DATA_HOME="$HOME/.local/share"
# XDG_RUNTIME_DIR automatically set to /var/run/xdg/djwilcox

# firefox
export MOZ_ENABLE_WAYLAND=1
# need for firefox 123.01,2
#export MOZ_DISABLE_WAYLAND_PROXY=1

# qt5
export QT_QPA_PLATFORMTHEME=qt5ct

# ssh-add
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"

# less
export LESSHISTFILE="${XDG_CONFIG_HOME}/less/history"
export LESSKEY="${XDG_CONFIG_HOME}/less/keys"

# set emacsclient as editor
#export ALTERNATE_EDITOR=""
#export EDITOR="emacsclient -a emacs"
#export VISUAL="emacsclient -a emacs"

# tell ls to be colourfull
#export LSCOLORS=ExFxCxDxBxegedabagacad
#export CLICOLOR=1

# vi mode
export KEYTIMEOUT=1

# mpd host variable for mpc
export MPD_HOST="/home/djwilcox/.config/mpd/socket"

# dark theme needed for handbrake
export GTK_THEME=Adwaita-dark:dark

zsh tangle

zshrc tangle

  • home dir
<<zshrc>>
  • current dir
<<zshrc>>

zshenv tangle

  • home dir
<<zshenv>>
  • current dir
<<zshenv>>

mpv

input.conf

# vim keybindings
l seek  5
h seek -5
k seek  60
j seek -60

# subtitles
J cycle sub 
K cycle sub down

# Audio filters:
F1 show-text "F2: loudnorm | F3: dynaudnorm | F4: low Bass | F5: low Treble" 2000

# loudnorm:
F2 af toggle lavfi=[loudnorm=I=-16:TP=-3:LRA=4]

# dynaudnorm:
F3 af toggle lavfi=[dynaudnorm=g=5:f=250:r=0.9:p=0.5]

# lowered bass:
F4  af toggle "superequalizer=6b=2:7b=2:8b=2:9b=2:10b=2:11b=2:12b=2:13b=2:14b=2:15b=2:16b=2:17b=2:18b=2"

# lowered treble:
F5  af toggle "superequalizer=1b=2:2b=2:3b=2:4b=2:5b=2:6b=2:7b=2:8b=2:9b=2:10b=2:11b=2:12b=2"

mpv.conf

# mpv.conf

# list profiles with: mpv --profile=help

# load hwdec profile automatically
profile=hwdec 

# hardware acceleration profile
[hwdec]
profile-desc="hardware acceleration, no cache, yt-dlp 1080 or less"
vo=gpu
#hwdec=vaapi

# hide: GNOME's wayland compositor lacks support for the idle inhibit protocol. 
#msg-level=ffmpeg=fatal,vo/gpu/wayland=no

# cache no for internet streams
cache=no

# yt-dlp best format 1080 or less
ytdl-format="bestvideo[height<=?1080]+bestaudio/best"

# show milliseconds in the on screen display
osd-fractions

# alsa pipewire audio device
#audio-device=oss//dev/dsp0

# youtube subs - J to switch to subs
sub-auto=fuzzy
ytdl-raw-options=sub-lang="en",write-sub=,write-auto-sub=
sub-font='NotoColorEmoji'

# screenshot timecode
screenshot-template="%F-[%P]v%#01n"

# show progress bar in the terminal
#term-osd-bar


# cache profile: mpv --profile=cache
[cache]
profile-desc="hardware acceleration, cache, yt-dlp 1080 or less"
# include hwdec profile 
profile=hwdec
# override hwdec profile cache setting
cache=auto


# youtube conditional auto profile match any youtube url
[youtube]
profile-desc="youtube hardware acceleration, cache"
profile-cond=path:find('youtu%.?be') ~= nil
# include hwdec profile 
profile=hwdec
# override hwdec profile cache setting
cache=yes
# fullscreen 2nd display
fs
#fs-screen-name=DP-3


# invidious conditional auto profile match any youtube url
[invidious]
profile-desc="invidious hardware acceleration, cache"
profile-cond=path:find('http://127.0.0.1:3000') ~= nil
# include hwdec profile 
profile=hwdec
# override hwdec profile cache setting
cache=no
# fullscreen 2nd display
fs
#fs-screen-name=DP-3


# archive.org conditional auto profile match any archive.org url
[archive]
profile-desc="archive hardware acceleration, cache"
profile-cond=path:find('archive.org') ~= nil
# include hwdec profile 
profile=hwdec
# override hwdec profile cache setting
cache=auto
# fullscreen 2nd display
fs
#fs-screen-name=DP-3


# bbc iplayer conditional auto profile match any bbc iplayer url
[iplayer]
profile-desc="iplayer hardware acceleration, cache"
profile-cond=path:find('bbc.co.uk/iplayer') ~= nil
# include hwdec profile 
profile=hwdec
# override hwdec profile cache setting
cache=no
# fullscreen 2nd display
fs
#fs-screen-name=DP-3


# bbc iplayer conditional auto profile match any bbc iplayer url
[bbc]
profile-desc="bbc hardware acceleration, cache"
profile-cond=path:find('bbc:pips:service') ~= nil
# include hwdec profile 
profile=hwdec
# override hwdec profile cache setting
cache=no
# fullscreen 2nd display
fs
#fs-screen-name=DP-3

# kodi invidious conditional auto profile match any youtube url
[kodi]
profile-desc="kodi invidious hardware acceleration, cache"
profile-cond=path:find('http?s://inv.tux.pizza') ~= nil
# include hwdec profile 
profile=hwdec
# override hwdec profile cache setting
cache=no
# fullscreen 2nd display
fs
fs-screen-name=DP-3

mpv tangle

input.conf tangle
  • home dir
<<input.conf>>
  • current dir
<<input.conf>>
mpv.conf tangle
  • home dir
<<mpv.conf>>
  • current dir
<<mpv.conf>>

kodi

kodi config

playercorefactory.xml

<playercorefactory>
 <players>
   <player name="save url" type="ExternalPlayer" audio="true" video="true">
	<filename>printf</filename>
     <args>"%s\n" "{0}" > "$HOME/desktop/url-$(date +"%Y-%m-%d-%H-%M-%S").txt"</args>
     <hidexbmc>false</hidexbmc>
   </player>
   <player name="play" type="ExternalPlayer" audio="false" video="true">
	<filename>"$HOME/.venv/pilfer/bin/pilferplay"</filename>
     <args>-i "{0}"</args>
     <hidexbmc>true</hidexbmc>
   </player>  
   <player name="mpv" type="ExternalPlayer" audio="false" video="true">
	<filename>mpv</filename>
     <args>"{0}"</args>
     <hidexbmc>true</hidexbmc>
   </player>  
   <player name="emacs" type="ExternalPlayer" audio="false" video="true">
	<filename>emacsclient</filename>
     <args>-u -e "(mpv-play-remote-video \"{0}\")"</args>
     <hidexbmc>true</hidexbmc>
   </player>  
   <player name="record video" type="ExternalPlayer" audio="false" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-i "{0}" &</args>
     <hidexbmc>false</hidexbmc>
   </player>  
   <player name="record video - 30 minutes" type="ExternalPlayer" audio="false" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-i "{0}" -t 00:30:00 &</args>
     <hidexbmc>false</hidexbmc>
   </player> 
   <player name="record video - 1 hour" type="ExternalPlayer" audio="false" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-i "{0}" -t 01:00:00 &</args>
     <hidexbmc>false</hidexbmc>
   </player> 
   <player name="record video - 2 hours" type="ExternalPlayer" audio="false" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-i "{0}" -t 02:00:00 &</args>
     <hidexbmc>false</hidexbmc>
   </player> 
   <player name="record video - 3 hours" type="ExternalPlayer" audio="false" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-i "{0}" -t 03:00:00 &</args>
     <hidexbmc>false</hidexbmc>
   </player> 
   <player name="record audio" type="ExternalPlayer" audio="true" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-a "{0}" &</args>
     <hidexbmc>false</hidexbmc>
   </player>  
   <player name="record audio - 30 minutes" type="ExternalPlayer" audio="true" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-a "{0}" -t 00:30:00 &</args>
     <hidexbmc>false</hidexbmc>
   </player> 
   <player name="record audio - 1 hour" type="ExternalPlayer" audio="true" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-a "{0}" -t 01:00:00 &</args>
     <hidexbmc>false</hidexbmc>
   </player> 
   <player name="record audio - 2 hours" type="ExternalPlayer" audio="true" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-a "{0}" -t 02:00:00 &</args>
     <hidexbmc>false</hidexbmc>
   </player> 
   <player name="record audio - 3 hours" type="ExternalPlayer" audio="true" video="true">
	<filename>"ts $HOME/.venv/pilfer/bin/pilfer"</filename>
     <args>-a "{0}" -t 03:00:00 &</args>
     <hidexbmc>false</hidexbmc>
   </player> 
 </players>
 <rules action="overwrite">
   <rule internetstream="true" player="play"></rule>
   <rule video="true" player="mpv"></rule>
   <!-- <rule internetstream="true" player="play"></rule> -->

   <!-- change the default player below -->

   <!-- <rule protocols="nfs|smb" player="dvdplayer"></rule> -->
   <!-- uncomment to make play the default player
    <rule video="true" player="play"></rule>
   -->
   
   <!-- uncomment to make record the default player
    <rule video="true" player="record"></rule>
   -->
   
 </rules>
</playercorefactory>

favourites.xml

<favourites>
    <favourite name="The Haunted Manor" thumb="https://yt3.ggpht.com/FTZm2JIjRFbv883G-ykPXykZG7ggj2PuWl0xL2fdsmx7jV88f71P11rrdghr8XhMZXxgV9v3fVU=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UCRlKarGoPgHU-DbSxOzRDPQ/?category_label=The%20Haunted%20Manor&quot;,return)</favourite>
    <favourite name="New Castle After Dark" thumb="https://yt3.ggpht.com/rn-wcv90NG-7hJVhf01wjLYrU9x8Pb3SbvyBHUqm-LC-AgGK9GUnLBTvMpqVBBh3FqoWspwPuo8=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UC951AqujycbBI083GmKRY3A/?category_label=New%20Castle%20After%20Dark&quot;,return)</favourite>
    <favourite name="The Bill">ActivateWindow(10025,&quot;https://archive.org/download/the-bill_202211/&quot;,return)</favourite>
    <favourite name="The Magpie Channel TV" thumb="https://yt3.ggpht.com/ytc/AIdro_l7guMug0Qnial-Y2kEyFndznIi7_YiFlBxU2YONG7NdA=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UCzbwOixfdDkOEl4c2Gy1Xow/?category_label=The%20Magpie%20Channel%20TV&quot;,return)</favourite>
    <favourite name="Roobenstein" thumb="https://yt3.ggpht.com/FdztOigwufG5iEIpsPregv9dzbdoAiJuPEKqY9B-En6Zv2GaXHatZAs58fE54xl6ee3k5c1nsQ=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UC2WTz3aJZ65nN3p5_LMJAzg/?category_label=Roobenstein&quot;,return)</favourite>
    <favourite name="Adam Pearson" thumb="https://yt3.ggpht.com/ytc/AIdro_lMR8RCVSH3F8XJGwe5FVDDxdmohRQFZuIUdqZV31ZfeDs=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UCbXlSJHSuY1nNHoxSElKiIA/?category_label=Adam%20Pearson&quot;,return)</favourite>
    <favourite name="Newcastle United" thumb="https://yt3.ggpht.com/BWvcV6nWayFXr8E9pNuDl_yuW47k4QhOG-VBx5P88cHg6nd3J5W-_JXc08dpo8raeNPud7BXYg=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UCywGl_BPp9QhD0uAcP2HsJw/?category_label=Newcastle%20United&quot;,return)</favourite>
    <favourite name="Farron Balanced" thumb="https://yt3.ggpht.com/ytc/AIdro_m_zmnVM0g_KtmR0w3Cmc_hmY8g-CHPi6Batrw_mygZ1n0=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UC5dUUCs748wCYQl682LX6bg/?category_label=Farron%20Balanced&quot;,return)</favourite>
    <favourite name="The Ring of Fire" thumb="https://yt3.ggpht.com/jJwLtO9uiqKO2yQZ1q1M1556ACegIF9Wy-ocssYVuK3_q4JPMG-86y_-YTlat7_3Xmp-k9oyDw=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UCYWIEbibRcZav6xMLo9qWWw/?category_label=The%20Ring%20of%20Fire&quot;,return)</favourite>
    <favourite name="Mike Zamansky" thumb="https://yt3.ggpht.com/ytc/AIdro_knGduEqLuRvb8SbuOe75ERGX3H4wP0gD9Pmr7NIsrHaOe6=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UCxkMDXQ5qzYOgXPRnOBrp1w/?category_label=Mike%20Zamansky&quot;,return)</favourite>
    <favourite name="OrgMode tutorial" thumb="https://i.ytimg.com/vi/sQS06Qjnkcc/hqdefault.jpg">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UCfbGTpcJyEOMwKP-eYz3_fg/playlist/PLVtKhBrRV_ZkPnBtt_TD1Cs9PJlU0IIdE/?category_label=OrgMode%20tutorial&quot;,return)</favourite>
    <favourite name="System Crafters" thumb="https://yt3.ggpht.com/ytc/AIdro_lyKTyQXxB_3HJ08fFXcD3EAJUzMll3LWVs9g5bpYmt=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UCAiiOTio8Yu69c3XnR7nQBQ/?category_label=System%20Crafters&quot;,return)</favourite>
    <favourite name="Protesilaos Stavrou" thumb="https://yt3.ggpht.com/ytc/AIdro_nyYP0GEb2Jm2rNtdKdj823s7lajF5VfI2AY6tbHHBcFkB7=s240-c-k-c0x00ffffff-no-rj">ActivateWindow(10025,&quot;plugin://plugin.video.youtube/channel/UC0uTPqBCFIpZxlz_Lv1tk_g/?category_label=Protesilaos%20Stavrou&quot;,return)</favourite>
</favourites>

sources.xml

<sources>
    <programs>
        <default pathversion="1"></default>
    </programs>
    <video>
        <default pathversion="1"></default>
        <source>
            <name>The Bill</name>
            <path pathversion="1">https://archive.org/download/the-bill_202211/</path>
            <allowsharing>true</allowsharing>
        </source>
    </video>
    <music>
        <default pathversion="1"></default>
    </music>
    <pictures>
        <default pathversion="1"></default>
    </pictures>
    <files>
        <default pathversion="1"></default>
    </files>
    <games>
        <default pathversion="1"></default>
    </games>
</sources>

kodi tangle

playercorefactory.xml tangle

  • home dir
<<playercorefactory.xml>>
  • current dir
<<playercorefactory.xml>>

favourites.xml tangle

  • home dir
<<favourites.xml>>
  • current dir
<<favourites.xml>>

sources.xml tangle

  • home dir
<<sources.xml>>
  • current dir
<<sources.xml>>

tofi

tofi config

anchor = top
#output = "eDP-1"
border-width = 0
drun-launch = true
font = "/usr/local/share/fonts/firacode/FiraCode-Bold.ttf"
font-size = 12
height = 32
hint-font = false
horizontal = true
min-input-width = 0
num-results = 10
outline-width = 0
padding-bottom = 0
padding-left = 0
padding-right = 0
padding-top = 0
prompt-color = #eee8d5
prompt-text = ""
input-color = #eee8d5
result-spacing = 18
selection-color = #002b36
default-result-color = #eee8d5
text-color = #eee8d5
width = 100%
default-result-background = #073642
selection-background = #268bd2
background-color = #005577 
#background-color = #2b2b2b
prompt-background=#002b36
selection-background-padding = 4
#selection-background-corner-radius = 6
default-result-background-padding = 4
#default-result-background-corner-radius = 6

tofi tangle

  • home dir
<<tofi>>
  • current dir
<<tofi>>

wlr-which-key

wlr-which-key config

# Theming
font: Fira Code 18
background: "#282828d0"
color: "#fbf1c7"
border: "#005577"
separator: ""
border_width: 2
corner_r: 10
padding: 15 # Defaults to corner_r

# Anchor and margin
anchor: center # One of center, left, right, top, bottom, bottom-left, top-left, etc.
# Only relevant when anchor is not center
margin_right: 0
margin_bottom: 0
margin_left: 0
margin_top: 0

menu: 
  "w":
    desc: general
    submenu:
      "m": { desc: mpv, cmd: ts mpv "$(wl-paste)" 1>/dev/null }
      "p": { desc: pinch, cmd: pinch -i "$(wl-paste)" }
      "y": { desc: yt-dlp, cmd: ts yt-dlp "$(wl-paste)" -o "$HOME/downloads/%(title)s.%(ext)s" }
  "k":
    desc: kodi
    submenu:
      "k": { desc: kyt-send, cmd: kyt-send -i "$(wl-paste)" }
      "m": { desc: m3u-kodi, cmd: m3u-kodi -i "$(wl-paste)" }
  "s":
    desc: screenshot
    submenu:
      "l": { desc: laptop, cmd: grim -o eDP-1 }
      "m": { desc: monitor, cmd: grim -o DP-3 }
      "b": { desc: both, cmd: grim }
  "e":
    desc: emacs
    submenu:
      "m": { desc: mpv, cmd: emacsclient -cF "((visibility . nil))" -e "(mpv-play-clipboard)" }
      "l": { desc: links, cmd: org-playlist -i "$(wl-paste)" }
  "o":
    desc: obs
    submenu:
      "h": { desc: laptop, cmd: obs-cmd scene switch laptop }
      "j": { desc: monitor, cmd: obs-cmd scene switch monitor }
      "k": { desc: both, cmd: obs-cmd scene switch both }
      "l": { desc: ffmpeg, cmd: obs-cmd scene switch ffmpeg }
      "r": { desc: record, cmd: obs-cmd recording toggle }

wlr-which-key tangle

  • home dir
<<wlr-which-key>>
  • current dir
<<wlr-which-key>>

tmux

tmux config

# .tmux.conf

# vi mode
#set-option -g default-shell "/usr/local/bin/zsh"
#set-option -g default-command "/usr/local/bin/zsh"
#set -g default-command "${SHELL}"
set-window-option -g mode-keys vi

# Some tweaks to the status line
set -g status-right "%H:%M"
set -g status-right-style fg=color245

# If running inside tmux ($TMUX is set), then change the status line to red
%if #{TMUX}
set -g status-bg red
%endif

# Enable RGB colour if running in xterm(1)
set-option -sa terminal-overrides ",xterm*:Tc"

# Change the default $TERM to screen
set -g default-terminal "xterm-256color"

# No bells at all
set -g bell-action none

# close panes after command has finished
set -g remain-on-exit off

# Change the prefix key to C-a
set -g prefix C-a
unbind C-b
bind C-a send-prefix

# Turn the mouse on, but without copy mode dragging
set -g mouse on

# multiple places
bind F set -w window-size

# Keys to toggle monitoring activity in a window and the synchronize-panes option
bind m set monitor-activity
bind y set synchronize-panes\; display 'synchronize-panes #{?synchronize-panes,on,off}'

# Start windows and panes at 1, not 0
set -g base-index 1
setw -g pane-base-index 1

# reload ~/.tmux.conf using PREFIX r
bind r source-file ~/.config/tmux/tmux.conf \; display "Reloaded!"

# default statusbar colors
set -g status-style bg=default,fg=yellow #yellow

# default window title colors
set -g window-status-style fg=brightblue,bg=default

# active window title colors
set -g window-status-current-style fg=black,bg=blue

# pane border
set -g pane-border-style fg=black #base02
set -g pane-active-border-style fg=black #base01

# message text
set -g message-style bg=black,fg=brightred #orange

# pane number display
set-option -g display-panes-active-colour blue #blue
set-option -g display-panes-colour brightred #orange

# clock
set-window-option -g clock-mode-colour green #green

# vim key bindings
setw -g mode-keys vi
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
bind-key -r C-h select-window -t :-
bind-key -r C-l select-window -t :+

# resize panes using PREFIX H, J, K, L
bind H resize-pane -L 5
bind J resize-pane -D 5
bind K resize-pane -U 5
bind L resize-pane -R 5

# copy and paste
set-window-option -g automatic-rename on

# toggle statusbar
bind-key s set -g status

# copying selection vim style
bind-key Escape copy-mode			# enter copy mode; default [
bind-key p paste-buffer				# paste; (default hotkey: ] )
bind-key P choose-buffer 			# tmux clipboard history
bind-key + delete-buffer \; display-message "Deleted current Tmux Clipboard History"

# Note: rectangle-toggle (aka Visual Block Mode) > hit v then C-v to trigger it
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi V send-keys -X select-line
bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle
bind-key -T choice-mode-vi h send-keys -X tree-collapse
bind-key -T choice-mode-vi l send-keys -X tree-expand
bind-key -T choice-mode-vi H send-keys -X tree-collapse-all
bind-key -T choice-mode-vi L send-keys -X tree-expand-all
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "wl-copy && wl-paste -n | wl-copy -p"
bind-key p run "wl-paste -n | tmux load-buffer - ; tmux paste-buffer"

# urlview as context and url view
bind-key u capture-pane \; save-buffer /tmp/tmux-buffer \; \
new-window -n "urlview" '$SHELL -c "urlview < /tmp/tmux-buffer"'

# tmux auto rename pane 
set-option -g status-interval 1
set-option -g allow-rename on
set-option -g automatic-rename on
set-option -g automatic-rename-format "#{?#{==:#{pane_current_command},zsh},#{b:pane_title},#{pane_current_command}}"

# tmux title program name
set-option -g set-titles on
set-option -g set-titles-string "#W"

tmux tangle

  • home dir
<<tmux>>
  • current dir
<<tmux>>

yt-dlp

yt-dlp config

# download 1080p video in mp4 format
#-f 'bestvideo[height<=1080][vcodec!=?vp9]+bestaudio[acodec!=?opus]'

# external downloader aria2
--downloader aria2c --downloader-args aria2c:'-c -j 3 -x 3 -s 3 -k 1M'

# native downloader for dash and m3u8
--downloader 'dash,m3u8:native'

# restrict filenames
--restrict-filenames

# merge output format mkv
--merge-output-format mkv

yt-dlp tangle

  • home dir
<<yt-dlp>>
  • current dir
<<yt-dlp>>

mpd

# mpd config

music_directory		"/home/djwilcox/music"
playlist_directory	"/home/djwilcox/.config/mpd/playlists"
db_file			"/home/djwilcox/.config/mpd/mpd.db"
log_file		"/home/djwilcox/.config/mpd/mpd.log"
pid_file		"/home/djwilcox/.config/mpd/mpd.pid"
state_file		"/home/djwilcox/.config/mpd/mpdstate"
sticker_file		"/home/djwilcox/.config/mpd/sticker.sql"
user			"djwilcox"
group			"djwilcox"
bind_to_address		"/home/djwilcox/.config/mpd/socket"

input {
        plugin "curl"
}

audio_output {
	type		"oss"
	name		"My OSS Device"
#	device		"/dev/dsp"	# optional
	mixer_type      "hardware"	# optional
	mixer_device	"/dev/mixer"	# optional
#	mixer_control	"PCM"		# optional
	mixer_control	"vol"		# optional
}

mpd tangle

  • home dir
<<mpd>>
  • current dir
<<mpd>>

ncmpc

## Configuration file for ncmpc (~/.ncmpc/config)

host = "/home/djwilcox/.config/mpd/socket"
screen-list = playlist browse
seek-time = 30
list-format = "%name%|[%artist% - ]%title%|%file%"
status-format = "[%artist% - ]%title%|%shortfile%"
visible-bitrate = yes
wrap-around = yes

## Enable/disable colors.
enable-colors = no

## Set the background color.
color background = none

## Set the text color for the title row.
color title = none,black

## Set the text color for the title row (the bold part).
color title-bold = blue,bold

## Set the color of the line on the second row.
color line = black

## Set the text color used to indicate mpd flags on the second row.
color line-flags = black,bold

## Set the text color in the main area of ncmpc.
color list = none

## Set the bold text color in the main area of ncmpc.
color list-bold = none,bold

## Sets the text color of directories in the browser
color browser-directory = none

## Sets the text color of playlists in the browser
color browser-playlist = none

## Set the color of the progress indicator.
color progressbar = black

## Set the text color used to display mpd status in the status window.
color status-state = black,bold

## Set the text color used to display song names in the status window.
color status-song  = black

## Set the text color used to display time the status window.
color status-time  = black

## Text color used to display alerts in the status window.
color alert = black,bold

ncmpc tangle

  • home dir
<<ncmpc>>
  • current dir
<<ncmpc>>

aria2

#
## aria2 config
#
# man page  = http://aria2.sourceforge.net/manual/en/html/aria2c.html
# file path = $HOME/.aria2/aria2.conf

# Download Directory: specify the directory all files will be downloaded to.
# When this directive is commented out, aria2 will download the files to the
# current directory where you execute the aria2 binary.
#dir=/usr/home/djwilcox/downloads


# Bit Torrent: If the speed of the incoming data (download) from other peers is
# greater then the peer-speed-limit, then do not allow any more connections
# than max-peers. The idea is to limit the amount of clients our system will
# connect with to reduce our overall load when we are already saturating our
# incoming bandwidth.  Make sure to set the the peer-speed-limit to your
# preferred incoming (download) speed. Speeds must be whole numbers so 5.5M is
# illegal, but 5500K is valid.  For unlimited connections set
# request-peer-speed-limit something high like 10000M (10gig).
 bt-max-peers=0
 bt-request-peer-speed-limit=0


# Bit Torrent: the max upload speed for all torrents combined. Again, only
# whole numbers are valid. We find a global upload limit is more flexible then
# an upload limit per torrent. Zero(0) is unrestricted upload spreeds.
 max-overall-upload-limit=128k


# Bit Torrent: When downloading a torrent remove ALL trackers from the listing.
# This is a good way to only use distributed hash table (DHT) and Peer eXchange
# (PeX) for connections. We find start up of the torrent takes a little longer
# with all trackers disabled, but helps reduce the load on trackers.
# bt-exclude-tracker="*"
 bt-external-ip=127.0.0.1


# Bit Torrent: ports and protocols used for bit torrent TCP and UDP
# connections. Make sure DHT is enabled in order to connect to UDP trackers as
# well as negotiating with DHT and PEX peers. 
 dht-listen-port=6882
 enable-dht=true
 enable-peer-exchange=true
 listen-port=6881


# When running aria2 on FreeBSD with ZFS, disable disk-cache due to ZFS's use
# of Adaptive Replacement Cache (ARC). ZFS can also take advantage of the
# "sparse files" format which is significantly faster then pre allocation of
# file space. For other file systems like EXT4 and XFS you can test
# file-allocation with "prealloc" and "falloc" to see which file-allocation
# allows arai2 to start quicker and use less disk I/O.
 disk-cache=0
 file-allocation=none


# Bit Torrent: fully encrypt the negotiation as well and the payload of all bit
# torrent traffic. With this configuration, encryption is required and all old,
# non-encrypted clients are ignored (dropped). This may help avoid some ISPs
# rate limiting P2P clients, but will also reduce the amount of clients aria2
# will talk to.
 bt-force-encryption=true
 bt-min-crypto-level=arc4
 bt-require-crypto=true


# Bit Torrent: Download the torrent file into memory (RAM) if there is no need
# to save the .torrent file itself. This option works with both magnet and
# torrent URL links.
 follow-torrent=mem


# Bit Torrent: The amount of time and the upload-to-download ratio you wish to
# seed to. If either the seed time limit ( minutes ) or the seed ratio is
# reached, torrent seeding will stop. You can set seed-time to zero(0) to
# disable seeding completely.
 seed-ratio=100
 seed-time=0


# Bit Torrent: timeout values for servers and clients.
#bt-tracker-connect-timeout=10
#bt-tracker-interval=900
#bt-tracker-timeout=10


# Bit Torrent: scripts or commands to execute before, during or after a
# download finishes.
# on-bt-download-complete=/path/to/script.sh
# on-download-complete=/path/to/script.pl
# on-download-error=/path/to/script
# on-download-pause=/path/to/script.sh
# on-download-start=/path/to/script.pl
# on-download-stop=/path/to/script


# Network: maximum socket receive buffer in bytes. 1M can sustain 1Gbit/sec.
# Default: 0 which is disabled.
 socket-recv-buffer-size=1M


# Event Multiplexing: set polling to the OS type you are using. For FreeBSD,
# OpenBSD and NetBSD set to "kqueue". For Linux set to "epoll".
 event-poll=kqueue


# Certificate Authority PEM : specify the full path to the OS certificate
# authority pem file to verify the peers. On FreeBSD with OpenSSL the following
# file path is valid. Without a valid pem file aria2 will print out the error,
# "[ERROR] Failed to load trusted CA certificates from no. Cause:
# error:02001002:system library:fopen:No such file or directory"
 ca-certificate=/usr/local/openssl/cert.pem


# Data Integrity: check the MD5 / SHA256 hash of metalink downloads as well as
# the hash of bit torrent chunks as our client receives them. CPU time is
# reasonably low for the high value of real time verified data. Note:
# check-integrity set as true will show "ERROR - Checksum error detected" for
# magnet links which can be ignored.
#check-integrity=true
 realtime-chunk-checksum=true


# File Names: Resume file downloads if we have a partial copy. Do not rename
# the file or make another copy if the same file is downloaded a second time.
 allow-overwrite=true
 always-resume=true
 auto-file-renaming=false
 continue=true
 remote-time=true


# User Agent: Disable the identification string of our client. If you connect
# to a server which requires a certain id string you can always add one here.
# Trackers should never use client id strings as security authentication or
# access control.
 peer-id-prefix=""
 user-agent=""


# Status Summery messages are disabled since the status of the download is
# updated in real time on the CLI anyways.
 summary-interval=0


# FTP: use passive ftp which is firewall friendly and reuse the ftp data
# connection when asking for multiple resources from the same server for
# efficiency.
 ftp-pasv=true
 ftp-reuse-connection=true


# Metalink: Set the country code to prefer mirrors closest to you. Prefer more
# secure https mirrors over http and ftp servers.
 metalink-language=en-US
 metalink-location=us
 metalink-preferred-protocol=https


# Disconnect from https, http or ftp servers who do not upload data to us
# faster then the specified value. Aria2 will then find another mirror in the
# metalink file which might be quicker. If there are no more mirrors left then
# the current slow mirror is still used. This value is NOT used for bit torrent
# connections though. NOTE: we hope to convince the developer to add a
# lower-speed value or even a minimal client U/D ratio to bit torrent some day
# to kick off leachers too.
 lowest-speed-limit=50K


# Concurrent downloads: Set the number of different servers to download from
# concurrently; i.e. in parallel. If we are downloading a single file then
# split that file into the same amount of streams. Make sure to keep in mind
# that if the amount of parallel downloads times the lowest-speed-limit is
# greater then your total download bandwidth then you will drop servers
# incorrectly. For example, we have ten(10) connections at a minimum of
# 50KiB/sec which equals 500KiB/sec. If our total download bandwidth is not at
# least 500KiB/sec then arai2 will think the mirrors are too slow and drop
# connection slowing down the whole download. Do not set the
# max-connection-per-server greater then three(3) as to avoid abusing a single
# server.
 max-concurrent-downloads=10
 max-connection-per-server=3
 min-split-size=5M
 split=10


# RPC Interface: To access aria2 through XML-RPC API, like using webui-aria2.
#enable-rpc
#rpc-listen-all
#rpc-user=username
#rpc-passwd=passwd


# Daemon Mode: To run aria2 in the background as a daemon. Use daemon mode to
# start aria2 on reboot or when using an RPC interface like webui-aria2.
#daemon


#
#
# Reference: the following options arethe developers defaults. We kept them
# here for reference.

# bt-max-open-files=100
# bt-save-metadata=false
# bt-stop-timeout=0
# bt-tracker="udp://tracker.openbittorrent.com:80/announce"
 check-certificate=true
 conditional-get=true
# dht-entry-point="dht.transmissionbt.com:6881"
# dht-file-path=$HOME/.aria2/dht.dat
# dht-message-timeout=10
 disable-ipv6=true
 http-accept-gzip=true
# log=$HOME/.aria2/aria2.log
# log-level=debug

### EOF ###

aria2 tangle

  • home dir
<<aria2>>
  • current dir
<<aria2>>

user-dirs.dirs

enabled=False
XDG_DESKTOP_DIR="$HOME/desktop"
XDG_DOCUMENTS_DIR="$HOME/documents"
XDG_DOWNLOAD_DIR="$HOME/downloads"
XDG_MUSIC_DIR="$HOME/music"
XDG_PICTURES_DIR="$HOME/pictures"
XDG_VIDEOS_DIR="$HOME/video"

user-dirs.dirs tangle

  • home dir
<<user-dirs.dirs>>
  • current dir
<<user-dirs.dirs>>

desktop files

desktop files config

chromium config

[Desktop Entry]
Type=Application
Version=1.0
Encoding=UTF-8
Name=Chromium
Comment=Google web browser based on WebKit
Icon=chrome
Exec=chrome --ozone-platform=wayland %U
Categories=Application;Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;
StartupNotify=true

obs config

[Desktop Entry]
Version=1.0
Name=OBS
GenericName=Streaming/Recording Software
Comment=Free and Open Source Streaming/Recording Software
Exec=obs
Icon=com.obsproject.Studio
Terminal=false
Type=Application
Categories=AudioVideo;Recorder;
StartupNotify=true
StartupWMClass=obs

emacs config

[Desktop Entry]
Name=Emacs
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=emacs %F
Icon=emacs
Type=Application
Terminal=false
Categories=Development;TextEditor;
StartupNotify=true
StartupWMClass=Emacs
Hidden=true

emacsclient config

[Desktop Entry]
Name=Emacs
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;x-scheme-handler/org-protocol;
Exec=sh -c "if [ -n \\"\\$*\\" ]; then exec /usr/local/bin/emacsclient --alternate-editor= --reuse-frame \\"\\$@\\"; else exec emacsclient --alternate-editor= --create-frame; fi" sh %F
Icon=emacs
Type=Application
Terminal=false
Categories=Development;TextEditor;
StartupNotify=true
StartupWMClass=Emacs
Keywords=emacsclient;
Actions=new-window;new-instance;

[Desktop Action new-window]
Name=New Window
Exec=/usr/local/bin/emacsclient --alternate-editor= --create-frame %F

[Desktop Action new-instance]
Name=New Instance
Exec=emacs %F

firefox config

[Desktop Entry]
Version=1.0
Name=Firefox
Comment=Browse the World Wide Web
GenericName=Web Browser
Keywords=Internet;WWW;Browser;Web;Explorer
Exec=firefox %U
Terminal=false
Type=Application
Icon=firefox
Categories=GNOME;GTK;Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;application/x-xpinstall;
StartupNotify=true
Actions=NewWindow;NewPrivateWindow;

[Desktop Action NewWindow]
Name=Open a New Window
Exec=firefox -new-window

[Desktop Action NewPrivateWindow]
Name=Open a New Private Window
Exec=firefox -private-window

mpv config

[Desktop Entry]
Type=Application
Name=mpv Media Player
GenericName=Multimedia player
Comment=Play movies and songs
Icon=mpv
TryExec=mpv
Exec=mpv --player-operation-mode=pseudo-gui -- %U
Terminal=false
Categories=AudioVideo;Audio;Video;Player;TV;
MimeType=application/ogg;application/x-ogg;application/mxf;application/sdp;application/smil;application/x-smil;application/streamingmedia;application/x-streamingmedia;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;audio/aac;audio/x-aac;audio/vnd.dolby.heaac.1;audio/vnd.dolby.heaac.2;audio/aiff;audio/x-aiff;audio/m4a;audio/x-m4a;application/x-extension-m4a;audio/mp1;audio/x-mp1;audio/mp2;audio/x-mp2;audio/mp3;audio/x-mp3;audio/mpeg;audio/mpeg2;audio/mpeg3;audio/mpegurl;audio/x-mpegurl;audio/mpg;audio/x-mpg;audio/rn-mpeg;audio/musepack;audio/x-musepack;audio/ogg;audio/scpls;audio/x-scpls;audio/vnd.rn-realaudio;audio/wav;audio/x-pn-wav;audio/x-pn-windows-pcm;audio/x-realaudio;audio/x-pn-realaudio;audio/x-ms-wma;audio/x-pls;audio/x-wav;video/mpeg;video/x-mpeg2;video/x-mpeg3;video/mp4v-es;video/x-m4v;video/mp4;application/x-extension-mp4;video/divx;video/vnd.divx;video/msvideo;video/x-msvideo;video/ogg;video/quicktime;video/vnd.rn-realvideo;video/x-ms-afs;video/x-ms-asf;audio/x-ms-asf;application/vnd.ms-asf;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvxvideo;video/x-avi;video/avi;video/x-flic;video/fli;video/x-flc;video/flv;video/x-flv;video/x-theora;video/x-theora+ogg;video/x-matroska;video/mkv;audio/x-matroska;application/x-matroska;video/webm;audio/webm;audio/vorbis;audio/x-vorbis;audio/x-vorbis+ogg;video/x-ogm;video/x-ogm+ogg;application/x-ogm;application/x-ogm-audio;application/x-ogm-video;application/x-shorten;audio/x-shorten;audio/x-ape;audio/x-wavpack;audio/x-tta;audio/AMR;audio/ac3;audio/eac3;audio/amr-wb;video/mp2t;audio/flac;audio/mp4;application/x-mpegurl;video/vnd.mpegurl;application/vnd.apple.mpegurl;audio/x-pn-au;video/3gp;video/3gpp;video/3gpp2;audio/3gpp;audio/3gpp2;video/dv;audio/dv;audio/opus;audio/vnd.dts;audio/vnd.dts.hd;audio/x-adpcm;application/x-cue;audio/m3u;
X-KDE-Protocols=ftp,http,https,mms,rtmp,rtsp,sftp,smb,srt,rist,webdav,webdavs
StartupWMClass=mpv
Hidden=true

pavucontrol config

[Desktop Entry]
Version=1.0
Name=Volume
GenericName=Volume Control
Comment=Adjust the volume level
Exec=pavucontrol
Icon=multimedia-volume-control
StartupNotify=true
Type=Application
Categories=AudioVideo;Audio;Mixer;GTK;Settings;X-XFCE-SettingsDialog;X-XFCE-HardwareSettings;
Keywords=pavucontrol;Microphone;Volume;Fade;Balance;Headset;Speakers;Headphones;Audio;Mixer;Output;Input;Devices;Playback;Recording;System Sounds;Sound Card;Settings;Preferences;

qt5ct config

[Desktop Entry]
X-Desktop-File-Install-Version=0.11
Name=Qt5 Settings
Comment=Qt5 Configuration Tool
Exec=qt5ct
Icon=preferences-desktop-theme
Terminal=false
Type=Application
Categories=Settings;DesktopSettings;Qt;
Keywords=settings;desktop;qt;qtsettings;qt5;
Hidden=true

vlc config

[Desktop Entry]
Version=1.0
Name=VLC
GenericName=Media player
Comment=Read, capture, broadcast your multimedia streams
Exec=/usr/local/bin/vlc --started-from-file %U
TryExec=/usr/local/bin/vlc
Icon=vlc
Terminal=false
Type=Application
Categories=AudioVideo;Player;Recorder;
MimeType=application/ogg;application/x-ogg;audio/ogg;audio/vorbis;audio/x-vorbis;audio/x-vorbis+ogg;video/ogg;video/x-ogm;video/x-ogm+ogg;video/x-theora+ogg;video/x-theora;audio/x-speex;audio/opus;application/x-flac;audio/flac;audio/x-flac;audio/x-ms-asf;audio/x-ms-asx;audio/x-ms-wax;audio/x-ms-wma;video/x-ms-asf;video/x-ms-asf-plugin;video/x-ms-asx;video/x-ms-wm;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvx;video/x-msvideo;audio/x-pn-windows-acm;video/divx;video/msvideo;video/vnd.divx;video/avi;video/x-avi;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;audio/vnd.rn-realaudio;audio/x-pn-realaudio;audio/x-pn-realaudio-plugin;audio/x-real-audio;audio/x-realaudio;video/vnd.rn-realvideo;audio/mpeg;audio/mpg;audio/mp1;audio/mp2;audio/mp3;audio/x-mp1;audio/x-mp2;audio/x-mp3;audio/x-mpeg;audio/x-mpg;video/mp2t;video/mpeg;video/mpeg-system;video/x-mpeg;video/x-mpeg2;video/x-mpeg-system;application/mpeg4-iod;application/mpeg4-muxcodetable;application/x-extension-m4a;application/x-extension-mp4;audio/aac;audio/m4a;audio/mp4;audio/x-m4a;audio/x-aac;video/mp4;video/mp4v-es;video/x-m4v;application/x-quicktime-media-link;application/x-quicktimeplayer;video/quicktime;application/x-matroska;audio/x-matroska;video/x-matroska;video/webm;audio/webm;audio/3gpp;audio/3gpp2;audio/AMR;audio/AMR-WB;video/3gp;video/3gpp;video/3gpp2;x-scheme-handler/mms;x-scheme-handler/mmsh;x-scheme-handler/rtsp;x-scheme-handler/rtp;x-scheme-handler/rtmp;x-scheme-handler/icy;x-scheme-handler/icyx;application/x-cd-image;x-content/video-vcd;x-content/video-svcd;x-content/video-dvd;x-content/audio-cdda;x-content/audio-player;application/ram;application/xspf+xml;audio/mpegurl;audio/x-mpegurl;audio/scpls;audio/x-scpls;text/google-video-pointer;text/x-google-video-pointer;video/vnd.mpegurl;application/vnd.apple.mpegurl;application/vnd.ms-asf;application/vnd.ms-wpl;application/sdp;audio/dv;video/dv;audio/x-aiff;audio/x-pn-aiff;video/x-anim;video/x-nsv;video/fli;video/flv;video/x-flc;video/x-fli;video/x-flv;audio/wav;audio/x-pn-au;audio/x-pn-wav;audio/x-wav;audio/x-adpcm;audio/ac3;audio/eac3;audio/vnd.dts;audio/vnd.dts.hd;audio/vnd.dolby.heaac.1;audio/vnd.dolby.heaac.2;audio/vnd.dolby.mlp;audio/basic;audio/midi;audio/x-ape;audio/x-gsm;audio/x-musepack;audio/x-tta;audio/x-wavpack;audio/x-shorten;application/x-shockwave-flash;application/x-flash-video;misc/ultravox;image/vnd.rn-realpix;audio/x-it;audio/x-mod;audio/x-s3m;audio/x-xm;application/mxf;
X-KDE-Protocols=ftp,http,https,mms,rtmp,rtsp,sftp,smb
Keywords=Player;Capture;DVD;Audio;Video;Server;Broadcast;

wayfire config

[Desktop Entry]
Name=Config 
Comment=Configure Wayfire Settings
Exec=wcm
Icon=wcm
Type=Application
Categories=Utility;

weechat config

[Desktop Entry]
Name=WeeChat
GenericName=Chat client
Comment=Extensible chat client
Keywords=WeeChat;extensible;chat;IRC;client;console;terminal;
Exec=weechat %u
Terminal=true
Icon=weechat
Type=Application
Categories=Network;Chat;IRCClient;ConsoleOnly;
MimeType=x-scheme-handler/irc;x-scheme-handler/ircs;
Hidden=true

vpn-chromium config

[Desktop Entry]
Type=Application
Version=1.0
Encoding=UTF-8
Name=vpn-Chromium
Comment=Google web browser based on WebKit
Icon=chrome
Exec=sh -c 'setfib 1 chrome --ozone-platform=wayland --ignore-gpu-blocklist --disable-gpu-driver-bug-workarounds --enable-gpu-rasterization --enable-unsafe-webgpu --enable-zero-copy --enable-drdc --skia-graphite --enable-webgl-draft-extensions --enable-features=Vulkan,UseSkiaRendererer --use-vulkan --enable-features=VaapiVideoDecoder,VaapiVideoEncoder --canvas-oop-rasterization --enable-webgpu-developer-features --origin-trial-enabled-features=WebGPU --test-type --v=0 %U'
Categories=Application;Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;
StartupNotify=true

vpn-firefox config

[Desktop Entry]
Version=1.0
Name=vpn-Firefox
Comment=Browse the World Wide Web
GenericName=Web Browser
Keywords=Internet;WWW;Browser;Web;Explorer
Exec=sh -c 'setfib 1 firefox %U'
Terminal=false
Type=Application
Icon=firefox
Categories=GNOME;GTK;Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;application/x-xpinstall;
StartupNotify=true
Actions=NewWindow;NewPrivateWindow;

[Desktop Action NewWindow]
Name=Open a New Window
Exec=setfib 1 firefox -new-window

[Desktop Action NewPrivateWindow]
Name=Open a New Private Window
Exec=setfib 1 firefox -private-window

vpn-transmission config

[Desktop Entry]
Name=vpn-Transmission
GenericName=BitTorrent Client
Comment=Download and share files over BitTorrent
Keywords=torrents;downloading;uploading;share;sharing;
Exec=sh -c 'setfib 1 transmission-gtk %U'
Icon=transmission
Terminal=false
TryExec=transmission-gtk
Type=Application
StartupNotify=true
MimeType=application/x-bittorrent;x-scheme-handler/magnet;
Categories=Network;FileTransfer;P2P;GTK;
X-Ubuntu-Gettext-Domain=transmission
X-AppInstall-Keywords=torrent
Actions=Pause;Minimize;

[Desktop Action Pause]
Name=Start Transmission with All Torrents Paused
Exec=setfib 1 transmission-gtk --paused

[Desktop Action Minimize]
Name=Start Transmission Minimized
Exec=setfib 1 transmission-gtk --minimized

desktop files tangle

chromium tangle

  • home dir
<<chromium-desktop>>
  • current dir
<<chromium-desktop>>

obs tangle

  • home dir
<<obs-desktop>>
  • current dir
<<obs-desktop>>

emacs tangle

  • home dir
<<emacs-desktop>>
  • current dir
<<emacs-desktop>>

emacsclient tangle

  • home dir
<<emacsclient-desktop>>
  • current dir
<<emacsclient-desktop>>

firefox tangle

  • home dir
<<firefox-desktop>>
  • current dir
<<firefox-desktop>>

mpv tangle

  • home dir
<<mpv-desktop>>
  • current dir
<<mpv-desktop>>

pavucontrol tangle

  • home dir
<<pavucontrol-desktop>>
  • current dir
<<pavucontrol-desktop>>

qt5ct tangle

  • home dir
<<qt5ct-desktop>>
  • current dir
<<qt5ct-desktop>>

vlc tangle

  • home dir
<<vlc-desktop>>
  • current dir
<<vlc-desktop>>

wayfire tangle

  • home dir
<<wayfire-desktop>>
  • current dir
<<wayfire-desktop>>

weechat tangle

  • home dir
<<weechat-desktop>>
  • current dir
<<weechat-desktop>>

vpn-chromium tangle

  • home dir
<<vpn-chromium-desktop>>
  • current dir
<<vpn-chromium-desktop>>

vpn-firefox tangle

  • home dir
<<vpn-firefox-desktop>>
  • current dir
<<vpn-firefox-desktop>>

vpn-transmission tangle

  • home dir
<<vpn-transmission-desktop>>
  • current dir
<<vpn-transmission-desktop>>

mutt

set from = "[email protected]"
set realname = "Daniel J Wilcox"

# mutt colours
#color normal default default
#color hdrdefault black green
#color quoted default default
#color signature default default
#color attachment default default
#color message default default
#color error default default
#color indicator black green
#color status black green
#color tree default default
#color normal default default
#color markers default default
#color search default default
#color tilde default default
#color index default default ~F
#color index default default "~N|~O"


# mutt colours
color normal default default
color hdrdefault black cyan
color quoted default default
color signature default default
color attachment default default
color message default default
color error default default
color indicator black cyan
color status black cyan
color tree default default
color normal default default
color markers default default
color search default default
color tilde default default
color index default default ~F
color index default default "~N|~O"

set imap_user = "[email protected]"
set smtp_url = "smtps://[email protected]:465/"
source "gpg -d ~/.config/mutt/mutt-passwords.gpg |"

set folder = "imaps://imap.gmail.com:993"
set spoolfile = "+Inbox"
set postponed = "+Drafts"
#set trash = "imaps://imap.gmail.com/Trash"
set record = "+Sent Mail"

set header_cache = ~/.config/mutt/cache/headers
set message_cachedir = ~/.config/mutt/cache/bodies
set certificate_file = ~/.config/mutt/certificates
set mailcap_path = ~/.config/mutt/mailcap       

set sort=threads
set sort_browser=reverse-date
set sort_aux=reverse-last-date-received

set move = "no" 
set imap_idle = "yes"
set mail_check = "60"
set imap_keepalive = "900"
set editor = "emacsclient"
#set pager = "emacsclient"
set beep_new

# Ctrl-R to mark all as read
macro index \Cr "T~U<enter><tag-prefix><clear-flag>N<untag-pattern>.<enter>" "mark all messages as read"

set query_command = "abook --mutt-query '%s'"
macro generic,index,pager \ca "<shell-escape>abook<return>" "launch abook"
macro index,pager A "<pipe-message>abook --add-email<return>" "add the sender address to abook"
bind editor <Tab> complete-query

bind index "^" imap-fetch-mail
bind compose p pgp-menu
macro compose Y pfy "send mail without GPG"

bind index gg first-entry
bind index G  last-entry

bind pager k  previous-line
bind pager j  next-line
bind pager gg top
bind pager G  bottom

# View URLs inside Mutt with urlview
macro index \cb "|urlview\n"
macro pager \cb "|urlview\n"


# Note that we explicitly set the comment armor header since GnuPG, when used
# in some localiaztion environments, generates 8bit data in that header, thereby
# breaking PGP/MIME.

# decode application/pgp
set pgp_decode_command="gpg --status-fd=2 --no-verbose --quiet --batch --output - %f"

# verify a pgp/mime signature
set pgp_verify_command="gpg --status-fd=2 --no-verbose --quiet --batch --output - --verify %s %f"

# decrypt a pgp/mime attachment
set pgp_decrypt_command="gpg --status-fd=2 --no-verbose --quiet --batch --output - %f"

# create a pgp/mime signed attachment
set pgp_sign_command="gpg --no-verbose --batch --quiet --output - --armor --detach-sign --textmode %?a?-u %a? %f"

# create a application/pgp signed (old-style) message
set pgp_clearsign_command="gpg --no-verbose --batch --quiet --output - %?p?--passphrase-fd 0? --armor --textmode --clearsign %?a?-u %a? %f"

# create a pgp/mime encrypted attachment
set pgp_encrypt_only_command="/usr/local/bin/pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust -- -r %r -- %f"

# create a pgp/mime encrypted and signed attachment
set pgp_encrypt_sign_command="/usr/local/bin/pgpewrap gpg --batch --quiet --no-verbose --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r -- %f"

# import a key into the public key ring
set pgp_import_command="gpg --no-verbose --import %f"

# export a key from the public key ring
set pgp_export_command="gpg --no-verbose --export --armor %r"

# verify a key
set pgp_verify_key_command="gpg --verbose --batch --fingerprint --check-sigs %r"

# read in the public key ring
set pgp_list_pubring_command="gpg --no-verbose --batch --quiet --with-colons --list-keys %r" 

# read in the secret key ring
set pgp_list_secring_command="gpg --no-verbose --batch --quiet --with-colons --list-secret-keys %r" 

# fetch keys
# set pgp_getkeys_command="pkspxycwrap %r"
# This will work when #172960 will be fixed upstream
# set pgp_getkeys_command="gpg --recv-keys %r"

# pattern for good signature - may need to be adapted to locale!

# set pgp_good_sign="^gpgv?: Good signature from "

# OK, here's a version which uses gnupg's message catalog:
# set pgp_good_sign="`gettext -d gnupg -s 'Good signature from "' | tr -d '"'`"

# This version uses --status-fd messages
set pgp_good_sign="^\\[GNUPG:\\] GOODSIG"

# daniel j wilcox pgp
set pgp_use_gpg_agent="yes"
set my_pgp_id="3B2C8BA1"

mutt tangle

  • home dir
<<mutt>>
  • current dir
<<mutt>>

profile

# $FreeBSD: releng/11.0/share/skel/dot.profile 278616 2015-02-12 05:35:00Z cperciva $
#
# .profile - Bourne Shell startup script for login shells
#
# see also sh(1), environ(7).
#

# These are normally set through /etc/login.conf.  You may override them here
# if wanted.
# PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:$HOME/bin; export PATH
# BLOCKSIZE=K;	export BLOCKSIZE

# Setting TERM is normally done through /etc/ttys.  Do only override
# if you're sure that you'll never log in via telnet or xterm or a
# serial line.
# TERM=xterm; 	export TERM

# set emacsclient as editor for ranger
#EDITOR=/usr/local/bin/emacsclient;   	export EDITOR
#PAGER=less;  	export PAGER

# set ENV to a file invoked each time sh is started for interactive use.
ENV=$HOME/.shrc; export ENV

profile tangle

  • home dir
<<profile>>
  • current dir
<<profile>>

login_conf

me:\
  :charset=UTF-8:\
  :lang=en_GB.UTF-8:\
  :setenv=LC_COLLATE=C:

login_conf tangle

  • home dir
<<login_conf>>
  • current dir
<<login_conf>>

gitconfig

[user]
name = Daniel J Wilcox
email = [email protected]
[color]
ui = true

gitconfig tangle

  • home dir
<<gitconfig>>
  • current dir
<<gitconfig>>

gpg-agent

gpg-agent config

pinentry-program /usr/local/bin/pinentry-curses
default-cache-ttl 36000
max-cache-ttl 36000

gpg-agent tangle

  • home dir
<<gpg-agent>>
  • current dir
<<gpg-agent>>

gtk-3.0

[Settings]
gtk-icon-theme-name = Adwaita-dark:dark
gtk-theme-name = Adwaita-dark:dark
gtk-application-prefer-dark-theme = true

gtk-3.0 tangle

  • home dir
<<gtk>>
  • current dir
<<gtk>>

xkb

keymap

keymap.xkb config

xkb_keymap {
xkb_keycodes "xfree86+aliases(qwerty)" {
    minimum = 8;
    maximum = 255;
    <MDSW> = 8;
     <ESC> = 9;
    <AE01> = 10;
    <AE02> = 11;
    <AE03> = 12;
    <AE04> = 13;
    <AE05> = 14;
    <AE06> = 15;
    <AE07> = 16;
    <AE08> = 17;
    <AE09> = 18;
    <AE10> = 19;
    <AE11> = 20;
    <AE12> = 21;
    <BKSP> = 22;
     <TAB> = 23;
    <AD01> = 24;
    <AD02> = 25;
    <AD03> = 26;
    <AD04> = 27;
    <AD05> = 28;
    <AD06> = 29;
    <AD07> = 30;
    <AD08> = 31;
    <AD09> = 32;
    <AD10> = 33;
    <AD11> = 34;
    <AD12> = 35;
    <RTRN> = 36;
    <LCTL> = 37;
    <AC01> = 38;
    <AC02> = 39;
    <AC03> = 40;
    <AC04> = 41;
    <AC05> = 42;
    <AC06> = 43;
    <AC07> = 44;
    <AC08> = 45;
    <AC09> = 46;
    <AC10> = 47;
    <AC11> = 48;
    <TLDE> = 49;
    <LFSH> = 50;
    <BKSL> = 51;
    <AB01> = 52;
    <AB02> = 53;
    <AB03> = 54;
    <AB04> = 55;
    <AB05> = 56;
    <AB06> = 57;
    <AB07> = 58;
    <AB08> = 59;
    <AB09> = 60;
    <AB10> = 61;
    <RTSH> = 62;
    <KPMU> = 63;
    <LALT> = 64;
    <SPCE> = 65;
    <CAPS> = 66;
    <FK01> = 67;
    <FK02> = 68;
    <FK03> = 69;
    <FK04> = 70;
    <FK05> = 71;
    <FK06> = 72;
    <FK07> = 73;
    <FK08> = 74;
    <FK09> = 75;
    <FK10> = 76;
    <NMLK> = 77;
    <SCLK> = 78;
     <KP7> = 79;
     <KP8> = 80;
     <KP9> = 81;
    <KPSU> = 82;
     <KP4> = 83;
     <KP5> = 84;
     <KP6> = 85;
    <KPAD> = 86;
     <KP1> = 87;
     <KP2> = 88;
     <KP3> = 89;
     <KP0> = 90;
    <KPDL> = 91;
    <SYRQ> = 92;
    <II5D> = 93;
    <LSGT> = 94;
    <FK11> = 95;
    <FK12> = 96;
    <HOME> = 97;
      <UP> = 98;
    <PGUP> = 99;
    <LEFT> = 100;
    <II65> = 101;
    <RGHT> = 102;
     <END> = 103;
    <DOWN> = 104;
    <PGDN> = 105;
     <INS> = 106;
    <DELE> = 107;
    <KPEN> = 108;
    <RCTL> = 109;
    <PAUS> = 110;
    <PRSC> = 111;
    <KPDV> = 112;
    <RALT> = 113;
     <BRK> = 114;
    <LWIN> = 115;
    <RWIN> = 116;
    <MENU> = 117;
    <FK13> = 118;
    <FK14> = 119;
    <FK15> = 120;
    <FK16> = 121;
    <FK17> = 122;
    <KPDC> = 123;
    <LVL3> = 124;
     <ALT> = 125;
    <KPEQ> = 126;
    <SUPR> = 127;
    <HYPR> = 128;
    <XFER> = 129;
     <I02> = 130;
    <NFER> = 131;
     <I04> = 132;
    <AE13> = 133;
     <I06> = 134;
     <I07> = 135;
     <I08> = 136;
     <I09> = 137;
     <I0A> = 138;
     <I0B> = 139;
     <I0C> = 140;
     <I0D> = 141;
     <I0E> = 142;
     <I0F> = 143;
     <I10> = 144;
     <I11> = 145;
     <I12> = 146;
     <I13> = 147;
     <I14> = 148;
     <I15> = 149;
     <I16> = 150;
     <I17> = 151;
     <I18> = 152;
     <I19> = 153;
     <I1A> = 154;
     <I1B> = 155;
    <META> = 156;
     <K59> = 157;
     <I1E> = 158;
     <I1F> = 159;
     <I20> = 160;
     <I21> = 161;
     <I22> = 162;
     <I23> = 163;
     <I24> = 164;
     <I25> = 165;
     <I26> = 166;
     <I27> = 167;
     <I28> = 168;
     <I29> = 169;
     <K5A> = 170;
     <I2B> = 171;
     <I2C> = 172;
     <I2D> = 173;
     <I2E> = 174;
     <I2F> = 175;
     <I30> = 176;
     <I31> = 177;
     <I32> = 178;
     <I33> = 179;
     <I34> = 180;
     <K5B> = 181;
     <K5D> = 182;
     <K5E> = 183;
     <K5F> = 184;
     <I39> = 185;
     <I3A> = 186;
     <I3B> = 187;
     <I3C> = 188;
     <K62> = 189;
     <K63> = 190;
     <K64> = 191;
     <K65> = 192;
     <K66> = 193;
     <I42> = 194;
     <I43> = 195;
     <I44> = 196;
     <I45> = 197;
     <K67> = 198;
     <K68> = 199;
     <K69> = 200;
     <K6A> = 201;
     <I4A> = 202;
     <K6B> = 203;
     <K6C> = 204;
     <K6D> = 205;
     <K6E> = 206;
     <K6F> = 207;
    <HKTG> = 208;
    <KANA> = 209;
    <EISU> = 210;
    <AB11> = 211;
     <I54> = 212;
     <I55> = 213;
     <I56> = 214;
     <I57> = 215;
     <I58> = 216;
     <I59> = 217;
     <I5A> = 218;
     <K74> = 219;
     <K75> = 220;
     <K76> = 221;
     <I5E> = 222;
     <I5F> = 223;
     <I60> = 224;
     <I61> = 225;
     <I62> = 226;
     <I63> = 227;
     <I64> = 228;
     <I65> = 229;
     <I66> = 230;
     <I67> = 231;
     <I68> = 232;
     <I69> = 233;
     <I6A> = 234;
     <I6B> = 235;
     <I6C> = 236;
     <I6D> = 237;
     <I6E> = 238;
     <I6F> = 239;
     <I70> = 240;
     <I71> = 241;
     <I72> = 242;
     <I73> = 243;
     <I74> = 244;
     <I75> = 245;
     <I76> = 246;
     <I77> = 247;
     <I78> = 248;
     <I79> = 249;
     <I7A> = 250;
     <I7B> = 251;
     <I7C> = 252;
     <I7D> = 253;
     <I7E> = 254;
     <I7F> = 255;
    indicator 1 = "Caps Lock";
    indicator 2 = "Num Lock";
    indicator 3 = "Scroll Lock";
    virtual indicator 4 = "Shift Lock";
    virtual indicator 5 = "Group 2";
    virtual indicator 6 = "Mouse Keys";
    alias <AE00> = <TLDE>;
    alias <HZTG> = <TLDE>;
    alias <HNGL> = <FK16>;
    alias <HJCV> = <FK17>;
    alias  <I05> = <AE13>;
    alias <IR7C> =  <I7C>;
    alias <IR7D> =  <I7D>;
    alias  <K5C> = <KPEQ>;
    alias  <K70> = <HKTG>;
    alias  <K71> = <KANA>;
    alias  <K72> = <EISU>;
    alias  <K73> = <AB11>;
    alias <LMTA> = <LWIN>;
    alias <RMTA> = <RWIN>;
    alias <COMP> = <MENU>;
    alias <POWR> =  <I0C>;
    alias <MUTE> =  <I0D>;
    alias <VOL-> =  <I0E>;
    alias <VOL+> =  <I0F>;
    alias <HELP> =  <I10>;
    alias <STOP> =  <I11>;
    alias <AGAI> =  <I12>;
    alias <PROP> =  <I13>;
    alias <UNDO> =  <I14>;
    alias <FRNT> =  <I15>;
    alias <COPY> =  <I16>;
    alias <OPEN> =  <I17>;
    alias <PAST> =  <I18>;
    alias <FIND> =  <I19>;
    alias  <CUT> =  <I1A>;
    alias <OUTP> =  <I56>;
    alias <KITG> =  <I57>;
    alias <KIDN> =  <I58>;
    alias <KIUP> =  <I59>;
    alias <ALGR> = <RALT>;
    alias <KPPT> =  <I06>;
    alias <AC12> = <BKSL>;
    alias <LatQ> = <AD01>;
    alias <LatW> = <AD02>;
    alias <LatE> = <AD03>;
    alias <LatR> = <AD04>;
    alias <LatT> = <AD05>;
    alias <LatY> = <AD06>;
    alias <LatU> = <AD07>;
    alias <LatI> = <AD08>;
    alias <LatO> = <AD09>;
    alias <LatP> = <AD10>;
    alias <LatA> = <AC01>;
    alias <LatS> = <AC02>;
    alias <LatD> = <AC03>;
    alias <LatF> = <AC04>;
    alias <LatG> = <AC05>;
    alias <LatH> = <AC06>;
    alias <LatJ> = <AC07>;
    alias <LatK> = <AC08>;
    alias <LatL> = <AC09>;
    alias <LatZ> = <AB01>;
    alias <LatX> = <AB02>;
    alias <LatC> = <AB03>;
    alias <LatV> = <AB04>;
    alias <LatB> = <AB05>;
    alias <LatN> = <AB06>;
    alias <LatM> = <AB07>;
};

xkb_types "complete" {

    virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;

    type "ONE_LEVEL" {
        modifiers= none;
        level_name[Level1]= "Any";
    };
    type "TWO_LEVEL" {
        modifiers= Shift;
        map[Shift]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
    };
    type "ALPHABETIC" {
        modifiers= Shift+Lock;
        map[Shift]= Level2;
        map[Lock]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "Caps";
    };
    type "KEYPAD" {
        modifiers= Shift+NumLock;
        map[Shift]= Level2;
        map[NumLock]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "Number";
    };
    type "SHIFT+ALT" {
        modifiers= Shift+Alt;
        map[Shift+Alt]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift+Alt";
    };
    type "PC_SUPER_LEVEL2" {
        modifiers= Mod4;
        map[Mod4]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "Super";
    };
    type "PC_CONTROL_LEVEL2" {
        modifiers= Control;
        map[Control]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "Control";
    };
    type "PC_LCONTROL_LEVEL2" {
        modifiers= LControl;
        map[LControl]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "LControl";
    };
    type "PC_RCONTROL_LEVEL2" {
        modifiers= RControl;
        map[RControl]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "RControl";
    };
    type "PC_ALT_LEVEL2" {
        modifiers= Alt;
        map[Alt]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "Alt";
    };
    type "PC_LALT_LEVEL2" {
        modifiers= LAlt;
        map[LAlt]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "LAlt";
    };
    type "PC_RALT_LEVEL2" {
        modifiers= RAlt;
        map[RAlt]= Level2;
        level_name[Level1]= "Base";
        level_name[Level2]= "RAlt";
    };
    type "CTRL+ALT" {
        modifiers= Shift+Control+Alt+LevelThree;
        map[Shift]= Level2;
        preserve[Shift]= Shift;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        preserve[Shift+LevelThree]= Shift;
        map[Control+Alt]= Level5;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
        level_name[Level5]= "Ctrl+Alt";
    };
    type "LOCAL_EIGHT_LEVEL" {
        modifiers= Shift+Lock+Control+LevelThree;
        map[Shift+Lock]= Level1;
        map[Shift]= Level2;
        map[Lock]= Level2;
        map[LevelThree]= Level3;
        map[Shift+Lock+LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[Lock+LevelThree]= Level4;
        map[Control]= Level5;
        map[Shift+Lock+Control]= Level5;
        map[Shift+Control]= Level6;
        map[Lock+Control]= Level6;
        map[Control+LevelThree]= Level7;
        map[Shift+Lock+Control+LevelThree]= Level7;
        map[Shift+Control+LevelThree]= Level8;
        map[Lock+Control+LevelThree]= Level8;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Level3";
        level_name[Level4]= "Shift Level3";
        level_name[Level5]= "Ctrl";
        level_name[Level6]= "Shift Ctrl";
        level_name[Level7]= "Level3 Ctrl";
        level_name[Level8]= "Shift Level3 Ctrl";
    };
    type "THREE_LEVEL" {
        modifiers= Shift+LevelThree;
        map[Shift]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level3;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Level3";
    };
    type "EIGHT_LEVEL" {
        modifiers= Shift+LevelThree+LevelFive;
        map[Shift]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[LevelFive]= Level5;
        map[Shift+LevelFive]= Level6;
        map[LevelThree+LevelFive]= Level7;
        map[Shift+LevelThree+LevelFive]= Level8;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
        level_name[Level5]= "X";
        level_name[Level6]= "X Shift";
        level_name[Level7]= "X Alt Base";
        level_name[Level8]= "X Shift Alt";
    };
    type "EIGHT_LEVEL_ALPHABETIC" {
        modifiers= Shift+Lock+LevelThree+LevelFive;
        map[Shift]= Level2;
        map[Lock]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[Lock+LevelThree]= Level4;
        map[Shift+Lock+LevelThree]= Level3;
        map[LevelFive]= Level5;
        map[Shift+LevelFive]= Level6;
        map[Lock+LevelFive]= Level6;
        map[LevelThree+LevelFive]= Level7;
        map[Shift+LevelThree+LevelFive]= Level8;
        map[Lock+LevelThree+LevelFive]= Level8;
        map[Shift+Lock+LevelThree+LevelFive]= Level7;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
        level_name[Level5]= "X";
        level_name[Level6]= "X Shift";
        level_name[Level7]= "X Alt Base";
        level_name[Level8]= "X Shift Alt";
    };
    type "EIGHT_LEVEL_LEVEL_FIVE_LOCK" {
        modifiers= Shift+Lock+NumLock+LevelThree+LevelFive;
        map[Shift]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[LevelFive]= Level5;
        map[Shift+LevelFive]= Level6;
        preserve[Shift+LevelFive]= Shift;
        map[LevelThree+LevelFive]= Level7;
        map[Shift+LevelThree+LevelFive]= Level8;
        map[NumLock]= Level5;
        map[Shift+NumLock]= Level6;
        preserve[Shift+NumLock]= Shift;
        map[NumLock+LevelThree]= Level7;
        map[Shift+NumLock+LevelThree]= Level8;
        map[Shift+NumLock+LevelFive]= Level2;
        map[NumLock+LevelThree+LevelFive]= Level3;
        map[Shift+NumLock+LevelThree+LevelFive]= Level4;
        map[Shift+Lock]= Level2;
        map[Lock+LevelThree]= Level3;
        map[Shift+Lock+LevelThree]= Level4;
        map[Lock+LevelFive]= Level5;
        map[Shift+Lock+LevelFive]= Level6;
        preserve[Shift+Lock+LevelFive]= Shift;
        map[Lock+LevelThree+LevelFive]= Level7;
        map[Shift+Lock+LevelThree+LevelFive]= Level8;
        map[Lock+NumLock]= Level5;
        map[Shift+Lock+NumLock]= Level6;
        preserve[Shift+Lock+NumLock]= Shift;
        map[Lock+NumLock+LevelThree]= Level7;
        map[Shift+Lock+NumLock+LevelThree]= Level8;
        map[Shift+Lock+NumLock+LevelFive]= Level2;
        map[Lock+NumLock+LevelThree+LevelFive]= Level3;
        map[Shift+Lock+NumLock+LevelThree+LevelFive]= Level4;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
        level_name[Level5]= "X";
        level_name[Level6]= "X Shift";
        level_name[Level7]= "X Alt Base";
        level_name[Level8]= "X Shift Alt";
    };
    type "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK" {
        modifiers= Shift+Lock+NumLock+LevelThree+LevelFive;
        map[Shift]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[LevelFive]= Level5;
        map[Shift+LevelFive]= Level6;
        preserve[Shift+LevelFive]= Shift;
        map[LevelThree+LevelFive]= Level7;
        map[Shift+LevelThree+LevelFive]= Level8;
        map[NumLock]= Level5;
        map[Shift+NumLock]= Level6;
        preserve[Shift+NumLock]= Shift;
        map[NumLock+LevelThree]= Level7;
        map[Shift+NumLock+LevelThree]= Level8;
        map[Shift+NumLock+LevelFive]= Level2;
        map[NumLock+LevelThree+LevelFive]= Level3;
        map[Shift+NumLock+LevelThree+LevelFive]= Level4;
        map[Lock]= Level2;
        map[Lock+LevelThree]= Level3;
        map[Shift+Lock+LevelThree]= Level4;
        map[Lock+LevelFive]= Level5;
        map[Shift+Lock+LevelFive]= Level6;
        map[Lock+LevelThree+LevelFive]= Level7;
        map[Shift+Lock+LevelThree+LevelFive]= Level8;
        map[Lock+NumLock]= Level5;
        map[Shift+Lock+NumLock]= Level6;
        map[Lock+NumLock+LevelThree]= Level7;
        map[Shift+Lock+NumLock+LevelThree]= Level8;
        map[Lock+NumLock+LevelFive]= Level2;
        map[Lock+NumLock+LevelThree+LevelFive]= Level4;
        map[Shift+Lock+NumLock+LevelThree+LevelFive]= Level3;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
        level_name[Level5]= "X";
        level_name[Level6]= "X Shift";
        level_name[Level7]= "X Alt Base";
        level_name[Level8]= "X Shift Alt";
    };
    type "EIGHT_LEVEL_SEMIALPHABETIC" {
        modifiers= Shift+Lock+LevelThree+LevelFive;
        map[Shift]= Level2;
        map[Lock]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[Lock+LevelThree]= Level3;
        preserve[Lock+LevelThree]= Lock;
        map[Shift+Lock+LevelThree]= Level4;
        preserve[Shift+Lock+LevelThree]= Lock;
        map[LevelFive]= Level5;
        map[Shift+LevelFive]= Level6;
        map[Lock+LevelFive]= Level6;
        preserve[Lock+LevelFive]= Lock;
        map[Shift+Lock+LevelFive]= Level6;
        preserve[Shift+Lock+LevelFive]= Lock;
        map[LevelThree+LevelFive]= Level7;
        map[Shift+LevelThree+LevelFive]= Level8;
        map[Lock+LevelThree+LevelFive]= Level7;
        preserve[Lock+LevelThree+LevelFive]= Lock;
        map[Shift+Lock+LevelThree+LevelFive]= Level8;
        preserve[Shift+Lock+LevelThree+LevelFive]= Lock;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
        level_name[Level5]= "X";
        level_name[Level6]= "X Shift";
        level_name[Level7]= "X Alt Base";
        level_name[Level8]= "X Shift Alt";
    };
    type "FOUR_LEVEL" {
        modifiers= Shift+LevelThree;
        map[Shift]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
    };
    type "FOUR_LEVEL_ALPHABETIC" {
        modifiers= Shift+Lock+LevelThree;
        map[Shift]= Level2;
        map[Lock]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[Lock+LevelThree]= Level4;
        map[Shift+Lock+LevelThree]= Level3;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
    };
    type "FOUR_LEVEL_SEMIALPHABETIC" {
        modifiers= Shift+Lock+LevelThree;
        map[Shift]= Level2;
        map[Lock]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[Lock+LevelThree]= Level3;
        preserve[Lock+LevelThree]= Lock;
        map[Shift+Lock+LevelThree]= Level4;
        preserve[Shift+Lock+LevelThree]= Lock;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
    };
    type "FOUR_LEVEL_MIXED_KEYPAD" {
        modifiers= Shift+NumLock+LevelThree;
        map[Shift+NumLock]= Level1;
        map[NumLock]= Level2;
        map[Shift]= Level2;
        map[LevelThree]= Level3;
        map[NumLock+LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[Shift+NumLock+LevelThree]= Level4;
        level_name[Level1]= "Base";
        level_name[Level2]= "Number";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
    };
    type "FOUR_LEVEL_X" {
        modifiers= Shift+Control+Alt+LevelThree;
        map[LevelThree]= Level2;
        map[Shift+LevelThree]= Level3;
        map[Control+Alt]= Level4;
        level_name[Level1]= "Base";
        level_name[Level2]= "Alt Base";
        level_name[Level3]= "Shift Alt";
        level_name[Level4]= "Ctrl+Alt";
    };
    type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" {
        modifiers= Shift+Lock+LevelThree;
        map[Shift]= Level2;
        map[Lock]= Level4;
        preserve[Lock]= Lock;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[Lock+LevelThree]= Level3;
        preserve[Lock+LevelThree]= Lock;
        map[Shift+Lock+LevelThree]= Level3;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "AltGr Base";
        level_name[Level4]= "Shift AltGr";
    };
    type "FOUR_LEVEL_PLUS_LOCK" {
        modifiers= Shift+Lock+LevelThree;
        map[Shift]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[Lock]= Level5;
        map[Shift+Lock]= Level2;
        map[Lock+LevelThree]= Level3;
        map[Shift+Lock+LevelThree]= Level4;
        level_name[Level1]= "Base";
        level_name[Level2]= "Shift";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Shift Alt";
        level_name[Level5]= "Lock";
    };
    type "FOUR_LEVEL_KEYPAD" {
        modifiers= Shift+NumLock+LevelThree;
        map[Shift]= Level2;
        map[NumLock]= Level2;
        map[LevelThree]= Level3;
        map[Shift+LevelThree]= Level4;
        map[NumLock+LevelThree]= Level4;
        map[Shift+NumLock+LevelThree]= Level3;
        level_name[Level1]= "Base";
        level_name[Level2]= "Number";
        level_name[Level3]= "Alt Base";
        level_name[Level4]= "Alt Number";
    };
};

xkb_compatibility "complete" {

    virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper;

    interpret.useModMapMods= AnyLevel;
    interpret.repeat= False;
    interpret.locking= False;
    interpret ISO_Level2_Latch+Exactly(Shift) {
        useModMapMods=level1;
        action= LatchMods(modifiers=Shift,clearLocks,latchToLock);
    };
    interpret Shift_Lock+AnyOf(Shift+Lock) {
        action= LockMods(modifiers=Shift);
    };
    interpret Num_Lock+AnyOf(all) {
        virtualModifier= NumLock;
        action= LockMods(modifiers=NumLock);
    };
    interpret ISO_Level3_Shift+AnyOf(all) {
        virtualModifier= LevelThree;
        useModMapMods=level1;
        action= SetMods(modifiers=LevelThree,clearLocks);
    };
    interpret ISO_Level3_Latch+AnyOf(all) {
        virtualModifier= LevelThree;
        useModMapMods=level1;
        action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock);
    };
    interpret ISO_Level3_Lock+AnyOf(all) {
        virtualModifier= LevelThree;
        useModMapMods=level1;
        action= LockMods(modifiers=LevelThree);
    };
    interpret Alt_L+AnyOf(all) {
        virtualModifier= Alt;
        action= SetMods(modifiers=modMapMods,clearLocks);
    };
    interpret Alt_R+AnyOf(all) {
        virtualModifier= Alt;
        action= SetMods(modifiers=modMapMods,clearLocks);
    };
    interpret Meta_L+AnyOf(all) {
        virtualModifier= Meta;
        action= SetMods(modifiers=modMapMods,clearLocks);
    };
    interpret Meta_R+AnyOf(all) {
        virtualModifier= Meta;
        action= SetMods(modifiers=modMapMods,clearLocks);
    };
    interpret Super_L+AnyOf(all) {
        virtualModifier= Super;
        action= SetMods(modifiers=modMapMods,clearLocks);
    };
    interpret Super_R+AnyOf(all) {
        virtualModifier= Super;
        action= SetMods(modifiers=modMapMods,clearLocks);
    };
    interpret Hyper_L+AnyOf(all) {
        virtualModifier= Hyper;
        action= SetMods(modifiers=modMapMods,clearLocks);
    };
    interpret Hyper_R+AnyOf(all) {
        virtualModifier= Hyper;
        action= SetMods(modifiers=modMapMods,clearLocks);
    };
    interpret Scroll_Lock+AnyOf(all) {
        virtualModifier= ScrollLock;
        action= LockMods(modifiers=modMapMods);
    };
    interpret ISO_Level5_Shift+AnyOf(all) {
        virtualModifier= LevelFive;
        useModMapMods=level1;
        action= SetMods(modifiers=LevelFive,clearLocks);
    };
    interpret ISO_Level5_Latch+AnyOf(all) {
        virtualModifier= LevelFive;
        useModMapMods=level1;
        action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock);
    };
    interpret ISO_Level5_Lock+AnyOf(all) {
        virtualModifier= LevelFive;
        useModMapMods=level1;
        action= LockMods(modifiers=LevelFive);
    };
    interpret Mode_switch+AnyOfOrNone(all) {
        virtualModifier= AltGr;
        useModMapMods=level1;
        action= SetGroup(group=+1);
    };
    interpret ISO_Level3_Shift+AnyOfOrNone(all) {
        action= SetMods(modifiers=LevelThree,clearLocks);
    };
    interpret ISO_Level3_Latch+AnyOfOrNone(all) {
        action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock);
    };
    interpret ISO_Level3_Lock+AnyOfOrNone(all) {
        action= LockMods(modifiers=LevelThree);
    };
    interpret ISO_Group_Latch+AnyOfOrNone(all) {
        virtualModifier= AltGr;
        useModMapMods=level1;
        action= LatchGroup(group=2);
    };
    interpret ISO_Next_Group+AnyOfOrNone(all) {
        virtualModifier= AltGr;
        useModMapMods=level1;
        action= LockGroup(group=+1);
    };
    interpret ISO_Prev_Group+AnyOfOrNone(all) {
        virtualModifier= AltGr;
        useModMapMods=level1;
        action= LockGroup(group=-1);
    };
    interpret ISO_First_Group+AnyOfOrNone(all) {
        action= LockGroup(group=1);
    };
    interpret ISO_Last_Group+AnyOfOrNone(all) {
        action= LockGroup(group=2);
    };
    interpret KP_1+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=-1,y=+1);
    };
    interpret KP_End+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=-1,y=+1);
    };
    interpret KP_2+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+0,y=+1);
    };
    interpret KP_Down+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+0,y=+1);
    };
    interpret KP_3+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+1,y=+1);
    };
    interpret KP_Next+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+1,y=+1);
    };
    interpret KP_4+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=-1,y=+0);
    };
    interpret KP_Left+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=-1,y=+0);
    };
    interpret KP_6+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+1,y=+0);
    };
    interpret KP_Right+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+1,y=+0);
    };
    interpret KP_7+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=-1,y=-1);
    };
    interpret KP_Home+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=-1,y=-1);
    };
    interpret KP_8+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+0,y=-1);
    };
    interpret KP_Up+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+0,y=-1);
    };
    interpret KP_9+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+1,y=-1);
    };
    interpret KP_Prior+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+1,y=-1);
    };
    interpret KP_5+AnyOfOrNone(all) {
        repeat= True;
        action= PtrBtn(button=default);
    };
    interpret KP_Begin+AnyOfOrNone(all) {
        repeat= True;
        action= PtrBtn(button=default);
    };
    interpret KP_F2+AnyOfOrNone(all) {
        repeat= True;
        action= SetPtrDflt(affect=button,button=1);
    };
    interpret KP_Divide+AnyOfOrNone(all) {
        repeat= True;
        action= SetPtrDflt(affect=button,button=1);
    };
    interpret KP_F3+AnyOfOrNone(all) {
        repeat= True;
        action= SetPtrDflt(affect=button,button=2);
    };
    interpret KP_Multiply+AnyOfOrNone(all) {
        repeat= True;
        action= SetPtrDflt(affect=button,button=2);
    };
    interpret KP_F4+AnyOfOrNone(all) {
        repeat= True;
        action= SetPtrDflt(affect=button,button=3);
    };
    interpret KP_Subtract+AnyOfOrNone(all) {
        repeat= True;
        action= SetPtrDflt(affect=button,button=3);
    };
    interpret KP_Separator+AnyOfOrNone(all) {
        repeat= True;
        action= PtrBtn(button=default,count=2);
    };
    interpret KP_Add+AnyOfOrNone(all) {
        repeat= True;
        action= PtrBtn(button=default,count=2);
    };
    interpret KP_0+AnyOfOrNone(all) {
        repeat= True;
        action= LockPtrBtn(button=default,affect=lock);
    };
    interpret KP_Insert+AnyOfOrNone(all) {
        repeat= True;
        action= LockPtrBtn(button=default,affect=lock);
    };
    interpret KP_Decimal+AnyOfOrNone(all) {
        repeat= True;
        action= LockPtrBtn(button=default,affect=unlock);
    };
    interpret KP_Delete+AnyOfOrNone(all) {
        repeat= True;
        action= LockPtrBtn(button=default,affect=unlock);
    };
    interpret F25+AnyOfOrNone(all) {
        repeat= True;
        action= SetPtrDflt(affect=button,button=1);
    };
    interpret F26+AnyOfOrNone(all) {
        repeat= True;
        action= SetPtrDflt(affect=button,button=2);
    };
    interpret F27+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=-1,y=-1);
    };
    interpret F29+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+1,y=-1);
    };
    interpret F31+AnyOfOrNone(all) {
        repeat= True;
        action= PtrBtn(button=default);
    };
    interpret F33+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=-1,y=+1);
    };
    interpret F35+AnyOfOrNone(all) {
        repeat= True;
        action= MovePtr(x=+1,y=+1);
    };
    interpret Pointer_Button_Dflt+AnyOfOrNone(all) {
        action= PtrBtn(button=default);
    };
    interpret Pointer_Button1+AnyOfOrNone(all) {
        action= PtrBtn(button=1);
    };
    interpret Pointer_Button2+AnyOfOrNone(all) {
        action= PtrBtn(button=2);
    };
    interpret Pointer_Button3+AnyOfOrNone(all) {
        action= PtrBtn(button=3);
    };
    interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) {
        action= PtrBtn(button=default,count=2);
    };
    interpret Pointer_DblClick1+AnyOfOrNone(all) {
        action= PtrBtn(button=1,count=2);
    };
    interpret Pointer_DblClick2+AnyOfOrNone(all) {
        action= PtrBtn(button=2,count=2);
    };
    interpret Pointer_DblClick3+AnyOfOrNone(all) {
        action= PtrBtn(button=3,count=2);
    };
    interpret Pointer_Drag_Dflt+AnyOfOrNone(all) {
        action= LockPtrBtn(button=default,affect=both);
    };
    interpret Pointer_Drag1+AnyOfOrNone(all) {
        action= LockPtrBtn(button=1,affect=both);
    };
    interpret Pointer_Drag2+AnyOfOrNone(all) {
        action= LockPtrBtn(button=2,affect=both);
    };
    interpret Pointer_Drag3+AnyOfOrNone(all) {
        action= LockPtrBtn(button=3,affect=both);
    };
    interpret Pointer_EnableKeys+AnyOfOrNone(all) {
        action= LockControls(controls=MouseKeys);
    };
    interpret Pointer_Accelerate+AnyOfOrNone(all) {
        action= LockControls(controls=MouseKeysAccel);
    };
    interpret Pointer_DfltBtnNext+AnyOfOrNone(all) {
        action= SetPtrDflt(affect=button,button=+1);
    };
    interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) {
        action= SetPtrDflt(affect=button,button=-1);
    };
    interpret AccessX_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=AccessXKeys);
    };
    interpret AccessX_Feedback_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=AccessXFeedback);
    };
    interpret RepeatKeys_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=RepeatKeys);
    };
    interpret SlowKeys_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=SlowKeys);
    };
    interpret BounceKeys_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=BounceKeys);
    };
    interpret StickyKeys_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=StickyKeys);
    };
    interpret MouseKeys_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=MouseKeys);
    };
    interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=MouseKeysAccel);
    };
    interpret Overlay1_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=Overlay1);
    };
    interpret Overlay2_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=Overlay2);
    };
    interpret AudibleBell_Enable+AnyOfOrNone(all) {
        action= LockControls(controls=AudibleBell);
    };
    interpret Terminate_Server+AnyOfOrNone(all) {
        action= Terminate();
    };
    interpret Alt_L+AnyOfOrNone(all) {
        action= SetMods(modifiers=Alt,clearLocks);
    };
    interpret Alt_R+AnyOfOrNone(all) {
        action= SetMods(modifiers=Alt,clearLocks);
    };
    interpret Meta_L+AnyOfOrNone(all) {
        action= SetMods(modifiers=Meta,clearLocks);
    };
    interpret Meta_R+AnyOfOrNone(all) {
        action= SetMods(modifiers=Meta,clearLocks);
    };
    interpret Super_L+AnyOfOrNone(all) {
        action= SetMods(modifiers=Super,clearLocks);
    };
    interpret Super_R+AnyOfOrNone(all) {
        action= SetMods(modifiers=Super,clearLocks);
    };
    interpret Hyper_L+AnyOfOrNone(all) {
        action= SetMods(modifiers=Hyper,clearLocks);
    };
    interpret Hyper_R+AnyOfOrNone(all) {
        action= SetMods(modifiers=Hyper,clearLocks);
    };
    interpret Shift_L+AnyOfOrNone(all) {
        action= SetMods(modifiers=Shift,clearLocks);
    };
    interpret XF86Switch_VT_1+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=1,!same);
    };
    interpret XF86Switch_VT_2+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=2,!same);
    };
    interpret XF86Switch_VT_3+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=3,!same);
    };
    interpret XF86Switch_VT_4+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=4,!same);
    };
    interpret XF86Switch_VT_5+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=5,!same);
    };
    interpret XF86Switch_VT_6+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=6,!same);
    };
    interpret XF86Switch_VT_7+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=7,!same);
    };
    interpret XF86Switch_VT_8+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=8,!same);
    };
    interpret XF86Switch_VT_9+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=9,!same);
    };
    interpret XF86Switch_VT_10+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=10,!same);
    };
    interpret XF86Switch_VT_11+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=11,!same);
    };
    interpret XF86Switch_VT_12+AnyOfOrNone(all) {
        repeat= True;
        action= SwitchScreen(screen=12,!same);
    };
    interpret XF86LogGrabInfo+AnyOfOrNone(all) {
        repeat= True;
        action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00);
    };
    interpret XF86LogWindowTree+AnyOfOrNone(all) {
        repeat= True;
        action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00);
    };
    interpret XF86Next_VMode+AnyOfOrNone(all) {
        repeat= True;
        action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00);
    };
    interpret XF86Prev_VMode+AnyOfOrNone(all) {
        repeat= True;
        action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00);
    };
    interpret ISO_Level5_Shift+AnyOfOrNone(all) {
        action= SetMods(modifiers=LevelFive,clearLocks);
    };
    interpret ISO_Level5_Latch+AnyOfOrNone(all) {
        action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock);
    };
    interpret ISO_Level5_Lock+AnyOfOrNone(all) {
        action= LockMods(modifiers=LevelFive);
    };
    interpret Caps_Lock+AnyOfOrNone(all) {
        action= LockMods(modifiers=Lock);
    };
    interpret Any+Exactly(Lock) {
        action= LockMods(modifiers=Lock);
    };
    interpret Any+AnyOf(all) {
        action= SetMods(modifiers=modMapMods,clearLocks);
    };
    group 2 = AltGr;
    group 3 = AltGr;
    group 4 = AltGr;
    indicator "Caps Lock" {
        !allowExplicit;
        whichModState= locked;
        modifiers= Lock;
    };
    indicator "Num Lock" {
        !allowExplicit;
        whichModState= locked;
        modifiers= NumLock;
    };
    indicator "Scroll Lock" {
        whichModState= locked;
        modifiers= ScrollLock;
    };
    indicator "Shift Lock" {
        !allowExplicit;
        whichModState= locked;
        modifiers= Shift;
    };
    indicator "Group 2" {
        !allowExplicit;
        groups= 0xfe;
    };
    indicator "Mouse Keys" {
        indicatorDrivesKeyboard;
        controls= mouseKeys;
    };
};

xkb_symbols "pc+gb(mac)" {

    name[group1]="English (UK, Macintosh)";

    key <MDSW> {         [     Mode_switch ] };
    key  <ESC> {         [          Escape ] };
    key <AE01> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               1,          exclam,     onesuperior,      exclamdown ]
    };
    key <AE02> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               2,              at,        EuroSign,       oneeighth ]
    };
    key <AE03> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               3,        sterling,      numbersign,        sterling ]
    };
    key <AE04> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               4,          dollar,      onequarter,          dollar ]
    };
    key <AE05> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               5,         percent,         onehalf,    threeeighths ]
    };
    key <AE06> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               6,     asciicircum,   threequarters,     fiveeighths ]
    };
    key <AE07> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               7,       ampersand,       braceleft,    seveneighths ]
    };
    key <AE08> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               8,        asterisk,     bracketleft,       trademark ]
    };
    key <AE09> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               9,       parenleft,    bracketright,       plusminus ]
    };
    key <AE10> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [               0,      parenright,      braceright,          degree ]
    };
    key <AE11> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [           minus,      underscore,       backslash,    questiondown ]
    };
    key <AE12> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [           equal,            plus,    dead_cedilla,     dead_ogonek ]
    };
    key <BKSP> {         [       BackSpace,       BackSpace ] };
    key  <TAB> {         [             Tab,    ISO_Left_Tab ] };
    key <AD01> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               q,               Q,              at,     Greek_OMEGA ]
    };
    key <AD02> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               w,               W,         lstroke,         Lstroke ]
    };
    key <AD03> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               e,               E,               e,               E ]
    };
    key <AD04> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               r,               R,       paragraph,      registered ]
    };
    key <AD05> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               t,               T,          tslash,          Tslash ]
    };
    key <AD06> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               y,               Y,       leftarrow,             yen ]
    };
    key <AD07> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               u,               U,       downarrow,         uparrow ]
    };
    key <AD08> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               i,               I,      rightarrow,        idotless ]
    };
    key <AD09> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               o,               O,          oslash,          Oslash ]
    };
    key <AD10> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               p,               P,           thorn,           THORN ]
    };
    key <AD11> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [     bracketleft,       braceleft,  dead_diaeresis,  dead_abovering ]
    };
    key <AD12> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [    bracketright,      braceright,      dead_tilde,     dead_macron ]
    };
    key <RTRN> {         [          Return ] };
    key <LCTL> {         [           Alt_L,          Meta_L ] };
    key <AC01> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               a,               A,              ae,              AE ]
    };
    key <AC02> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               s,               S,          ssharp,         section ]
    };
    key <AC03> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               d,               D,             eth,             ETH ]
    };
    key <AC04> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               f,               F,         dstroke,     ordfeminine ]
    };
    key <AC05> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               g,               G,             eng,             ENG ]
    };
    key <AC06> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               h,               H,         hstroke,         Hstroke ]
    };
    key <AC07> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               j,               J,       dead_hook,       dead_horn ]
    };
    key <AC08> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               k,               K,             kra,       ampersand ]
    };
    key <AC09> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               l,               L,         lstroke,         Lstroke ]
    };
    key <AC10> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [       semicolon,           colon,      dead_acute, dead_doubleacute ]
    };
    key <AC11> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [      apostrophe,        quotedbl, dead_circumflex,      dead_caron ]
    };
    key <TLDE> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [         section,       plusminus,         notsign,         notsign ]
    };
    key <LFSH> {         [         Shift_L ] };
    key <BKSL> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [       backslash,             bar,      dead_grave,      dead_breve ]
    };
    key <AB01> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               z,               Z,   guillemotleft,            less ]
    };
    key <AB02> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               x,               X,  guillemotright,         greater ]
    };
    key <AB03> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               c,               C,            cent,       copyright ]
    };
    key <AB04> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               v,               V, leftdoublequotemark, leftsinglequotemark ]
    };
    key <AB05> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               b,               B, rightdoublequotemark, rightsinglequotemark ]
    };
    key <AB06> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [               n,               N,               n,               N ]
    };
    key <AB07> {
        type= "FOUR_LEVEL_SEMIALPHABETIC",
        symbols[Group1]= [               m,               M,              mu,       masculine ]
    };
    key <AB08> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [           comma,            less,  horizconnector,        multiply ]
    };
    key <AB09> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [          period,         greater,  periodcentered,        division ]
    };
    key <AB10> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [           slash,        question,   dead_belowdot,   dead_abovedot ]
    };
    key <RTSH> {         [         Shift_R ] };
    key <KPMU> {
        type= "CTRL+ALT",
        symbols[Group1]= [     KP_Multiply,     KP_Multiply,     KP_Multiply,     KP_Multiply,   XF86ClearGrab ]
    };
    key <LALT> {         [         Super_L ] };
    key <SPCE> {         [           space ] };
    key <CAPS> {         [       Caps_Lock ] };
    key <FK01> {
        type= "CTRL+ALT",
        symbols[Group1]= [              F1,              F1,              F1,              F1, XF86Switch_VT_1 ]
    };
    key <FK02> {
        type= "CTRL+ALT",
        symbols[Group1]= [              F2,              F2,              F2,              F2, XF86Switch_VT_2 ]
    };
    key <FK03> {
        type= "CTRL+ALT",
        symbols[Group1]= [              F3,              F3,              F3,              F3, XF86Switch_VT_3 ]
    };
    key <FK04> {
        type= "CTRL+ALT",
        symbols[Group1]= [              F4,              F4,              F4,              F4, XF86Switch_VT_4 ]
    };
    key <FK05> {
        type= "CTRL+ALT",
        symbols[Group1]= [              F5,              F5,              F5,              F5, XF86Switch_VT_5 ]
    };
    key <FK06> {
        type= "CTRL+ALT",
        symbols[Group1]= [              F6,              F6,              F6,              F6, XF86Switch_VT_6 ]
    };
    key <FK07> {
        type= "CTRL+ALT",
        symbols[Group1]= [              F7,              F7,              F7,              F7, XF86Switch_VT_7 ]
    };
    key <FK08> {
        type= "CTRL+ALT",
        symbols[Group1]= [              F8,              F8,              F8,              F8, XF86Switch_VT_8 ]
    };
    key <FK09> {
        type= "CTRL+ALT",
        symbols[Group1]= [              F9,              F9,              F9,              F9, XF86Switch_VT_9 ]
    };
    key <FK10> {
        type= "CTRL+ALT",
        symbols[Group1]= [             F10,             F10,             F10,             F10, XF86Switch_VT_10 ]
    };
    key <NMLK> {         [        Num_Lock ] };
    key <SCLK> {         [     Scroll_Lock ] };
    key  <KP7> {         [         KP_Home,            KP_7 ] };
    key  <KP8> {         [           KP_Up,            KP_8 ] };
    key  <KP9> {         [        KP_Prior,            KP_9 ] };
    key <KPSU> {
        type= "CTRL+ALT",
        symbols[Group1]= [     KP_Subtract,     KP_Subtract,     KP_Subtract,     KP_Subtract,  XF86Prev_VMode ]
    };
    key  <KP4> {         [         KP_Left,            KP_4 ] };
    key  <KP5> {         [        KP_Begin,            KP_5 ] };
    key  <KP6> {         [        KP_Right,            KP_6 ] };
    key <KPAD> {
        type= "CTRL+ALT",
        symbols[Group1]= [          KP_Add,          KP_Add,          KP_Add,          KP_Add,  XF86Next_VMode ]
    };
    key  <KP1> {         [          KP_End,            KP_1 ] };
    key  <KP2> {         [         KP_Down,            KP_2 ] };
    key  <KP3> {         [         KP_Next,            KP_3 ] };
    key  <KP0> {         [       KP_Insert,            KP_0 ] };
    key <KPDL> {         [       KP_Delete,      KP_Decimal ] };
    key <LSGT> {
        type= "FOUR_LEVEL",
        symbols[Group1]= [           grave,      asciitilde,             bar,       brokenbar ]
    };
    key <FK11> {
        type= "CTRL+ALT",
        symbols[Group1]= [             F11,             F11,             F11,             F11, XF86Switch_VT_11 ]
    };
    key <FK12> {
        type= "CTRL+ALT",
        symbols[Group1]= [             F12,             F12,             F12,             F12, XF86Switch_VT_12 ]
    };
    key <HOME> {         [            Home ] };
    key   <UP> {         [              Up ] };
    key <PGUP> {         [           Prior ] };
    key <LEFT> {         [            Left ] };
    key <RGHT> {         [           Right ] };
    key  <END> {         [             End ] };
    key <DOWN> {         [            Down ] };
    key <PGDN> {         [            Next ] };
    key  <INS> {         [          Insert ] };
    key <DELE> {         [          Delete ] };
    key <KPEN> {
        type= "ONE_LEVEL",
        symbols[Group1]= [ ISO_Level3_Shift ]
    };
    key <RCTL> {         [       Control_R ] };
    key <PAUS> {
        type= "PC_CONTROL_LEVEL2",
        symbols[Group1]= [           Pause,           Break ]
    };
    key <PRSC> {
        type= "PC_ALT_LEVEL2",
        symbols[Group1]= [           Print,         Sys_Req ]
    };
    key <KPDV> {
        type= "CTRL+ALT",
        symbols[Group1]= [       KP_Divide,       KP_Divide,       KP_Divide,       KP_Divide,      XF86Ungrab ]
    };
    key <RALT> {
        type= "ONE_LEVEL",
        symbols[Group1]= [ ISO_Level3_Shift ]
    };
    key <LWIN> {         [       Control_L ] };
    key <RWIN> {         [         Super_R ] };
    key <MENU> {         [            Menu ] };
    key <LVL3> {
        type= "ONE_LEVEL",
        symbols[Group1]= [ ISO_Level3_Shift ]
    };
    key  <ALT> {         [        NoSymbol,           Alt_L ] };
    key <KPEQ> {         [        KP_Equal ] };
    key <SUPR> {         [        NoSymbol,         Super_L ] };
    key <HYPR> {         [        NoSymbol,         Hyper_L ] };
    key  <I06> {         [      KP_Decimal,      KP_Decimal ] };
    key <META> {         [        NoSymbol,          Meta_L ] };
    key  <I56> {         [     XF86Display ] };
    key  <I57> {         [ XF86KbdLightOnOff ] };
    key  <I58> {         [ XF86KbdBrightnessDown ] };
    key  <I59> {         [ XF86KbdBrightnessUp ] };
    modifier_map Mod5 { <MDSW> };
    modifier_map Control { <LWIN> };
    modifier_map Shift { <LFSH> };
    modifier_map Shift { <RTSH> };
    modifier_map Mod4 { <LALT> };
    modifier_map Lock { <CAPS> };
    modifier_map Mod2 { <NMLK> };
    modifier_map Control { <RCTL> };
    modifier_map Mod4 { <LALT> };
    modifier_map Mod4 { <RWIN> };
    modifier_map Mod5 { <LVL3> };
    modifier_map Mod4 { <SUPR> };
    modifier_map Mod4 { <HYPR> };
    modifier_map Mod1 { <ALT> };
    modifier_map Mod1 { <META> };
};

xkb_geometry "pc(pc104)" {

    width=       470;
    height=      180;

    alias <AC00> = <CAPS>;
    alias <AA00> = <LCTL>;

    baseColor=   "white";
    labelColor=  "black";
    xfont=       "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1";
    description= "Generic 104";

    shape "NORM" {
        corner= 1,
        { [  18,  18 ] },
        { [   2,   1 ], [  16,  16 ] }
    };
    shape "BKSP" {
        corner= 1,
        { [  38,  18 ] },
        { [   2,   1 ], [  36,  16 ] }
    };
    shape "TABK" {
        corner= 1,
        { [  28,  18 ] },
        { [   2,   1 ], [  26,  16 ] }
    };
    shape "BKSL" {
        corner= 1,
        { [  28,  18 ] },
        { [   2,   1 ], [  26,  16 ] }
    };
    shape "RTRN" {
        corner= 1,
        { [  42,  18 ] },
        { [   2,   1 ], [  40,  16 ] }
    };
    shape "CAPS" {
        corner= 1,
        { [  33,  18 ] },
        { [   2,   1 ], [  31,  16 ] }
    };
    shape "LFSH" {
        corner= 1,
        { [  42,  18 ] },
        { [   2,   1 ], [  40,  16 ] }
    };
    shape "RTSH" {
        corner= 1,
        { [  52,  18 ] },
        { [   2,   1 ], [  50,  16 ] }
    };
    shape "MODK" {
        corner= 1,
        { [  27,  18 ] },
        { [   2,   1 ], [  25,  16 ] }
    };
    shape "SMOD" {
        corner= 1,
        { [  23,  18 ] },
        { [   2,   1 ], [  21,  16 ] }
    };
    shape "SPCE" {
        corner= 1,
        { [ 113,  18 ] },
        { [   2,   1 ], [ 111,  16 ] }
    };
    shape "KP0" {
        corner= 1,
        { [  37,  18 ] },
        { [   2,   1 ], [  35,  16 ] }
    };
    shape "KPAD" {
        corner= 1,
        { [  18,  37 ] },
        { [   2,   1 ], [  16,  35 ] }
    };
    shape "LEDS" { { [  75,  20 ] } };
    shape "LED" { { [   5,   1 ] } };
    section "Function" {
        key.color= "grey20";
        priority=  7;
        top=       22;
        left=      19;
        width=     351;
        height=    19;
        row {
            top=  1;
            left= 1;
            keys {
                {  <ESC>, "NORM",   1 },
                { <FK01>, "NORM",  20, color="white" },
                { <FK02>, "NORM",   1, color="white" },
                { <FK03>, "NORM",   1, color="white" },
                { <FK04>, "NORM",   1, color="white" },
                { <FK05>, "NORM",  11, color="white" },
                { <FK06>, "NORM",   1, color="white" },
                { <FK07>, "NORM",   1, color="white" },
                { <FK08>, "NORM",   1, color="white" },
                { <FK09>, "NORM",  11, color="white" },
                { <FK10>, "NORM",   1, color="white" },
                { <FK11>, "NORM",   1, color="white" },
                { <FK12>, "NORM",   1, color="white" },
                { <PRSC>, "NORM",   8, color="white" },
                { <SCLK>, "NORM",   1, color="white" },
                { <PAUS>, "NORM",   1, color="white" }
            };
        };
    }; // End of "Function" section

    section "Alpha" {
        key.color= "white";
        priority=  8;
        top=       61;
        left=      19;
        width=     287;
        height=    95;
        row {
            top=  1;
            left= 1;
            keys {
                { <TLDE>, "NORM",   1 }, { <AE01>, "NORM",   1 },
                { <AE02>, "NORM",   1 }, { <AE03>, "NORM",   1 },
                { <AE04>, "NORM",   1 }, { <AE05>, "NORM",   1 },
                { <AE06>, "NORM",   1 }, { <AE07>, "NORM",   1 },
                { <AE08>, "NORM",   1 }, { <AE09>, "NORM",   1 },
                { <AE10>, "NORM",   1 }, { <AE11>, "NORM",   1 },
                { <AE12>, "NORM",   1 },
                { <BKSP>, "BKSP",   1, color="grey20" }
            };
        };
        row {
            top=  20;
            left= 1;
            keys {
                {  <TAB>, "TABK",   1, color="grey20" },
                { <AD01>, "NORM",   1 }, { <AD02>, "NORM",   1 },
                { <AD03>, "NORM",   1 }, { <AD04>, "NORM",   1 },
                { <AD05>, "NORM",   1 }, { <AD06>, "NORM",   1 },
                { <AD07>, "NORM",   1 }, { <AD08>, "NORM",   1 },
                { <AD09>, "NORM",   1 }, { <AD10>, "NORM",   1 },
                { <AD11>, "NORM",   1 }, { <AD12>, "NORM",   1 },
                { <BKSL>, "BKSL",   1 }
            };
        };
        row {
            top=  39;
            left= 1;
            keys {
                { <CAPS>, "CAPS",   1, color="grey20" },
                { <AC01>, "NORM",   1 }, { <AC02>, "NORM",   1 },
                { <AC03>, "NORM",   1 }, { <AC04>, "NORM",   1 },
                { <AC05>, "NORM",   1 }, { <AC06>, "NORM",   1 },
                { <AC07>, "NORM",   1 }, { <AC08>, "NORM",   1 },
                { <AC09>, "NORM",   1 }, { <AC10>, "NORM",   1 },
                { <AC11>, "NORM",   1 },
                { <RTRN>, "RTRN",   1, color="grey20" }
            };
        };
        row {
            top=  58;
            left= 1;
            keys {
                { <LFSH>, "LFSH",   1, color="grey20" },
                { <AB01>, "NORM",   1 }, { <AB02>, "NORM",   1 },
                { <AB03>, "NORM",   1 }, { <AB04>, "NORM",   1 },
                { <AB05>, "NORM",   1 }, { <AB06>, "NORM",   1 },
                { <AB07>, "NORM",   1 }, { <AB08>, "NORM",   1 },
                { <AB09>, "NORM",   1 }, { <AB10>, "NORM",   1 },
                { <RTSH>, "RTSH",   1, color="grey20" }
            };
        };
        row {
            top=  77;
            left= 1;
            keys {
                { <LCTL>, "MODK",   1, color="grey20" },
                { <LWIN>, "SMOD",   1, color="grey20" },
                { <LALT>, "SMOD",   1, color="grey20" },
                { <SPCE>, "SPCE",   1 },
                { <RALT>, "SMOD",   1, color="grey20" },
                { <RWIN>, "SMOD",   1, color="grey20" },
                { <MENU>, "SMOD",   1, color="grey20" },
                { <RCTL>, "SMOD",   1, color="grey20" }
            };
        };
    }; // End of "Alpha" section

    section "Editing" {
        key.color= "grey20";
        priority=  9;
        top=       61;
        left=      312;
        width=     58;
        height=    95;
        row {
            top=  1;
            left= 1;
            keys {
                {  <INS>, "NORM",   1 }, { <HOME>, "NORM",   1 },
                { <PGUP>, "NORM",   1 }
            };
        };
        row {
            top=  20;
            left= 1;
            keys {
                { <DELE>, "NORM",   1 }, {  <END>, "NORM",   1 },
                { <PGDN>, "NORM",   1 }
            };
        };
        row {
            top=  58;
            left= 20;
            keys {
                {   <UP>, "NORM",   1 }
            };
        };
        row {
            top=  77;
            left= 1;
            keys {
                { <LEFT>, "NORM",   1 }, { <DOWN>, "NORM",   1 },
                { <RGHT>, "NORM",   1 }
            };
        };
    }; // End of "Editing" section

    section "Keypad" {
        key.color= "grey20";
        priority=  10;
        top=       61;
        left=      376;
        width=     77;
        height=    95;
        row {
            top=  1;
            left= 1;
            keys {
                { <NMLK>, "NORM",   1 }, { <KPDV>, "NORM",   1 },
                { <KPMU>, "NORM",   1 }, { <KPSU>, "NORM",   1 }
            };
        };
        row {
            top=  20;
            left= 1;
            keys {
                {  <KP7>, "NORM",   1, color="white" },
                {  <KP8>, "NORM",   1, color="white" },
                {  <KP9>, "NORM",   1, color="white" },
                { <KPAD>, "KPAD",   1 }
            };
        };
        row {
            top=  39;
            left= 1;
            keys {
                {  <KP4>, "NORM",   1, color="white" },
                {  <KP5>, "NORM",   1, color="white" },
                {  <KP6>, "NORM",   1, color="white" }
            };
        };
        row {
            top=  58;
            left= 1;
            keys {
                {  <KP1>, "NORM",   1, color="white" },
                {  <KP2>, "NORM",   1, color="white" },
                {  <KP3>, "NORM",   1, color="white" },
                { <KPEN>, "KPAD",   1 }
            };
        };
        row {
            top=  77;
            left= 1;
            keys {
                {  <KP0>, "KP0",   1, color="white" },
                { <KPDL>, "NORM",   1, color="white" }
            };
        };
    }; // End of "Keypad" section

    solid "LedPanel" {
        top=      22;
        left=     377;
        priority= 0;
        color= "grey10";
        shape= "LEDS";
    };
    indicator "Num Lock" {
        top=      37;
        left=     382;
        priority= 1;
        onColor= "green";
        offColor= "green30";
        shape= "LED";
    };
    indicator "Caps Lock" {
        top=      37;
        left=     407;
        priority= 2;
        onColor= "green";
        offColor= "green30";
        shape= "LED";
    };
    indicator "Scroll Lock" {
        top=      37;
        left=     433;
        priority= 3;
        onColor= "green";
        offColor= "green30";
        shape= "LED";
    };
    text "NumLockLabel" {
        top=      25;
        left=     378;
        priority= 4;
        width=  19.8;
        height=  10;
        XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1";
        text=  "Num\nLock";
    };
    text "CapsLockLabel" {
        top=      25;
        left=     403;
        priority= 5;
        width=  26.4;
        height=  10;
        XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1";
        text=  "Caps\nLock";
    };
    text "ScrollLockLabel" {
        top=      25;
        left=     428;
        priority= 6;
        width=  39.6;
        height=  10;
        XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1";
        text=  "Scroll\nLock";
    };
};

};

keymap.xkb tangle

  • home dir
<<keymap.xkb>>
  • current dir
<<keymap.xkb>>

rules

evdev

evdev config
! option = symbols
  custom:alt_win_ctrl = +custom(alt_win_ctrl)

! include %S/evdev
evdev tangle
  • home dir
<<evdev>>
  • current dir
<<evdev>>

evdev.xml

evdev.xml config
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xkbConfigRegistry SYSTEM "xkb.dtd">
<xkbConfigRegistry version="1.1">
  <layoutList>
    <layout>
      <configItem>
        <name>gb</name>
      </configItem>
      <variantList>
        <variant>
          <configItem>
            <name>alt_win_ctrl</name>
            <shortDescription>alt_win_ctrl</shortDescription>
            <description>GB(alt_win_ctrl)</description>
          </configItem>
        </variant>
      </variantList>
    </layout>
  </layoutList>
  <optionList>
    <group allowMultipleSelection="true">
      <configItem>
        <name>custom</name>
        <description>custom options</description>
      </configItem>
      <option>
        <configItem>
          <name>custom:alt_win_ctrl</name>
          <description>Ctrl is mapped to Alt, Alt to Win, and Win to the Ctrl key.</description>
        </configItem>
      </option>
    </group>
  </optionList>
</xkbConfigRegistry>

evdev.xml tangle
  • home dir
<<evdev.xml>>
  • current dir
<<evdev.xml>>

symbols

custom

custom config
// Ctrl is mapped to Alt, Alt to Win, and Win to the Ctrl key.
partial modifier_keys
xkb_symbols "alt_win_ctrl" {
    key <LALT> { [ Super_L ] };
    key <LWIN> { [ Control_L, Control_L ] };
    key <LCTL> { [ Alt_L, Meta_L ] };
    key <AE03> { [ 3, numbersign, sterling ] };
};
custom tangle
  • home dir
<<custom>>
  • current dir
<<custom>>

gb

gb config
default partial alphanumeric_keys 
xkb_symbols "alt_win_ctrl" {

    // mac swap alt_win_ctrl

    // include "macintosh_vndr/gb"

    name[Group1]= "alt_win_ctrl - Mac";

    key <LALT> { [ Super_L ] };
    key <LWIN> { [ Control_L, Control_L ] };
    key <LCTL> { [ Alt_L, Meta_L ] };
    key <AE03> { [ 3, numbersign, sterling ] };
};

gb tangle
  • home dir
<<gb>>
  • current dir
<<gb>>