Rapport Emacs
an Amiable and Literate Companion

Table of Contents

Synopsis

  • An Emacs project in the Rapport initiative.
  • An opinionated and shareable experimentation in an optimal Emacs experience.

Introduction

Foreword

  • What is Rapport?

    From The Collaborative International Dictionary of English v.0.48 [gcide]:

    Rapport \Rap*port"\ (r[a^]p*p[=o]rt"; F. r[.a]`p[^o]r"), n. [F., fr. rapporter to bring again or back, to refer; pref. re- re-

    • apporter to bring, L. apportare. Cf. Report.]

    Relation; proportion; conformity; correspondence; accord. [1913 Webster]

    'T is obvious what rapport there is between the conceptions and languages in every country. –Sir W. Temple. [1913 Webster]

    En` rap`port" ([aum]N` r[.a]`p[^o]r") [F.], in accord, harmony, or sympathy; having a mutual, especially a private, understanding; in hypnotism, in that relation of sympathy which permits influence or communication. [1913 Webster]

    From WordNet (r) 3.0 (2006) [wn]:

    rapport n 1: a relationship of mutual understanding or trust and agreement between people [syn: rapport, resonance]

  • What is Emacs?

    From The Free On-line Dictionary of Computing (30 December 2018) [foldoc]:

    Emacs GNU Emacs

    <text, tool> ee'maks (Editing MACroS, or Extensible MACro System, GNU Emacs) A popular screen editor for Unix and most other operating systems.

  • for More Rapport with Emacs Org-Mode [rtd|git]
  • tasks and features are planned at https://coherent.atlassian.net/browse/EMACS
  • many personal configuration details, (including an extensive customize file), are stored separately
    • so cloning and running this repo alone will not yield exactly my same config
    • I'm interested in removing this incogruency, (to the extent thats possible), in order to make it easier for people to reference and copy this config.
  • this configuration is inspired by the content and organization of a number of great thinkers and system designers.1
  • Where nix-shell is available, the control.org file may be directly executed to dynamically load Emacs, support libraries, and tools with a single invocation.
    • This is a good example of the strange and fascinating useful of Nix. This method bring it's own runtime, including Emacs, which means that control.org is executable to run Rapport Emacs, even when Emacs isn't already installed.

Motivation

It's important to understand that Emacs wasn't my first choice.

All I knew was what I wanted - a tool for note-taking with these criteria:

  • Ubiquitous (cross-platform, available where I need it, inexpensive such that I can afford and recommend it without disadvantage)
  • Stable (with future-proof data formats, adequate governance)
  • Adaptable (supportive of various workflows, rapid knowledge capture organization and retrieval)
  • Durable (vibrant and supportive community, annihilation-resistant, charismatic-leader resistant)

There were (and always will be) lots of other choices, (RIP Google Buzz) that seemed like far more obvious candidates.

I was nascently aware of Emacs of course but just as readily dismissed it as unsuitably arcane.

Over a course of time and trial, I gradually came to understand that what was missing from my list of criteria - what flowed between them and fastened them, was freedom.

Startlingly and certainly my awareness shifted, and as I reappraised Emacs in this new light I appreciated that it merited more than a second look.

Freedom is the guarantor, the primacy, the fastener through which these myriad expressions are bound.

Chapter 0, Establish Rapport

Rapport Core

Early Initialization, early-init.el

setup Emacs's early init

;; Initialization Speed Hacks
(let*
    ((gc-cons-threshold-orig      800000)             ;; The default value is 800,000 bytes (aka 800k).
     (gc-cons-threshold-startup   (* 1024 1000 500))  ;; During the value is bumped up to 512 MB during initialization.
     (gc-cons-percentage-adjusted 0.4))               ;; The value to use after Emacs is initialized.
  (progn
    ;; Make startup faster by reducing the frequency of garbage collection and then use a hook to measure Emacs startup time.
    (setq
     gc-cons-threshold gc-cons-threshold-startup ;; Number of bytes of consing between garbage collections.
     gc-cons-threshold most-positive-fixnum      ;; Very large threshold for garbage collector during init
     package-enable-at-startup nil)              ;; We'll use elpaca

    ;; Reset the garbage collector limit after init process has ended (8Mo)
    `(add-hook 'after-init-hook
               (lambda ()
                 (setq gc-cons-threshold  ,gc-cons-threshold-orig
                       gc-cons-percentage ,gc-cons-percentage-adjusted)))))


;; Lightweight Start-Up
;; - No site-wide run-time initializations.
(setq site-run-file nil)
;; - No site-wide default library
(setq inhibit-default-init t)


;; register the location of "require-able" Rapport feature-files, (including build-time defaults)
(setq-default rapport-emacs-uri-control "/builds/rapport-org/emacs/control.org")
;; register the location of "require-able" Rapport feature-files, (including build-time defaults)
(add-to-list 'load-path (or (getenv "RAPPORT_EMACS__URI_LIBDIR") ;; runtime config
                            "")) ;; buildtime config

;; load Rapport's FeatureSet
;; ,NB: it's helpful for this to be the first feature loaded to support defining feature sets and inhibits.
(require 'rapport-core-featureset)
;; register the location of "require-able" Rapport feature-files, (including runtime config)
(add-to-list 'load-path (rapport-fn-featureset-get-uri-libdir))
;; load Tangle Rapport data and functions.
(rapport-fn-featureset-load-preset 'tangle-during-earlyinit)
;; ,NB: In the event that 'tangle-during-earlyinit is inhibited, the tangle operation is skipped.
(when (functionp 'rapport-fn-tangle-files-maybe)
  ;; tangle if needed to render updates.
  (rapport-fn-tangle-files-maybe))

;; Now that any needed tangling has happened, we'll continue on to load the remaining (potentially updated) early-init portions of Rapport.

;; ,NOTICE:
;;    The 'rapport-core-featureset and 'rapport-core-tangle are
;;    loaded prior to the tangle and won't include updates from the
;;    tangle. To mitigate the potential and risk of incorrect behavior
;;    as a result of mixing pre-tangle and post-tangle versions, these
;;    features are/should generally minimize interdependencies and
;;    mutability. Re-tangling and restarting is recommended for a
;;    comprehensively updated Rapport Emacs.

;; Set the presumed (rapport-fn-context-get-label) naively based on early-init available system information.
(rapport-fn-featureset-load-preset 'context-during-earlyinit)

;; Native Compilation
;; - Path to look-aside compilation directory. This specificity protects against spurious rebuilds when swapping emacs version or sharing a cache.
;;   ,TODO: this references some Rapport variables before they're set by Emacs's initialization. It uses safe fall-backs but perhaps we can improve this?
(setq native-comp-eln-load-path (list
                                 ;; approx. "~/.uris/.vault-var/emacs/eln-cache/<system-type>-<os-kernel>/<emacs-version>/custom-<system-name>-<user-name>-context"
                                 (expand-file-name
                                  (format "%s" (or (when (functionp 'rapport-fn-context-get-label)
                                                     (rapport-fn-context-get-label))
                                                   ".unset-label"))
                                  (expand-file-name
                                   (format "emacs-%s" emacs-version)
                                   (expand-file-name
                                    (string-replace "/" "+" (format "%s-%s" (car (split-string system-configuration "-")) system-type))
                                    (expand-file-name "eln-cache" (or
                                                                   (bound-and-true-p rapport-uri-vault-var-emacs)
                                                                   (when (getenv "RAPPORT__URI_VAULT_VAR")
                                                                     (expand-file-name "emacs" (getenv "RAPPORT__URI_VAULT_VAR")))
                                                                   (bound-and-true-p no-littering-var-directory)
                                                                   (when (file-directory-p "~/.uris/.vault-var/emacs")
                                                                     "~/.uris/.vault-var/emacs")
                                                                   (when (stringp (getenv "RAPPORT_EMACS__URI_INITDIR"))
                                                                      (getenv "RAPPORT_EMACS__URI_INITDIR"))
                                                                   user-emacs-directory)))))
                                 ;; end list
                                 ))

;; - Use the Newer Source if the Byte-Compiled files are older
(setq load-prefer-newer t)


;; present simple start-up stats to Messages buffer
(add-hook 'after-init-hook
          (lambda () (message " (rapport) Ready in %s with %d garbage collections."
                              (format "%.2f seconds" (float-time (time-subtract after-init-time before-init-time)))
                              gcs-done)))


;; load early-init portions of Rapport configs
(rapport-fn-featureset-load-preset 'earlyinit)


;;
(provide 'rapport-core-emacsearlyinit)

Initialization, init.el

setup Emacs initialization

;;; init.el --- Emacs init file used to bootstrap packages and configurations.
;;; Commentary:
;;; Code:

;;(package-initialize)

;; Display Rapport's startup/readiness time.
(message " (rapport) ::core|emacsinit::  starting ...")


;; Simplify and Tidy Interface
(setq-default
 auto-save-list-file-prefix nil ;; Initially disabled to avoid spurious auto-save creation in 'user-emacs-directory.
 inhibit-startup-screen t
 initial-scratch-message "")


;; Suppress Specious, Spurious and Otherwise Inconsequential Start-Up Warning Messages
(setq-default
                                        ;max-lisp-eval-depth (* 1600 10000)
 native-comp-async-report-warnings-errors 'silent ; Suppress Native-Comp and Other Innocuous Warnings
 ad-redefinition-action 'accept                   ; Silence warnings for redefinition
 custom-unlispify-menu-entries nil                ; Prefer kebab-case for titles
 custom-unlispify-tag-names nil                   ; Prefer kebab-case for symbols
 native-comp-async-report-warnings-errors 'silent ; Skip compilation error buffers
 read-process-output-max (* 1024 1024)            ; Increase read size per process
 ;; end-of-list
 )


;; Initialization Speed Hacks
(let*
    ((gc-cons-threshold-orig      800000)             ;; The default value is 800,000 bytes (aka 800k).
     (gc-cons-threshold-startup   (* 1024 1000 500))  ;; During the value is bumped up to 512 MB during initialization.
     (gc-cons-percentage-adjusted 0.4))               ;; The value to use after Emacs is initialized.
  (progn
    ;; Make startup faster by reducing the frequency of garbage collection and then use a hook to measure Emacs startup time.
    (setq gc-cons-threshold ;; Number of bytes of consing between garbage collections.
          gc-cons-threshold-startup)
    ;; Reset the default
    `(add-hook 'emacs-startup-hook
               (lambda ()
                 (setq gc-cons-threshold  ,gc-cons-threshold-orig
                       gc-cons-percentage ,gc-cons-percentage-adjusted)))))


;;
(require 'rapport-core-featureset)
(rapport-fn-featureset-load-preset 'init)

;; initiate Emacs Performance Reporting
;; https://punchagan.muse-amuse.in/blog/how-i-learnt-to-use-emacs-profiler/
(if (bound-and-true-p rapport-emacs-opt-profiler)
    (add-hook 'after-init-hook #'(lambda () (profiler-start rapport-emacs-opt-profiler)) 't)
  (message " (rapport) nfo: profiling not enabled"))


;; enable loading rapport configuration from environment variables
(defcustom rapport-emacs-opt-featureset-load-custom-from-env nil "")
(defcustom rapport-emacs-opt-featureset-load-presets-from-env t "")

;;
(add-hook 'after-init-hook (lambda ()
                             ;; ,HINT: load the default 'afterinit preset
                             (rapport-fn-featureset-load-preset 'afterinit)
                             ;; ,HINT: discover and register the listing of additional loadable featuresets from the "rapport" directory
                             (unless
                                 (or (bound-and-true-p rapport-emacs-opt-featureset-inhibit-discovery-at-startup)
                                     (and
                                      (stringp (getenv "RAPPORT_EMACS__OPT_FEATURESET_INHIBIT_DISCOVERY_AT_STARTUP"))
                                      (string-match "^[yYtT]" (getenv "RAPPORT_EMACS__OPT_FEATURESET_INHIBIT_DISCOVERY_AT_STARTUP"))))
                               (message (format " (rapport) ::core|emacsinit:: registered %s featureset-presets via discovery."
                                                (length (rapport-fn-featureset-add-presets-from-discovery)))))
                             ;; ,HINT: this will load lisp-formatted featureset data during after-init, may require featureset discovery as a pre-req if the featureset preset isn't defined by default.
                             ;; ,EXAMPLE: export RAPPORT_EMACS__OPT_FEATURESET_LOAD_CUSTOM='((acculturations) (editors . (humans)) (endeavors . (teams projects campaigns practices)) (correspondences) (eminences) (charms . (baubles glamours))))'
                             (when (and (bound-and-true-p rapport-emacs-opt-featureset-load-custom-from-env)
                                        (<= 1 (length (string-trim (getenv "RAPPORT_EMACS__OPT_FEATURESET_LOAD_CUSTOM")))))
                               (let*
                                   ((custom-featureset (read-from-string (getenv "RAPPORT_EMACS__OPT_FEATURESET_LOAD_CUSTOM")))
                                    (custom-featureset (if (consp custom-featureset) custom-featureset nil)))
                                 (when custom-featureset
                                   (and
                                    (rapport-fn-featureset-load custom-featureset)
                                    (message " (rapport) ::core|emacsinit:: registered featureset presets via discovery.")))))
                             ;; ,HINT: this will load a list of whitespace-delimited feature presets during after-init, may require featureset discovery as a pre-req if the featureset preset isn't defined by default.
                             ;; ,EXAMPLE: export RAPPORT_EMACS__OPT_FEATURESET_LOAD_PRESETS='researcher &rapport-acculturations-concepts'
                             (when (and (bound-and-true-p rapport-emacs-opt-featureset-load-presets-from-env)
                                        (<= 1 (length (string-trim (getenv "RAPPORT_EMACS__OPT_FEATURESET_LOAD_PRESETS")))))
                               (let*
                                   ((feature-presets (string-split (getenv "RAPPORT_EMACS__OPT_FEATURESET_LOAD_PRESETS"))))
                                 (when feature-presets (mapcar #'rapport-fn-featureset-load-preset feature-presets))))
                             ;; close-lambda
                             ))


;;
(provide 'rapport-core-emacsinit)
;; init.el ends here

Feature Set Management

;; ,NB: the 'xtrialx' featureset is included in discovery but excluded from the '&everything' preset, so that it's never loaded implicitly
(require 'subr-x) ;; ,HINT: needed for #'string-join
;;
(defcustom rapport-featureset-discovered-presets-fmt "&" "")
(defcustom rapport-featureset-filename-rx-parts '("rapport-" ".*" ".el" "$") "")
(defcustom rapport-featureset-filename-rx (string-join rapport-featureset-filename-rx-parts) "")
;; auxilliary features
(defcustom rapport-featureset-auxdirs-discovered-presets-fmt "+" "")
(defcustom rapport-featureset-auxdirs-filename-rx-parts '("rapport-" ".*" ".el" "$") "")
(defcustom rapport-featureset-auxdirs-filename-rx (string-join rapport-featureset-auxdirs-filename-rx-parts) "")

;; ,TODO: is there a robust way to fetch (rather than hard-code) this value during early-init
(defcustom rapport-featureset-presets
  `(
    ;; start-up and initialization presets
    (tangle-during-earlyinit . ((core . tangle)))
    (context-during-earlyinit . ((core . context)))
    (earlyinit . ((core . (context featureset functions variables pkgs))))
    (init . ((core . (context featureset functions variables pkgs org sysint customize))))
    (afterinit . (
                  (editors . (sysnav switchboard text org))
                  (endeavors . (forges  workspaces tasks))
                  (charms . (glamours))
                  ))
    ;; supplemental use-case presets
    (mediakit . (
                 (acculturations)
                 (endeavors . (practices))
                 (acculturations . (infowebs media))
                 (charms)
                 ))
    (swdev . (
              (editors . (swdev))
              (endeavors . (practices teams))
              (acculturations . (infowebs media))
              ))
    (devops . (
               (editors . (infradev))
               (endeavors . (practices teams))
               (acculturations . (infowebs))
               (coherence)
               ))
    (researcher . (
                   (editors . (data humans))
                   (acculturations)
                   (coherence)
                   (correspondences)
                                        ;?; eminences
                   ))
    (manager . (
                (acculturations)
                (editors . (humans))
                (endeavors . (teams projects campaigns practices))
                (correspondences)
                (eminences)
                (charms . (baubles glamours))
                ))
    (executive . (
                  (endeavors . (teams projects campaigns practices composure))
                  (acculturations)
                  (correspondences)
                  (eminences)
                  (charms . (baubles glamours))
                  ))
    ;; do-nothing case
    (nil . nil))
  "List of Rapport Modules to load. Inspipred by org-modules.
      The format is a named, ordered traversal list. (eg. '(key . (step1 . (step2))) ) ... which may also be written '(key step1 step2) becuase the underlying repesentation is identical.
      NOTE: The initial/default value for this variable may be expected to change when the Emacs Customization file is loaded, (potentially as a result of loading the 'rapport-core-customize feature)."
  :group 'rapport)
;;
(defun rapport-fn-featureset-get-uri-initdir () "Get the path to the directory used by Rapport Emacs during initialization. Note: Uses a tangled insert from the 'rapport-sbe--get-initdir Org-mode Source Block in the Control file."
       (or (bound-and-true-p rapport-emacs-uri-initdir)
           (and (stringp (getenv "RAPPORT_EMACS__URI_INITDIR"))
                (expand-file-name (getenv "RAPPORT_EMACS__URI_INITDIR")))
           (when (functionp '(rapport-fn-featureset-get-uri-initdir))
             (rapport-fn-featureset-get-uri-initdir))
           (expand-file-name user-emacs-directory)))
;;
(defun rapport-fn-featureset-get-uri-control () "Get the path to the file used by Rapport Emacs to control it's configuration and execution during build. Note: Uses a tangled insert from the 'rapport-sbe--get-control Org-mode Source Block in the Control file."
       (or (bound-and-true-p rapport-emacs-uri-control)
           (let ((from-env (getenv "RAPPORT_EMACS__URI_CONTROL")))
             (when (stringp from-env) from-env))
           buffer-file-name))
;;
(defun rapport-fn-featureset-get-uri-libdirs ()
  "Get an ordered list of all valid Rapport LIBDIR paths. Note: Uses a tangled insert from the 'rapport-sbe--get-libdirs Org-mode Source Block in the Control file. "
       (let*
           ((from-var (when (and
                             (bound-and-true-p rapport-emacs-uri-libdirs)
                             (listp rapport-emacs-uri-libdirs))
                        rapport-emacs-uri-libdirs))
            (from-env-libdir (getenv "RAPPORT_EMACS__URI_LIBDIR"))
            (from-env-libdir (when (stringp from-env-libdir)
                               (list from-env-libdir)))
            (from-env-libdirs (getenv "RAPPORT_EMACS__URI_LIBDIRS"))
            (from-env-libdirs (when (stringp from-env-libdirs)
                                (split-string from-env-libdirs nil t)))
            (from-runtime-default (getenv "RAPPORT_EMACS__URI_INITDIR"))
            (from-runtime-default (when (stringp from-runtime-default)
                                    (list (expand-file-name ".rapport.d" from-runtime-default))))
            (from-buildtime-default (list (expand-file-name ".rapport.d" user-emacs-directory))))
         (delete-dups
          (remove nil
                  (append
                   from-var
                   from-env-libdir
                   from-env-libdirs
                   from-runtime-default
                   from-buildtime-default)))))
;;
(defun rapport-fn-featureset-get-uri-libdir () "The primary LIBDIR path. Typically this is the 'car of LIBDIRS."
       (or (bound-and-true-p rapport-emacs-uri-libdir)
           (car (rapport-fn-featureset-get-uri-libdirs))))
;;
(defun rapport-fn-featureset-decorate-preset-key (key &optional key-decorate-fmt) ""
       (let*
           ((default-fmt "%s")
            ;; ,HINT: convert key from symbol to string
            (key (string-trim
                  (or (and (symbolp key) (symbol-name key))
                      (and (stringp key) key))))
            ;; ,HINT: lookup fmt to use, either passed in, or set via Customization, else use 'default-fmt
            (key-decorate-fmt (string-trim
                               (or (bound-and-true-p key-decorate-fmt)
                                   (bound-and-true-p rapport-featureset-discovered-presets-fmt)
                                   default-fmt)))
            ;; ,HINT: ensure that key-decorate-fmt includes one format-string (eg "%s") for the key to be interpolated. Where absent, append it.
            (key-decorate-fmt (or (and (string-match default-fmt key-decorate-fmt)
                                       key-decorate-fmt)
                                  (string-join `(,key-decorate-fmt "%s")))))
         (intern
          (cond
           ;; ,HINT: if there's no decoration in the format string, skip formatting and return the intern
           ((string-equal key-decorate-fmt default-fmt) key)
           (t (format key-decorate-fmt key))))))
;;
(defun rapport-fn-featureset-derive-preset-key-from-file (uri &optional key-decorate-fmt) ""
       (let*
           ((strip-prefix (car rapport-featureset-filename-rx-parts))
            (split-sep "-")
            (file-basename (file-name-base uri))
            (key (rapport-fn-featureset-decorate-preset-key file-basename))
            (file-kebab (string-remove-prefix strip-prefix file-basename))
            (feat-parts-str (split-string file-kebab split-sep))
            (feat-parts-sym (mapcar 'intern feat-parts-str)))
         (cons key (list feat-parts-sym))))
;;
(defun rapport-fn-featureset-list-feature-files (&optional dir) ""
       (let
           ((dir (or (bound-and-true-p dir)
                     (rapport-fn-featureset-get-uri-libdir))))
         (directory-files dir t rapport-featureset-filename-rx)))
;;
(defun rapport-fn-featureset-reduce-set (unimplemented) "")
;;
(defun rapport-fn-featureset-discovery (&optional dir) ""
       (let*
           ((dir (or (bound-and-true-p dir)
                     (rapport-fn-featureset-get-uri-libdir)))
            (files (rapport-fn-featureset-list-feature-files dir))
            (sets (mapcar 'rapport-fn-featureset-derive-preset-key-from-file files)))
         ;; let-body
         sets))
;;
(defun rapport-fn-featureset-add-presets-from-discovery () ""
       (interactive)
       (mapcar (lambda (set) (add-to-list 'rapport-featureset-presets set)) (rapport-fn-featureset-discovery)))
;;
(defun rapport-fn-featureset-remove-presets-from-discovery () ""
       (interactive)
       (mapcar (lambda (set) (setq rapport-featureset-presets (remove set rapport-featureset-presets))) (rapport-fn-featureset-discovery)))
;;
(defun rapport-fn-featureset-filter-keys-by-regex (&optional match action presets)
  "regex, (opt) op: one of include or exclude, (opt) presets"
  (let*
      ((default-match ".*")
       (match (or (and (stringp (bound-and-true-p match)) match)
                  default-match))
       (actions-alist '((include-match #'when)
                        (exclude-match #'unless)))
       (valid-actions (mapcar 'car actions-alist))
       (default-action (car valid-actions))
       (action (or (and (bound-and-true-p action)
                        (car (member action valid-actions)))
                   default-action))
       (presets (or (bound-and-true-p presets)
                    (rapport-fn-featureset-discovery)))
       (action-fn (car (alist-get action actions-alist))))
    ;; ,TODO: refactor to use funcall w/ the cdr from the selected action-alist
    (remove nil
            (mapcar (lambda (entry)
                      (cond
                       ((eq action 'include-match) (when (string-match-p match (symbol-name (car entry))) entry))
                       ((eq action 'exclude-match) (unless (string-match-p match (symbol-name (car entry))) entry))))
                    presets))))
;;
(defun rapport-fn-featureset-add-preset-everything (&optional key)
  "optional string KEY, defaults to 'everything.
Notably, components for 'xtrialx are intentionally not included in this definition of everything."
  (interactive)
  (let*
      ((key (if (and (bound-and-true-p key) (stringp key))
                key
              (concat rapport-featureset-discovered-presets-fmt "everything"))))
    (add-to-list 'rapport-featureset-presets
                 `(,(intern key) . ,(mapcar 'cadr
                                            ;; remove xtrialx to exclude it from the definition of the 'everything preset
                                            (rapport-fn-featureset-filter-keys-by-regex "xtrial" 'exclude-match (rapport-fn-featureset-discovery)))))))
;;
(defun rapport-fn-featureset-presets (&optional key) ""
       (cdr (assoc key rapport-featureset-presets)))
;;
(defun rapport-fn-featureset-presets-list () ""
       (mapcar 'car rapport-featureset-presets))
;;
(defun rapport-fn-featureset-load (&optional featureset)
  "declare the startup ingredients and order for starting Rapport Emacs"
  (mapcar (lambda (featureset)
            (cond
             ;; ,example: 'featname
             ((symbolp featureset)
              (require (intern (format "%s-%s" "rapport" featureset))))
             ;; ,example: '(featname)
             ;; ,example: '(featname . nil)
             ((and (consp featureset) (null (cdr featureset)))
              (require (intern (format "%s-%s" "rapport" (car featureset)))))
             ;; ,example: '(featname . symbvar)
             ((and (consp featureset) (null (null (cdr featureset))) (null (listp (cdr featureset))) (symbolp (cdr featureset)))
              (require (intern (format "%s-%s-%s" "rapport" (car featureset) (cdr featureset)))))
             ;; ,example: '(featname symbvar1 symbvar2 symbvar3)
             ;; ,example: '(featname . '(symbvar1 symbvar2 symbvar3)
             ((and (consp featureset) (null (null (cdr featureset))) (listp (cdr featureset)))
              (mapcar (lambda (x) (require (intern (format "%s-%s-%s" "rapport" (car featureset) x)))) (cdr featureset)))))
          (or (bound-and-true-p featureset) (bound-and-true-p rapport-emacs-featureset-requested) nil)))
    ;;;###autoload
(defun rapport-fn-featureset-load-preset (key)
  "preset key must already exist as a top-level symbol in the variable 'rapport-featureset-presets.
This function is a convenience wrapper on top of functions 'rapport-fn-featureset-load and 'rapport-fn-featureset-presets."
  (interactive (list (intern (completing-read "Select a Preset: " (rapport-fn-featureset-presets-list)))))
  (let*
      ((valid-keys (rapport-fn-featureset-presets-list))
       (inhibits-from-cfgs (when (and (bound-and-true-p rapport-emacs-opt-featureset-inhibit-presets)
                                      (listp rapport-emacs-opt-featureset-inhibit-presets)
                                      (<= 1 (length rapport-emacs-opt-featureset-inhibit-presets)))
                             rapport-emacs-opt-featureset-inhibit-presets))
       (inhibits-from-env (when (stringp  (getenv "RAPPORT_EMACS__OPT_FEATURESET_INHIBIT_PRESETS"))
                            (split-string (getenv "RAPPORT_EMACS__OPT_FEATURESET_INHIBIT_PRESETS"))))
       (inhibits (remove nil (append inhibits-from-env inhibits-from-cfgs)))
       (key (cond ((stringp key) (intern key))
                  ((listp key) (car key))
                  (t key)))
       (key-valid-type-p (symbolp key))
       (key-valid-membership-p (member key valid-keys))
       (key-valid-inhibit-p (null (member (symbol-name key) inhibits)))
       (key-valid-p (and key-valid-type-p key-valid-membership-p key-valid-inhibit-p)))

    (cond
     ;; the special cases
     ((string-equal "nil" (symbol-name key)) (message " (rapport) ::core|featureset:: requested special-case preset-key 'nil' which is a no-op, and doesn't loads anything."))

     ;; the error cases
     ((not key-valid-type-p) (message " (rapport) ::core|featureset:: invalid-type for variable 'key (expected: symbol)."))
     ((not key-valid-membership-p) (message (format " (rapport) ::core|featureset:: value for variable `'key `'%s not found in #'(rapport-fn-featureset-presets-list) ." (symbol-name key))))
     ((not key-valid-inhibit-p) (message (format " (rapport) ::core|featureset:: inhibited preset %s from loading due to inhibit envVar config '%s'" (symbol-name key) inhibits)))

     ;; the success case
     (key-valid-p (progn
                    (rapport-fn-featureset-load (rapport-fn-featureset-presets key))
                    (message (format " (rapport) ::core|featureset:: loaded preset '%s'" key))))
     ;; the canary case
     (t (message " (rapport) unhandled case encountered")))))


;; Update listing of Rapport presets to include dynamically discovered features
(add-hook 'after-init #'rapport-fn-featureset-add-presets-from-discovery)
;; Add special-case preset 'everything to load all Rapport features
(add-hook 'after-init #'rapport-fn-featureset-add-preset-everything)


;;
(provide 'rapport-core-featureset)

Determine Context Label

;; Set the custom-file path based on the first file found from a ranked list of generated candidate paths.
(defcustom rapport-context-custom-label nil
  "most of the time, this value should remain 'nil.  To fetch the value for Rapport's context-label, please use the '(rapport-fn-context-get-label) function instead.  This variable should only be used as an indirect override, not as a way to retrieve this value."
  :group 'rapport :type '(file :must-match t))

;;
(defun rapport-fn-context-candidate-label-list () ""
       (or (bound-and-true-p rapport-context-custom-label)
           (remove nil (list
                        (format "custom-%s-%s-context" (string-replace "." "+" system-name) user-login-name)
                        (format "custom-%s--context" user-login-name)
                        (format "custom---context")))))
;;
(defun rapport-fn-context-candidate-confdir-list () ""
       (remove nil
               (delete-dups
               (list
                    ;; ,example: ~/.vault/cfgs/emacs
                    (and (bound-and-true-p rapport-uri-vault-cfgs-emacs)
                         (file-directory-p rapport-uri-vault-cfgs-emacs)
                         rapport-uri-vault-cfgs-emacs)
                    ;; ,example: ~/.vault/cfgs/emacs
                    (and (bound-and-true-p rapport-uri-vault-cfgs)
                         (file-directory-p (expand-file-name "emacs" rapport-uri-vault-cfgs))
                         (expand-file-name "emacs" rapport-uri-vault-cfgs))
                    ;;
                    (and (not (null (getenv "RAPPORT__URI_VAULT_CFGS")))
                         (file-directory-p  (getenv "RAPPORT__URI_VAULT_CFGS"))
                         (file-directory-p (expand-file-name "emacs" (getenv "RAPPORT__URI_VAULT_CFGS")))
                         (expand-file-name "emacs" (getenv "RAPPORT__URI_VAULT_CFGS")))
                    ;;
                    (and (bound-and-true-p rapport-uri-vault)
                         (file-directory-p (expand-file-name "emacs" (expand-file-name "cfgs" rapport-uri-vault)))
                         (expand-file-name "emacs" (expand-file-name "cfgs" rapport-uri-vault)))
                    ;;
                    (and (not (null (getenv "RAPPORT__URI_VAULT")))
                         (file-directory-p  (getenv "RAPPORT__URI_VAULT"))
                         (file-directory-p (expand-file-name "emacs" (expand-file-name "cfgs"  (getenv "RAPPORT__URI_VAULT"))))
                         (expand-file-name "emacs" (expand-file-name "cfgs"  (getenv "RAPPORT__URI_VAULT"))))
                    ;;
                    (and (not (null (getenv "HOME")))
                         (file-directory-p (getenv "HOME"))
                         (file-directory-p (expand-file-name "emacs" (expand-file-name "cfgs" (expand-file-name ".vault" (getenv "HOME")))))
                         (expand-file-name "emacs" (expand-file-name "cfgs" (expand-file-name ".vault" (getenv "HOME")))))
                    ;;
                    (expand-file-name "" user-emacs-directory)))))
;; ,TODO: unimplemented
;;;###autoload
(defun rapport-fn-context-discover () "return a cons of '( uri . label )"
       (let
           ((candidate_labels_lst (rapport-fn-context-candidate-label-list))
            (candidate_confdirs_lst (rapport-fn-context-candidate-confdir-list)))
         ;; prefer the best label across valid confdirs locations, inputs are sorted so we'll return on the first match.
         (catch 'match
           (mapcar (lambda (label)
                     (mapcar (lambda (confdir)
                               (when (file-readable-p (format "%s.el" (expand-file-name label confdir)))
                                 (throw 'match (cons (format "%s.el" (expand-file-name label confdir)) label))))
                             candidate_confdirs_lst))
                   candidate_labels_lst)
           ;; if no existing files are found, return a generic fallback label value, "custom---context.el"
           (cons
            (expand-file-name (format "%s.el" (car (last candidate_labels_lst))) (car (last candidate_confdirs_lst)))
            (car (last candidate_labels_lst))))))
;;;###autoload
(defun rapport-fn-context-get-label ()
  "Return the context-label string after generating a ranked-list and selecting the most desirable best-available-match (or fall-back) option.  The best-available-match calculation is based on a system scan of config names. It's possible, likely, and even intended for the returned selection to change over time to become more tightly matched and more highly specified.  This function is used in the determination of the path/filename for the 'custom-file variable, taken from the first match of a contextually derived ranked list.  System, User, label used to distinguish and designate among various configs, paths, and other variables. Perhaps most notably used with 'custom-file' and session-persistence variables. Taken from the first match of a contextually derived ranked list."
  (interactive)
  (or (bound-and-true-p rapport-context-custom-label)
      (cdr (rapport-fn-context-discover))))

;;;###autoload
(defun rapport-fn-context-get-uri ()
  "Return the URI to the presumptive 'custom-file'"
  (car (rapport-fn-context-discover)))


;;
(provide 'rapport-core-context)

Conditional Tangle

;;
(defcustom rapport-tangle-files-map
  `((,(rapport-fn-featureset-get-uri-control) . ,(list
                                                  (expand-file-name "early-init.el" (rapport-fn-featureset-get-uri-initdir))
                                                  (expand-file-name "init.el" (rapport-fn-featureset-get-uri-initdir))
                                                  (expand-file-name "rapport-acculturations-concepts.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-acculturations-media.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-acculturations-infowebs.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-acculturations.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-charms-baubles.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-charms-glamours.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-charms-hints.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-charms-jests.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-charms.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-coherence.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-context.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-customize.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-emacsearlyinit.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-emacsinit.el" (rapport-fn-featureset-get-uri-libdir))
                                                  ;(expand-file-name "rapport-core-entrypoints.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-featureset.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-functions.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-measurements.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-org.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-pkgs.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-sysint.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-tangle.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-core-variables.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-correspondences.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors-data.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors-data2viz.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors-humans.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors-infradev.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors-org.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors-swdev.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors-switchboard.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors-sysnav.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors-text.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-editors.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-eminences.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-endeavors-campaigns.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-endeavors-composure.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-endeavors-forges.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-endeavors-practices.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-endeavors-projects.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-endeavors-tasks.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-endeavors-teams.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-endeavors-workspaces.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-endeavors.el" (rapport-fn-featureset-get-uri-libdir))
                                                  (expand-file-name "rapport-miscellany.el" (rapport-fn-featureset-get-uri-libdir))
                                                  ;; end-of-list
                                                  )))
  "The as an associative list of Rapport Tangle Source files and their Expected Tangle files."
  :group 'rapport :type '(set (file :must-match t)))
;;
(defun rapport-fn-tangle-source-files-list (&optional files-map)
  "Paths to the Rapport Tangle Source Files."
  (mapcar (lambda (x) (expand-file-name "" x))
          (mapcar 'car (or (bound-and-true-p files-map)
                           rapport-tangle-files-map))))
;;
(defun rapport-fn-tangle-target-files-expected (source-uri) ""
       (let
           ((source-uri (or (and (bound-and-true-p source-uri)
                                 (file-readable-p source-uri)
                                 source-uri))))
         (cdr (assoc source-uri rapport-tangle-files-map))))
;;
(defun rapport-fn-tangle-wanted-p (source-uri)
  "if source-uri is newer than it's corresponding target-uri, then flag for tangle by returning non-nil. source-uri must be in the list returned by #'rapport-fn-tangle-source-files-list"
  (let*
      ((source-uri (and (bound-and-true-p source-uri)
                        (member source-uri (rapport-fn-tangle-source-files-list))
                        source-uri))
       (source-mtime (file-attribute-modification-time (file-attributes source-uri)))
       (tangle-targets (rapport-fn-tangle-target-files-expected source-uri)))
    (catch 'tangle-wanted
      ;; loop while there are targets and no tangle requests
      (mapcar
       (lambda (target)
         (or
          (and (not (file-readable-p target)) ;; if it doesn't exist
               (message (format " (rapport) ::core|tangle:: requesting retangle of %s (because %s doesn't exist)" source-uri target))
               (throw 'tangle-wanted source-uri))
          (and (time-less-p (file-attribute-modification-time (file-attributes target)) source-mtime) ;; if it's newer than it's source
               (message (format " (rapport) ::core|tangle:: requesting retangle of %s (because it's newer than %s)" source-uri target))
               (throw 'tangle-wanted source-uri))
          (message (format " (rapport) ::core|tangle:: skipping retangle of %s (wasn't needed for %s)" source-uri target))))
       tangle-targets)
      nil)))
;;
(defun rapport-fn-tangle-maybe (&optional source-uri) ""
       (let ((source-uri (or (bound-and-true-p source-uri)
                             (rapport-fn-featureset-get-uri-control))))
         (when (rapport-fn-tangle-wanted-p source-uri)
           (message (format " (rapport) ::core|tangle:: tangling %s " (file-name-nondirectory source-uri)))
           (message "\t--->> //--- \n\t exit-code: %s \n\t---// <<--- "
                    (with-temp-buffer
                      (add-to-list 'exec-path "/usr/local/bin")
                      (add-to-list 'exec-path "c:/ProgramData/chocolatey")
                      (call-process-shell-command (format "%s --batch -Q -l org --eval '(setq org-confirm-babel-evaluate nil)'  -l ob-tangle %s -f org-babel-tangle --kill"
                                                          (executable-find "emacs") source-uri)
                                                  nil '(t t) nil))))))


      ;;;###autoload
(defun rapport-fn-tangle-files-maybe () ""
       (interactive)
       (mapcar (lambda (source-uri) (rapport-fn-tangle-maybe source-uri))
               (rapport-fn-tangle-source-files-list)))



;; The function =rapport-fn-tangle-maybe= tangles a single source URI if it is newer than its corresponding target URIs. It first checks if the source URI is valid and in the list of tangle source files. If so, it checks the modification time of the source URI and compares it to the modification time of the corresponding target URIs. If any target URI is newer than the source URI, it requests a retangle of the source URI.

;; If a retangle is requested, the function calls Emacs to tangle the source URI using the command =emacs --batch -Q -l org --eval '(setq org-confirm-babel-evaluate nil)' -l ob-tangle <source-uri> -f org-babel-tangle --kill=. The output of the tangle process is displayed in the message buffer.

;; The function =rapport-fn-tangle-files-maybe= tangles all source URIs in the list of tangle source files. It is typically called interactively, but can also be called programmatically.

;;
(provide 'rapport-core-tangle)

Define Functions

;;; Required Libraries
(require 'subr-x) ;; needed by '(rapport-fn-file-to-feature . (string-remove-prefix))


;;
(defun rapport-fn-file-to-feature (uri)
  "Generate a feature symbol from URI in support of dynamically discovered features."
  (intern (replace-regexp-in-string "\\." "-" (string-remove-prefix "." (file-name-base uri)))))
;;
(defun rapport-fn-feature-to-file (sym)
  "Generate a URI from a feature symbol in support of dynamically discovered features."
  (expand-file-name (format ".%s.%s.%s.el"
                            (car (split-string (symbol-name sym) "-"))
                            (nth 1 (split-string (symbol-name sym) "-"))
                            (string-join (cddr (split-string (symbol-name sym) "-")) "-"))
                    rapport-uri-rapport))

;;
;; (defun rapport/org/tangle-by-tag () ""
;;        (catch 'tag (mapc (lambda (x) (when (string-match "^tangle#" x 0 t) (throw 'tag (string-remove-prefix "tangle#" x)))) (split-string (nth 5 (org-heading-components)) ":" t))))


;;
(defun rapport-fn-current-time-as-string ()
  "Return a string of the current time."
  (concat
   (format-time-string "%Y-%m-%dT%H%M%SZ%z")))

;;
(defun rapport/doct/append (oct) (mapc (lambda (x) (add-to-list 'org-capture-templates x)) oct))


;;
(provide 'rapport-core-functions)

Control Variables

;; Set top-level features to On or Off.
(defcustom rapport-emacs-opt-load-custom-file (or (getenv "RAPPORT_EMACS__OPT_LOAD_CUSTOM_FILE") t)
  "Load the local custom file."
  :group 'rapport :type '(boolean))

(defcustom rapport-emacs-opt-theme (or (getenv "RAPPORT_EMACS__OPT_THEME") "ef-trio-dark")
  "A name used to selectively match theming configuration presets defined in Rapport."
  :group 'rapport :type '(string))
(defcustom rapport-emacs-opt-modeline (or (getenv "RAPPORT_EMACS__OPT_MODELINE") "lambda")
  "A name used to selectively match theming configuration presets defined in Rapport."
  :group 'rapport :type '(string))
(defcustom rapport-emacs-opt-org-modified
  (let*
      ((option-from-env (getenv "RAPPORT_EMACS__OPT_ORG_MODIFIED"))
       (option-from-env (and (stringp (bound-and-true-p option-from-env))
                             (car (member-ignore-case option-from-env
                                                      '("agenda" "buffer")))))
       (option-from-env (when option-from-env (intern option-from-env))))
    option-from-env)
  "Enable Modification TS tracking for Headings in Org-Mode."
  :group 'rapport :type '(radio
                          (const :tag "Agenda" 'agenda)
                          (const :tag "Buffer" 'buffer)
                          (const :tag "Tag" 'tag)
                          (const :tag "None" 'nil)))

;; TODO:
(defcustom rapport-emacs-opt-profiler
  (let*
      ((profiler-option-from-env (getenv "RAPPORT_EMACS__OPT_PROFILER"))
       (profiler-option-from-env (and (stringp (bound-and-true-p profiler-option-from-env))
                                      (car (member-ignore-case profiler-option-from-env
                                                               '("cpu" "mem" "cpu+mem")))))
       (profiler-option-from-env (when profiler-option-from-env (intern profiler-option-from-env))))
    profiler-option-from-env)
  "Profile the init-aux file."
  :group 'rapport :type '(radio
                          (const :tag "None" 'nil)
                          (const :tag "CPU" 'cpu)
                          (const :tag "Memory" 'mem)
                          (const :tag "Both CPU and Memory" 'cpu+mem)))


(defcustom rapport-emacs-opt-debug-on-error
  (let*
      ((debugger-option-from-env (getenv "RAPPORT_EMACS__OPT_DEBUG_ON_ERROR"))
       (debugger-option-from-env (and
                                  (bound-and-true-p debugger-option-from-env)
                                  (stringp debugger-option-from-env)
                                  (numberp (string-match-p "^[tTyY]" debugger-option-from-env)))))
    debugger-option-from-env)
  "Enable Debug on Error for troubleshooting purposes."
  :group 'rapport :type '(boolean))
(setq-default debug-on-error rapport-emacs-opt-debug-on-error)

                ;;; Rapport Path (aka URI) Variables for Import Locations.

(defcustom rapport-uri-emacsdotd
  (file-truename
   (or user-emacs-directory
       (file-name-directory buffer-file-name)))
  "Location of the Emacs Directory."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-rapport (rapport-fn-featureset-get-uri-libdir) "" :group 'rapport :type '(directory))

(defcustom rapport-uri-vault (or (getenv "RAPPORT__URI_VAULT")
                                 (expand-file-name ".vault" "~"))
  "Location of the root directory for personal data."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-uris (or (getenv "RAPPORT__URI_VAULT_URIS")
                                      "~/.uris"    ;; ,TODO: this option is valid only-if: it's a symlink that points to a location somewhere in rapport-uri-vault, else 'nil
                                      (expand-file-name (format ".vault-uris.%s" system-name) (expand-file-name "uris" rapport-uri-vault)))
  "Location of the navigational links directory for personal, system, and project data."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-apps (or (getenv "RAPPORT__URI_VAULT_APPS")
                                      (expand-file-name "apps" rapport-uri-vault))
  "Location of the personal executables directory for personal applications."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-docs (or (getenv "RAPPORT__URI_VAULT_DOCS")
                                      (expand-file-name "docs" rapport-uri-vault))
  "Location of the documents directory for personal data."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-docs-calendars (expand-file-name "calendars" rapport-uri-vault-docs)
  "Location of the directory for Concept documents, (typically within the personal documents directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-docs-concepts (expand-file-name "concepts" rapport-uri-vault-docs)
  "Location of the directory for Concept documents, (typically within the personal documents directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-docs-contacts (expand-file-name "contacts" rapport-uri-vault-docs)
  "Location of the directory for Contact documents, (typically within the personal documents directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-docs-status (expand-file-name ".status" rapport-uri-vault-docs)
  "Location of the directory for Status documents, (typically within the personal documents directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-docs-tasks (expand-file-name "tasks" rapport-uri-vault-docs)
  "Location of the directory for Task documents, (typically within the personal documents directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-docs-media (expand-file-name "media" rapport-uri-vault-docs)
  "Location of the directory for Media documents, (typically within the personal documents directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-docs-practices (expand-file-name "practices" rapport-uri-vault-docs)
  "Location of the directory for Practices documents and workspaces, (typically within the personal documents directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-var (or (getenv "RAPPORT__URI_VAULT_VAR")
                                     (file-truename (expand-file-name ".vault-var" rapport-uri-vault-uris)))
  "Location of the var/tmp directory for personal data."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-var-emacs (expand-file-name "emacs" rapport-uri-vault-var)
  "Location of the var/tmp directory for Emacs data."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-cfgs (or (getenv "RAPPORT__URI_VAULT_CFGS")
                                      (expand-file-name "cfgs" rapport-uri-vault))
  "Location of the root directory for personal data."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-cfgs-emacs (expand-file-name "emacs" (expand-file-name "cfgs" rapport-uri-vault))
  "Location of the Emacs configuration directory, (typicall within the personal data directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-cfgs-emacs-apps (expand-file-name "apps" rapport-uri-vault-cfgs-emacs)
  "Location of the config directory for Emacs applications, (typically within the Emacs configuration directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-cfgs-emacs-apps-org (expand-file-name "org" rapport-uri-vault-cfgs-emacs-apps)
  "Location of the config directory for Org-Mode, (typically within the Emacs applications directory)."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-cfgs-emacs-apps-org-setupfile (concat "~/" (file-relative-name (expand-file-name "org-setupfile" rapport-uri-vault-cfgs-emacs-apps-org) "~"))
  "Location of the default 'org-setupfile for bootstrapping Org-Mode files with configs."
  :group 'rapport :type '(directory))
(defcustom rapport-uri-vault-cfgs-emacs-pkgs (expand-file-name "pkgs" rapport-uri-vault-cfgs-emacs)
  ""
  :group 'rapport :type '(directory))

(provide 'rapport-core-variables)

Package and Dependency Management

Introductory Setup

;; pre-requisite features
(require 'rapport-core-context)
(require 'rapport-core-featureset)
(require 'rapport-core-functions)
(require 'rapport-core-variables)

;;
(defconst rapport-emacs-opt-pkgs-mgmt
  (let*
      ((valid-values '(
                               elpaca
                               straight
                        )) ;; previously this supported using 'elpaca and/or 'straight . As of 2024 and for the forseeable future only 'elpaca is supported  
       (default-value (list (car valid-values)))
       (errlog_msg_fmt " (rapport) ::core|pkgs:: [WARN] the input value '%s' for 'rapport-emacs-opt-pkgs-mgmt taken from environment variable '%s', was skipped becuase it failed a '%s' validation check")
       (from-env-lookup-keyword "RAPPORT_EMACS__OPT_PKGS_MGMT")
       (input-from-env (getenv from-env-lookup-keyword))
       (input-from-env (when (stringp input-from-env)
                         (split-string input-from-env)))
       (input-from-env-type-valid? (when (listp input-from-env)))
       ;; ,HINT: remove any non-strings or zero length strings and convert list items from string to symbol
       (input-from-env (when input-from-env-type-valid?
                         (remove nil (mapcar (lambda (x)
                                               (if (and (stringp x) (length> x 0))
                                                   (intern x)
                                                 (message (format errlog_msg_fmt x input-from-env-lookup-keyword "non-zero-length"))))
                                             input-from-env))))
       (input-from-env-value-valid? (and input-from-env-type-valid?
                                         (remove nil
                                                 (mapcar (lambda (x) (car (member x valid-values))) input-from-env)))))
    (or input-from-env-value-valid? default-value))
  "A precedence-ordered list of package management features to enable. The first entry is used as the primary, and any other entries in the list are taken as supplemental features or modifying behaviors. For example if 'elpaca is the first in the list and 'straight is the second, then 'elpaca will be setup as the primary package manager and 'straight will be installed using 'elpaca. If the list contains only one entry, 'elpaca for example, then elpaca would be setup to manage packages and straight support would be ommited. This has some implications because Rapport seeks to harmoniously support more than one package management system, so to prevent errors within a config that makes reference to multiple systems, any unused (non-primary and non-supplemental) systems will be partially or innocously declared as no-ops to prevent spurious errors from undefined references to keywords and functions.")


;;
(defun rapport-fn-pkgs-get-builds-dir (&optional basedir)
  (let*
      ((basedir (or (bound-and-true-p basedir)
                    (and (bound-and-true-p rapport-emacs-opt-pkgs-mgmt)
                         (bound-and-true-p rapport-uri-vault-var-emacs)
                         (expand-file-name (symbol-name (car rapport-emacs-opt-pkgs-mgmt)) rapport-uri-vault-var-emacs))
                    user-emacs-directory)))
    (expand-file-name
     (string-replace "/" "+"
                     (format "build_v%s-%s-%s" emacs-version (car (split-string system-configuration "-")) system-type))
     basedir)))

;; designate pre-configs for elpaca
(when (member 'elpaca rapport-emacs-opt-pkgs-mgmt)
  (defconst elpaca-directory (expand-file-name "elpaca"  rapport-uri-vault-var-emacs))
  (defconst elpaca-builds-directory (rapport-fn-pkgs-get-builds-dir elpaca-directory))
  (defconst elpaca-repos-directory (expand-file-name "repos" elpaca-directory))
  ;; set a fall-back value if unset by elpaca distribution
  (when (or (not (bound-and-true-p elpaca-core-date))
            (equal elpaca-core-date '(-1)))
    (setq-default elpaca-core-date '(20240101)))
  ;; ensure 'elpaca is added to load-path
  (add-to-list 'load-path (expand-file-name "elpaca" (if (file-exists-p (expand-file-name "elpaca.el" (expand-file-name "elpaca" elpaca-builds-directory))) elpaca-builds-directory elpaca-repos-directory))))

;; designate pre-configs for straight
(when (member 'straight rapport-emacs-opt-pkgs-mgmt)
  (defconst straight-base-dir rapport-uri-vault-var-emacs)
  (defconst straight-build-dir (rapport-fn-pkgs-get-builds-dir (expand-file-name "straight" rapport-uri-vault-var-emacs))))

Package Management w/ elpaca.el

Install and configure elpaca
(when (equal (car rapport-emacs-opt-pkgs-mgmt) 'elpaca)
  ;; <elpaca-init>
    ;;; elpaca.el --- emacs package manager
    ;;; Commentary:
    ;;; Code:
  (defvar elpaca-installer-version 0.8)
  ;; (defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
  ;; (defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
  ;; (defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
  (defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
                                :ref nil :depth 1
                                :files (:defaults "elpaca-test.el" (:exclude "extensions"))
                                :build (:not elpaca--activate-package)))
  (let* ((repo  (expand-file-name "elpaca/" elpaca-repos-directory))
         (build (expand-file-name "elpaca/" elpaca-builds-directory))
         (order (cdr elpaca-order))
         (default-directory repo))
    (add-to-list 'load-path (if (file-exists-p build) build repo))
    (unless (file-exists-p repo)
      (make-directory repo t)
      (when (< emacs-major-version 28) (require 'subr-x))
      (condition-case-unless-debug err
          (if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
                   ((zerop (apply #'call-process `("git" nil ,buffer t "clone"
                                                   ,@(when-let ((depth (plist-get order :depth)))
                                                       (list (format "--depth=%d" depth) "--no-single-branch"))
                                                   ,(plist-get order :repo) ,repo))))
                   ((zerop (call-process "git" nil buffer t "checkout"
                                         (or (plist-get order :ref) "--"))))
                   (emacs (concat invocation-directory invocation-name))
                   ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
                                         "--eval" "(byte-recompile-directory \".\" 0 'force)")))
                   ((require 'elpaca))
                   ((elpaca-generate-autoloads "elpaca" repo)))
              (progn (message "%s" (buffer-string)) (kill-buffer buffer))
            (error "%s" (with-current-buffer buffer (buffer-string))))
        ((error) (warn "%s" err) (delete-directory repo 'recursive))))
    (unless (require 'elpaca-autoloads nil t)
      (require 'elpaca)
      (elpaca-generate-autoloads "elpaca" repo)
      (load "./elpaca-autoloads")))
  (add-hook 'after-init-hook #'elpaca-process-queues)
  ;; ,ORIG: (elpaca `(,@elpaca-order))
  ;; ,WARN: the above expands to the below. The two should be interchangable, but _seem_ not to be ... ?
  (elpaca '(elpaca :repo "https://github.com/progfolio/elpaca.git" :ref nil :depth 1 :files (:defaults "elpaca-test.el" (:exclude "extensions")) :build (:not elpaca--activate-package)))
  ;; </elpaca-init>
  ;; for systems which cannot create symlinks:
  (when (member system-type '(cygwin haiku ms-dos windows-nt))
      (elpaca-no-symlink-mode))
  ;; activate
  (elpaca-wait)
  (progn))
setup elpaca as the default package-fulfillment system for use-package
;; <elpaca-with-use-package>
;;
;; use 'elpaca to install and pre-reqs of 'use-package
(elpaca bind-key)
(elpaca-wait)
;; Install 'use-package using 'elpaca
(elpaca use-package
  (progn
    ;; https://gitlab.com/rapport1/emacsdotd/-/issues/167
    ;; 20200121_NGa eval "always-defer" for faster and more incremental start-up
    (setq use-package-always-defer t)
    ;; ,ref: https://github.com/progfolio/elpaca/issues/255#issuecomment-1939076449
    (setq use-package-always-ensure t)
    ;; enable use-package-statistics
    (setq use-package-compute-statistics t)))
(elpaca-wait)
;; Enable elpaca via the ':ensure use-package keyword.
(elpaca elpaca-use-package
  (progn
    (elpaca-use-package-mode)
    ;; Assume 'elpaca package fulfillment unless otherwise specified.
    (setq elpaca-use-package-by-default t)))
;; sync-action before proceeding
(elpaca-wait)
;;
;; </elpaca-with-use-package>


;;
(add-hook
 ;; NB: When using Elpaca, add configuration which rely on
 ;;       after-init-hook, emacs-startup-hook, etc to
 ;;       'elpaca-after-init-hook so it runs after Elpaca has
 ;;       activated all queued packages.
 (if (featurep 'elpaca) 'elpaca-after-init-hook 'after-init-hook)
 (lambda nil (rapport-fn-featureset-load-presets 'afterinit)))

;; prevents `elpaca-after-init-hook` from running more than once.
;; ,ref: https://github.com/progfolio/elpaca/wiki/after-init-hook%3F-emacs-startup-hook%3F
(add-hook 'after-init-hook
          (lambda ()
            (setq elpaca-after-init-time (or elpaca-after-init-time (current-time)))
            (elpaca-wait)))

extend use-package with Configs and Add-Ons

supplemental integration configs for Rapport package management, using use-package
;; use the :ensure-system-package keyword w/i use-package
;(use-package use-package-ensure-system-package :after (:all elpaca) :hook elpaca)
;; use the :delight keyword to manage mode-line
(use-package delight :after (:all elpaca) :hook elpaca)

;; 'hydra is required by 'use-package-hydra and 'major-mode-hydra
(use-package hydra :after (:all elpaca) :hook elpaca)
;; setup the :hydra keyword using the same arguments as defhydra
(use-package use-package-hydra :after (:all elpaca hydra) :hook hydra)
;; add =major-mode-hydra= ,, https://github.com/jerrypnz/major-mode-hydra.el
(use-package major-mode-hydra
  :after (:all elpaca hydra use-package-hydra)
  :hook (use-package-hydra)
  :bind ("C-c M-@" . major-mode-hydra)
  :config (progn))


;; Opportunisticly Use Native-Comp (feat: speed-ups)
;; ,ref: https://emacs.stackexchange.com/questions/185/can-i-avoid-outdated-byte-compiled-elisp-files/186
;; (use-package auto-compile
;;   :init
;;   (setq load-prefer-newer t)
;;   :custom
;;   (auto-compile-on-load-mode t)
;;   :config
;;   (progn))

;; sync-action before proceeding
(elpaca-wait)
establish Common and Native Libraries via Package Mgmt

creating and Loading Lockfiles

;;
(defun rapport-fn-pkgs-get-mgmt-sys-name ()
  ""
  (car  (or (and
             (functionp 'use-package-handler/:elpaca)
             (member 'elpaca features))
            (and
             (functionp 'use-package-handler/:straight)
             (member 'straight features)))))
;;
(defun rapport-fn-pkgs-get-uri-statefile ()
  ""
  (require 'rapport-core-context)
  (expand-file-name
   (format "_%s.%s.lockfile.eld"
           (rapport-fn-pkgs-get-mgmt-sys-name)
           (rapport-fn-context-get-label))
   rapport-uri-vault-cfgs-emacs-pkgs))
;;
(defun rapport-fn-pkgs-statefile-save (&optional uri-statefile)
  ""
  (interactive)
  (let*
      ((uri-statefile (or
                       (bound-and-true-p uri-statefile)
                       (rapport-fn-pkgs-get-uri-statefile)))
       (pkg-sys (rapport-fn-pkgs-get-mgmt-sys-name)))
    ;;
    (unless (file-readable-p uri-statefile)
      (save-buffer (find-file uri-statefile)))
    (cond
     ((eq pkg-sys 'elpaca)  (elpaca-write-lockfile uri-statefile))
                                        ;((= pkg-sys 'straight)  (straight-freeze-versions)
     ;; as fall-through case, do nothing
     (t))))
;;
(defun rapport-fn-pkgs-statefile-load (&optional uri-statefile)
    ""
  (interactive)
  (let*
      ((uri-statefile (or
                       (bound-and-true-p uri-statefile)
                       (rapport-fn-pkgs-get-uri-statefile)))
       (pkg-sys (rapport-fn-pkgs-get-mgmt-sys-name)))
    ;;
    (unless (file-readable-p uri-statefile)
      (error " ... state file '%s' is not readable." (find-file uri-statefile)))
    (cond
     ((eq pkg-sys 'elpaca)  (elpaca-load-lockfile uri-statefile))

                                        ;((= pkg-sys 'straight)  (straight-thaw-versions)

     ;; as fall-through case, do nothing
     (t))))

Core Org-Mode Functionality

setup Org-Mode

enable the inimitable https://orgmode.org

;;
 (use-package org
   :demand t
   ;:ensure nil

   ;; :init
   ;; ;; ,REF: https://github.crookster.org/switching-to-straight.el-from-emacs-26-builtin-package.el/#put-in-place-org-workaround
   ;; ;; ,REF: https://github.com/raxod502/radian/blob/afe2882e3eb85c3284d90fd374be4a5ef9c8775a/radian-emacs/radian-org.el#L54-L92

   ;; ;; There are three things missing from our version of Org: the
   ;; ;; functions `org-git-version' and `org-release', and the feature
   ;; ;; `org-version'. We provide all three of those ourself, therefore.

   ;; ;; The following functions rely on reading `git tags`, which
   ;; ;;   may not be included in your checkout. If absent, tags can
   ;; ;;   be added by running `git fetch --tags`.

   ;; (defun org-git-version (&optional fallback-version)
   ;;   "The Git version of org-mode. Inserted by installing org-mode or when a release is made."

   ;;   (let* ((git-repo (expand-file-name
   ;;                     "straight/repos/org/" rapport-uri-vault-var-emacs))
   ;;          (fallback-version (or (bound-and-true-p fallback-version)
   ;;                                "release_9.9.9"))
   ;;          (version (string-trim (or
   ;;                                 (ignore-errors (git-run "describe"
   ;;                                                         "--tags"  ;; .HINT: this shouldnt be needed and may err toward inclusivity
   ;;                                                         "--match=release_\*"
   ;;                                                         "--abbrev=6"
   ;;                                                         "HEAD"))
   ;;                                 fallback-version))))
   ;;     version))


   ;; (defun org-release ()
   ;;   "The release version of org-mode.
   ;;           Inserted by installing org-mode or when a release is made."
   ;;   (string-trim
   ;;    (car
   ;;     (split-string
   ;;      (string-remove-prefix
   ;;       "release_"
   ;;       (org-git-version))
   ;;      "-"))))

   ;; (defalias 'org-version 'org-release "")
   ;; ;(provide 'org-version)

   :bind
   (("C-c C-x C-j" . org-clock-goto)
    ("C-c a" . org-agenda)
    :map org-mode-map
    ("C-c ~" . nil) ;; ,NB: the keybind for #'org-table-create-with-table.el is inhibited so that it may be used globally as a prefix for flycheck
    ;; mode-specific jump keybind
    ("C-c j j" . consult-org-heading))

   :custom
   (org-directory rapport-uri-vault-docs)
   (org-default-notes-file (expand-file-name
                            (format "_INBOX._%s.org" (rapport-fn-context-get-label))
                            rapport-uri-vault-docs-tasks))
   (org-attach-id-dir (expand-file-name "org_attach" (expand-file-name ".assets" rapport-uri-vault-docs)))
   (org-src-preserve-indentation t) ;; https://gitlab.com/rapport1/emacsdotd/issues/130
   ;; omit a link to an HTML validation service when exporting to HTML
   (org-html-validation-link "")
   :config
   (require 'org)
   (require 'org-macro)
   ;; remove broken legacy capture config, if present
   (setq org-structure-template-alist (remove '("n" "#+BEGIN_NOTES\n?\n#+END_NOTES") org-structure-template-alist))
   (require 'subr-x)
   (progn))


 (use-package org-contrib
   :after (:all org)
   :demand t
   :config
   (progn))

apply Performance Tweaks

;; http://orgmode.org/worg/agenda-optimization.html
;; https://punchagan.muse-amuse.in/blog/how-i-learnt-to-use-emacs-profiler/
(setq org-agenda-inhibit-startup t) ;; ~50x speedup
(setq org-agenda-use-tag-inheritance nil) ;; 3-4x speedup during startup,
(add-hook 'after-init-hook                ;;   then revert after-init
          #'(lambda () (setq org-agenda-show-inherited-tags 'always)))
(setq-default org-agenda-skip-scheduled-if-deadline-is-shown 'not-today)

Introspection and Internals

Host-System Intg.

enable no-littering package for a tidy ~/.emacs.d
(use-package no-littering
  :demand t
  :init
  (setq no-littering-etc-directory rapport-uri-vault-cfgs-emacs-apps)
  (setq no-littering-var-directory rapport-uri-vault-var-emacs)
  :config
  (setq auto-save-file-name-transforms `((".*" ,(no-littering-expand-var-file-name "auto-save/"))))
  (setq backup-directory-alist `(("." . ,(no-littering-expand-var-file-name "auto-save/"))))
  ;;
  (setq url-history-file (expand-file-name "url/history" rapport-uri-vault-var-emacs))
  ;; (opt.) exclude no-littering dirs from recentf lookup dir listing
  (eval-after-load 'recentf-mode
    (lambda () (progn
                 (add-to-list 'recentf-exclude no-littering-var-directory)
                 (add-to-list 'recentf-exclude no-littering-etc-directory))))
  (progn))
Emacs Subprocess will Inherit their Environment from Emacs
(use-package inheritenv
  :config
  (progn))
update the System PATH environment variable

Set PATH from the Shell when in GUI Mode. This is unnecessary when running within the CLI.

;; Copy Environment PATH from Shell
(use-package exec-path-from-shell
  :demand t
  :if (memq window-system '(mac nx x))
  :custom
  (exec-path-from-shell-arguments '("-l" "-i"))
  (exec-path-from-shell-variables '(
                                    "PATH"
                                    "MANPATH"
                                    ;;
                                    "RAPPORT__URI_VAULT"
                                    "RAPPORT__URI_VAULT_APPS"
                                    "RAPPORT__URI_VAULT_CFGS"
                                    "RAPPORT__URI_VAULT_DOCS"
                                    "RAPPORT__URI_VAULT_URIS"
                                    "RAPPORT__URI_VAULT_VAR"
                                    "RAPPORT_EMACS__OPT_THEME"
                                    "RAPPORT_EMACS__OPT_MODELINE"
                                    "RAPPORT_EMACS__OPT_PROFILER"
                                    ;;
                                    "HM_FLAKE_URI"
                                    ))
:config
(exec-path-from-shell-initialize))
copy clipboard to kill-ring
;; http://pragmaticemacs.com/emacs/add-the-system-clipboard-to-the-emacs-kill-ring/
;; Save whatever’s in the current (system) clipboard before
;; replacing it with the Emacs’ text.
;; https://github.com/dakrone/eos/blob/master/eos.org
(setq save-interprogram-paste-before-kill t)
helper for MacOSX
setup Flyspell keybind
;; If you’re using a Mac, you may need this config to pick up right-clicks
(when (eq system-type 'darwin)
  (eval-after-load "flyspell"
    '(progn
       (define-key flyspell-mouse-map [down-mouse-3] #'flyspell-correct-word)
       (define-key flyspell-mouse-map [mouse-3] #'undefined))))
setup Command key as Meta
;; I prefer cmd key for meta
;; https://superuser.com/questions/297259/set-emacs-meta-key-to-be-the-mac-key
(when (eq system-type 'darwin)
    (setq mac-option-key-is-meta nil
          mac-command-key-is-meta t
          mac-command-modifier 'meta
          mac-option-modifier 'none))
helper for MSWin
;; mswin tweaks, hoping to take the edge off
(when (eq system-type 'windows-nt)
  ;; try to improve slow performance on windows
  (message " (rapport) using <%s> system configs" system-type)
  (setq w32-get-true-file-attributes nil)

  ;; Recycle Bin
  ;;  - The following line configures Emacs so that files deleted via
  ;;    Emacs are moved to the Recycle.
  (setq delete-by-moving-to-trash t)

  ;; ref: https://caiorss.github.io/Emacs-Elisp-Programming/Emacs_On_Windows.html

  ;; Use Unix's \n (LF- Line Feed) and utf instead of Windows \r\n
  ;;   (CRLF - Carriage Return and Line Feed) as end of line
  ;;   character. It may not be desirable if most files or project
  ;;   edited are for Windows or building tools that may fail if the
  ;;   source file doens't CRLF as line ending.
  (setq-default buffer-file-coding-system 'utf-8-unix)
  ;; Uniformly UTF-8
  (set-terminal-coding-system 'utf-8)
  (set-language-environment 'utf-8)
  (set-keyboard-coding-system 'utf-8)
  (prefer-coding-system 'utf-8)
  (setq locale-coding-system 'utf-8)
  (set-default-coding-systems 'utf-8)
  (set-terminal-coding-system 'utf-8)


  ;; Enable visual bell, (i.e. dont rely on audio)
  (setq-default visible-bell t)
  ;; Do not open file or user dialog.
  (setq use-file-dialog nil)
  (setq use-dialog-box nil)


  ;; wrap Powershell shell
  (defun run-powershell ()
    "Run powershell"
    (interactive)
    (async-shell-command (executable-find "powershell") nil nil))

  ;; wrap CMD.exe shell
  (defun run-cmdexe ()
    (interactive)
    (let ((shell-file-name (executable-find "cmd")))
      (shell "*cmd:shell*")))

  ;; wrap Bash shell
  (defun run-bash ()
    (interactive)
    (let ((shell-file-name (executable-find "bash"))
          (shell "*bash:shell*"))))

  ;;(when (string-equal (getenv "LANG") "ENU")
  ;;  (setenv "LANG" "en_US"))

  ;;; https://gist.github.com/michaelmhoffman/285e1024b4195aec7bd34d34bc9accd0
  ;; - Flyspell is hooked to =text-mode-hook= later in the config.
  ;; #$> choco install hunspell.portable

  ;; (eval-after-load 'ispell
  ;;   (lambda ()
  ;;     (progn
  ;;       (setq-default ispell-program-name (executable-find "hunspell"))
  ;;       ;; XXX: hunspell doesn't work because Emacs wants to figure out where its
  ;;       ;; directories are, and for win32 hunspell 1.7.0, `hunspell -D` *never* runs listdicpath()
  ;;       ;; https://github.com/hunspell/hunspell/issues/669

  ;;       ;; to correct, copied this bit from ispell-find-hunspell-dictionaries and
  ;;       ;; changed so that it removes a .dic extension from the list of dictionaries
  ;;       ;; used so can find the appropriate .aff file

  ;;       ;; XXX: should be advice instead of running absolutely
  ;;       (let ((hunspell-found-dicts
  ;;              (eval-when-compile
  ;;                (split-string
  ;;                 (with-temp-buffer
  ;;                   (ispell-call-process ispell-program-name
  ;;                                        null-device
  ;;                                        t
  ;;                                        nil
  ;;                                        "-D"
  ;;                                        "-a"
  ;;                                        null-device)
  ;;                   (buffer-string))
  ;;                 "[\n\r]+"
  ;;                 t))))
  ;;         (dolist (dict hunspell-found-dicts)
  ;;           (let* ((full-name (file-name-nondirectory dict))
  ;;                  (basename (file-name-sans-extension full-name))
  ;;                  ;; CHANGED from ispell.el: remove .dic if it's there
  ;;                  (affix-file (concat (file-name-sans-extension dict) ".aff")))
  ;;             (if (and (not (assoc basename ispell-hunspell-dict-paths-alist))
  ;;                      (file-exists-p affix-file))
  ;;                 ;; Entry has an associated .aff file and no previous value.
  ;;                 (let ((affix-file (expand-file-name affix-file)))
  ;;                   (cl-pushnew (list basename affix-file)
  ;;                               ispell-hunspell-dict-paths-alist :test #'equal)))))))))

  (progn))

(ex.) add an Emacs option to Explorer, (Windows File-Browser)

  • The following registry script creates an “Open with Emacs” option in the Windows file explorer context menu.

    Windows Registry Editor Version 5.00
    
    [HKEY_CLASSES_ROOT\*\Shell\Open In Emacs\Command]
    @="\"C:\\bin\\Emacs-23.1\\bin\\emacsclientw.exe\" -a \"C:\\bin\\Emacs-23.1\\bin\\runemacs.exe\" \"%1\""
    
    

(ex.) set path to iSpell on Windows

helper for Linux
setup NixOS integrations
;(use-package company-nixos-options :config (progn))
(use-package nix-buffer            :config (progn))
(use-package nix-env-install       :config (progn))
(use-package nix-haskell-mode      :after (:all nix-mode) :config (progn))
(use-package nix-mode              :after (:all transient seq) :config (progn))
(use-package nix-modeline          :config (progn))
(use-package nix-sandbox           :config (progn))
(use-package nix-update            :config (progn))
(use-package nixos-options         :config (progn))
(use-package nixpkgs-fmt           :config (progn))
helper for Mobile Devices
(setq-default battery-load-critical 8
              battery-load-low 20
              battery-mode-line-limit 55)
(setq display-battery-mode t)
enable 3rd-Party Application File Handling

setup openwith

;;
(use-package openwith
  :config
  (setq openwith-associations
        (list
          (list (openwith-make-extension-regexp
                '("mpg" "mpeg" "mp3" "mp4"
                  "avi" "wmv" "wav" "mov" "flv"
                  "ogm" "ogg" "mkv"))
                "mpv"
                '(file))
          (list (openwith-make-extension-regexp
                '("xbm" "pbm" "pgm" "ppm" "pnm"
                  "png" "gif" "bmp" "tif" "jpeg")) ;; Removed jpg because Telega was
                  ;; causing feh to be opened...
                  "feh"
                  '(file))
          (list (openwith-make-extension-regexp
                '("pdf"))
                "zathura"
                '(file))))
  (openwith-mode 1))

Emacs Adaptive Tweaks

conveniently restart Emacs
(use-package restart-emacs)
helpful, for a more Ergonomic Emacs Help system
;; https://github.com/Wilfred/helpful
(use-package helpful
                                        ;:demand
  ;; :bind ("C-h" . helpful-hydra/body)
  ;; :prettyh-ydra
  ;; ((:color teal :quit-key "q")
  ;;  ("Helpful"
  ;;   (("f" helpful-callable "callable")
  ;;    ("F" helpful-function "Look up *F*unctions (excludes macros).")
  ;;    ("v" helpful-variable "variable")
  ;;    ("k" helpful-key "key")
  ;;    ("c" helpful-command "command")
  ;;    ("d" helpful-at-point "Lookup the current symbol at point."))))
  :init
  ;; If you want to replace the default Emacs help keybindings, you can do so:

  ;; Note that the built-in `describe-function' includes both functions
  ;; and macros. `helpful-function' is functions only, so we provide
  ;; `helpful-callable' as a drop-in replacement.
  (global-set-key (kbd "C-h f") #'helpful-callable)

  (global-set-key (kbd "C-h v") #'helpful-variable)
  (global-set-key (kbd "C-h k") #'helpful-key)
  :commands (helpfull-callable helpful-variable helpful-key)
  ;; :pretty-hydra
  ;; ((:color teal :quit-key "q")
  ;;  ("Helpful"
  ;;   (("f" helpful-callable "callable")
  ;;    ("v" helpful-variable "variable")
  ;;    ("k" helpful-key "key")
  ;;    ("c" helpful-command "command")
  ;;    ("d" helpful-at-point "thing at point"))))

  :config
  ;; I also recommend the following keybindings to get the most out of helpful:

  ;; Lookup the current symbol at point. C-c C-d is a common keybinding
  ;; for this in lisp modes.
  (global-set-key (kbd "C-c C-d") #'helpful-at-point)

  ;; Look up *F*unctions (excludes macros).
  ;;
  ;; By default, C-h F is bound to `Info-goto-emacs-command-node'. Helpful
  ;; already links to the manual, if a function is referenced there.
  (global-set-key (kbd "C-h F") #'helpful-function)

  ;; Look up *C*ommands.
  ;;
  ;; By default, C-h C is bound to describe `describe-coding-system'. I
  ;; don't find this very useful, but it's frequently useful to only
  ;; look at interactive functions.
  (global-set-key (kbd "C-h C") #'helpful-command)
  (progn))
enable Emacs-Async for Improved Responsiveness
(use-package async
  :config
  (progn))
Don't warn for large files (shows up when launching videos)
(setq large-file-warning-threshold nil)
Don't warn for following symlinked files
(setq vc-follow-symlinks t)
Don't warn when advice is added for functions
(setq ad-redefinition-action 'accept)

Local Customization

import customize data

;; get Rapport's context to distinguish distinct per-profile-per-host customization files
(require 'rapport-core-context)


;; Set the 'custom-file' using the value of '(rapport-fn-context-get-uri)
(setq-default custom-file (rapport-fn-context-get-uri))


;; load the custom file, (may sometimes load additional features)
(and
 rapport-emacs-opt-load-custom-file
 (bound-and-true-p custom-file)
 (or (file-readable-p custom-file)
     ;; create Rapport's custom file in Vault if it doesn't already exist
     (save-buffer (find-file custom-file)))
(or (load-file custom-file)
     (message "wrn: unable to load dynamic custom-file." )))

on Application Entrypoints using Org-Babel

These org-babel source block functions are available in a naive and minimalistic tangle context, as encountered during the pre-flight-check activities in the initialization activities in Rapport's nix shell shebang and start-up configs. In other words they are used only to create the Rapport Emacs config, but are intentionally absent from that config.

on Emacs Entrypoint Script

(opt.) launch script

#,wip: readonly cfg_LOGLEVEL=""
readonly cfg_OPTSTRING="thgGq"
readonly msg_USAGE<<-EOM
        this is a strange and mysterious tool, no?
        NB: as a result of the adoption of 'nix env shell' semantics, the minimum required version of Nix is v2.24
EOM

##
export RAPPORT_EMACS__URI_CONTROL="${RAPPORT_EMACS__URI_CONTROL:-${HOME}/.uris/emacsdotd/control.org}"
export RAPPORT_EMACS__URI_INITDIR="${RAPPORT_EMACS__URI_INITDIR:-$(dirname $(realpath "${RAPPORT_EMACS__URI_CONTROL}"))}"
##
log_ERR(){ "ERR: $*" ; }
log(){ local LEVEL="${1}" ; shift ; log_${LEVEL^^} "${*}" ; }
nope(){ log ERR "$*" ; }

#
##
###
##
#

args=$(getopt ${cfg_OPTSTRING} $*)
if [[ $? -ne 0 ]] ; then nope "invalid argument. exiting" ; fi
set -- $args
while :; do
    case "$1" in
        # ,HINT: single-character args

        -t)
            export RAPPORT_EMACS__OPT_GUI=n
            shift
            ;;
        -g)
            export RAPPORT_EMACS__OPT_GUI=t
            #export RAPPORT_EMACS__OPT_DETACH=t
            shift
            ;;
        -G)
            export RAPPORT_EMACS__OPT_GUI=t
            export RAPPORT_EMACS__OPT_DETACH=t
            export RAPPORT_EMACS__OPT_ARGS="${RAPPORT_EMACS__OPT_ARGS} --funcall toggle-frame-fullscreen "
            shift
            ;;
        -h)
            echo -e "${msg_USAGE}"
            exit
            ;;
        # ,HINT: compound/keyword args
        # ,HINT: structural/special matches
        --)
            shift
            export RAPPORT_EMACS__OPT_ARGS="${RAPPORT_EMACS__OPT_ARGS} ${*}"
            break
            ;;
        *)
            break
            ;;
    esac
done


case ${1} in
    show-config)
        for i in ${!RAPPORT_EMACS__*} ; do printf "%45s  ~>  %s\n"  "${i}" "${!i# }" | sort ;done
        # ,WIP: for i in $(seq ${#RAPPORT_EMACS__URI_LIBDIRS[@]}) ; do echo -e ' (rapport)::Emacs \\t RAPPORT_EMACS__URI_LIBDIRS['$(($i-1))'] \\t == \\t '${RAPPORT_EMACS__URI_LIBDIRS[i]}'' ; done
        ;;
    *)
        cd "${RAPPORT_EMACS__URI_INITDIR}"
        if [[ "${RAPPORT_EMACS__OPT_DETACH}" =~ ^[yYtT] ]] ; then
            exec ./$(basename "${RAPPORT_EMACS__URI_CONTROL}") ${@} &
        else
            exec ./$(basename "${RAPPORT_EMACS__URI_CONTROL}") ${@}
        fi
        ;;
esac


## EOF

Instrument and Test Rapport

support testing

enable esup

(use-package esup
  :demand
  :config
  (progn))

support testing an Rapport Emacs config without restarting current Rapport Emacs instance

  ;;;###autoload
(defun rapport-fn-profile-startup ()
  "Profile Emacs Rapport's Start-Up using Esup."
  (interactive)
  (progn
    (rapport-fn-tangle-files-maybe)
    (require 'esup)
    (esup)))

Chapter 1, Universal Editor

as OS Navigation and Management Editor

enable File Browser and Directory Editor w/ DirEd

    ;;; dired
    (use-package dired
      :ensure nil
;      :init
;      (require 'dired)
;      :no-require t
;      :after (dired)
      :bind
      (:map dired-mode-map
            ("Y" . dired-do-relsymlink)
            ;; 20200811 NOTE: this opens the file at point but also kills the original dired buffer which makes subsequent navigation a bit awkward ;; ("RET" . dired-find-alternate-file) ; was dired-find-file
            ("^" . (lambda () (interactive) (find-alternate-file "..")))  ; was dired-up-directory
            ("<mouse-2>" . dired-find-alternate-file)) ; was dired-find-file
      :custom
      (dired-auto-revert-buffer t)
      (dired-listing-switches "-alH")
                                            ;(setq dired-listing-switches "-alGh1v")
      (dired-use-ls-dired 'unspecified)
      ;; Change time format
      (ls-lisp-format-time-list  '("%Y-%m-%d %a %H:%M"  "%Y-%m-%d %a %H:%M"))
      (ls-lisp-use-localized-time-format t)
      :config
      (dired-async-mode t)  ;; ,HINT: uses rsync in an async subprocess to enable non-blocking file operations in Dired
      (progn))
enable DirEd-subtree
(use-package dired-subtree
  :after (:all dired)
  :bind
  (:map dired-mode-map
        ("TAB" . dired-subtree-toggle))
  :config
  ;(advice-add 'dired-subtree-toggle :after (lambda () (interactive) (when nerd-icons-dired-mode (revert-buffer))))
  (progn))
enable Mouse click-to-open within DirEd
(put 'dired-find-alternate-file 'disabled nil)

enable Transparent Remote Access using Tramp

enable Tramp's support for Vagrant

setup vagrant-tramp

(use-package vagrant-tramp
  :if (and
       (executable-find "vagrant")
       (not (eq system-type 'windows-nt))) ;; 20200528_NGa disabled on windows to quell EM
  :after (:all vagrant tramp))
enable Native, Capable terminal w/ EAT

Emulate-A-Terminal aka EAT

(use-package eat
  :bind
  (:map eat-mode-map
        ("C-x p '" . bury-buffer))
  :config
  (progn))

enable async Process Mgmt using Detached

  • from project page (sr.ht), (ref: Melpa, talk: EmacsConf'22)

    (use-package detached
      :if (executable-find "dtach")
      :bind
      (;; Replace `async-shell-command' with `detached-shell-command'
       ([remap async-shell-command] . detached-shell-command)
       ;; Replace `compile' with `detached-compile'
       ([remap compile] . detached-compile)
       ([remap recompile] . detached-compile-recompile)
       ;; Replace built in completion of sessions with `consult'
       ([remap detached-open-session] . detached-consult-session))
      :custom
      (detached-show-output-on-attach t)
      (detached-terminal-data-command system-type)
      :config
      (detached-init)
      (unless (and
               (file-directory-p detached-db-directory)
               (file-exists-p detached-db-directory))
        (make-directory detached-db-directory t))
      (progn))
    

as Command Interaction (UX) Switchboard

Commanding Selection

context
  • info/notes
    • on Initial Understanding a/o Discovery
      • to ignore candidates and immediately use the search text, type C-u C-j
enhanced Candidate Selection w/ Vertico
;; https://github.com/minad/vertico
(use-package vertico
  ;; :init
  ;; (vertico-mode)
  :demand
                                        ;:bind
                                        ;(:map vertico-map
                                        ;("C-j" . vertico-next)
                                        ;("C-k" . vertico-previous)
                                        ;("<escape>" . minibuffer-keyboard-quit) ; Close minibuffer
  :hook
  ((rfn-eshadow-update-overlay . vertico-directory-tidy)) ; Clean up file path when typing
  :custom
  (enable-recursive-minibuffers t)

  ;; Different scroll margin
  ;; (setq vertico-scroll-margin 0)

  ;; Show more candidates
  ;; (setq vertico-count 20)

  ;; Grow and shrink the Vertico minibuffer
  ;; (setq vertico-resize t)

  :config
  (eval-after-load 'vertico-save (add-hook 'minibuffer-setup-hook 'vertico-repeat-save))  ;; Make sure vertico state is saved for `vertico-repeat'
  ;; enable wrap-around navigation for `vertico-next' and `vertico-previous'.
  (setq vertico-cycle t)
  ;; enable vertico-mode
  (vertico-mode 1)
  ;; for best results, Vertico recommends using the savehist package to save history over Emacs restarts. Vertico sorts by history position.
  (progn))

ergonomic Functionality Library Consult
;; Example configuration for Consult
(use-package consult
  ;; Replace bindings. Lazily loaded due by `use-package'.
  :bind (;; C-c bindings (mode-specific-map)
         ("C-c h" . consult-history)
         ("C-c m" . consult-mode-command) ;; ,NB: this is AWESOME for discovering functionality w/i modes!
         ("C-c k" . consult-kmacro)
         ;; global navigation/jump helper commands
         ("C-c j g" . consult-ls-git) ;; jump to file from candidates annotated with Git Status info
         ("C-c j i" . consult-imenu)  ;; jump to location in file based on Imenu structure
         ;; Note: several keybinds for mode-specific behavior are defined futher down in this use-package macro
         ;; HINT: "C-c j j" should always be defined for major-mode specific navigation
         ("C-c J" . consult-org-agenda) ;; the Org-Agenda provides System-wide navigation
         ;; Custom M-# bindings for fast register access
         ("M-#" . consult-register-load)
         ("M-'" . consult-register-store)          ;; orig. abbrev-prefix-mark (unrelated)
         ("C-M-#" . consult-register)
         ;; Other custom bindings
         ("M-y" . consult-yank-pop)                ;; orig. yank-pop
         ("<help> a" . consult-apropos)            ;; orig. apropos-command
         ;; M-g bindings (goto-map)
         ("M-g e" . consult-compile-error)
         ;("M-g f" . consult-flymake)               ;; Alternative: (consult-flycheck)
         ("M-g g" . consult-goto-line)             ;; orig. goto-line
         ("M-g M-g" . consult-goto-line)           ;; orig. goto-line
         ("M-g o" . consult-outline)               ;; Alternative: consult-org-heading
         ("M-g m" . consult-mark)
         ("M-g k" . consult-global-mark)
         ("M-g i" . consult-imenu)
         ("M-g I" . consult-imenu-multi)
         ;; M-s bindings (search-map)
         ("M-s f" . consult-find)
         ("M-s D" . consult-locate)
         ("M-s g" . consult-grep)
         ("M-s G" . consult-git-grep)
         ("M-s r" . consult-ripgrep)
         ("M-s l" . consult-line)
         ("M-s L" . consult-line-multi)
         ("M-s m" . consult-multi-occur)
         ("M-s k" . consult-keep-lines)
         ("M-s u" . consult-focus-lines)
         ;; Isearch integration
         ("M-s e" . consult-isearch-history)
         :map ctl-x-map
         ;; C-x bindings (ctl-x-map)
         ("M-:" . consult-complex-command)     ;; orig. repeat-complex-command
         ("b" . consult-buffer)                ;; orig. switch-to-buffer
         ("4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
         ("5 b" . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
         ("r b" . consult-bookmark)            ;; orig. bookmark-jump
         ;wip;("C-x p b" . consult-project-buffer)      ;; orig. project-switch-to-buffer
         ("C-r" . consult-recent-file)         ;; orig. find-file-read-only
         :map isearch-mode-map
         ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
         ("M-s e" . consult-isearch-history)       ;; orig. isearch-edit-string
         ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
         ("M-s L" . consult-line-multi)            ;; needed by consult-line to detect isearch
         ;; Minibuffer history
         :map minibuffer-local-map
         ("M-s" . consult-history)                 ;; orig. next-matching-history-element
         ("M-r" . consult-history)                 ;; orig. previous-matching-history-element
         )

  ;; Enable automatic preview at point in the *Completions* buffer. This is
  ;; relevant when you use the default completion UI.
  :hook
  (completion-list-mode . consult-preview-at-point-mode)

  ;; The :init configuration is always executed (Not lazy)
  :init

  ;; Optionally configure the register formatting. This improves the register
  ;; preview for `consult-register', `consult-register-load',
  ;; `consult-register-store' and the Emacs built-ins.
  (setq register-preview-delay 0.5
        register-preview-function #'consult-register-format)

  ;; Optionally tweak the register preview window.
  ;; This adds thin lines, sorting and hides the mode line of the window.
  (advice-add #'register-preview :override #'consult-register-window)

  ;; Use Consult to select xref locations with preview
  (setq xref-show-xrefs-function #'consult-xref
        xref-show-definitions-function #'consult-xref)

  ;; Configure other variables and modes in the :config section,
  ;; after lazily loading the package.
  :config

  (require 'consult-xref)

  ;; Optionally configure preview. The default value
  ;; is 'any, such that any key triggers the preview.
  ;; (setq consult-preview-key 'any)
  ;; (setq consult-preview-key (kbd "M-."))
  ;; (setq consult-preview-key (list (kbd "<S-down>") (kbd "<S-up>")))
  ;; For some commands and buffer sources it is useful to configure the
  ;; :preview-key on a per-command basis using the `consult-customize' macro.
  (consult-customize
   consult-theme
   :preview-key '(:debounce 0.2 any)
   consult-ripgrep consult-git-grep consult-grep
   consult-bookmark consult-recent-file consult-xref
   consult--source-bookmark consult--source-recent-file
   consult--source-project-recent-file
   :preview-key "M-.")

  ;; Optionally configure the narrowing key.
  ;; Both < and C-+ work reasonably well.
  (setq consult-narrow-key "<") ;; (kbd "C-+")

  ;; Optionally make narrowing help available in the minibuffer.
  ;; You may want to use `embark-prefix-help-command' or which-key instead.
  ;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)

  ;; By default `consult-project-function' uses `project-root' from project.el.

  (progn))

Additional Packages to Add:

Quick Directory Traversal in Consult using Consult-Dir
(use-package consult-dir
  :after (:all consult)
  :hook (consult)
  :bind (("C-x C-d" . consult-dir)
         :map vertico-map
         ("C-x C-d" . consult-dir)
         ("C-x C-j" . consult-dir-jump-file))
  :config
  (progn))
Consult + LSP-Mode using Consult-LSP
(use-package consult-lsp
  :after (:all consult lsp)
  :config
  (progn))
Consult + Eglot using Consult-Eglot
(use-package consult-eglot :after (:all consult eglot))
Consult + Flycheck using Consult-Flycheck
(use-package consult-flycheck :after (:all consult flycheck))
Consult + Flyspell using Consult-Flyspell
(use-package consult-flyspell
  :after (:all consult flyspell)
  :bind
  (:map flyspell-mode-map
        ("C-c j $" . consult-flyspell))
  :config
  (progn))
Consult + Ls Git using Consult-Ls-Git
(use-package consult-ls-git)
Consult + Org-Roam using Consult-Org-Roam
(use-package consult-org-roam
  :after (:all org-roam consult)
  :bind
  ;; Define some convenient keybindings as an addition
  (("C-c n e" . consult-org-roam-file-find)
   ("C-c n b" . consult-org-roam-backlinks)
   ("C-c n B" . consult-org-roam-backlinks-recursive)
   ("C-c n f"  . consult-org-roam-forward-links)
   ("C-c n l"  . org-roam-node-insert)
   ("M-s d" . consult-org-roam-search) ;; ,HINT: text search through docs 
   ("C-c n r" . consult-org-roam-search))
  :custom
  ;; Use `ripgrep' for searching with `consult-org-roam-search'
  (consult-org-roam-grep-func #'consult-ripgrep)
  ;; Configure a custom narrow key for `consult-buffer'
  (consult-org-roam-buffer-narrow-key ?r)
  ;; Display org-roam buffers right after non-org-roam buffers
  ;; in consult-buffer (and not down at the bottom)
  (consult-org-roam-buffer-after-buffers t)
  :config
  (require 'consult-org-roam)
  (require 'consult-org-roam-buffer)
  ;; Activate the minor mode
  (consult-org-roam-mode t)
  ;; Eventually suppress previewing for certain functions
  (consult-customize
   consult-org-roam-forward-links
   :preview-key "M-."))
Consult + Project.el using Consult-Project-Extra
;; ,ref: https://github.com/Qkessler/consult-project-extra
(use-package consult-project-extra
  :after (:all consult project)
  :bind
  (:map project-prefix-map
        ("f" . consult-project-extra-find)
        ("o" . consult-project-extra-find-other-window))
  :commands
  consult-project-extra-find
  consult-project-extra-find-other-window
  :config
  (progn))
Consult + Yasnippet using Consult-Yasnippet
(use-package consult-yasnippet
  :after (:all consult yasnippet))
More Predictive Selection Ordering w/ Orderless
;; Optionally use the `orderless' completion style.
(use-package orderless
  :custom
  ;; _Component matching styles_

  ;;   Each component of a pattern can match in any of several
  ;;     matching styles. A matching style is simply a function from
  ;;     strings to strings that maps a component to a regexp to match
  ;;     against, so it is easy to define new matching styles. The
  ;;     predefined ones are:

  ;; orderless-regexp
  ;;     - the component is treated as a regexp that must match somewhere in the candidate.
  ;;     - If the component is not a valid regexp, it is ignored.
  ;; orderless-literal
  ;;     - the component is treated as a literal string that must occur in the candidate.
  ;;     - This is just regexp-quote.
  ;; orderless-without-literal
  ;;     - the component is a treated as a literal string that must not occur in the candidate.
  ;;     - Note that nothing is highlighted for this matching style. You probably don’t want to use this style directly in orderless-matching-styles but with a style dispatcher instead. There is an example in the section on style dispatchers.
  ;; orderless-prefixes
  ;;     - the component is split at word endings and each piece must match at a word boundary in the candidate, occurring in that order.
  ;;     - This is similar to the built-in partial-completion completion-style. For example, re-re matches query-replace-regexp, recode-region and magit-remote-list-refs; f-d.t matches final-draft.txt.
  ;; orderless-initialism
  ;;     - each character of the component should appear as the beginning of a word in the candidate, in order.
  ;;     - This maps abc to \<a.*\<b.*\c.
  ;; orderless-flex
  ;;     - the characters of the component should appear in that order in the candidate, but not necessarily consecutively.
  ;;     - This maps abc to a.*b.*c.


  ;; The variable orderless-matching-styles can be set to a list of the desired matching styles to use. By default it enables the literal and regexp styles.
  (completion-styles '(orderless partial-completion basic))
  (completion-category-defaults nil)
  (completion-category-overrides '((file (styles basic partial-completion))))
  ;; (var) orderless-matching-styles  default: (orderless-literal orderless-regexp)
  (orderless-matching-styles  (list
                               'orderless-literal
                               'orderless-regexp
                               'orderless-prefixes
                               'orderless-initialism
                                        ;'orderless-flex
                               ;; end of list
                               ))
  :config
  (progn))
Supplemental Contextual Info for Selections using Marginalia
;; Enable richer annotations using the Marginalia package
(use-package marginalia
  :after (:all vertico)
  ;; Either bind `marginalia-cycle` globally or only in the minibuffer
  :bind (("M-A" . marginalia-cycle)
         :map minibuffer-local-map
         ("M-A" . marginalia-cycle))
  :init
  ;; Must be in the :init section of use-package such that the mode gets
  ;; enabled right away. Note that this forces loading the package.
  (marginalia-mode)
  :custom
  (marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
  :config
  (add-to-list 'marginalia-command-categories '(project-find-file . file)))
In-Situ Mini-Buffer Supplimental Selection Behaviors w/ Embark
;; https://github.com/oantolin/embark
(use-package embark
  :init
  ;; Optionally replace the key help with a completing-read interface
  (setq prefix-help-command #'embark-prefix-help-command)
  :bind
  (("C-." . embark-act)         ;; pick some comfortable binding
   ("C-;" . embark-dwim)        ;; good alternative: M-.
   ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
  :config
  ;; Hide the mode line of the Embark live/completions buffers
  (add-to-list 'display-buffer-alist
               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
                 nil
                 (window-parameters (mode-line-format . none))))
  ;;;; from ahmed-shariff
  (add-to-list 'display-buffer-alist
               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" nil
                 (window-parameters
                  (mode-line-format . none))))
  (define-key embark-file-map "o" nil)
  (define-key embark-file-map "ocn" #'copy-buffer-file-name)
  (define-key embark-file-map "ocf" #'copy-file-full-path)
  (defun embark-which-key-indicator nil "An embark indicator that displays keymaps using which-key.\nThe which-key help message will show the type and value of the\ncurrent target followed by an ellipsis if there are further\ntargets."
         (lambda
           (&optional keymap targets prefix)
           (if
               (null keymap)
               (which-key--hide-popup-ignore-command)
             (which-key--show-keymap
              (if
                  (eq
                   (plist-get
                    (car targets)
                    :type)
                   'embark-become)
                  "Become"
                (format "Act on %s '%s'%s"
                        (plist-get
                         (car targets)
                         :type)
                        (embark--truncate-target
                         (plist-get
                          (car targets)
                          :target))
                        (if
                            (cdr targets)
                            "…" "")))
              (if prefix
                  (pcase
                      (lookup-key keymap prefix 'accept-default)
                    ((and
                      (pred keymapp)
                      km)
                     km)
                    (_
                     (key-binding prefix 'accept-default)))
                keymap)
              nil nil t
              (lambda
                (binding)
                (not
                 (string-suffix-p "-argument"
                                  (cdr binding))))))))
  (setq embark-indicators
        '(embark-which-key-indicator embark-highlight-indicator embark-isearch-highlight-indicator))
  (defun embark-hide-which-key-indicator
      (fn &rest args)
    "Hide the which-key indicator immediately when using the completing-read prompter."
    (which-key--hide-popup-ignore-command)
    (let
        ((embark-indicators
          (remq #'embark-which-key-indicator embark-indicators)))
      (apply fn args)))
  (advice-add #'embark-completing-read-prompter :around #'embark-hide-which-key-indicator)
  (progn))
extend Embark with Consult integration
;; Consult users will also want the embark-consult package.
(use-package embark-consult
  :after (:all consult embark)
  ;:demand t ; only necessary if you have the hook below
  ;; if you want to have consult previews as you move around an
  ;; auto-updating embark collect buffer
  :hook (embark-collect-mode . consult-preview-at-point-mode)
  :config
  (progn))
extend Embark with Org-Roam integration
(use-package embark-org-roam
  :after (org-roam embark)
  :ensure (embark-org-roam
           :type git
           :host github
           :repo "bramadams/embark-org-roam")
  :config
  (progn))
display key-press options in-flight w/ Which Key

setup which-key

  • Guide-key a/o emacs-which-key

    ;;
    (use-package which-key
      :demand t
      :custom
      ;; location of which-key window. valid values: top, bottom, left, right,
      ;; or a list of any of the two. If it's a list, which-key will always try
      ;; the first location first. It will go to the second location if there is
      ;; not enough room to display any keys in the first location
      (which-key-side-window-location 'bottom)
    
      ;; max width of which-key window, when displayed at left or right.
      ;; valid values: number of columns (integer), or percentage out of current
      ;; frame's width (float larger than 0 and smaller than 1)
      (which-key-side-window-max-width 0.33)
    
      ;; max height of which-key window, when displayed at top or bottom.
      ;; valid values: number of lines (integer), or percentage out of current
      ;; frame's height (float larger than 0 and smaller than 1)
      (which-key-side-window-max-height 0.25)
    
      ;; Set the time delay (in seconds) for the which-key popup to appear. A value of
      ;; zero might cause issues so a non-zero value is recommended.
      (which-key-idle-delay 22)
    
      ;; Set the maximum length (in characters) for key descriptions (commands or
      ;; prefixes). Descriptions that are longer are truncated and have ".." added.
      (which-key-max-description-length 37)
    
      ;; Use additonal padding between columns of keys. This variable specifies the
      ;; number of spaces to add to the left of each column.
      (which-key-add-column-padding 0)
    
      ;; The maximum number of columns to display in the which-key buffer. nil means
      ;; don't impose a maximum.
      (which-key-max-display-columns nil)
    
      ;; Set the separator used between keys and descriptions. Change this setting to
      ;; an ASCII character if your font does not show the default arrow. The second
      ;; setting here allows for extra padding for Unicode characters. which-key uses
      ;; characters as a means of width measurement, so wide Unicode characters can
      ;; throw off the calculation.
      (which-key-separator " → " )
      (which-key-unicode-correction 3)
    
      ;; Set the prefix string that will be inserted in front of prefix commands
      ;; (i.e., commands that represent a sub-map).
      (which-key-prefix-prefix "+" )
    
      ;; Set the special keys. These are automatically truncated to one character and
      ;; have which-key-special-key-face applied. Disabled by default. An example
      ;; setting is
      ;; (which-key-special-keys '("SPC" "TAB" "RET" "ESC" "DEL"))
      (which-key-special-keys nil)
    
      ;; Show the key prefix on the left, top, or bottom (nil means hide the prefix).
      ;; The prefix consists of the keys you have typed so far. which-key also shows
      ;; the page information along with the prefix.
      (which-key-show-prefix 'left)
    
      ;; Set to t to show the count of keys shown vs. total keys in the mode line.
      (which-key-show-remaining-keys t)
    
      :config
      ;; integration with lsp-mode, when used
      (with-eval-after-load 'lsp-mode
        (add-hook 'lsp-mode-hook #'lsp-enable-which-key-integration))
    
            (which-key-mode t)
      ;; location of which-key window. valid values: top, bottom, left, right,
      ;; or a list of any of the two. If it's a list, which-key will always try
      ;; the first location first. It will go to the second location if there is
      ;; not enough room to display any keys in the first location
      (which-key-setup-side-window-right-bottom)
      (progn))
    
enable simpler prompts

setup y-or-n-p for simpler prompts

;; http://pragmaticemacs.com/emacs/make-all-prompts-y-or-n/
;; change all prompts to y or n
(fset 'yes-or-no-p 'y-or-n-p)

Sessions

Auto-Saving Changed Files (Persist Files to Disk, Improved harmony with Ext. File-Sync)

setup setup-save

(use-package super-save
  :demand t
  :init
  (super-save-mode t)
  :delight
  :custom
  (super-save-auto-save-when-idle t)
  (super-save-auto-idle-duration 6)
  (auto-save-visited-mode t)
  :hook
  (after-focus-chage-function . super-save-command)
  :config
  (progn))

Enable Auto-Revert Mode Globally, useful when file syncing to disambiguate between files and buffers

setup global-auto-revert-mode

;; ref: https://www.gnu.org/software/emacs/manual/html_node/emacs/Reverting.html
(use-package emacs
  :ensure nil

  :custom
  (global-auto-revert-mode t)
  (auto-revert-remote-files t)

  ;; When you edit a file that changes automatically and
  ;;   frequently—for example, a log of output from a process
  ;;   that continues to run—it may be useful for Emacs to
  ;;   revert the file without querying you. To request this
  ;;   behavior, set the variable revert-without-query to a
  ;;   list of regular expressions. When a file name matches
  ;;   one of these regular expressions, find-file and
  ;;   revert-buffer will revert it automatically if it has
  ;;   changed—provided the buffer itself is not modified. (If
  ;;   you have edited the text, it would be wrong to discard
  ;;   your changes.)
  (revert-without-query '(".*"))
  :delight
  :config
  (global-auto-revert-mode 't)
  (auto-revert-mode 't))
persist Emacs variables, commands, history using SaveHist
;;; reload
(unless (or
         (bound-and-true-p psession-savehist-mode))
  (savehist-mode 1))
restore Cursor to Previous Location when Re-Opening a File
(use-package save-place
  :ensure nil

  :custom
  (save-place-file (expand-file-name "places" rapport-uri-vault-var-emacs))
  :config
  (require 'saveplace)
  (save-place-mode t))
enable Emacs Session Restore after restart using Desktop-Save-Mode
(use-package desktop-save-mode
  :ensure nil

  :after (:all no-littering)
  :custom
  (desktop-restore-eager 0)  ; ,HINT: Number of buffers to restore immediately. Remaining buffers are restored lazily (when Emacs is idle). If value is t, all buffers are restored immediately.
  (desktop-save 'if-exists)  ; ,HINT: save if desktop file exists, otherwise don’t save.
  (desktop-lazy-verbose t)
  (desktop-auto-save-timeout 55)  ; ,HINT: Number of seconds of idle time before auto-saving the desktop. (default: 30)
  (desktop-file-name-format 'tilde)  ; ,HINT: record file paths relative to '~' (default: abs-paths)
  (desktop-lazy-idle-delay 25)  ; ,HINT: Idle delay before starting to create buffers. (default: 5)
  (desktop-path `(
                  ,(expand-file-name "desktop" no-littering-var-directory)
                  ,(expand-file-name "desktop" rapport-uri-vault-cfgs-emacs-apps)
                  ;; end-of-list
                  ))
  :config
  (desktop-save-mode t)
  (progn))

Files

line and word wrap

how to adjust line and work wrap

  • example func and variables to tweak

    ;;  (longlines-mode t)
    ;;  (toggle-longlines-mode)
    ;;  (toggle-word-wrap)
    
Recently Used Files w/ recentf

setup recentf

(use-package recentf
  :ensure nil

  :commands (recentf recentf-open recentf-open-files)
  :custom
  (recentf-save-file (expand-file-name "recentf" (expand-file-name "cache" rapport-uri-vault-var-emacs)))
  :hook (after-init . (lambda () (unless recentf-enabled-p (recentf-mode))))
  :config
  (progn))
;; ,TODO: setup after-init and command activation, recentf is not activating on startup except w/ the below
(recentf-mode +1)
Asynchronous Fuzzy Finder for Emacs (aka Affe)
(use-package affe
  :if (or (executable-find "rg") (executable-find "fd"))
  :bind
  ;; ,hint: prefix with =C-u= to set the starting directory prior to search
  ("M-s a f" . affe-find)
  ("M-s a g" . affe-grep)
  ;:ensure-system-package (rg fd)
  :commands (affe-find affe-grep)
  :custom
  (affe-find-command "fd --color=never --hidden  --follow")  ; ,HINT: (default: "rg --color=never --files")
  :config
  ;; Manual preview key for `affe-grep'
  (consult-customize affe-grep :preview-key (kbd "M-."))
  (progn))

Windows and Frames

disable Unused GUI Elements for Maximum Screen Space
;; disable toolbar
(tool-bar-mode -1)

;; disable menu bar
(menu-bar-mode -1)

;; disable scroll bar
(scroll-bar-mode -1)
use a Visual Prompt instead of an Audible Bell
;; Set up the visible bell
(setq visible-bell t)
Frame Mgmt with Nameframe

nameframe

;; https://github.com/john2x/nameframe
(use-package nameframe
  ;; If your OS can't switch between applications windows by default *cough* OS X *cough* you can have a shortcut to switch between existing frames by name
  :bind (("M-P" . nameframe-switch-frame))
  :config
  (progn))
Buffer Listing w/ BS

setup bs

(use-package bs
  :ensure nil

  :demand t
  :commands (bs-show)
  :config
    (require 'bs))
enable Window and Frame Workspace Mgmt

winner

  • winner

    ;; winner-mode
    (use-package winner
      :ensure nil
    
      :init
      (winner-mode 1))
    
windmove and buffer-move
(use-package windmove :ensure nil)
(use-package buffer-move
  :ensure nil

  :after windmove)
Balanced Window Splits

auto-balance windows using Zoom

;; https://github.com/cyrus-and/zoom
(use-package zoom
  :bind
  ("C-x +" . zoom)
  :custom
  ;; Resize the selected window using the golden ratio
  (zoom-size '(0.618 . 0.618))
  ;(zoom-ignored-major-modes '(dired-mode markdown-mode))
  ;(zoom-ignored-buffer-names '("zoom.el" "init.el"))
  (zoom-ignored-buffer-name-regexps '("^*calc"))
  (zoom-ignore-predicates '((lambda () (> (count-lines (point-min) (point-max)) 20))))
  :config
  (progn))
Window Profiles Mgmt

setup eyebrowse

  • nb
  • setup eyebrowse

    ;; https://github.com/wasamasa/eyebrowse
    ;; C-c C-w <      Switch to previous window config
    ;; C-c C-w >      Switch to next window config
    ;; C-c C-w '      Switch to last window config
    ;; C-c C-w "      Close current window config
    ;; C-c C-w ,      Rename current window config
    ;; C-c C-w 0      Switch to window config 0
    ;; ...    ...
    ;; C-c C-w 9      Switch to window config 9
    (use-package eyebrowse
      ;; TODO: adjust keybinds to emulate the style used by tmux and perspective
      :custom
      (eyebrowse-keymap-prefix (kbd "C-c C-] C-w")) ;; slightly psycho but I stand by it :D
      (eyebrowse-mode-line-separator ";")
      (eyebrowse-new-workspace t)
      :config
      (progn))
    

as General Editing and Authoring Environment

enable Contextual Folding w/ Origami.el

  • setup https://github.com/gregsexton/origami.el

    (use-package origami
      :init
      (defun rapport/org-super-agenda/origami-fold-default-groups ()
        "Groups will be folded (minimized) on initial display in the Org Super Agenda buffer. This list of groups to fold is read from the variable 'rapport/org-super-agenda/auto-show-groups ."
        (interactive)
        (when (and
               org-super-agenda-mode
               (bound-and-true-p rapport/org-super-agenda/auto-show-groups)
               (listp rapport/org-super-agenda/auto-show-groups))
          (forward-line 3)
          (cl-loop do (origami-forward-toggle-node (current-buffer) (point))
                   while (origami-forward-fold-same-level (current-buffer) (point)))
          (--each rapport/org-super-agenda/auto-show-groups
            (goto-char (point-min))
            (when (re-search-forward (rx-to-string `(seq bol " " ,it)) nil t)
              (origami-show-node (current-buffer) (point))))))
      :hook
      ((org-agenda-mode . origami-mode)
       (org-agenda-finalize . rapport/org-super-agenda/origami-fold-default-groups))
      :bind (
             :map org-agenda-mode-map
             ("M-s s" . rapport/org-super-agenda/-toggle-and-refresh)
             ("M-s M-s" . rapport/org-super-agenda/-toggle-and-refresh)
             ("M-s f" . rapport/org-super-agenda/origami-fold-default-groups)
             :map org-super-agenda-header-map
             ("<tab>" . origami-toggle-node)
             ("M-s f" . rapport/org-super-agenda/origami-fold-default-groups)
             )  
      :config
      (progn))
    

enable Browseable Kill-Ring

(use-package browse-kill-ring)

undo-fu

;; ,ref: https://codeberg.org/ideasman42/emacs-undo-fu
(use-package undo-fu
  :init
  (global-unset-key (kbd "C-z"))
  (global-set-key (kbd "C-z")   'undo-fu-only-undo)
  (global-set-key (kbd "C-S-z") 'undo-fu-only-redo)
  :config
  (progn))

undo-fu-session

;; ,ref: https://codeberg.org/ideasman42/emacs-undo-fu-session
(use-package undo-fu-session
  :after (:all undo-fu)
  :hook
  (after-init . global-undo-fu-session-mode)
  :config
  (progn))

vundo

;; ,ref: https://github.com/casouri/vundo
(use-package vundo
;; By default, you need to press RET to “commit” your change and return
;; to the buffer.  If instead you quit with q or C-g, the changes made by
;; vundo are rolled back. You can set ‘vundo-roll-back-on-quit’ to nil to
;; disable rolling back.

;; Diff:
;; Vundo uses Emacs' facilities to provide diffs among arbitrary undo
;; states: just (m)ark and (d)iff.  By default, vundo's diff window is
;; buried when vundo quits; see `vundo-diff-quit' for other options.

;; Terminal users may encounter unwanted control characters in the diff
;; output.  Emacs colors diff buffers itself, so this can be remedied by
;; instructing diff not to print color codes:

;;     (setq diff-switches "-u --color=never")

;; Comparing to undo-tree:

;; Vundo doesn’t need to be turned on all the time nor replace the undo
;; commands like undo-tree does. Vundo displays the tree horizontally,
;; whereas undo-tree displays a tree vertically.  Diff is provided
;; on-demand between any nodes.

:bind
("C-x u" . vundo)
;; Vundo (visual undo) displays the undo history as a tree and lets you
;; move in the tree to go back to previous buffer states. To use vundo,
;; type M-x vundo RET in the buffer you want to undo. An undo tree buffer
;; should pop up. To move around, type:
;;
;;   f   to go forward
;;   b   to go backward
;;
;;   n   to go to the node below when at a branch point
;;   p   to go to the node above
;;
;;   a   to go back to the last branching point
;;   w   to go forward to the next branching point
;;   e   to go forward to the end/tip of the branch
;;   l   to go to the last saved node
;;   r   to go to the next saved node
;;
;;   m   to mark the current node for diff
;;   u   to unmark the marked node
;;   d   to show a diff between the marked (or parent) and current nodes
;;
;;   q   to quit, you can also type C-g
;;
;;   C-c C-s (or whatever binding you used for save-buffer)
;;       to save the buffer at the current undo state
;;
;; n/p may need some more explanation. In the following tree, n/p can
;; move between A and B because they share a parent (thus at a branching
;; point), but not C and D. To make it clear, branches you can switch
;; between are highlighted with bold face.
;;
;;          A  C
;;     ──○━━○──○──○──○
;;       ┃  ↕︎
;;       ┗━━○──○──○
;;          B  D
;;

;; :custom-face
;; - vundo-default 
;; - vundo-node
;; - vundo-stem
;; - vundo-highlight
;; - vundo-saved
;; (vundo-last-saved ((t (:foreground "dark gray" :weight bold))))

:config
;; If you want to use prettier Unicode characters to draw the tree like
;; this:
;;     ○──○──○
;;     │  └──●
;;     ├──○
;;     └──○
;; set vundo-glyph-alist by
;;     (setq vundo-glyph-alist vundo-unicode-symbols)
;; Your default font needs to contain these Unicode characters, otherwise
;; they look terrible and don’t align. You can find a font that covers
;; these characters (eg, Symbola, Unifont), and set ‘vundo-default’ face
;; to use that font:
;;     (set-face-attribute 'vundo-default nil :family "Symbola")


;; By default, you need to press RET to “commit” your change and return
;; to the buffer.  If instead you quit with q or C-g, the changes made by
;; vundo are rolled back. You can set ‘vundo-roll-back-on-quit’ to nil to
;; disable rolling back.

;; You might see some green nodes in the tree, those are the buffer
;; states that have been saved to disk; the last saved node is emphasized
;; in bold. You can type "l" to jump to the last saved node.

(progn))

enable visual Version Control Change Hints using Diff-HL

(use-package diff-hl
  :config
  (global-diff-hl-mode)
  (progn))

whitespace indentation highlight using Highlight-Indent-Guides

;; ,ref: https://github.com/DarthFennec/highlight-indent-guides
(use-package highlight-indent-guides
  ;:hook (prog-mode)
  :custom
  (highlight-indent-guides-method 'character) ;; ,opt: 'column, 'bitmap, 'character
  (highlight-indent-guides-character ?‖)
  (highlight-indent-guides-responsive 'top)
  ;; (highlight-indent-guides-responsive 'stack)
  ;; (highlight-indent-guides-auto-enabled nil)
  ;; (set-face-background 'highlight-indent-guides-odd-face "darkgray")
  ;; (set-face-background 'highlight-indent-guides-even-face "dimgray")
  ;; (set-face-foreground 'highlight-indent-guides-character-face "dimgray")
  (highlight-indent-guides-auto-set-faces t)
  :config
  (progn))

Inhibit Electric Indent for more Predictable Paste-In of Text

disable electric-indent-mode, which is an Emacs native package and enabled by default

(electric-indent-mode nil)

enable Jump Navigation

enable Jump to Visible Word using Ace-Jump
;; ,refs: https://github.com/winterTTr/ace-jump-mode
(use-package ace-jump-mode
  :demand t
  :custom
  (ace-jump-mode-move-keys (cl-loop for i from ?a to ?z collect i))
  (ace-jump-mode-case-fold t)
  (ace-jump-mode-submode-list '(ace-jump-word-mode       ;; the first one always map to : C-c SPC
                                ace-jump-char-mode       ;; the second one always map to: C-u C-c SPC
                                ace-jump-line-mode))     ;; the third one always map to :C-u C-u C-c SPC
  :bind
  (("C-c j a" . ace-jump-mode)
   ("C-c j A" . ace-jump-mode-pop-mark)
   ("C-x SPC" . ace-jump-mode-pop-mark))
  :config
  ;(autoload 'ace-jump-mode "ace-jump-mode" "Emacs quick move minor mode" t)
  ;(autoload 'ace-jump-mode-pop-mark "ace-jump-mode" "Ace jump back:-)" t)
  (ace-jump-mode-enable-mark-sync)
  (progn))
enable Quickly Switching Windows using Ace-Window
  • nb, bound to M-p, prefix w/ C-u to swap w/ target, prefix with C-u C-u to kill target
  • setup

    (use-package ace-window
      ;:after (:all ace-jump-mode)
      :bind
      (("M-p" . ace-select-window)
       ("C-x o" . ace-select-window))
      :custom
      ;; use the keys are on the home row as selection targets, (0-9 by default)
      (aw-keys '(?a ?s ?d ?f ?j ?k ?l))
      (aw-dispatch-always t)
      (aw-dispatch-alist '((?x aw-delete-window "Ace - Delete Window")
                           (?c aw-swap-window "Ace - Swap Window")
                           (?n aw-flip-window)
                           (?v aw-split-window-vert "Ace - Split Vert Window")
                           (?h aw-split-window-horz "Ace - Split Horz Window")
                           (?m delete-other-windows "Ace - Maximize Window")
                           (?g delete-other-windows)
                           (?b balance-windows)
                           (?u (lambda ()
                                 (progn
                                   (winner-undo)
                                   (setq this-command 'winner-undo))))
                           (?r winner-redo)))
      :config
      ;; (defhydra hydra-window-size (:color red)
      ;;   "Windows size"
      ;;   ("h" shrink-window-horizontally "shrink horizontal")
      ;;   ("j" shrink-window "shrink vertical")
      ;;   ("k" enlarge-window "enlarge vertical")
      ;;   ("l" enlarge-window-horizontally "enlarge horizontal"))
      ;; (defhydra hydra-window-frame (:color red)
      ;;   "Frame"
      ;;   ("f" make-frame "new frame")
      ;;   ("x" delete-frame "delete frame"))
      ;; (defhydra hydra-window-scroll (:color red)
      ;;   "Scroll other window"
      ;;   ("n" scroll-other-window "scroll")
      ;;   ("p" scroll-other-window-down "scroll down"))
      ;; (add-to-list 'aw-dispatch-alist '(?w hydra-window-size/body) t)
      ;; (add-to-list 'aw-dispatch-alist '(?o hydra-window-scroll/body) t)
      ;; (add-to-list 'aw-dispatch-alist '(?\; hydra-window-frame/body) t)
      (ace-window-display-mode t)
      (progn))
    

configure Org-Mode Navigation

;; org-goto
;; https://emacs.stackexchange.com/questions/20759/all-org-subheadings-in-imenu
;; accessible as C-j
;;; imenu in org-mode
(use-package emacs
  :ensure nil

  :no-require t
  :init
  (setq org-goto-interface 'outline-path-completion)
  (setq org-outline-path-complete-in-steps nil)
  :custom
  (org-imenu-depth 5) ;; default: 2
  (imenu-list-update-hook '((lambda () (toggle-truncate-lines t))))
  :config
  (progn))

inhibit Org-Mode folding when Comparing Files using Ediff

;; ,REF: https://emacs.stackexchange.com/questions/21335/prevent-folding-org-files-opened-by-ediff
(with-eval-after-load 'outline
   (add-hook 'ediff-prepare-buffer-hook #'org-show-all))

configure Org-Mode Links

add headline-search completion support when creating org-id links

(require 'org-id)
(defun org-id-complete-link (&optional arg)
  "Create an id: link using completion"
  (concat "id:" (org-id-get-with-outline-path-completion org-refile-targets)))

(org-link-set-parameters "id" :complete 'org-id-complete-link)

use Persistent UUID References

setup org-id

(setq-default org-id-link-to-org-use-id t)
(setq-default org-id-locations-file (expand-file-name
                                     (format ".org-id-locations._%s.el" (rapport-fn-context-get-label))
                                     rapport-uri-vault-docs-status))
(require 'org-id)

enable Text Search in a Buffer using ctrlf

comparable to packages such as Isearch, Swiper, and helm-swoop.

an intuitive and efficient solution for single-buffer text search in Emacs.

;; https://github.com/radian-software/ctrlf
(use-package ctrlf
  :init
  (ctrlf-mode +1)
  :custom
  (ctrlf-auto-recenter t)
  (ctrlf-default-search-style 'regexp)
  (ctrlf-alternate-search-style 'literal)
  :config
  ;wip; (setq org-fold-core-style 'overlays) ;; work-around, (hopefully temporary), https://github.com/radian-software/ctrlf/issues/118
  (progn))

Transparently Incorporate External Documents by Reference using Org-Tranclusion

setup org-transclusion via nobiot/org-transclusion to enable transclusion with Org Mode

;;
(use-package org-transclusion
  :after org
  :init
  (define-key global-map (kbd "<f12>") #'org-transclusion-add)
  :custom
  (org-transclusion-remember-transclusions t)
  ;default;(org-transclusion-extensions '(org-transclusion-src-lines org-transclusion-font-lock))
  :config
  (progn))

as Human Documents Editor

enable Distraction-Free writing using Darkroom

(use-package darkroom
  :init
  ;; ,hint: don't scale the text, so ugly man!
  (setq darkroom-text-scale-increase 3))

enable Distraction-Free writing using Olivetti

(use-package olivetti
  :init
  (setq olivetti-body-width 100)
  (setq olivetti-recall-visual-line-mode-entry-state t))

enable Dictionary

(use-package dictionary)

enable Thesaurus

setup powerthesaurus

(use-package powerthesaurus)

as Software Development Environment

general Version Control Support

browse Git revisions
(use-package git-timemachine
  :init (setq git-timemachine-show-minibuffer-details t)
  :hook (git-time-machine-mode . prog-mode)
  ;; :bind
  ;; (general-nmap "SPC g t" 'git-timemachine-toggle)
  ;; (git-timemachine-mode-map
  ;;  "C-k" 'git-timemachine-show-previous-revision
  ;;  "C-j" 'git-timemachine-show-next-revision
  ;;  "q" 'git-timemachine-quit)
  :config
  (progn))
support Conventional Commit
(use-package conventional-commit
  :ensure (conventional-commit  :host github :repo "akirak/conventional-commit.el")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;  :straight (conventional-commit  :host github :repo "akirak/conventional-commit.el")
  :hook (git-commit-mode . conventional-commit-setup)
  :config
  (progn))

general Code Authoring Support

Enable Semanticaly-Aware Parsing using Tree-Sitter
(use-package tree-sitter
  :hook (after-init . global-tree-sitter-mode)
  :config
  (progn))

(use-package tree-sitter-langs
  :after (:all tree-sitter)
  :custom
  (tree-sitter-langs--bundle-version "0.12.16")
  ;:files ("langs/*.el" "langs/queries")
  :config
  (progn))

(use-package tree-sitter-indent
  :after (:all tree-sitter tree-sitter-langs)
  :config
  (progn))

(use-package tree-sitter-ispell
    :after (:all tree-sitter)
    :config
    (progn))
Enable Delimiter Match Highlighting
;; visual block enclosing
(use-package paren
  :ensure nil

  :hook (after-init)
  :init (show-paren-mode 't))
Rainbow Delimiters Makes Delimiters More Visually Distinct
(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode)
  :config
  (progn))
Templates with Yasnippet
(use-package yasnippet
  :init
  ;; (yas-global-mode 1)
  :config
  (use-package yasnippets-orgmode)
  (use-package aws-snippets)
  (use-package auto-yasnippet)
  (use-package el-autoyas))
enable On the Fly Validity Checking using Flycheck
;; #http://www.emacswiki.org/emacs/FlymakeCursor
(use-package flycheck
  :bind-keymap ("C-c ~" . flycheck-command-map) ;; rather than "C-c !", to prevent stomping on org-time-stamp-inactive
  :bind
  (:map flycheck-mode-map   ;; mode-specific jump keybind
   ("C-c j c" . consult-flycheck))
  :custom
  (flycheck-keymap-prefix (kbd "C-c ~"))
  (help-at-pt-timer-delay 0.9)
  (help-at-pt-display-when-idle '(flymake-overlay))
  :hook
  (prog-mode . flycheck-mode)
                                        ;(org-mode . flycheck-mode)
  :config
                                        ;(global-flycheck-mode 1)
  (progn))

Quickly Traverse a Document Structure within the Menu-bar using iMenu-List
;;; https://github.com/bmag/imenu-list
(use-package imenu-list
  :bind (("C-c C-\\" . imenu-list-smart-toggle))
  :hook (prog-mode . imenu-add-to-menubar-index)
  :config
  (setq imenu-list-focus-after-activation t
          imenu-list-auto-resize nil)
  (progn))
Enable Source Code Indexing, Navigation using XRef

setup xref

(use-package xref
  :hook (prog-mode)
  :config
  (progn))
support GNU Global as Xref backend, gXref
(use-package gxref
  ;; ,ref: https://emacs.stackexchange.com/questions/14802/never-keep-current-list-of-tags-tables-also
  ;; ,ref: https://melpa.org/#/gxref
  ;; ,ref: https://github.com/dedi/gxref
  :if (executable-find "global")  ;; ,HINT: requires that the `global` tool be installed and availab
  :after (:all xref)
  :init
  (setq tags-add-tables t)
  :hook
  (prog-mode)
  :config
  (require 'gxref)
  :custom
  (gxref-update-db-on-save t)
  :functions
  (gxref-xref-backend)
  :config
  (add-to-list 'xref-backend-functions 'gxref-xref-backend)
  (progn))
support Just-In-Time search as Xref-backend, Dumb-Jump
(use-package dumb-jump
  :demand
  :after (:all xref)
  :custom
  (xref-show-definitions-function #'xref-show-definitions-completing-read)
  :config
  (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
  (progn))

support Emacs Language Server using LSP-Mode

setup emacs-lsp

;; https://github.com/emacs-lsp/lsp-mode

;; You could go minimal and use lsp-mode as it is without external
;; packages with the built-in flymake and completion-at-point or you
;; could install the following extensions for better experience:

;; install lsp-ui for flycheck integration and higher level UI modules.
;; install lsp-treemacs for project wide error overview.
;; install lsp-ivy provides on type completion for xref-apropos.
;; install dap-mode if your language is supported by the debugger.


;; Commands

;; When using lsp-mode most of the features depend on server capabilities. lsp-mode provides default bindings which are dynamically enabled/disabled based on the server functionality. All the commands are configured lsp-command-map which is bound to lsp-keymap-prefix (default s-l).
;; Keybinding       Description
;; s-l s s  Entry point for the server startup.
;; s-l s r  Restart language server
;; s-l s q  Shutdown language server
;; s-l s d  Describes current dession
;; s-l s D  Disconnect the buffer from the language server keeping the server running.
;; s-l = =  Ask the server to format this document.
;; s-l = r  Ask the server to format the region, or if none is selected, the current line.
;; s-l F a  Add new project root to the list of workspace folders.
;; s-l F r  Remove project root from the list of workspace folders.
;; s-l F b  Remove project root from the workspace blacklist.
;; s-l T l  Toggle code-lens overlays.
;; s-l T L  Toggle client-server protocol logging.
;; s-l T h  Toggle symbol highlighting.
;; s-l T S  Toggle minor mode for showing information for current line in sideline. (requires lsp-ui)
;; s-l T d  Toggle minor mode for showing hover information in child frame. (requires lsp-ui)
;; s-l T s  Toggle signature auto activate.
;; s-l T f  Toggle on type formatting.
;; s-l T T  Toggle global minor mode for synchronizing lsp-mode workspace folders and treemacs projects. (requires lsp-treemacs)
;; s-l g g  Find definitions of the symbol under point.
;; s-l g r  Find references of the symbol under point.
;; s-l g i  Find implementations of the symbol under point.
;; s-l g t  Find type definitions of the symbol under point.
;; s-l g d  Find declarations of the symbol under point.
;; s-l g h  Show the incoming call hierarchy for the symbol at point. (requires lsp-treemacs)
;; s-l g a  Find all meaningful symbols that match pattern.
;; s-l h h  Display the type signature and documentation of the thing at
;; s-l h s  Activate signature help.
;; s-l h g  Trigger display hover information popup and hide it on next typing.
;; s-l r r  Rename the symbol (and all references to it).
;; s-l r o  Perform the source.organizeImports code action, if available.
;; s-l a a  Execute code action action.
;; s-l a l  Click lsp lens using ‘avy’ package.
;; s-l a h  Highlight symbol at point.
;; s-l G g  Peek definitions to the identifier at point. (requires lsp-ui)
;; s-l G r  Peek references to the identifier at point. (requires lsp-ui)
;; s-l G i  Peek implementation locations of the symbol at point. (requires lsp-ui)
;; s-l G s  Peek symbols in the worskpace. (requires lsp-ui)



;; ,NB: lsp-mode integration with which-key is setup in which-key's use-package macro
(use-package lsp-mode
  :hook ( ;; <hook>
         ;; if you want which-key integration
         (lsp-mode . lsp-enable-which-key-integration)
         ;; setup lsp completion
         (lsp-completion-mode . (lambda ()
                                  (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults))
                                        '(orderless))
                                  ;; Optionally configure the first word as flex filtered.
                                  (add-hook 'orderless-style-dispatchers #'my/orderless-dispatch-flex-first nil 'local)
                                  ;; Optionally configure the cape-capf-buster.
                                  (setq-local completion-at-point-functions (list (cape-capf-buster #'lsp-completion-at-point)))))

         ;; replace XXX-mode with concrete major-mode(e. g. python-mode)
         ;;(XXX-mode . lsp)

         ;; refs, setup Python LS, https://vxlabs.com/2018/06/08/python-language-server-with-emacs-and-lsp-mode/
         (python-mode . lsp-deferred) ;; to install Python Language Server, (https://github.com/palantir/python-language-server)
         ;;   $> python3 -mpip install python-language-server[all] # for Python3
         ;;   $> pip install python-language-server[all] # for Python2

         ;; refs, setup Rust LS, https://www.mortens.dev/blog/emacs-and-the-language-server-protocol/
         (rust-mode . lsp-deferred)

         ) ;; </hook>
  :commands (lsp lsp-deferred)
  :bind-keymap ("C-c l" . lsp-keymap-prefix)    ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
  :custom
  (lsp-completion-provider :none) ;; we use Corfu!
  (lsp-enable-snippet nil)
  (lsp-prefer-flymake nil) ;; Prefer using lsp-ui (flycheck) over flymake.
  :config
  (setq lsp-yaml-server-command `("comma" "yaml-language-server" "--stdio"))
  (progn))
enable Contextual Hints w/ lsp-ui
(use-package lsp-ui
  :requires lsp-mode flycheck
  :commands lsp-ui-mode
  :hook (lsp-mode . lsp-ui-mode)
  :custom
  (lsp-ui-peek-always-show t)
  (lsp-ui-sideline-show-hover t)
  (lsp-ui-doc-enable nil)
  (lsp-ui-doc-enable t)
  (lsp-ui-doc-use-childframe t)
  (lsp-ui-doc-position 'top)
  (lsp-ui-doc-include-signature t)
  (lsp-ui-sideline-enable t)
  (lsp-ui-sideline-ignore-duplicate t)
  (lsp-ui-flycheck-enable t)
  (lsp-ui-flycheck-list-position 'right)
  (lsp-ui-flycheck-live-reporting t)
  (lsp-ui-peek-enable t)
  (lsp-ui-peek-list-width 60)
  (lsp-ui-peek-peek-height 25)
  :config
  ;; make sure we have lsp-imenu everywhere we have LSP
  (when (featurep 'lsp-ui-imenu) (require 'lsp-ui-imenu))
  (add-hook 'lsp-mode-hook 'lsp-ui-mode)
  (add-hook 'lsp-after-open-hook 'lsp-enable-imenu))
configure Treemacs support via LSP-Treemacs
;; https://github.com/emacs-lsp/lsp-treemacs
(use-package lsp-treemacs
  :after (:all treemacs lsp)
  :hook (lsp-mode)
  :commands (lsp-treemacs-errors-list lsp-treemacs-sync-mode)
  :ensure (lsp-treemacs :git git :host github :repo "emacs-lsp/lsp-treemacs")
  :config
  (lsp-treemacs-sync-mode 1)
  (progn))

support C

  • c-eldoc

    ;; (require 'load-mode__c-eldoc)   ; show the args of C functions in minibuffer
    
    ;;;
    ;;; load-config__fspaths.el
    ;;; sets a list of file-system path variables
    
    
    ;; add in your commonly used packages/include directories here, for
    ;; example, SDL or OpenGL. this shouldn't slow down cpp, even if
    ;; you've got a lot of them
    
    ;;; register
    (use-package c-eldoc
      :config
      (global-eldoc-mode t)
      (add-hook 'c-mode-hook 'eldoc-mode)
      (add-hook 'c-mode-hook 'c-turn-on-eldoc-mode))
    
  • When LSP's activated, use lsp-ccls

    (use-package ccls
      :after (:all lsp)
      :mode "\\.c(pp)?"
      :config
      (progn))
    

support Emacs Lisp

Emacs-Lisp IDE for Emacs


support Guile Scheme

enable Flycheck support for Guile using Flycheck-Guile
(use-package flycheck-guile
  :after (:all flycheck guile)
  :hook (guile)
  :config
  (progn))
Geiser IDE setup
  • setup Geiser, which supports several flavors of Scheme

    (use-package geiser)
    (use-package geiser-guile  :after (:all gieser)
      :config
      (progn))
    
enable LSP-Scheme
(use-package lsp-scheme
  :after (:all lsp scheme)
  :hook (scheme-mode . lsp-scheme-guile)
  :config
  (progn))

support Python

;;
(use-package python
  :custom
  (python-indent-guess-indent-offset-verbose nil)
  :hook (pyenv flycheck-pycheckers-setup))
  • flycheck

    ;;
    (use-package flycheck-pycheckers
      :after (flycheck python)
      :if (executable-find "mypy")
      ;:ensure-system-package mypy
      :hook (python-mode . flycheck-pycheckers-setup))
    
using Python Executable Tracker, aka PET
(use-package pet
  :ensure-system-package (dasel sqlite3)
  :config
  (add-hook 'python-mode-hook
            (lambda ()
              (setq-local python-shell-interpreter (pet-executable-find "python")
                          python-shell-virtualenv-root (pet-virtualenv-root))

              ;; (pet-eglot-setup)
              ;; (eglot-ensure)

              (pet-flycheck-setup)
              (flycheck-mode)

              (setq-local lsp-jedi-executable-command
                          (pet-executable-find "jedi-language-server"))

              (setq-local lsp-pyright-python-executable-cmd python-shell-interpreter
                          lsp-pyright-venv-path python-shell-virtualenv-root)

              (lsp)

              (setq-local dap-python-executable python-shell-interpreter)

              (setq-local python-pytest-executable (pet-executable-find "pytest"))

              (when-let ((ruff-executable (pet-executable-find "ruff")))
                (setq-local ruff-format-command ruff-executable)
                (ruff-format-on-save-mode))

              (when-let ((black-executable (pet-executable-find "black")))
                (setq-local python-black-command black-executable)
                (python-black-on-save-mode))

              (when-let ((isort-executable (pet-executable-find "isort")))
                (setq-local python-isort-command isort-executable)
                (python-isort-on-save-mode))))
  (progn))
enable Linter, Ruff
(use-package ruff-format
    :after (:all python)
    :hook (python-mode . ruff-format-on-save-mode)
    :config
    (progn))
enable Linter, i-Sort
(use-package python-isort
      :after (:all python)
    :hook (python-mode . python-isort-on-save-mode)
    :config
    (progn))
enable Test Framework, PyTest
(use-package python-pytest
    :after (:all python)
    :hook (python-mode)
    :config
    (progn))
configure Python support in LSP-Mode

lsp-pyright supports the following configuration. Each configuration is described in detail in Pyright Settings.

  • pyright.disableLanguageServices via lsp-pyright-disable-language-services
  • pyright.disableOrganizeImports via lsp-pyright-disable-organize-imports
  • python.analysis.autoImportCompletions via lsp-pyright-auto-import-completions
  • python.analysis.useLibraryCodeForTypes via lsp-pyright-use-library-code-for-types
  • python.analysis.typeshedPaths via lsp-pyright-typeshed-paths
  • python.analysis.diagnosticMode via lsp-pyright-diagnostic-mode
  • python.analysis.typeCheckingMode via lsp-pyright-typechecking-mode
  • python.analysis.logLevel via lsp-pyright-log-level
  • python.analysis.autoSearchPaths via lsp-pyright-auto-search-paths
  • python.analysis.extraPaths via lsp-pyright-extra-paths
  • python.venvPath via lsp-pyright-venv-path

Projects can be further configured using pyrightconfig.json file. For further details please see Pyright Configuration.

enable pyright LS
(use-package lsp-pyright
  :after (:all lsp)
  :hook (python-mode . (lambda ()
                          (require 'lsp-pyright)
                          (lsp-deferred))) ;; lsp or lsp-deferred
  :config
  (progn))
enable Jedi LS
(use-package lsp-jedi
  :after (:all lsp))

support Rust using Rustic-Mode

Common Rust tools

  • install the toolchain mgmt app, rustup
  • add ~/.cargo/bin/ to PATH
  • clone: git clone https://github.com/rust-lang/rust ~/.extrefs/rust-lang
  • install: cargo install rustfmt
  • install: cargo install racer
;; ,HINT: add support for Rust in org-babel
;; ,ref: https://github.com/brotzeit/rustic#parameters
(use-package ob-rust :config (require 'ob-rust))


;; ,ref: https://robert.kra.hn/posts/rust-emacs-setup/
(use-package rustic
  :ensure
  :bind (:map rustic-mode-map
              ("M-j" . lsp-ui-imenu)
              ("M-?" . lsp-find-references)
              ;("C-c C-c l" . flycheck-list-errors)
              ("C-c C-c a" . lsp-execute-code-action)
              ("C-c C-c r" . lsp-rename)
              ("C-c C-c q" . lsp-workspace-restart)
              ("C-c C-c Q" . lsp-workspace-shutdown)
              ("C-c C-c s" . lsp-rust-analyzer-status))
  :config
  ;; uncomment for less flashiness
  ;; (setq lsp-eldoc-hook nil)
  ;; (setq lsp-enable-symbol-highlighting nil)
  ;; (setq lsp-signature-auto-activate nil)

  ;; comment to disable rustfmt on save
  (setq rustic-format-on-save t)
  (add-hook 'rustic-mode-hook 'rk/rustic-mode-hook))

(defun rk/rustic-mode-hook ()
  ;; so that run C-c C-c C-r works without having to confirm, but don't try to
  ;; save rust buffers that are not file visiting. Once
  ;; https://github.com/brotzeit/rustic/issues/253 has been resolved this should
  ;; no longer be necessary.
  (when buffer-file-name
    (setq-local buffer-save-without-query t))
  (add-hook 'before-save-hook 'lsp-format-buffer nil t))

;;;
;; (use-package cargo)
;; (use-package racer) ; code completion
;; (use-package flycheck)
;; (use-package flycheck-rust)

;; ;; nb, Rustic now depends/extends rust-mode  [[https://www.reddit.com/r/emacs/comments/q9dz4e/rustic_now_depends_on_rustmode/][1]]
;; (use-package rustic
;;   :mode "\\.rs\\'"
;;   ;; :hook
;;   ;; (rustic . (lambda ()
;;   ;;                "" ()
;;   ;;                (progn
;;   ;;                  (setq racer-cmd (executable-find "racer")) ;; Racer binaries in Rust/Cargo PATH
;;   ;;                                         ;(setq racer-rust-src-path "~/.extrefs/rust-lang/src")
;;   ;;                  (local-set-key (kbd "TAB") 'company-indent-or-complete-common)
;;   ;;                  (electric-pair-local-mode 1)
;;   ;;                  (local-set-key (kbd "C-c q") 'rust-format-buffer))))
;;   ;; (rust-mode . cargo-minor-mode)
;;   ;; (rust-mode . racer-mode)
;;   ;; (racer-mode . eldoc-mode)
;;   ;;                                         ; (flycheck-mode . flycheck-rust-setup)
;;   ;; (racer-mode . company-mode)
;;   :custom
;;   (rustic-lsp-mode 'rust-analyzer) ;(default);
;;   :config
;;   ;; check for installed cargo dependencies: racer, rustfmt
;;   ;;  - if cargo is found in path and crate is absent, attempt to install via cargo
;;   (if (executable-find "cargo")
;;       (progn
;;         (unless (executable-find "racer")
;;           ;; func-sig: (call-process executable input output showbuff **args) => exitcode: int
;;           ;; example: (call-process "echo" nil nil nil "testing 123")
;;           (call-process "cargo" nil nil nil "install" "racer"))
;;         (unless (executable-find "rustfmt")
;;           (call-process "cargo" nil nil nil "install" "rustfmt")))
;;     (message "WRN: executable 'cargo' not found. Please check path and / or install."))
;;   (progn))

support Bash

;; #,ref: https://github.com/bash-lsp/bash-language-server
;; #,ref: https://www.youtube.com/watch?v=LTC6SP7R1hA
(use-package sh-script
  :ensure nil

  :custom
  (sh-basic-offset 2)
  (sh-indentation 2)
  :hook
  (sh-mode . flycheck-mode)
  :config
  ;; flycheck-shellcheck configs, enable in non-executable/lib-style script files
  (eval-after-load 'flycheck-shellcheck
    (if (bound-and-true-p flycheck-shellcheck-supported-shells)
        (add-to-list 'flycheck-shellcheck-supported-shells 'false)
      (setq flycheck-shellcheck-supported-shells '('false))))
  ;;
  (progn))

(use-package flymake-shellcheck)

(use-package flycheck-bashate
  :if (executable-find "bashate")
  :after (flycheck)
  :hook (sh-mode . flycheck-bashate-setup))

(use-package flycheck-checkbashisms
  :if (executable-find "checkbashisms")
  :after (flycheck)
  :hook (sh-mode . flycheck-checkbashisms-setup))

support Powershell

setup powershell language support

;;
(use-package powershell
  :mode ("\\.ps[dm]?1\\'" . powershell-mode))

support Nix

provide buffer-local Nix enabled shells w/i Org-Babel
  • create a named org-babel source block containing a shell definition

    #+name: my-shell
    #+begin_src nix
      { pkgs ? import <nixpkgs> {} }:
      pkgs.mkShell {
        buildInputs = [ pkgs.hello ];
      }
    #+end_src
    
  • later, use the nix shell definition in other shells by using the org-babel header-arg :nix-shell <name>, when <name> is the named nix shell source block to use

    #+begin_src sh :nix-shell "my-shell"
      hello   # use 'hello' from 'my-shell'
    #+end_src
    
;; https://github.com/AntonHakansson/org-nix-shell
(use-package org-nix-shell
  ;:ensure '(org-nix-shell :type git :host github :repo "AntonHakansson/org-nix-shell")
  :after (:all org)
  :hook (org-mode . org-nix-shell-mode)
  :config
  (progn))

support NuShell via NuShell-TS-Mode

(use-package nushell-ts-mode
  :config
  (require 'nushell-ts-babel)
  (corfu-mode 1)
  (highlight-parentheses-mode 1)
  (electric-pair-local-mode 1)
  (electric-indent-local-mode 1)
(progn))

support Terraform

  • terraform-mode

    (use-package terraform-mode
      :ensure (terraform-mode :git git :host github :repo "hcl-emacs/terraform-mode")
      :custom (terraform-indent-level 4)
      :config
      (outline-minor-mode 1)
      (progn))
    
  • with LSP-mode

    ;; ,ref: https://emacs-lsp.github.io/lsp-mode/page/lsp-terraform-ls/
    (use-package emacs
      :ensure nil
      :after (:all lsp-mode)
      :no-require t
      :init
      (when (executable-find "nix-shell")
        (setq
         lsp-terraform-ls-server (executable-find "terraform-ls")
         lsp-disabled-clients '(tfls)  ;; ,HINT: for Terraform, only use the official languge-server
         lsp-terraform-ls-enable-show-reference t
         ;; end-of-setq
         ))
      :config
      ;(lsp-terraform-modules-mode t)
      (progn))
    

as Systems Editor

DevOps, and Infrastructure mgmt

authoring Docker and Docker-Compose

(use-package dockerfile-mode)
(use-package docker-compose-mode)

enable Docker Mgmt within Emacs using Docker.el

;; ,REF: https://github.com/Silex/docker.el
(use-package docker
  :config
  ;; ,NB: this package includes docker-tramp
  (progn))

authoring Markdown

setup markdown-mode+

;; https://jblevins.org/projects/markdown-mode/
(use-package markdown-mode
  :commands (markdown-mode gfm-mode)
  :mode (("README\\.md\\'" . gfm-mode)
         ("\\.md\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode))
  :config
  (progn
    ;; for editing code-block regions as indirect buffers
    (use-package edit-indirect))
  :init (setq markdown-command "multimarkdown"))

setup Org-Export to Markdown

;; Associated Functions
;;  - org-md-export-to-markdown
;;  - org-md-export-as-markdown
;;  - org-md-convert-region-to-md, convert region to MD
(add-to-list 'org-export-backends 'md)
(use-package auto-org-md)

support Config-Mgmt via Saltstack

setup salt-mode via use-package

(use-package salt-mode
  :mode "\\.sls\\'"
  :config
  (progn))

support Terraform

setup terraform-mode

(use-package terraform-mode :mode "\\.tf\\'")

support Kubernetes

Manage Kubernetes w/ kubel

setup kubel

;; https://github.com/abrochard/kubel
(use-package kubel
  :custom
  (kubel-use-namespace-list 'on)
  :config
  (progn))

support Rego (as used in Open Policy Agent, etc.)

setup rego-mode

;; https://github.com/psibi/rego-mode
(use-package rego-mode
  :if (executable-find "opa")
  ;; Prerequisites:
  ;; - Make sure that you install opa and it's available in your system.
  ;:ensure-system-package (opa)
  ;; Features:
  ;; - Syntax highlighting (Using font lock)
  ;; - Basic indentation, commenting
  ;; - Automatic formatting on save (Configurable via variable). Uses opa fmt for it.
  ;; - REPL support. The function rego-repl-show will load a plain
  ;;   REPL. You can also use rego-repl-with-data to pass file or
  ;;   directory which will be loaded to the REPL.
  :config
  (progn))

support Vagrant

enable use of vagrant from w/i Emacs

  • activate vagrant package via use-package

    (use-package vagrant
      :if (executable-find "vagrant")
      :config
      (progn))
    
    

support Cloud, AWS

  • snippets

    (use-package aws-snippets)
    

as Data File Editor

support CSV

(use-package csv-mode)

support YAML

;;;
(use-package yaml-mode
  :mode ("\\.y[a]?ml\\'" . yaml-mode) ("\\.sls\\'" . salt-mode)
  :config
  (add-hook 'yaml-mode-hook
            (progn
              #'(lambda () (define-key yaml-mode-map "\C-m" 'newline-and-indent))
              #'(lambda () (yafolding-mode))
              #'(lambda () (indent-tools-minor-mode))
                                    ;#'(lambda () (highlight-indent-guides-mode))
            )))

;;; https://github.com/psycofdj/yaml-path
(use-package yaml-imenu) ;; 20200208_NGa under evaluative testing

;;;
(use-package indent-tools
  :bind ("C-c >" . indent-tools-hydra/body))

;;;
(use-package flycheck-yamllint  ; reqs 'pip install yamllint'
  :mode ("\\.y[a]?ml\\'" . yaml-mode) ("\\.sls\\'" . salt-mode)
  :init
  (eval-after-load 'flycheck '(add-hook 'flycheck-mode-hook #'flycheck-yamllint-setup))
  (eval-after-load 'flycheck '(add-hook 'after-init-hook #'global-flycheck-mode)))

support JSON

;;
(use-package json-mode
  :mode ("\\.json\\'" . json-mode)
  :commands (json-mode-show-path json-mode-beautify)
  :config
  (progn))

(use-package json-reformat)

support Visual RegEx

setup visual-regexp

(use-package visual-regexp-steroids)

as Data Services Interface and Editor

as Data Analytics Editor

enable Jupyter Notebook client using EIN

https://millejoh.github.io/emacs-ipython-notebook/

(use-package ein
  :config
  (progn))

as Data and System Visualization Editor

PlantUML Support

setup PlantUML support

;; https://github.com/skuro/plantuml-mode
(use-package plantuml-mode
  :if (executable-find "plantuml")
  :mode (("\\.plantuml\\'" . plantuml-mode)
         ("\\.puml\\'" . plantuml-mode))
  :init
  (setq plantuml-default-exec-mode 'executable)

  :custom
  ;; not used
  (plantuml-jar-path      "~/.vault/cfgs/emacs/apps/plantuml/plantuml.jar")
  ;; used
  (org-plantuml-jar-path "~/.vault/cfgs/emacs/apps/plantuml/plantuml.jar")
  (org-plantuml-exec-mode 'plantuml)
  (plantuml-executable-args '("-quiet" "-darkmode"))
  (plantuml-output-type "svg")
  (plantuml-indent-level 4)
  ;:ensure-system-package (plantuml) ;; NB: this is a potentially heavy-weight install w/ deps

  ;; discretionary quality-of-life configs ;;

  ;; (org-babel-default-header-args:plantuml
  ;;  (cons '(:exports . "results")
  ;;     (cons '(:cache . "yes")
  ;;           (cons '(:file . (make-temp-file (concat (rapport-fn-context-get-label) "--" (buffer-name) "-buffer--" (rapport-fn-current-time-as-string)) nil (concat "." plantuml-output-type)))
  ;;                 (cons '(:noweb . "yes")
  ;;                       (assq-delete-all :exports
  ;;                                        (assq-delete-all :cache
  ;;                                                         (assq-delete-all :file
  ;;                                                                          (assq-delete-all :noweb
  ;;                                                                                           org-babel-default-header-args)))))))))

  :config
  ;; download the Plantuml JAR if it's not already in place at plantuml-jar-path
                                        ;(unless (file-exists-p plantuml-jar-path) (plantuml-download-jar))
                                        ;(add-to-list 'org-src-lang-modes '("plantuml" . plantuml))
                                        ;(add-to-list 'org-babel-load-languages '(plantuml . t))
                                        ;(org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages)
  (defun rapport/live-preview/-command (&optional src-buffer dst-buffer render-type dst-buffer-hooks)
    "src-buffer is a string, dst-buffer is a string ... prereq: live-preview-mode"
    (interactive)
    (let*
        ((src-buffer (or (when (and (bound-and-true-p src-buffer)
                                    (get-buffer src-buffer))
                           (get-buffer src-buffer))
                         (get-buffer (current-buffer))))
         (render-from (buffer-local-value 'mode-name src-buffer))
         (render-from-conf 'nil)
         (render-to 'nil)
         (render-to-conf 'nil)
         (render-type (concat render-from (when (bound-and-true-p render-to)
                                            (format "-as-%s" render-to))))
         ;; args: dst-buffer render-type
                                        ;(dst-buffer-auto-name-format "*Live Preview Output: %s |%s|*")
                                        ;(err-buffer-auto-name-format "*Live Preview Error: %s |%s|*")
         (dst-buffer-auto-name (when (bound-and-true-p dst-buffer-auto-name-format)
                                 (format dst-buffer-auto-name-format
                                         src-buffer
                                         render-type)))
         (dst-buffer (or (when (and (bound-and-true-p dst-buffer)
                                    (buffer-name (get-buffer dst-buffer)))
                           (get-buffer-create dst-buffer))
                         (when (bound-and-true-p dst-buffer-auto-name)
                           (get-buffer-create dst-buffer-auto-name))
                         (get-buffer-create "*live-preview*"))))
      (save-excursion
        (with-current-buffer dst-buffer
          (mark-whole-buffer)
          ;(delete-active-region)
          (insert
           (plantuml-preview-string t
                                    (with-current-buffer src-buffer (buffer-substring-no-properties (point-min) (point-max)))))
          ;; normal-mode or set-buffer-major-mode
          (normal-mode))))))

Create Mind-Map using Org-Mind-Map

  • from

    (use-package org-mind-map
      :after (:all  org ox ox-org)
      :commands
      org-mind-map-write
      org-mind-map-write-current-tree
      org-mind-map-write-current-branch
                                            ;:ensure-system-package (gvgen . graphviz)
      :custom
      (org-mind-map-engine "dot")       ; Default. Directed Graph
                                            ;(org-mind-map-engine "neato")  ; Undirected Spring Graph
                                            ;(org-mind-map-engine "twopi")  ; Radial Layout
                                            ;(org-mind-map-engine "fdp")    ; Undirected Spring Force-Directed
                                            ;(org-mind-map-engine "sfdp")   ; Multiscale version of fdp for the layout of large graphs
                                            ;(org-mind-map-engine "twopi")  ; Radial layouts
                                            ;(org-mind-map-engine "circo")  ; Circular Layout
      (org-mind-map-tag-colors nil) ;; default: nil .. An alist of (TAG . COLOR) pairs for choosing colors for tags.
      (org-mind-map-include-text nil) ;; default: t .. A boolean indicating whether our not to include paragraph text in body of nodes.
      (org-mind-map-include-images nil) ;; default: t .. A boolean indicating whether our not to include images in body of nodes.
      :config
      (progn))
    

using Graphviz-Dot-Mode

(use-package graphviz-dot-mode
  :config
  (progn))

support GnuPlot

setup GNUPlot

(use-package gnuplot
  :custom
  (gnuplot-image-format "svg")
  :config
  (progn))

as Notes, Artifacts, Journal Editor and Organizer

using Org-Agenda

setup Org Agenda

;; Org-Agenda

(use-package emacs
  :ensure nil

  :no-require t
  :init
  ;; set org-agenda-files, if unset
  (unless (bound-and-true-p org-agenda-files)
    (setq org-agenda-files (expand-file-name  (format "org-agenda-files._%s.txt" (rapport-fn-context-get-label)) rapport-uri-vault-docs-status)))
  ;; create org-agenda-file, if doesnt exist
  (let
      ((idem-file org-agenda-files))
    (unless (file-exists-p idem-file)
      (unless (file-directory-p (file-name-parent-directory idem-file))
        (make-directory (file-name-parent-directory idem-file) t))
      (with-temp-buffer (write-file idem-file))))
  :custom
  ;;; Org Agenda Section

  ;; (nb) press C-c C-t followed by the selection key, ('SPC' will remove TODO info), and the entry will be switched to this state.
  ;; !=timestamp, @=note w/ timestamp, |= describes sequence (to-left not-done, to-right done)
  (org-todo-keywords
   '((sequence "OPEN(o!)" "|" "SHUT(C!)")  ;; Generic States
     (sequence "TODO(t!)" "WAIT(w@)" "NEXT(n@)" "|" "STOP(K@)" "DONE(D@)"))) ;; Task states (used by Org-GTD)

  (org-todo-keyword-faces '(
                            ;; Basic
                            ("OPEN" :foreground "orange"  :weight bold)
                            ("SHUT" :foreground "purple" :background "darkgrey"  :weight bold)
                            ;; GTD
                            ;("TODO" :foreground "red" :background "black" :weight bold)  ;; ,HINT: uncomment this line for bolder 'TODO faces
                            ("NEXT" :foreground "white" :background "blue" :weight bold)
                            ("WAIT" :foreground "yellow" :weight bold)
                            ("STOP" :foreground "green" :strike-through t :weight bold)
                            ("DONE" :foreground "green" :weight bold)
                            ))
  ;; global Effort estimate values
  (org-sort-agenda-noeffort-is-high 't) ; absent effort-estimate means unbound-high

  ;; Agenda log mode items to display (closed and state changes by default)
  (org-agenda-log-mode-items (quote (state)))

  ;; This one is pretty awesome; it forces you to mark all child tasks
  ;;   as “DONE” before you can mark the parent as “DONE.”  The agenda
  ;;   view already has the notion of “blocked” tasks (those with
  ;;   incomplete child tasks), which should appear dimmed (that, of
  ;;   course, is also customizable). This makes it even harder to
  ;;   slack off on your work.
  (org-enforce-todo-dependencies t)


  ;; customize org TODO priorities and faces
  ;; A="URGENT (drop everything else)", B="HIGH (work this first)", C="NORMAL (important but not pressing)", D="LOW (needed but can wait)", E="DEFERED (not needed, nice to have)"
  ;;  - taken from load-conf__org-agenda.el
  (org-highest-priority ?A)
  (org-default-priority ?D)
  (org-lowest-priority  ?E)
  ;; (add-to-list 'org-priority-faces
  ;;           '(
  ;;             (?A . (:foreground "red" :weight bold :underline 't))
  ;;             (?B . (:foreground "orange" :weight bold :underline 'nil))
  ;;             (?C . (:foreground "green" :weight normal :underline 'nil))
  ;;             (?D . (:foreground "light green" :weight normal :underline 'nil))
  ;;             (?E . (:foreground "gray80" :weight normal :underline 'nil))))


  ;; org-agenda formatting ;;

  (org-agenda-time-grid
   '((daily today)
     (600 800 1000 1200 1400 1600 1800 2000 2200)
     "    "
     "----------------"))
  (org-agenda-current-time-string "——————————————⌚⌚⌚—————————————")
  ;;(org-pretty-entities t)
  (org-agenda-span 'day) ;; set the default view to 1 day, (instead of 1 week), for quicker start-ups.
  ;; Agenda clock report parameters
  (org-agenda-clockreport-parameter-plist
   (quote (:link t :maxlevel 5 :fileskip0 t :compact t :narrow 80 :properties ("CATEGORY" "TAGS"))))

  ;; Define custom Agenda quick-commands
  ;;   - from http://stackoverflow.com/questions/1361595/emacs-org-mode-agenda-filter-by-owner
  ;;   - ex. (list " <your filter string here /> " )

  (org-agenda-custom-commands
   '(("n" "Overview"
      ((agenda "" ((org-agenda-overriding-header "           AGENDA OF THE DAY / DEADLINES in 3 months\n")
                   ;; limits the agenda display to a single day)
                   (org-agenda-span 1)
                   (org-deadline-warning-days 90)        ;; [1]
                   ))
       (agenda "" ;; Birthdays in this week
               ((org-agenda-overriding-header "           ANNIVERSARIES IN 7 DAYS\n")
                (org-agenda-span 7)
                (org-agenda-show-all-dates nil)
                (org-agenda-start-on-weekday nil)
                (org-agenda-time-grid nil)
                (org-agenda-entry-types '(:sexp))))
       (todo "NEXT|TODO|OPEN"
             ((org-agenda-overriding-header "           NEXT THING TO DO\n")
              (org-agenda-skip-function '(org-agenda-skip-entry-if
                                          'scheduled))
              ))
       (tags    "type@project|type@objective"
                ((org-agenda-overriding-header "           PROJECTS STATUS\n")
                 (org-agenda-sorting-strategy '(priority-down))
                 (org-agenda-skip-function '(org-agenda-skip-entry-if
                                             'todo '("DONE" "STOP" "WAIT")))
                 ))
       (tags    "task@impediment|task@inquiry|_review|evalutate|_inquire"
                ((org-agenda-overriding-header "           OPEN PROBLEMS\n")
                 (org-agenda-sorting-strategy '(priority-down))
                 (org-agenda-skip-function '(org-agenda-skip-entry-if
                                             'todo '("DONE" "SHUT" "STOP")))
                 ))
       (tags-todo "-project-@question"
                  ((org-agenda-overriding-header "           TODO LIST\n")
                   (org-agenda-skip-function '(org-agenda-skip-entry-if
                                               'scheduled
                                               'deadline
                                               'todo '("NEXT" "CALL" "REVIEW")))
                   (org-agenda-sorting-strategy '(priority-down))
                   ))
       ))
     ;;
     ;; ("o" "(wip/demo) tasks for olaf"
     ;;  ((org-agenda-list)
     ;;   (org-agenda-filter-apply ("+oleg")))
     ;;  ((org-agenda-remove-tags t)))
     ;; ("k" "(wip/demo) tasks for karl"
     ;;  ((org-agenda-list)
     ;;   (org-agenda-filter-apply ("+karl")))
     ;;  ((org-agenda-remove-tags t)))
     ;; ;;
     ;; ("O" "(wip/demo) Office block agenda"
     ;;  ((agenda "" ((org-agenda-ndays 1)))
     ;;   ;; limits the agenda display to a single day
     ;;   (tags-todo "+PRIORITY=\"A\"")
     ;;   (tags-todo "computer|office|phone")
     ;;   (tags "project+CATEGORY=\"elephants\"")
     ;;   (tags "review" ((org-agenda-files '("~/org/circuspeanuts.org"))))
     ;;   ;; limits the tag search to the file circuspeanuts.org
     ;;   (todo "WAITING"))
     ;;  ((org-agenda-compact-blocks t))) ;; options set here apply to the entire block

     ;; ...other commands here

     ))


  ;; ,HINT: define Org property Keywords and preset selectable values
  (org-global-properties `(
                           ;; ,HINT: the first item in the list should be the maximum all-inclusive LOE for a GTD "do now" task
                           ;; ,HINT: these task estimation times are intentionally jagged, because humans are bad at estimating, (especially this one)
                           ;; ,HINT: generally only "leaf-node" tasks should be estimated, project estimation should accumulate and sum these estimates
                           ("Effort_ALL" . "0:20 0:40 1:20 2:40 5:20 10:40 21:20 42:40")
                           ("STYLE_ALL" . "habit")
                           ("REPEAT_TO_STATE_ALL" . "TODO NEXT")
                           ("resource_ALL" . "")
                           ("allocate_ALL" . "")
                           ))


  ;:custom-face
  ;(org-agenda-column-dateline ((t (:background "dim gray" :foreground "magenta" :weight bold))))
  ;(org-agenda-structure ((t (:foreground "dark gray" :weight bold))))
  ;(org-column ((t (:weight normal))))
  ;(org-column-title ((t (:background "cyan" :foreground "white" :underline t :weight bold))))
  :config
  ;; #,HINT: Supply Generic Tags and Tag-Group presets. Personal Tags and Tag-Groups may be set in the 'custom-file

  ;; (setq org-tag-alist `(

  ;;                    ;; Group by Domain
  ;;                    (:startgrouptag)
  ;;                    ("ctx")
  ;;                    (:grouptags)
  ;;                    ("@assets" . ?A)
  ;;                    ("@community" . ?C)
  ;;                    ("@events" . ?E)
  ;;                    ("@family" . ?F)
  ;;                    ("@household" . ?H)
  ;;                    ("@practices" . ?P)
  ;;                    ("@work" . ?W)
  ;;                    (:endgrouptag)

  ;; #+TAGS: [ GTD : Control Persp ]
  ;; In this example, ‘GTD’ is the group tag and it is related to two other tags: ‘Control’, ‘Persp’. Defining ‘Control’ and ‘Persp’ as group tags creates a hierarchy of tags:
  ;; #+TAGS: [ Control : Context Task ]
  ;; #+TAGS: [ Persp : Vision Goal AOF Project ]
  ;; #+TAGS: { Context : @Home @Work @Call }
  ;; #+TAGS: [ Vision : {V@.+} ]
  ;; #+TAGS: [ Goal : {G@.+} ]
  ;; #+TAGS: [ AOF : {AOF@.+} ]
  ;; #+TAGS: [ Project : {P@.+} ]


  ;; ;; Group by Activity Heirarchies
  ;; (:startgrouptag)

  ;; (:startgrouptag)
  ;; ("activity/physical")
  ;; (:grouptags)
  ;; ("moving objects")
  ;; ("using tools")
  ;; ("manipulating materials")
  ;; (:endgrouptag)


  ;; (:startgrouptag)
  ;; ("activity/cognitive")
  ;; (:grouptags)
  ;; ("communicating")
  ;; ("problem-solving")
  ;; ("decision-making")
  ;; ("planning")
  ;; ("organizing")
  ;; ("time management")
  ;; ("learning")
  ;; ("creativity")
  ;; ("critical thinking")
  ;; (:endgrouptag)


  ;; (:startgrouptag)
  ;; ("social-activity")
  ;; (:grouptags)
  ;; ("teamwork")
  ;; ("leadership")
  ;; ("motivation")
  ;; ("self-discipline")
  ;; (:endgrouptag)


  ;; (:startgrouptag)
  ;; ("Activity")
  ;; (:grouptag)
  ;; ("_acquire" . ?a)
  ;; ("_applaud" . ?d)
  ;; ("_build" . ?b)
  ;; ("_clean" . ?l)
  ;; ("_communicate" . ?c)
  ;; ("_design" . ?i)
  ;; ("_draft" )
  ;; ("_edit" . ?e)
  ;; ("_help" . ?h)
  ;; ("_learn" . ?l)
  ;; ("_maint" . ?m)
  ;; ("_move" . ?v)
  ;; ("_present" . ?p)
  ;; ("_give" . ?g)
  ;; ("_publish")
  ;; ("_repair" . ?f)
  ;; ("_review" . ?r)

  ;; ;; # ^^misc other activities: inform, influence, lead-gen, shape opportunity, drive, lead, inspire, manage-risk
  ;; (:endgrouptag)

  ;; (:startgrouptags)
  ;; ("Assets")
  ;; (:grouptags)
  ;; ("{asset@.+}")
  ;; (:endgrouptags)

  ;; end-of-list


  (setq org-tag-persistent-alist '(
                                   ;; Composure Item Types
                                   (:startgroup)
                                   ("type@task" . nil)
                                   ("type@scope" . nil)
                                   ("type@contact" . nil)
                                   (:endgroup)

                                   ;; Composure Task types
                                   (:startgroup)
                                   ("task@project" . nil)
                                   ("task@objective" . nil)
                                   (:endgroup)

                                   ;; Composure Scope types
                                   (:startgroup)
                                   ("scope@tld")
                                   ("scope@job")

                                   (:endgroup)

                                   ;; Composure Contact types
                                   (:startgroup)
                                   ("contact@vendor" . nil)
                                   ("contact@client" . nil)
                                   ("contact@person" . nil)
                                   ("contact@team" . nil)
                                   (:endgroup)

                                   ;; ;; Composure Activity Types
                                   ;; (:startgroup)
                                   ;; ("HOME" . ?h)
                                   ;; ("RESEARCH" . ?r)
                                   ;; ("TEACHING" . ?t)
                                   ;; (:endgroup)

                                   ;; ;;  Composure Contact Types
                                   ;; (:startgroup)
                                   ;; ("OS" . ?o)
                                   ;; ("DEV" . ?d)
                                   ;; ("WWW" . ?w)
                                   ;; (:endgroup)

                                   ;; (:startgroup)
                                   ;; ("EASY" . ?e)
                                   ;; ("MEDIUM" . ?m)
                                   ;; ("HARD" . ?a)
                                   ;; (:endgroup)

                                   ;; ("URGENT" . ?u)
                                   ("export" . nil)
                                   ("noexport" . ?x)

                                   ))


  ;; ,HINT in this config tags are still heavily WIP, and retained here for example purposes
  (setq org-tag-faces '(
                        ;; ("HOME" . (:foreground "GoldenRod" :weight bold))
                        ;; ("RESEARCH" . (:foreground "GoldenRod" :weight bold))
                        ;; ("TEACHING" . (:foreground "GoldenRod" :weight bold))
                        ;; ("OS" . (:foreground "IndianRed1" :weight bold))
                        ;; ("DEV" . (:foreground "IndianRed1" :weight bold))
                        ;; ("WWW" . (:foreground "IndianRed1" :weight bold))
                        ;; ("URGENT" . (:foreground "Red" :weight bold))
                        ;; ("KEY" . (:foreground "Red" :weight bold))
                        ;; ("EASY" . (:foreground "OrangeRed" :weight bold))
                        ;; ("MEDIUM" . (:foreground "OrangeRed" :weight bold))
                        ;; ("HARD" . (:foreground "OrangeRed" :weight bold))
                        ;; ("BONUS" . (:foreground "GoldenRod" :weight bold))
                        ;; ("UCANCODE" . (:foreground "GoldenRod" :weight bold))
                        ("noexport" . (:foreground "darkgrey"))
                        ))

                                        ;(setq org-fast-tag-selection-single-key t)
                                        ;(setq org-use-fast-todo-selection t)








  (progn))

using Org-Attach

allow Automatic version-control with Git

;; https://orgmode.org/manual/Automatic-version_002dcontrol-with-Git.html#Automatic-version_002dcontrol-with-Git

;; If the directory attached to an outline node is a Git repository,
;;   Org can be configured to automatically commit changes to that
;;   repository when it sees them.

;; To make Org mode take care of versioning of attachments for you,
;;   add the following to your Emacs config:

(require 'org-attach-git)

allow Attach from Dired

;; https://orgmode.org/manual/Attach-from-Dired.html#Attach-from-Dired

;; It is possible to attach files to a subtree from a Dired buffer. To
;;   use this feature, have one window in Dired mode containing the
;;   file(s) to be attached and another window with point in the
;;   subtree that shall get the attachments. In the Dired window, with
;;   point on a file, M-x org-attach-dired-to-subtree attaches the
;;   file to the subtree using the attachment method set by variable
;;   org-attach-method. When files are marked in the Dired window then
;;   all marked files get attached.

;; Add the following lines to the Emacs init file to have C-c C-x a attach files in Dired buffers.

(add-hook 'dired-mode-hook
          (lambda ()
            (define-key dired-mode-map
              (kbd "C-c C-x a")
              #'org-attach-dired-to-subtree)))

;; The following code shows how to bind the previous command with a specific attachment method.

(add-hook 'dired-mode-hook
          (lambda ()
            (define-key dired-mode-map (kbd "C-c C-x c")
              (lambda ()
                (interactive)
                (let ((org-attach-method 'cp))
                  (call-interactively #'org-attach-dired-to-subtree))))))

Allow jumping to the Org heading corresponding to an Org-Attach file or location

;; ,refs: originally from https://fuco1.github.io/2023-02-08-Visit-the-org-headline-from-the-attach-dired-buffer.html
(defun rapport/org-attach/visit-headline-from-dired ()
  "Go to the headline corresponding to this org-attach directory."
  (interactive)
  (let* ((id-parts (last (split-string default-directory "/" t) 2))
         (id (apply #'concat id-parts)))
    (let ((m (org-id-find id 'marker)))
      (unless m (user-error "Cannot find entry with ID \"%s\"" id))
      (pop-to-buffer (marker-buffer m))
      (goto-char m)
      (move-marker m nil)
      (org-show-entry))))

using Org-Archive

(use-package org-archive
  :ensure nil

  :custom
  (org-archive-location (expand-file-name "%s_archive::datetree/" (expand-file-name "archive" (expand-file-name ".artifacts" rapport-uri-vault-docs))))
  :config
  (progn))

using Org-Babel

setup Org Babel

;; disable the confirm prompt for code block evaluation
                                      ;(setq org-confirm-babel-evaluate t)

;; ;; auto-activate Babel languages as their used
(defadvice org-babel-execute-src-block (around load-language nil activate)
  "Load language if needed"
  (let ((language (org-element-property :language (org-element-at-point))))
    (unless (cdr (assoc (intern language) org-babel-load-languages))
      (add-to-list 'org-babel-load-languages (cons (intern language) t))
      (org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages))
    ad-do-it))

;; DESC: w/r/t NoWeb syntax in Tangle'd Source Blocks
;;  - in such cases the dereferencing will still work (untested), but syntax highlighting will break in bothersome ways
;;  - if desired, to work better in such cases, we may change the noweb markers to {{{ and }}}
;;  - as of [2015-10-04], NGa will set these as buffer-local
;;    variable/value overrides, rather than globally, in order to
;;    avoid incompatible breaks with users of the default config

pre-load the shell language, ob-shell

(require 'ob-shell)

using Org-Capture

setup doct, aka Declarative Org Capture Template

;; Org-Capture
;; Quickly record notes without interupting thought process or workflow

;; https://github.com/progfolio/doct
(use-package doct
  :after (:all org)
  :demand t
  :init
  (require 'org-macs)
  (require 'org-capture)
  (require 'org-protocol)
  ;; #,TODO: consider relocating the org-default-task-body variables to a more suitable spot
  (setq org-default-task-body "
-----
--- _/overview/_ ---


-----
--- _/info/notes/_ ---

- *on Sources*
    #+NAME: %(org-id-get-create)-srcs
    #+CAPTION: reference list
    |!|title|url|desc|rowid|
    | |title|url|desc|rowid|
    |-|-----|---|----|-----|
    |/|     |   |    | <7> |
    |#|     |   |    |     |
    #+TBLFM: $5='(if (and (string= @1$rowid \"rowid\") (string= $rowid \"\")) (concat \"<<\"(org-id-new) \">>\") $rowid)

- *on Inquiries*
- *on Discourse*
\n\n")
  (rapport/doct/append
   (doct
    `(
      ;; General/Personal/Global
      ("Tasks" :keys "t"
       ;; ,NB: empty string defaults to `org-default-notes-file'
       :file ""
       :empty-lines-after 1
       :template ("* %{_preface} %?    %{_tags}"
                  ":PROPERTIES:"
                  ":ID: %(org-id-new)"
                  ":CREATED: %U"
                  ":END:")
       :_preface "TODO"
       :_tags ":type@task:"
       :clock-in t :clock-resume t
       :children
       (("todo" :keys "t")
        ("task" :keys "a" :template ("* %{_preface} %?" ":PROPERTIES:" ":ID: %(org-id-new)" ":CREATED: %U" ":END:"  ,org-default-task-body))
        ("habits" :keys "h"
         :file ""
         :template ("* %{_preface} %?    %{_tags}"
                    "SCHEDULED: %(format-time-string \"<%Y-%m-%d .+1d/3d>\")"
                    ":PROPERTIES:"
                    ":STYLE: habit"
                    ":REPEAT_TO_STATE: TODO"
                    ":RESET_CHECK_BOXES: t"
                    ":END:")
         :_tags: ":HABIT:")))
      ("Notes" :keys "n"
       :file ""
       ;; :file ,(expand-file-name (format "journal._%s.org"
       ;;                                       (rapport-fn-context-get-label))
       ;;                               rapport-uri-vault-docs-calendars)
       :empty-lines-after 1
       :template ("* %{_preface} %?    %{_tags}"
                  ":PROPERTIES:"
                  ":ID: %(org-id-new)"
                  ":CREATED: %U"
                  ":END:")
       :_preface ""
       :_tags ":type@note:"
       :clock-in t :clock-resume t
       :children
       (("Note" :keys "n"
         :file ""
         ;:datetree t
         :clock-in nil :clock-resume nil)
        ("Observation a/o Impression (encrypted note to self)" :keys "o"
         ;; :file ,(expand-file-name (format "journal._%s.org"
         ;;                                     (rapport-fn-context-get-label))
         ;;                             rapport-uri-vault-docs-calendars)
         :_tags ":OBSERVED:crypt:"
         ;:datetree t
         :_preface ""
         :clock-in nil :clock-resume nil)
        ("Review (to Inbox for later review)" :keys "r"
         :file ""  ;; ,NB: Counter to type, REVIEW items go to the Inbox
         ;:datetree t
         :_preface "REVIEW")
        ("Journal" :keys "j"
         :template ("* %?\n%U\n")
         ;:datetree t
         :_tags ":JOURNAL:")
        ;; ("Link" :keys "l"
        ;;  :type plain
        ;;  :clock-in nil :clock-resume nil
        ;;  :headline "COMMENT Links"
        ;;  :template ("\n---\n - %?\n %x\n"))
        ("Fact (Org-Drill)" :keys "f"
         :file ""  ;; ,NB: Counter to type, Fact items go to the Inbox
         :empty-lines 1
         :immediate-finish t
         :_preface ""
         :_tags ":drill:"
         :children
         (("Unrefined Fact" :keys "0" :olp ("Org-Drill" "Unrefined Fact") :_tags ":drill:docmerge:" :_preface "REPORTED [#E]"
           :children
           (("Unrefined from Clipboard" :keys "c"
             :template ("* %{_preface} Read article: '%:description'    %{_tags}"
                        "URL: %c\n\n"))
            ("Unrefined Fact from Web-Browser" :keys "w"
             :template ("* %{_preface} Fact: '%:description'    %{_tags}"
                        ":\n:PROPERTIES:\n:DATE_ADDED: %u\n:SOURCE_URL: %c\n:END:\n"
                        "%i\n%?\n"))))

          ("Directed (Simple) Flashcard" :keys "1" :olp ("Org-Drill" "Directed aka Simple")
           :template ("* %^{Question Title|Question}    %{_tags}%^G"
                      ":PROPERTIES:"
                      ":ID: %(org-id-new)"
                      ":CREATED: %U"
                      ":END:\n"
                      " %^{Question Text}"
                      "** %^{Answer Title|Answer}\n %^{Answer Text}"))
          ("Symmetric (2-sided) Flashcard" :keys "2" :olp ("Org-Drill" "Symmetric aka 2-Sided")
           :template ("* %^{Question Title|Question}    %{_tags}%^G"
                      ":PROPERTIES:"
                      ":ID: %(org-id-new)"
                      ":DRILL_CARD_TYPE: twosided"
                      ":CREATED: %U"
                      ":END:\n"
                      " %^{Question Text}"
                      "** %^{First Side - Answer Title}\n %^{First Side - Answer Text}"
                      "** %^{Second Side - Answer Title}\n %^{Second Side - Answer Text}"
                      "** %^{Response Companion Title}\n %^{Response Companion Text}"))
          ("Polygonal (*-sided) Flashcard" :keys "3" :olp ("Org-Drill" "Polygonal aka Multi-Sided")
           :template ("* %^{Question Title} \t%{_tags}%^G"
                      ":PROPERTIES:"
                      ":ID: %(org-id-new)"
                      ":DRILL_CARD_TYPE: multisided"
                      ":CREATED: %U"
                      ":END:\n"
                      " %^{Question Text}"
                      "** %^{First Side - Answer Title}\n %^{First Side - Answer Text}"
                      "** %^{Second Side - Answer Title}\n %^{Second Side - Answer Text}"
                      "** %^{Third Side - Answer Title}\n %^{Third Side - Answer Text}"))

          ("Multi-Fill Flashcard" :keys "4" :olp ("Org-Drill" "Cloze aka Fill-In the Blank")
           :template ("* %^{Question Title} \t%{_tags}%^G"
                      ":PROPERTIES:"
                      ":ID: %(org-id-new)"
                      ":DRILL_CARD_TYPE: %^{DRILL_CARD_TYPE|hide1cloze|show1cloze|hide2cloze|show2cloze}"
                      ":CREATED: %U"
                      ":END:\n"
                      " %^{Question Text}"
                      "** %^{First Side - Answer Title|Answer 1}\n %^{First Side - Answer Text}"
                      "** %^{Second Side - Answer Title|Answer 2}\n %^{Second Side - Answer Text}"
                      "** %^{Third Side - Answer Title|Answer 3}\n %^{Third Side - Answer Text}"))
          ))))

      ("Correspondence" :keys "c"
       :file ""
       ;; :file ,(expand-file-name (format "correspondence._%s.org"
       ;;                                       (rapport-fn-context-get-label))
       ;;                               rapport-uri-vault-docs-calendars)
       ;:datetree t
       :empty-lines-after 1
       :template ("* %{_preface} %?        [/]    %{_tags}"
                  ":PROPERTIES:"
                  ":ID: %(org-id-new)"
                  ":CREATED: %U"
                  ":END:")
       :_tags ":type@correspondence:"
       :clock-in t :clock-resume t
       :children
       (("Meeting" :keys "m" :_preface "MEETING with " :_tags ":MEETING:")
        ("Phone Call" :keys "p" :_preface "PHONE" :_tags ":PHONE:")
        ("Email" :keys "e" :_preface "EMAIL" :_tags ":EMAIL:")
        ("Text Chat" :keys "t" :_preface "TEXT CHAT" :_tags ":TEXTCHAT:")
        ("Virtual Meeting (tele-conference)" :keys "v" :_preface "MEETING with " :_tags ":MEETING:VIRTUAL_TELECONF:")))
      ("Schedulings" :keys "s"
       :file ""
       ;; :file ,(expand-file-name (format "schedule._%s.org"
       ;;                                       (rapport-fn-context-get-label))
       ;;                               rapport-uri-vault-docs-calendars)
       :empty-lines-after 1
       :template ("* %{_preface} %?        %{_tags}"
                  ":PROPERTIES:"
                  ":ID: %(org-id-new)"
                  ":CREATED: %U"
                  ":END:")
       :_tags ":type@event:"
       :clock-in t :clock-resume t
       :children
       ;; ,TODO: A point in time should be a Reminder, a span of time should be an Appointment
       (("Appointment" :keys "a"
         ;; :file "calendars.org"
         :template ("* APPT %^{Description} %^g\n%?\nAdded: %U")
         :_tags ":APPOINTMENT:"
         :headline "Calendar")
        ("Calendar (appt/duration)" :keys "c"
         ;; :file "journal.org"
         ;:datetree t
         :_tags ":CALENDAR:"
         :template ("* %^{What?}\n%^{start-time}T--%^{end-time}T\n%?"))
        )))))

  :bind
  ;; set org-capture to global keychord "C-c c"
  ("C-c c" . org-capture)
  :commands (doct)
  :config
  (progn))

using Org-Protocol

install Firefox's org-capture Add-on

  • locate and install the add-on here, https://addons.mozilla.org/en-US/firefox/addon/org-capture/
  • view and configure the org-capture template keys to invoke when the button is pressed with text is selected and when the button is pressed with no text selected.
  • the add-on is a complete and preferred replacement for the use of JS bookmarklets

install Org-protocol on macOS

  • nb
  • add desktop file

    [Desktop Entry]
    Name=org-protocol
    Exec=emacsclient -t -a '' -n %u
    Type=Application
    Terminal=false
    Categories=System;
    MimeType=x-scheme-handler/org-protocol;
    
  • ensure a suitable EmacsClient "App" is available

    on emacsclient(input)
            do shell script "/usr/local/bin/emacsclient -n -c '" & input & "'"
    end emacsclient
    
    on open location input
            emacsclient(input)
    end open location
    
    on open inputs
            repeat with raw_input in inputs
                    set input to POSIX path of raw_input
                    emacsclient(input)
            end repeat
    end open
    
    on run
            do shell script emacsclient("")
    end run
    
  • Add
  • Install pandoc

    brew install pandoc
    
  • Install and run desktop-file-utils to update the ~/.local/share/applications/mimeinfo.cache

    brew install desktop-file-utils && update-desktop-database ~/.local/share/applications/
    
  • If succeeded, a file named “mimeinfo.cache” will be created or recently updated in this folder.

    ls -l ~/.local/share/applications/mimeinfo.cache
    

using Org-Clocking

setup Org Clocking

;; org-clocking.el --- org-mode clocking prefs
(use-package emacs
  :ensure nil

  :no-require t
  :after (org)
  :init
  (require 'org-clock)
  ;; Resume clocking task when emacs is restarted
  (org-clock-persistence-insinuate)
  :custom
  ;; Separate drawers for clocking/log and properties
  (org-drawers (quote ("PROPERTIES" "LOGBOOK")))
  ;; Save clock data and state changes and notes in the LOGBOOK drawer
  (org-clock-into-drawer t)
  ;; keep clocking info in properties, it's tidier looking
  (org-log-into-drawer "LOGBOOK")
  ;; Adding yet further auditing, this option causes Org to insert
  ;;   annotations when you change the deadline of a task, which
  ;;   will note the previous deadline date and when it was
  ;;   changed. Very useful for figuring out how many times you
  ;;   “kicked the can down the road.”
  (org-log-redeadline (quote time))
  ;; This does the same as above, but for the scheduled dates,
  ;;   which I use more often.
  (org-log-reschedule (quote time))
  ;; Include current clocking task in clock reports
  (org-clock-report-include-clocking-task t)
  ;; track org-mode todo state changes , http://orgmode.org/manual/Tracking-TODO-state-changes.
  (org-log-done 't)

  ;; When you perform a text search (the “s” selection from the
  ;;   org-agenda pop-up), include the archives for all of the
  ;;   files in Org’s agenda files list. If you archive things
  ;;   regularly, which I do, this helps you dig stuff out of
  ;;   there when you’re looking for it.
  (org-agenda-text-search-extra-files '(agenda-archives))

  ;; I tend to leave a blank line at the end of the content of
  ;;   each task entry. This causes Org to automatically place a
  ;;   blank line before a new heading or plain text list item,
  ;;   just the way I like it.
  (org-blank-before-new-entry (quote ((heading) (plain-list-item))))

  ;; Clock out when moving task to a done state
  (org-clock-out-when-done t)
  ;; Resume clocking task on clock-in if the clock is open
  (org-clock-in-resume t)
  ;; Save the running clock and all clock history when exiting Emacs, load it on startup
  (org-clock-persist t)
  (org-clock-persist-file (expand-file-name (format "org-clock-save._%s.eld"
                                                    (rapport-fn-context-get-label))
                                            rapport-uri-vault-docs-status))

  ;; Do not prompt to resume an active clock
  (org-clock-persist-query-resume nil)
  ;; Enable auto clock resolution for finding open clocks
  (org-clock-auto-clock-resolution (quote when-no-clock-is-running))
  ;; prompt if idle for X mins, (disabled when using a Termnal where idle detection isn't support)
  ;;  - When the clock is running and Emacs is idle for more than this number of minutes, the clock will be clocked out automatically.
  ;;  - Use ‘M-x org-clock-toggle-auto-clockout RET’ to temporarily turn this on or off.
  ;;  - Set 'org-clock-idle-time to 'nil to disable the idle timer, ex. ~(setq org-clock-idle-time nil)!~
  (org-clock-idle-time (when (display-graphic-p) 40))
  ;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration
  (org-clock-out-remove-zero-time-clocks t)
  ;; Show lot of clocking history so it's easy to pick items off the C-F11 list
  (org-clock-history-length 36)
  ;; default values for Clock Reports
  (org-clocktable-defaults
   '(:maxlevel 2 :lang "en" :scope file :block nil :wstart 1 :mstart 1
           :tstart nil :tend nil :step nil :stepskip0 t :fileskip0 t
           :tags nil :match nil :emphasize nil :link t :narrow 40!
           :indent t :filetitle nil :hidefiles t :formula %
           :timestamp nil :level nil :tcolumns nil :formatter nil))
  ;; as used w/ Org-Agenda's Clock Report.
  ;; ,HINT: All the same options as 'org-clocktable-defaults except for :name, :tstart, :tend, :block, and :scope
  (setq org-agenda-clockreport-parameter-plist '(
                                                 :lang "en"
                                                 :compact t
                                                 :emphasize t
                                                 :fileskip0 t
                                                 :filetitle nil
                                                 ;:formula %
                                                 :formula ""  ; ,TODO: build out a robust set of computed fields a/o columns here
                                                 :hidefiles t
                                                 :indent nil
                                                 ;:level 3
                                                 :link t
                                                 :match nil
                                                 ;:maxlevel 5
                                                 :narrow 48!
                                                 :step day
                                                 :stepskip0 t
                                                 :sort (1 . ?a)
                                                 ;:tags t
                                                 ;:tcolumns 5
                                                 ;:timestamp t
                                                 :properties (
                                                              ;"PRIORITY"
                                                              ;"TODO"
                                                              ;"BLOCKED"
                                                              ;"ITEM"
                                                              ;"ORG_GTD"
                                                              "CATEGORY"
                                                              "Effort"
                                                              ;"DEADLINE"
                                                              ;"DELEGATED_TO"
                                                              ;"ORG_GTD_TIMESTAMP"
                                                              ;"CLOCKSUM"
                                                              ;"account"
                                                              ;"CREATED"
                                                              ;"CLOSED"
                                                              ;"SCHEDULED"
                                                              ;"allocate"
                                                              ;"EXPIRY"
                                                              ;"EXPIRED"
                                                              ;"MODIFIED"
                                                              ;"HASH"
                                                 )))
  :config
  (progn))

using Org-InlineTask

setup org-inlinetask

(use-package emacs
  :ensure nil

  :no-require t
  :init
  (require 'org-inlinetask)
  :custom
  (org-inlinetask-default-state "TODO")
  (org-inlinetask-show-first-star t)
  :config
  (progn))

using Org-Crypt

setup auth-sources

;; include Emacs built-in integration to Freedesktop.org Secrets systems, (eg. Gnome Keyring, KDE Wallet)
;; - https://www.gnu.org/software/emacs/manual/html_mono/auth.html
(when (or
       (eq system-type 'gnu/linux)
       ;wip; (eq system-type 'darwin)
       )
  (require 'secrets))

;; add/register specific authinfo sources
(setq auth-sources (remove 'nil `(
                                  ;; for Rapport
                                  ,(when (file-readable-p (expand-file-name "authinfo.json.gpg" rapport-uri-vault-cfgs-emacs))
                                     (expand-file-name "authinfo.json.gpg" rapport-uri-vault-cfgs-emacs))
                                  ,(when (file-readable-p (expand-file-name "authinfo.gpg" rapport-uri-vault-cfgs-emacs))
                                     (expand-file-name "authinfo.gpg" rapport-uri-vault-cfgs-emacs))
                                  ,(when (expand-file-name "authinfo.json" rapport-uri-vault-cfgs-emacs)
                                     (expand-file-name "authinfo.json" rapport-uri-vault-cfgs-emacs))
                                  ,(when (file-readable-p (expand-file-name "authinfo" rapport-uri-vault-cfgs-emacs))
                                     (expand-file-name "authinfo" rapport-uri-vault-cfgs-emacs))

                                  ;; upstream defaults
                                  ,(when (file-readable-p "~/.authinfo")
                                     "~/.authinfo")
                                  ,(when (file-readable-p "~/.authinfo.gpg")
                                     "~/.authinfo.gpg")
                                  ,(when (file-readable-p "~/.netrc")
                                     "~/.netrc")

                                  ;; integrate with 3rd-party auth-sources
                                        ;default

                                  ;; The Secret Service API is a
                                  ;;   standard from freedesktop.org
                                  ;;   to securely store passwords
                                  ;;   and other confidential
                                  ;;   information. This API is
                                  ;;   implemented by system daemons
                                  ;;   such as the GNOME Keyring and
                                  ;;   the KDE Wallet (these are
                                  ;;   GNOME and KDE packages
                                  ;;   respectively and should be
                                  ;;   available on most modern
                                  ;;   GNU/Linux systems).
                                  ,@(when (featurep 'secrets)
                                      '("secrets:Login"
                                        "secrets:session" ))

                                  ;; ,@(when (eq system-type 'darwin)
                                  ;;    '(macos-keychain-internet
                                  ;;   macos-keychain-generic))
                                  )))

setup EPA

;; If non-nil, cache passphrase for symmetric encryption. The default value is nil.
(setq-default epa-file-cache-passphrase-for-symmetric-encryption t)
;; If non-nil, disable auto-saving when opening an encrypted file. The default value is t.
(setq-default epa-file-inhibit-auto-save t)

;; https://emacs.stackexchange.com/questions/27841/unable-to-decrypt-gpg-file-using-emacs-but-command-line-gpg-works#comment82263_27870
(setf epa-pinentry-mode 'loopback)

setup Org Crypt

    ;; Org-Crypt
    ;; gpg encypt any org-mode headings w/ the 'crypt' tag
(eval-after-load 'org
  (lambda () (progn
    ;; see http://orgmode.org/worg/org-tutorials/encrypting-files.html
    (require 'org-crypt)
    (org-crypt-use-before-save-magic)
    (setq org-tags-exclude-from-inheritance (quote (
                                                    "type@{.*}"
                                                    "crypt"
                                                    "task@objective"
                                                    "task@project"
                                                    )))

    ;; GPG key to use for encryption
    ;; Either the Key ID or set to nil to use symmetric encryption.
    ;; #+HINT: allow 'org-crypt-key to be set from customize system
                                        ;(setq org-crypt-key nil)

    ;; add a hook that will encrypt entries before a save is written to disk
    (org-crypt-use-before-save-magic)

    ;; explicitly set org-crypt to symmetric
                                        ;(setq epa-file-select-keys nil)
    )))

using Org-Export

setup Org Export

(with-eval-after-load 'org-contrib
  ;; activate confluence export, executable as (org-confluence-export-as-confluence)
  (add-to-list 'org-export-backends 'confluence)
  (require 'ox-confluence)
  ;; activate deck.js export
  (require 'ox-deck)
    ;;; post-init
  ;; remove pointless HTML postamble
  (setq org-export-html-postamble-format nil)
  ;; org-mode code-blocks syntax highlighting on html export
  (setq org-src-fontify-natively t)
  ;; inhibit org-export interpret subscript and superscript
                                        ;(setq org-export-with-sub-superscripts nil)
  ;; require enclosing braces to mark-up sub- and super-scripts
  (setq org-use-sub-superscripts "{}")
    ;;; LaTeX export
  ;; nb, COMMENT sub-trees and lines starting w/ '#' are never exported
  ;; nb, useful LaTeX commands
  ;;    in-buffer latex preview: C-c C-x C-l (requires installed dvipng /o imagemagik)
  ;;    remove preview overlay: C-c C-c
  ;;    insert RefTeX citation: C-c C-x [
  ;; nb, LaTeX config is based in a '#+LATEX_CLASS:' class type,
  ;;    modifiable by providing '#+LATEX_CLASS_OPTIONS:' option
  ;;    directives from there the document structure/formatting is
  ;;    controlled by '#+LATEX_HEADER:' and '#+LATEX_HEADER_EXTRA:'
  ;;    (which isn't loaded on preview) directives. At the final
  ;;    level, '#+LATEX:' permits the insertion of arbitrary LaTeX
  ;;    commands/snippets
    ;;; ODT Export
  ;; requires 'zip' program =sudo aptitude install zip=
  ;;
  )

using Org-Refile

setup Org Refile

;;; Org-Refile settings
;; refs:
;;  - https://blog.aaronbieber.com/2017/03/19/organizing-notes-with-refile.html
(use-package emacs
  :ensure nil

  :no-require t
  :custom
  ;; Targets include this file and any file contributing to the agenda - up to 9 levels deep
  (org-refile-targets '((nil :maxlevel . 9)
                             (org-agenda-files :maxlevel . 9)))
  ;; Include the File in the refile target selection
  (org-refile-use-outline-path 'file)
  ;; Use full outline paths for refile targets
  (org-outline-path-complete-in-steps nil)
  ;; Allow refile to create parent tasks with confirmation
  (org-refile-allow-creating-parent-nodes 'confirm)
  (org-indirect-buffer-display 'current-window)
  (org-log-refile 'note)
  (org-refile-target-verify-function
        #'(lambda ()
           "Exclude DONE state tasks from refile targets"
           (not (member (nth 2 (org-heading-components)) org-done-keywords))))
  :config
  (require 'org-refile)
  (progn))

using Org as a Habit Tracker using Org-Habit

;; Org-Habit Config
;;   - ref: https://orgmode.org/manual/Tracking-your-habits.html
(eval-after-load 'org
  (lambda ()
    (progn
      (setq-default org-habit-preceding-days 13)
      (setq-default org-habit-following-days 2)
      (setq-default org-habit-graph-column 63)
      (require 'org-habit))))

using Org Columns

setup Org Columns

;; setup org-columns
(with-eval-after-load 'org
  ;; Change 20240228T1400_NGa seeks to integrate Org-GTD, WBS/Billing, and RACI matrix info
  (setq org-columns-default-format (concat
                                    " %1PRIORITY %4TODO(STATE) %1BLOCKED(B)"
                                    " %48ITEM(TaskDesc) %7ORG_GTD(Type) %12CATEGORY(AoF)"
                                    " %8Effort(ETC){+}"
                                    " %13DEADLINE(DUE)"
                                    " %5DELEGATED_TO(Del.)"
                                    " %ORG_GTD_TIMESTAMP(CheckIn)"
                                    " %8CLOCKSUM(WRKD){est+} %8account(CostCntr)"
                                    " %13CREATED"
                                    " %13CLOSED"
                                    " %13SCHEDULED(START)"
                                    " %allocate(RSRC_ALLOC)"
                                    ;; ,HINT: Works correctly but temporarily muted
                                    " %13EXPIRES"
                                    " %1EXPIRED(X)"
                                    " %13MODIFIED"
                                    " %HASH"
                                        ; " %TAGS"
                                        ; " %FILE"
                                        ; " %CLOCKSUM{est+} %CLOCKSUM %CLOCKSUM_T"
                                    ;; ,WIP: desired but not yet setup
                                        ; - a way to show certain types of tags, like Composure Activity Types
                                    ;; ,WIP: ideas w/ computed properties
                                        ; " num of work days in the span between START and FINISH"
                                        ; " num of remaining work days in the span between START and FINISH"
                                        ; " percent of remaining work span"
                                    ;; ,WIP: Interesting but possibly invalid
                                        ; " %{X%}"
                                        ; " %CHECKBOX{X%}"
                                        ; " %1Approved(A){X}"
                                        ; " %provide@utilization#work@delta(UTL?){X%}"
                                        ; " %8provide(Provide)"
                                        ; " %require(RSRC_REQST)"
                                    ))
  (progn))

using Block Templates

These templates enable you to type things like <el and then hit Tab to expand the template. More documentation can be found at the Org Mode Easy Templates documentation page.

;; This is needed as of Org 9.2
(require 'org-tempo)

(add-to-list 'org-structure-template-alist '("sh" . "src sh"))
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("sc" . "src scheme"))
(add-to-list 'org-structure-template-alist '("ts" . "src typescript"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("yaml" . "src yaml"))
(add-to-list 'org-structure-template-alist '("json" . "src json"))

using Org-Pomodoro

;;
(use-package org-pomodoro
  :after org
  :config
  (setq org-pomodoro-start-sound "~/.emacs.d/sounds/focus_bell.wav")
  (setq org-pomodoro-short-break-sound "~/.emacs.d/sounds/three_beeps.wav")
  (setq org-pomodoro-long-break-sound "~/.emacs.d/sounds/three_beeps.wav")
  (setq org-pomodoro-finished-sound "~/.emacs.d/sounds/meditation_bell.wav"))

enable Git-Link in Org

setup git-link

(use-package git-link
  :commands git-link
  :config
  (setq git-link-open-in-browser t))

Misc Org Features and Configs

setup Org Miscellaneous a/o Supplimental Features

  • visual presentation

    (setq org-ellipsis " ▾")
    ;(setq org-hide-emphasis-markers t)
    (setq org-src-fontify-natively t)
    (setq org-src-tab-acts-natively t)
    (setq org-edit-src-content-indentation 2)
    (setq org-hide-block-startup nil)
    (setq org-startup-folded 'content)
    (setq org-cycle-separator-lines 2)
    
  • miscellaneous

    (delight 'org)
    (delight 'helpful)
    (delight 'org-indent-mode)
    (org-indent-mode 1)
    

Chapter 2, Endeavors

Efforts and Assets

as Solution and Asset Development Forges

support Git w/ Magit

setup Magit

;; use Git w/i Emacs (req's Emacs v24.4+ and Git v1.9+)
;;(require 'load-mode__magit)     ; [2018-05-08] EM: "Error (use-package): Cannot load"
    ;;;
    ;;;  Magit - emacs interface to git
    ;;;

    ;;; DESCRIPTION
;;  To successfully build magit's next@{2014-11-08} a file, called
;;    with-editor.el, from git-modes's next@{2014-11-08} is required.
;;
;;  ex.
;;    cd ~/.emacs.d/mnt/magit && emacs -Q --batch -L . -L ../git-modes/. -L ../dash.el/. -f batch-byte-compile *.el


;; Instruction
;; install: =make && sudo make install=, compiles to [[/usr/local/share/emacs/site-lisp]] where Emacs will detect it.
;; init: (magit-status) or M-x magit-status


(use-package git-modes
  :after (dash with-editor gitattributes-mode)
  :config
  (and
                                        ;(use-package with-editor)
                                        ;(use-package gitattributes-mode)
   (require 'gitconfig-mode)
   (require 'gitignore-mode)
   (require 'git-rebase)))


(use-package magit
  :bind (
         ("C-c g" . magit-status)
         :map project-prefix-map
         ("m" . magit-project-status))
  :commands (magit-status magit magit-get-current-branch)
  :hook (dash git-modes)
  :custom
  (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
  :config
  (setq magit-last-seen-setup-instructions "1.4.0")
  (setq magit-auto-revert-mode t)
  (progn))


    ;;; extensions:
;;(require 'magit-svn) ;;integrates with git-svn. Hit 'N' to see your options.
;;(require 'magit-topgit) ;;integrates with topgit.
;;(require 'magit-stgit) ;;integrates with StGit.

;; bundle for git-annex enablements
(use-package git-annex
  :if (executable-find "git-annex"))

;; dired-git-annex.el - enhance Dired w/ git-annex support

;;  Magit Annex - magit support to git-annex
(use-package magit-annex :after (:all magit git-annex))

;;
(use-package hl-todo)
(use-package magit-todos
  :after (:all magit hl-todo)
  :commands (magit-todos-list)
  :hook (magit-mode)
  :config
  (magit-todos-mode t))

;;
(use-package forge
  ;; ,LOG: 20200528_NGa disabled to quell EM from windows
  :if (executable-find "sqlite3")
  :after (magit)
  :config (progn))

(use-package git-identity)

setup Multi-Repo Management using

;; https://github.com/luismbo/multi-magit

(use-package multi-magit
  :ensure (multi-magit :type git :host github :repo "luismbo/multi-magit" :files ("*.el"))
  :bind (("C-c G" . multi-magit-status))
  :custom
  ;; multi-magit-selected-repositories
  (multi-magit-selected-repositories (mapcar 'cdr (multi-magit--all-repositories)))
  (magit-repository-directory-depth 1)
  ;; NB, this variable has a fit when given smylinks
  (magit-repository-directories
   `((,rapport-uri-rapport . 0)
     ,(cons (file-truename rapport-uri-vault-uris) 1)
     ,(cons (file-truename (expand-file-name "extrefs" rapport-uri-vault-uris)) 1)))
  :config
  (progn))

enable Per-Directory direnv Config w/ EnvRC

(use-package envrc
  :config
  (envrc-global-mode t)
  (progn))

as Project Workspace Context Mgmt and Enablement Workbench

  • on Concepts and Contributory Tools

    Table 1: Concepts and Contributory Tools
      workflow projects
    tab-bar    
    project.el    
    Tabspaces    
  • on Context and Flow
  • on Using Tabspaces
  • on Keybindings and Adaptations

    kbd object/concept pkg desc originally adapted why? impl?
    C-x b buffer consult, tabspaces       shows buffers in the current project consult-project-buffer
    C-x p project project.el          
    C-u C-x b buffers         shows all buffers (across any project) switch-to-buffer
    C-x B buffers         shows all buffers in perspective organized by project  
    M-p window            
    M-P frame            
    C-x x domain workflow          
    C-c C-] workspace            

Context-local Functionality w/ Project.el

Project.el is a Project Interaction Library for Emacs (documentation: online)

;; 'project.el' is built-into Emacs. Still, we'll request a latest/specific version via Straight
(use-package project
  ;; ,NB: the 'consult project and the 'tabspaces project are used to integrate with and extend 'project 
  :demand
  :preface
  (defun rapport/affe-find/-in-project () "" (interactive) (affe-find (project-root (project-current t))))
  (defun rapport/affe-grep/-in-project () "" (interactive) (affe-grep (project-root (project-current t))))
  ;;;;;; WIP ;;;;;;
  (defun rapport/project/-refresh-project-list () "" (interactive)) ;; WARN: UNIMPLEMENTED
  ;;         (async-start
  ;;          (lambda ()
  ;;            (progn
  ;;              (message " (rapport) updating project list ... ")
  ;;              (require 'project)
  ;;              ;; ,NB: I'd like to use 'rapport-uri-vault-uris (in place of "~/.uris") but it seems to be unavailable in the async execution context
  ;;              (dolist (iter `(
  ;;                              ,(when (bound-and-true-p project-known-project-roots) project-known-project-roots)
  ;;                              ,(directory-files rapport-uri-vault-uris nil "^_worktree\.-\..*$")    ;; ,HINT: list all '_worktree' prefixed directories
  ;;                              ,(directory-files rapport-uri-vault-uris nil "^[^_.].*$")    ;; ,HINT: list all non-underscore prefixed directories
  ;;                              ;; ,(directory-files-recursively rapport-uri-vault-uris "^_.*$" t
  ;;                              ;;                                    #'(lambda (x) (and
  ;;                              ;;                                                   (bound-and-true-p x)
  ;;                              ;;                                                   (file-directory-p x)
  ;;                              ;;                                                   (file-readable-p x)))
  ;;                              ;;                                    t)
  ;;                                        ;,(project-remember-projects-under (or rapport-uri-vault-uris (expand-file-name "~/.uris")) t)  ;; ,HINT: the recursive one
  ;;                              )    ;; end-of-list
  ;;                            results)
  ;;            ;; ,HINT: start-loop-body
  ;;                ;; ,HINT: check each project-uri entry for validity
  ;;                (progn
  ;;                  (with-temp-buffer
  ;;                    (insert-file-contents project-list-file   project-remember-projects-under lt-uris (expand-file-name "~/.uris")) nil))
  ;;                (message (format-string "%s" iter))
  ;;            (setq results (append results iter))
  ;;            )  ;; ,HINT: end-loop-form
  ;;          results
  ;;          )  ;; ,HINT: end-lambda-form
  ;;              (sleep-for 1)
  ;;              (project-forget-zombie-projects)
  ;;              (message " (rapport) updating project list ... [async::started]")))
  ;;          (lambda ()
  ;;            (message " (rapport) updating project list ... [async::finished]"))))
  ;;;;;;; <end-wip> ;;;;;;
  :custom
  (project-list-file (expand-file-name (format "listing._%s.project.eld" (rapport-fn-context-get-label)) (expand-file-name "project" rapport-uri-vault-cfgs-emacs-apps)))
  (project-switch-use-entire-map t)
  (project-kill-buffers-display-buffer-list t)
  :commands (project-switch-project)
  :bind
  (:map project-prefix-map
        ;; add project buffer mgmt keybinds
        ("b" . consult-project-buffer)
        ("C-b" . rapport/ibuffer/group-by-project)
        ("C-x C-b" . rapport/ibuffer/group-by-project)
        ;; add project open or jump keybinds
        ("d" . project-find-dir)
        ("f" . consult-project-extra-find) ;; ,HINT: requires consult-project-extra package, which will be loaded on demand 
        ("o" . consult-project-extra-find-other-window)  ;; ,HINT: requires consult-project-extra package, which will be loaded on demand 
        ;; add project search, jump, or replace keybinds
        ("r" . project-query-replace-regexp)
        ("C-s f" . rapport/affe-find/-in-project)
        ("C-s g" . rapport/affe-grep/-in-project)
        ("s" . consult-line-multi)
        ("j" . consult-imenu-multi)
        ;; add project status keybinds
        ("@" . disproject-custom-dispatch)
        ("D" . dashboard-open)
        ("m" . magit-status)
        ("v" . project-vc-dir)
        ;; add project action keybinds
        ("\'" . eat-project)
        ("c" . project-compile)
        ("x" . project-execute-extended-command)
        ("`" . project-tasks)
        ("&" . project-async-shell-command)
        ;; ,HINT: Tab-Bar integrations
        ("C-," . tab-bar-rename-tab)
        ("C-n" . tab-bar-switch-to-next-tab)
        ("C-p" . tab-bar-switch-to-prev-tab)
        ("M-p" . tab-bar-switch-to-recent-tab)
        ;; add meta-project mgmt convenience keybinds
        ;; add project collection-mgmt convenience keybinds
        ("# #" . rapport/project/-refresh-project-list)  ; ,HINT: rediscover projects under "~/.uris"
        ("# +" . project-remember-project)
        ("# -" . project-forget-project)
        ;; end-of-list
        )

  :config
  ;; add projects under "~/.uris" on start
  (project-remember-projects-under rapport-uri-vault-uris nil)
  (project-forget-zombie-projects)
  ;; create project list file if it doesn't exist
  (let
      ((idem-file project-list-file))
    (unless (file-exists-p idem-file)
      (unless (file-directory-p (file-name-parent-directory idem-file))
        (make-directory (file-name-parent-directory idem-file) t))
      (with-temp-buffer
        (insert ";;; -*- lisp-data -*-" "\n" "()")
        (write-file idem-file))))
  (progn))

info/notes

  • on Getting Started
    • Just open some file in a version-controlled (e.g. git) or a project (e.g. maven) directory that's recognized by Project.el and you're ready for action. Project.el happens to recognize out of the box every common VCS and many popular project types for various programming languages. You can learn more about Project.el's notion of a project here.
    • The extend of the support for every VCS differs and Git is the best supported one. Project.el supports some advanced features like working with Git submodules and using git-grep instead GNU grep.
    • You need to know only a handful of Project.el commands to start benefiting from it.
    • Project.el default key prefix is C-x p
    • The file at path project-list-file contains a listing of known projects by path.
  • on Commands

    Keybinding Action operates-on Description  
    C-x p p project-switch-project      
      project-forget-project      
    C-x p f project-find-file files is a convenient way of visiting files (see Visiting Files) that belong to the current project. Unlike C-x C-f, this command doesn’t require to type the full file name of the file to visit, you can type only the file’s base name (i.e., omit the leading directories). In addition, the completion candidates considered by the command include only the files belonging to the current project, and nothing else. If there’s a file name at point, this command offers that file as the first element of the “future history”.  
    C-x p g project-find-regexp files is similar to rgrep (see Searching with Grep under Emacs), but it searches only the files that belong to the current project. The command prompts for the regular expression to search, and pops up an Xref mode buffer with the search results, where you can select a match using the Xref mode commands (see Commands Available in the xref Buffer). When invoked with a prefix argument, this command additionally prompts for the base directory from which to start the search; this allows, for example, to limit the search only to project files under a certain subdirectory of the project root. The way this command displays the matches is affected by the value of xref-auto-jump-to-first-xref (see Searching and Replacing with Identifiers).  
    M-x project-search   files is a sequential variant of project-find-regexp. It prompts for a regular expression to search in the current project’s files, but instead of finding all the matches and displaying them, it stops when it finds a match and visits the matched file at the locus of the match, allowing you to edit the matched file. To find the rest of the matches, type M-x fileloop-continue RET.  
    C-x p r project-query-replace-regexp files is similar to project-search, but it prompts you for whether to replace each match it finds, like query-replace does (see Query Replace), and continues to the next match after you respond. If your response causes Emacs to exit the query-replace loop, you can later continue with M-x fileloop-continue RET.  
    C-x p d project-find-dir files prompts you to choose a directory inside the current project, with completion. And opens a Dired buffer (see Dired, the Directory Editor) listing the files in it.  
    C-x p D project-dired files opens a Dired buffer (see Dired, the Directory Editor) listing the files in the current project’s root directory.  
    C-x p v project-vc-dir files opens a VC Directory buffer (see VC Directory Mode) listing the version control statuses of the files in a directory tree under the current project’s root directory.  
    C-x p s project-shell files starts a shell session (see Running Shell Commands from Emacs) in a new buffer with the current project’s root as the working directory.  
    C-x p e project-eshell files starts an Eshell session in a new buffer with the current project’s root as the working directory. See Eshell in Eshell: The Emacs Shell.  
    C-x p c project-compile files runs compilation (see Running Compilations under Emacs) in the current project’s root directory.  
    C-x p ! project-shell-command files runs shell-command in the current project’s root directory.  
    C-x p & project-async-shell-command files runs async-shell-command in the current project’s root directory.  
    C-x p b project-switch-to-buffer buffers Switch to another buffer belonging to the current project.  
    C-x p k project-kill-buffers buffers Kill all live buffers that belong to the current project.  

    Emacs provides commands for handling project files conveniently. This subsection describes these commands.

    All of the commands described here share the notion of the current project. The current project is determined by the default-directory (see File Names) of the buffer that is the current buffer when the command is invoked. If that directory doesn’t seem to belong to a recognizable project, these commands prompt you for the project directory.

extend Project.el
include Project.el info on Dashboard using Dashboard-Project-Status

Display a git project’s status in a dashboard widget. If magit is installed, a link to the project in magit will be provided as well.

;; ,ref: https://github.com/functionreturnfunction/dashboard-project-status
(use-package dashboard-project-status
  :after (:all dashboard project)
  :config
  (progn))
Group iBuffer listing per Project.el projects
(use-package ibuffer-project
  :hook
  (ibuffer . (lambda ()
               (setq ibuffer-filter-groups (ibuffer-project-generate-filter-groups))
               (unless (eq ibuffer-sorting-mode 'project-file-relative)
                 (ibuffer-do-sort-by-project-file-relative))))
  :autoload project-list-buffers-ibuffer
  :commands rapport/ibuffer/group-by-project
  :init
  (defun rapport/ibuffer/group-by-project () (interactive) (project-list-buffers-ibuffer (project-current)))
  :config
  (progn))
provide Project.el dispatch menus with disProject

Transient interface for managing and interacting with projects https://github.com/aurtzy/disproject

(use-package disproject
  :after (:all project transient)
  :ensure (disproject :host github :repo "aurtzy/disproject" :files (:default "disproject.el"))
  :hook (project)
  ;; :commands disproject-dispatch
  ;; :bind
  ;; (:map project-prefix-map
  ;;       ("@" . disproject-dispatch))
  :config
  (progn))
integrate Treemacs with Project.el using Project-Treemacs
(use-package project-treemacs
  :after (:all project treemacs)
  :hook (treemacs)
  :config
  (project-treemacs-mode +1) 
  (progn))
a Per-Project Org-Babel Task Runner with Project-Tasks

Efficient task runner for your project. (within Emacs + Org-Mode) (web)

(use-package project-tasks
  :after (:all project embark)
  :init
  ;; Show project-tasks when switching projects
  (add-to-list 'project-switch-commands '(project-tasks "tasks") t)
  (setq project-tasks-files '("control.org$" "\.control\.org$" ".control/.*\.org$" "docs/.control/.*\.org$"))  ;; ,HINT: Set the list of project-local files to check for tasks
  ;; Add action to embark-file map
  (with-eval-after-load 'embark
    (define-key embark-file-map (kbd "P") #'project-tasks-in-dir))
  :bind
  (:map project-prefix-map
        ([remap project-shell-command] . project-tasks))
  :commands (project-tasks)
  :custom
  ;; (project-tasks-ignore-files '("README.org"))   ;; ,HINT: Set the ignore files
  ;; (project-tasks-root-func #projct-tasks-'project-root)  ;; ,default: #'project-tasks-project-root ;; ,HINT: Set the function to get current project dir
  ;; (project-tasks-get-tasks-files-func #'project-tasks--get-task-files-by-vc)  ;; ,HINT: Function to get tasks files in root directory
  (project-tasks-separator (concat " " (nerd-icons-mdicon "nf-md-arrow_right_circle") " "))  ;; ,HINT: Set the separator between file name and task name
  :config
  (add-to-list 'marginalia-prompt-categories '("select task" . project-task))
  ;; (defvar-keymap embark-project-task-actions
  ;;   :doc "Keymap for actions for project-task (when mentioned by name)."
  ;;   :parent embark-general-map
  ;;   "`" #'project-tasks-goto-task)
  ;; (add-to-list 'embark-keymap-alist '(project-task . embark-project-task-actions))
  (progn))
Workspace Context Management with Tabspaces
(use-package tabspaces
  ;; https://github.com/mclear-tools/tabspaces
  :preface
  (setq tabspaces-default-tab "_")
  :demand
  :after (:all consult project)
  :init
  ;;
  (defun rapport/tabspaces/-with-consult ()
    "Deactivate isolated buffers when not using tabspaces."
    (require 'consult)
    (cond (tabspaces-mode
           ;; hide full buffer list (still available with "b")
           (consult-customize consult--source-buffer :hidden t :default nil)
           (add-to-list 'consult-buffer-sources 'consult--source-workspace))
          (t
           ;; reset consult-buffer to show all buffers
           (consult-customize consult--source-buffer :hidden nil :default t)
           (setq consult-buffer-sources (remove #'consult--source-workspace consult-buffer-sources)))))
  (defun rapport/tabspaces/-save-and-detach () ""
         (interactive)
         (tabspaces-save-current-project-session)
         (tabspaces-close-workspace))
      :hook
      ((elpaca-after-init . tabspaces-mode)
       (tabspaces-mode .
                       (rapport/tabspaces/-startup-config
                        rapport/tabspaces/-with-consult)))
      :commands (
                 tabspaces-clear-buffers
                 tabspaces-close-workspace
                 tabspaces-kill-buffers-close-workspace
                 tabspaces-open-or-create-project-and-workspace
                 tabspaces-remove-current-buffer
                 tabspaces-remove-selected-buffer
                 tabspaces-reset-buffer-list
                 tabspaces-restore-session
                 tabspaces-save-session
                 tabspaces-switch-or-create-workspace
                 tabspaces-switch-to-buffer
                 )
      :bind
      (:map project-prefix-map
            ;;
            ("p" . tabspaces-switch-or-create-workspace)
            ("\"" . tabspaces-open-or-create-project-and-workspace)
            ("k" . tabspaces-remove-current-buffer)
            ;; add self-destructive operation keybinds
            ("M-r" . tabspaces-reset-buffer-list) ;; ,HINT: reset the current tab's buffer list
            ("M-d" . tabspaces-close-workspace)
            ("M-k" . tabspaces-kill-buffers-close-workspace)
                                        ;wip; ("R" . tabspaces-remove-selected-buffer)
            ;; add Desktop-Save-Mode convenience keybinds
                                        ;wip; ("# 1"  tabspaces-save-current-project-session)
            ("# s" . tabspaces-save-current-project-session)
            ("# C-s" . tabspaces-save-session)
            ("# S" . tabspaces-save-session)
            ("# r" . tabspaces-restore-session)
            ;; end-of-list
            )
      ;;
      :custom
      (tabspaces-default-tab "_")
      (tabspaces-use-filtered-buffers-as-default t)
      (tabspaces-remove-to-default nil)
      (tabspaces-include-buffers `("*scratch*" "*Messages*" "*dashboard*" ,(format "CAPTURE-%s.org" (rapport-fn-context-get-label))))
      ;; session save and restore
      (tabspaces-session t)
      (tabspaces-session-auto-restore t)
      (tabspaces-session-file (expand-file-name (format "%s.sessions.eld" (rapport-fn-context-get-label)) (expand-file-name "tabspaces" no-littering-var-directory)))
      ;;
      (tabspaces-todo-file-name ".status/notes.org")
      (tabspaces-initialize-project-with-todo nil)
      :config
      ;; Create the tabspaces-session-file if tabspaces-session is enable and if the file doesn't already exist
      (and tabspaces-session
           (not (file-exists-p tabspaces-session-file))
           (with-temp-buffer (write-file tabspaces-session-file)))
      ;;
      (let
          ((idem-file tabspaces-session-file))
        (unless (file-exists-p idem-file)
          (unless (file-directory-p (file-name-parent-directory idem-file))
            (make-directory (file-name-parent-directory idem-file) t))
          (with-temp-buffer (write-file idem-file))))
      ;;
      ;; Filter Buffers for Consult-Buffer

      ;; (with-eval-after-load 'consult
      ;;   ;; hide full buffer list (still available with "b" prefix)
      ;;   (consult-customize consult--source-buffer :hidden t :default nil)
      ;;   ;; set consult-workspace buffer list
      ;;   (defvar consult--source-workspace
      ;;     (list :name     "Workspace Buffers"
      ;;           :narrow   ?w
      ;;           :history  'buffer-name-history
      ;;           :category 'buffer
      ;;           :state    #'consult--buffer-state
      ;;           :default  t
      ;;           :items    (lambda () (consult--buffer-query
      ;;                                  :predicate #'tabspaces--local-buffer-p
      ;;                                  :sort 'visibility
      ;;                                  :as #'buffer-name)))

      ;;     "Set workspace buffer list for consult-buffer.")
      ;;   (add-to-list 'consult-buffer-sources 'consult--source-workspace))


      ;; Filter Buffers for Consult-Buffer
      (with-eval-after-load 'consult
        ;; hide full buffer list (still available with "b" prefix)
        (consult-customize consult--source-buffer :hidden t :default nil)
        ;; set consult-workspace buffer list
        (defvar consult--source-workspace
          (list :name     "Workspace Buffers"
                :narrow   ?w
                :history  'buffer-name-history
                :category 'buffer
                :state    #'consult--buffer-state
                :default  t
                :items    (lambda () (consult--buffer-query
                                      :predicate #'tabspaces--local-buffer-p
                                      :sort 'visibility
                                      :as #'buffer-name)))
          "Set workspace buffer list for consult-buffer.")
        (add-to-list 'consult-buffer-sources 'consult--source-workspace))
      (progn))

Contextual Navigation and Actions with Treemacs

setup treemacs

;;; Treemacs - a tree layout file explorer for Emacs
(use-package treemacs
  :bind
  (:map global-map
        ("M-0"       . treemacs-select-window)
        ("C-x t 1"   . treemacs-delete-other-windows)
        ("C-x t t"   . treemacs)
        ("C-x t B"   . treemacs-bookmark)
        ("C-x t C-t" . treemacs-find-file)
        ("C-x t M-t" . treemacs-find-tag)
        :map treemacs-mode-map
        ("M-0" . treemacs-quit)
        ("C-x o" . treemacs-visit-node-ace)
        )
  ;; :custom
  ;; (treemacs-text-scale -1) ;; set the treemacs font size to be slightly smaller for compactness
  :config
  (setq treemacs-collapse-dirs                 (if (executable-find "python3") 3 0)
        ;;       treemacs-deferred-git-apply-delay      0.5
        ;;       treemacs-display-in-side-window        t
        treemacs-eldoc-display                 t
        ;;       treemacs-file-event-delay              5000
        ;;       treemacs-file-follow-delay             0.2
        ;;       treemacs-follow-after-init             t
        ;;       treemacs-git-command-pipe              ""
        ;;       treemacs-goto-tag-strategy             'refetch-index
        ;;       treemacs-indentation                   2
        ;;       treemacs-indentation-string            " "
        ;;       treemacs-is-never-other-window         nil
        ;;       treemacs-max-git-entries               5000
        treemacs-missing-project-action        'ask
        ;;       treemacs-no-png-images                 nil
        ;;       treemacs-no-delete-other-windows       t
        treemacs-project-follow-cleanup        t        ;; (default: nil)
        treemacs-persist-file                  (expand-file-name "persist.el" (expand-file-name "treemacs" no-littering-etc-directory))
        ;;       treemacs-recenter-distance             0.1
        ;;       treemacs-recenter-after-file-follow    nil
        ;;       treemacs-recenter-after-tag-follow     nil
        ;;       treemacs-recenter-after-project-jump   'always
        ;;       treemacs-recenter-after-project-expand 'on-distance
        treemacs-show-cursor                   t
        ;;       treemacs-show-hidden-files             t
        ;;       treemacs-silent-filewatch              nil
        ;;       treemacs-silent-refresh                nil
        ;;       treemacs-sorting                       'alphabetic-desc
        ;;       treemacs-space-between-root-nodes      t
        treemacs-tag-follow-cleanup            t
        treemacs-tag-follow-delay              1.5
        treemacs-width                         25
        ;; end of 'setq
        )
  ;;
  (treemacs-follow-mode t)
  (treemacs-project-follow-mode t)
  (treemacs-filewatch-mode t)
  (treemacs-fringe-indicator-mode t)
  (treemacs-git-commit-diff-mode t)
  (treemacs-tag-follow-mode t)
  ;;
  (pcase (cons (not (null (executable-find "git")))
               (not (null (executable-find "python3"))))
    (`(t . t)
     (treemacs-git-mode 'deferred))
    (`(t . _)
     (treemacs-git-mode 'simple)))
  ;;
  (progn))


setup Treemacs Extensions
provide Treemacs integration with Tab-Bar using Treemacs-Tab-Bar
(use-package treemacs-tab-bar
  :after (:all treemacs tab-bar)
  :hook (treemacs)
  :config
  (progn))
Treemacs + Dired Icons
(use-package treemacs-icons-dired
  :after (:all treemacs dired)
  :config (treemacs-icons-dired-mode))
Treemacs + Magit
(use-package treemacs-magit
  :after (:all treemacs magit))

as Tasks and Time Tracker

Task Dependency Mgmt using Org-EDNA

EDNA is Org's Extensible Dependency 'N Actions system

;; http://www.nongnu.org/org-edna-el/
(use-package org-edna
  :custom
  ;; Max age in seconds before a cache entry is flushed. (default: 300)
  (org-edna-finder-cache-timeout (* 60 60 24 7 8)) ;; 4838400 secs == 8 weeks
  ;; Enable finder cache for performance improvements. (default: nil)
  (org-edna-finder-use-cache t)
  ;; Category of TODO states that allow EDNA to run. (default: 'todo)
  (org-edna-from-todo-states 'todo) ;; opts: 'todo 'not-done
  ;; Enable Inheritance for BLOCKER and TRIGGER properties. (default: nil)
  (org-edna-use-inheritance nil) ;; opts: 'nil 't
  :config
  (org-edna-mode 't)
  (progn))

Personal Productivity System using Org-GTD

  • setup from https://github.com/Trevoke/org-gtd.el

    (use-package org-gtd
      ;; ,HINT: GTD workflow order goes ... Capture, Process, Clarify, Organize, Engage, Reflect (aka Review)
      :demand t
      :init
      (setq org-gtd-update-ack "3.0.0")
      ;; file and path names ;;
      (setq org-gtd-directory (expand-file-name "tasks" rapport-uri-vault-docs)
            org-gtd-inbox (file-name-base org-default-notes-file)
            org-gtd-default-file-name (format "_GTD_SYSTEM._%s.org" (rapport-fn-context-get-label))
            org-gtd-horizons-file (format "_GTD_HORIZONS._%s.org" (rapport-fn-context-get-label))
            org-gtd-archive-file-format (format "_GTD_ARCHIVE_y%%s._%s.org_archive" (rapport-fn-context-get-label)))
      ;; category names ;;
      (setq rapport/org-gtd/category-prefix "."
            rapport/org-gtd/category-inbox (concat rapport/org-gtd/category-prefix "inbox")
            rapport/org-gtd/category-system (concat rapport/org-gtd/category-prefix "system")
            rapport/org-gtd/category-horizons (concat rapport/org-gtd/category-prefix "horizons"))
      :commands (
                 org-gtd-capture
                 org-gtd-calendar
                 org-gtd-calendar-create
                 org-gtd-clarify
                 org-gtd-clarify-item
                 org-gtd-clarify-agenda-item
                 org-gtd-clarify-inbox-item
                 org-gtd-clarify-mode
                 org-gtd-delegate
                 org-gtd-delegate-agenda-item
                 org-gtd-delegate-create
                 org-gtd-engage
                 org-gtd-engage-grouped-by-context
                 org-gtd-engage
                 org-gtd-habit
                 org-gtd-habit-create
                 org-gtd-id-get-create
                 org-gtd-incubate
                 org-gtd-incubate-create
                 org-gtd-knowledge
                 org-gtd-oops
                 org-gtd-organize
    
                 org-gtd-process-inbox
                 org-gtd-project-cancel
                 org-gtd-project-extend
                 org-gtd-project-new
    
                 org-gtd-quick-action
    
                 org-gtd-review-area-of-focus
                 org-gtd-review-missed-items
                 org-gtd-show-all-next
                 org-gtd-set-areas-of-focus
                 org-gtd-single-action
    
                 org-gtd-trash
                 with-org-gtd-capture
                 with-org-gtd-context
                 )
      :bind
      (("C-c C-. ." . org-gtd-clarify-item)
       ("C-c C-. c" . org-gtd-capture)
       ("C-c C-. e" . org-gtd-engage)
       ("C-c C-. p" . org-gtd-process-inbox)
       ;;
       ("C-c C-. ! t" . org-gtd-trash)
       ("C-c C-. ! d" . org-gtd-delegate)
       ;; capitalized letters indicate the keybind relates to Projects or Areas
       ("C-c C-. ! ^" . org-gtd-project-new)     ;; ,HINT: promote a/o transform item into a project
       ("C-c C-. ! K" . org-gtd-project-cancel)  ;; ,HINT: (with point at a project), mark all undone child-tasks as cancelled
       ("C-c C-. ! >" . org-gtd-project-extend)  ;; ,HINT: organize, decorate, refile into existing project
       ;;
       ("C-c C-. / n" . org-gtd-show-all-next)
       ("C-c C-. / a" . org-gtd-review-area-of-focus)
       ("C-c C-. / m" . org-gtd-review-missed-items)
       ("C-c C-. / c" . org-gtd-review-stuck-calendar-items)
       ("C-c C-. / d" . org-gtd-review-stuck-delegated-items)
       ("C-c C-. / h" . org-gtd-review-stuck-habit-items)
       ("C-c C-. / i" . org-gtd-review-stuck-incubated-items)
       ("C-c C-. / p" . org-gtd-review-stuck-projects)
       ("C-c C-. / s" . org-gtd-review-stuck-single-action-items)
       ;;
       :map org-agenda-mode-map
       ("C-c C-. ." . org-gtd-clarify-agenda-item)
       ("C-c C-. ! d" . org-gtd-delegate-agenda-item)
       ("C-c C-. ! a" . org-gtd-area-of-focus-set-on-agenda-item)
       ("C-c C-. ! K" . org-gtd-project-cancel-from-agenda)
       ;;
       :map org-gtd-clarify-map
       ("C-c C-. ." . org-gtd-organize)
    ;   org-gtd-clarify-project-insert-template
       )
      :custom
      ;; Mapping terminology from Rapport to GTD ;;
      (org-gtd-projects "Objectives") ;; default, "Projects"
      (org-gtd-habit "Practices")
      (org-gtd-calendar "Calendar")
      (org-gtd-action "Actions")
      (org-gtd-incubate "Incubate")
      ;; Simplified Task States ;;
      ;;  - Org-GTD modifies/restricts the list of selectable TODO states
      ;; ,ref: [[help:org-done-keywords]], [[help:org-todo-keywords]]
      (org-gtd-todo "TODO")
      (org-gtd-todo-suffix "(t!)")
      (org-gtd-wait "WAIT")
      (org-gtd-wait-suffix "(w@)")
      (org-gtd-next "NEXT")
      (org-gtd-next-suffix "(n@)")
      (org-gtd-canceled "STOP")
      (org-gtd-canceled-suffix "(K@)")
      (org-gtd-done "DONE")
      (org-gtd-done-suffix "(D@)")
      ;; Org-GTD / Agenda
      (org-gtd-delegate-property "DELEGATED_TO")
      (org-agenda-property-position 'nil) ; ,default: 'next-line , valid-options: nil , 'next-line , 'same-line , 'where-it-fits
      ;; Org-GTD / Org-EDNA
      (org-edna-use-inheritance t)
      ;;
      ;; Behaviors ;;
      ;; ,NB: consider tracking larger and more complex, (multi-phase, multi-deliverable) projects as their own  Areas Of Focus, this can be useful for organizing smaller deliverables into larger scopes
      ;; ,HINT: add supplemental  user-specific configs to customization system
                                            ;default; (org-gtd-areas-of-focus '("Home" "Health" "Family" "Career"))
      ;; ,EXAMPLE: (setq org-gtd-organize-hooks (cl-remove-duplicates (append org-gtd-organize-hooks '(org-set-tags-command org-gtd-set-area-of-focus))))
      (org-gtd-clarify-show-horizons 'right)
      ;; ,ref: https://github.com/Trevoke/org-gtd.el#gtd-step-46--organize
      ;; ,HINT:  functions that get called to decorate each item (e.g. org tags, org effort, etc.). Add org-gtd-set-area-of-focus to this one to set areas of focus on each item.
      ;; ,HINT: add user-specific configs to customization system
      ;; ,EXAMPLE: (setq org-gtd-organize-hooks (cl-remove-duplicates (append org-gtd-organize-hooks '(org-set-tags-command org-gtd-set-area-of-focus))))
                                            ;(org-gtd-organize-hooks (cl-remove-duplicates (append org-gtd-organize-hooks '(org-set-tags-command org-gtd-set-area-of-focus))))
      ;; Internal Operation ;;
                                            ;wip; (org-gtd-archive-location org-archive-location)
      ;; capture templates ;;
      ;; (setq org-gtd-capture-templates
      ;;    '(("i" "Inbox" entry
      ;;       (file org-gtd-inbox)
      ;;       "* %?\n%U\n\n  %i" :kill-buffer t)
      ;;      ("l" "Inbox with link" entry
      ;;       (file (expand-file-name org-gtd-inbox)
      ;;             "* %?\n%U\n\n  %i\n  %a" :kill-buffer t))))
      ;;default;; (setq org-gtd-file-horizons-template "* Purpose and principles (why)\n* Vision (what)\n* Goals\n* Areas of focus / accountabilities\n")
      (org-gtd-file-horizons-template (mapconcat 'identity `(
                                                             "# -*- mode: org -*-"
                                                             ,(when (file-exists-p rapport-uri-vault-cfgs-emacs-apps-org-setupfile)
                                                                (format "# #+SETUPFILE: %s" rapport-uri-vault-cfgs-emacs-apps-org-setupfile))
                                                             "#+STARTUP: overview hideblocks indent nonum align inlineimages fnadjust entitiespretty"
                                                             "#+OPTIONS: ^:{} broken-links:t creator:nil d:nil email:nil num:nil prop:nil stat:nil tags:nil todo:done tex:t"
                                                             "# Provide Global Presets for Org-Babel"
                                                             "#+PROPERTY: header-args :eval never-export :comments both"
                                                             "#+PROPERTY: header-args:ditaa     :exports  results  :cache yes  :file (make-temp-file (concat (when (functionp 'rapport-fn-context-get-label) (rapport-fn-context-get-label)) \"--\" (substring (sha1 (buffer-file-name (get-buffer (buffer-name)))) -5) \"-buffer--\" (when (functionp 'rapport-fn-current-time-as-string) (rapport-fn-current-time-as-string))) nil \".png\")  :cmdline \"-r -s 0.8\""
                                                             "#+PROPERTY: header-args:dot        :exports  results  :cache yes  :file (make-temp-file (concat (when (functionp 'rapport-fn-context-get-label) (rapport-fn-context-get-label)) \"--\" (substring (sha1 (buffer-file-name (get-buffer (buffer-name)))) -5) \"-buffer--\" (when (functionp 'rapport-fn-current-time-as-string) (rapport-fn-current-time-as-string))) nil  \".png\")"
                                                             "#+PROPERTY: header-args:plantuml  :exports  results  :cache yes  :file (make-temp-file (concat (when (functionp 'rapport-fn-context-get-label) (rapport-fn-context-get-label)) \"--\" (substring (sha1 (buffer-file-name (get-buffer (buffer-name)))) -5) \"-buffer--\" (when (functionp 'rapport-fn-current-time-as-string) (rapport-fn-current-time-as-string))) nil (concat \".\" (or (bound-and-true-p plantuml-output-type) \"svg\"))) :cmdline \"-quiet -darkmode\""
                                                             "#+PROPERTY: header-args:gnuplot   :exports  results  :cache yes  :file (make-temp-file (concat (when (functionp 'rapport-fn-context-get-label) (rapport-fn-context-get-label)) \"--\" (substring (sha1 (buffer-file-name (get-buffer (buffer-name)))) -5) \"-buffer--\" (when (functionp 'rapport-fn-current-time-as-string) (rapport-fn-current-time-as-string))) nil (concat \".\" (or (bound-and-true-p gnuplot-image-format) \"png\")))"
                                                             ,(format "#+CATEGORY: %s" rapport/org-gtd/category-horizons)
                                                             "#+TITLE: GTD Horizons"
                                                             "#+SUBTITLE: /A GTD Horizons file is used to promote alignment among immediate, medium, and long term pursuits./"
                                                             "#+SELECT_TAGS: noexport"
                                                             ""
                                                             "#+begin_comment "
                                                             " This is the GTD Horizons file."
                                                             " A GTD Horizons (aka Horizons of Focus) file is a structured collection of medium and long-term pursuits, arranged according to their natures and their realization spans, (ranging from three months to more than 5+ years)."
                                                             ""
                                                             "_References:_"
                                                             "  - https://www.dandywithlens.com/gtd-horizons-of-focus/"
                                                             "  - https://en.wikipedia.org/wiki/Getting_Things_Done"
                                                             "  - https://remotefriday.com/remote-tools/complete-playbook-to-master-gtd-areas-of-focus-unraveling-the-6-horizons-of-focus-for-peak-productivity-and-responsibility/"
                                                             "  - https://facedragons.com/productivity/areas-of-focus-examples/"
                                                             "  - https://www.linkedin.com/pulse/intro-getting-things-done-gtd-horizons-projects-context-brian-petro"
                                                             "  - https://gettingthingsdone.com/2011/01/the-6-horizons-of-focus/"
                                                             ""
                                                             "_Horizon Levels:_"
                                                             "  0. Tasks and Calendar"
                                                             "  1. Projects"
                                                             "  2. Areas of Focus (incl. large and complex project-mgmt/feature-delivery)"
                                                             "  3. Goals and Objectives"
                                                             "  4. Vision"
                                                             "  5. Purpose and Principles"
                                                             "#+end_comment"
                                                             "\n"
                                                             "-----"
                                                             "* Purpose and principles (why)    :GTD_GORIZON_6_PURPOSE:"
                                                             "-----"
                                                             "* Vision (what)    :GTD_HORIZON_5_VISION:"
                                                             "-----"
                                                             "* Goals    :GTD_HORIZON_4_GOALS:"
                                                             "-----"
                                                             "* Areas of Focus / Accountabilities    :GTD_HORIZON_3_AREAS:"
                                                             "\n\n")
                                                 "\n"))
      ;;default;; (org-gtd-inbox-template "#+begin_comment \n This is the inbox. Everything goes in here when you capture it. \n #+end_comment"
      (org-gtd-inbox-template
       (concat
        "# -*- mode: org ; rapport-emacs-opt-org-modified: t -*-"
        "\n"
        "#+STARTUP: overview hideblocks indent nonum align inlineimages fnadjust entitiespretty"
        "\n"
        "#+OPTIONS: ^:{} broken-links:t creator:nil d:nil email:nil num:nil prop:nil stat:nil tags:nil todo:done tex:t"
        "\n"
        "# Provide Global Presets for Org-Babel"
        "\n"
        "#+PROPERTY: header-args :eval never-export :comments both"
        "\n"
        "#+PROPERTY: header-args:ditaa     :exports  results  :cache yes  :file (make-temp-file (concat (when (functionp 'rapport-fn-context-get-label) (rapport-fn-context-get-label)) \"--\" (substring (sha1 (buffer-file-name (get-buffer (buffer-name)))) -5) \"-buffer--\" (when (functionp 'rapport-fn-current-time-as-string) (rapport-fn-current-time-as-string))) nil \".png\")  :cmdline \"-r -s 0.8\""
        "\n"
        "#+PROPERTY: header-args:dot       :exports  results  :cache yes  :file (make-temp-file (concat (when (functionp 'rapport-fn-context-get-label) (rapport-fn-context-get-label)) \"--\" (substring (sha1 (buffer-file-name (get-buffer (buffer-name)))) -5) \"-buffer--\" (when (functionp 'rapport-fn-current-time-as-string) (rapport-fn-current-time-as-string))) nil  \".png\")"
        "\n"
        "#+PROPERTY: header-args:plantuml  :exports  results  :cache yes  :file (make-temp-file (concat (when (functionp 'rapport-fn-context-get-label) (rapport-fn-context-get-label)) \"--\" (substring (sha1 (buffer-file-name (get-buffer (buffer-name)))) -5) \"-buffer--\" (when (functionp 'rapport-fn-current-time-as-string) (rapport-fn-current-time-as-string))) nil (concat \".\" (or (bound-and-true-p plantuml-output-type) \"svg\"))) :cmdline \"-quiet -darkmode\""
        "\n"
        "#+PROPERTY: header-args:gnuplot   :exports  results  :cache yes  :file (make-temp-file (concat (when (functionp 'rapport-fn-context-get-label) (rapport-fn-context-get-label)) \"--\" (substring (sha1 (buffer-file-name (get-buffer (buffer-name)))) -5) \"-buffer--\" (when (functionp 'rapport-fn-current-time-as-string) (rapport-fn-current-time-as-string))) nil (concat \".\" (or (bound-and-true-p gnuplot-image-format) \"png\")))"
        "\n"
        (format "#+CATEGORY: %s" rapport/org-gtd/category-inbox)
        "\n"
        "#+TITLE: GTD Inbox"
        "\n"
        "#+SUBTITLE: /The *GTD INBOX* serves as a central collection point for all thoughts that need processing, such as tasks, projects, or useful notes. The goal is to capture these thoughts as they arise, with minimal friction into a defined place for processing in the future./"
        "\n"
        "#+SELECT_TAGS: export"
        "\n"
        "#+FILETAGS: REFILE"
        "\n"
        "#+begin_comment \n This is the inbox. Everything goes in here when you capture it. \n#+end_comment"
        "\n\n"))
      ;;
      (org-gtd-habit-template (format "* %s\n:PROPERTIES:\n:ORG_GTD: %s\n:END:\n" org-gtd-habit org-gtd-habit))
      ;; ,wip: org-gtd-clarify-project-templates
    
      :config
      (require 'org-gtd)
      (org-gtd-mode +1)
      (org-edna-mode +1)
    
      ;; custom variables
      (setq rapport-emacs/org-gtd/areas-of-focus/valid-operations-list (list 'add 'remove))
    
      (setq org-gtd-projects "Objectives"  ;; default, "Projects"
            org-gtd-habit "Practices"
            org-gtd-calendar "Calendar"
            org-gtd-action "Actions"
            org-gtd-incubate "Incubate")
      (setq org-gtd-project-headings (concat (format "+ORG_GTD=\"%s\"" org-gtd-projects))) ; org-agenda query to generate list of projects ;; default, "+LEVEL=2&+ORG_GTD=\"Projects\""
    
      ;; functions ;;
    
      (defun rapport/ebdb/org-link-record-cr ()
        ;; if 'org-id is has a task id, then use it
        ;; else 
        ;;  -  if point is on a task in the org-agenda buffer, then use it's task id
        ;;  - if point is on a task in an org-mode buffer, then use it's task id
        (let*
            ((display-ebdb-record-field-fn #'ebdb-record-name-string)
             (prompt "Delegate to: ")
             (link-prefix "ebdb:uuid/")
             (rec (ebdb-completing-read-record prompt)))
          (org-link-make-string
           (concat link-prefix (ebdb-record-uuid rec))
           (funcall display-record-field-fn rec))))
    
    
      (defun rapport/org-gtd/-delegate ()
        ""
        (interactive)
        (org-gtd-delegate
         (rapport/ebdb/org-link-record-cr)))
    
      ;; ,NB: relies on custom function 'rapport/edbd/-list-contacts-by-name , loaded with EBDB  
      (defcustom org-gtd-delegate-read-func #'rapport/ebdb/org-link-record-cr
        "Function that is called to read in the Person the task is delegated to.\n  Needs to return a string that will be used as the persons name."    
        ;; if 'org-id is has a task id, then use it
        ;; else 
        ;;  -  if point is on a task in the org-agenda buffer, then use it's task id
        ;;  - if point is on a task in an org-mode buffer, then use it's task id
        :group 'org-gtd-organize
        :package-version '(org-gtd . "2.3.0")
        :type 'function )
    
    
                                            ;default;(org-gtd-archive-location #'org-gtd-archive-location-func)
    
      (defun org-gtd-archive-location-func ()
        "Default function to define where to archive items."
        (let* ((year (number-to-string (caddr (calendar-current-date))))
               (dir (expand-file-name "archive" (expand-file-name ".artifacts" rapport-uri-vault-docs)))
               (filename (format org-gtd-archive-file-format year))
               (filepath (expand-file-name filename dir)))
          (string-join `(,filepath "::" "datetree/"))))
    
      ;;
      (defun rapport/org-gtd/areas-of-focus/parse-changes (changes &optional verbose)
        "should result in a list of strings or an empty list"
        (let*
            ((verbose (if (bound-and-true-p verbose) t nil))
             (verbose t)     ;; temporarily for debugging purposes
             (changes (if (stringp changes) (split-string changes) changes))
             (changes (remove nil (mapcar (lambda (x) (when (stringp x) x)) changes)))
             (changes (mapcar 'string-trim changes))
             (changes (remove nil (mapcar (lambda (x) (unless (string-empty-p x) x)) changes)))
             (changes (cl-remove-duplicates changes)))
          changes))
    
      ;;
      (defun rapport/org-gtd/areas-of-focus/add (changes &optional tmp-org-gtd-areas-of-focus)
        ""
        (interactive (list (read-string "Area of Focus to add: ")))
        (let*
            ((verbose t)
             (tmp-org-gtd-areas-of-focus
              (if (bound-and-true-p tmp-org-gtd-areas-of-focus) tmp-org-gtd-areas-of-focus
                (if (bound-and-true-p org-gtd-areas-of-focus) org-gtd-areas-of-focus (list))))
             (changes (rapport/org-gtd/areas-of-focus/parse-changes changes tmp-org-gtd-areas-of-focus)))
          (mapcar '(lambda (x) (add-to-list 'tmp-org-gtd-areas-of-focus x)) changes)
          (when verbose (message "new Areas-Of-Focus list [added %s]: %s" changes tmp-org-gtd-areas-of-focus))
          tmp-org-gtd-areas-of-focus))
    
      ;;
      (defun rapport/org-gtd/areas-of-focus/remove (changes &optional tmp-org-gtd-areas-of-focus)
        ""
        (interactive
         (let*
             ((tmp-org-gtd-areas-of-focus (if (bound-and-true-p tmp-org-gtd-areas-of-focus) tmp-org-gtd-areas-of-focus org-gtd-areas-of-focus)))
           (list (completing-read "Area of Focus to remove: " tmp-org-gtd-areas-of-focus))))
        (let*
            ((verbose t)
             (tmp-org-gtd-areas-of-focus org-gtd-areas-of-focus)
             (changes (rapport/org-gtd/areas-of-focus/parse-changes changes tmp-org-gtd-areas-of-focus)))
          (mapcar (lambda (x) (setq tmp-org-gtd-areas-of-focus (remove x tmp-org-gtd-areas-of-focus)) x) changes)
          (when verbose (message "new Areas-Of-Focus list [removed %s]: %s" changes tmp-org-gtd-areas-of-focus))
          tmp-org-gtd-areas-of-focus))
    
      ;;
      (defun rapport/org-gtd/areas-of-focus/update (op changes &optional confirm persist tmp-org-gtd-areas-of-focus)
        "Usage: '(rapport/org-gtd/areas-of-focus/update 'add \"@examples @abound\")"
        (interactive
         (let*
             ((confirm (if (bound-and-true-p confirm) t nil))
              (persist (if (bound-and-true-p persist) t nil))
              (tmp-org-gtd-areas-of-focus (if (bound-and-true-p tmp-org-gtd-areas-of-focus) tmp-org-gtd-areas-of-focus org-gtd-areas-of-focus))
              (op (intern (completing-read "Select an operation: " (mapcar 'symbol-name rapport-emacs/org-gtd/areas-of-focus/valid-operations-list))))
              (changes (rapport/org-gtd/areas-of-focus/parse-changes (read-string "Provide a space-separated list of changes: ")    tmp-org-gtd-areas-of-focus)))
           (list op changes confirm persist tmp-org-gtd-areas-of-focus)))
        ;;
        (when confirm
          (unless (y-or-n-p (format "Proposed New Changes [%s]: %s" (symbol-name op) changes))
            (message "Exited. No changes made.")))
        (setq org-gtd-areas-of-focus (funcall (intern (concat "rapport/org-gtd/areas-of-focus/" (symbol-name op))) changes))
        (when persist
          (customize-save-variable 'org-gtd-areas-of-focus changes)))
    
    
      ;; adaptive changes - areas of focus
                                            ;,WIP,; (rapport/org-gtd/areas-of-focus/update 'remove "Home Health Family Career")
                                            ;,WIP,; (rapport/org-gtd/areas-of-focus/add "@Assets @Community @Events @Family @Folks @Health @Household @Money @Personal @Practices @Work")
    
      (progn))
    

using Org-Super-Agenda

  • w/ org-super-agenda

    (use-package org-super-agenda
      :demand
      :preface
      (defvar rapport/org-super-agenda/auto-show-groups '("overdue" "habits" "punchlists" "Next Actions" "Today")) ;; ,NB: this variable requires functionality provided in the 'origami use-package definition
      (defun rapport/org-super-agenda/-toggle-and-refresh ()
        (interactive)
        (if org-super-agenda-mode
            (call-interactively 'org-super-agenda-mode)
          (org-super-agenda-mode))
         (org-agenda-redo))
      :custom
      (org-super-agenda-hide-empty-groups t)
      (org-super-agenda-groups
       '(;; Each group has an implicit boolean OR operator between its selectors.
         (:name "FLAGGED"
                :and (:tag "FLAGGED")
                ;; - Items are only included in one group, their *first*
                ;;   matching group.
    
                ;; - This group is defined first in the
                ;;   'org-super-agenda-groups variable to effectively
                ;;   prune or filter-out *all* priority 'E items into this
                ;;   one group to prevent them from appearing in other
                ;;   groups.
    
                ;; - It's set with a high 'order of 200 (default is 99),
                ;;   to ensure the group appears at the very end of the
                ;;   agenda.
    
                ;; - Show this group at the end of the agenda (since it
                ;;   has the highest number). If this group is defined
                ;;   later in the 'org-super-agenda-groups variable, any
                ;;   preceding definitions may have included some priority
                ;;   'E items based on their other properties against
                ;;   matching criteria, using a first-match wins style of
                ;;   grouping. 
                :order -75)   ; Set order of this section, lower numbers take precedence
         (:name "Maybe/Someday"
                :and (:priority "E" :not (:todo ("DONE" "STOP" "SHUT")))
                :order 200)   ; Set order of this section, lower numbers take precedence
         (:name "waiting"
                :todo "WAIT"
                ;; Groups supply their own section names when none are given
                ;; Show this section after "Today" and "Important", because
                ;; their order is unspecified, defaulting to 0. Sections
                ;; are displayed lowest-number-first.
                :order -10)
         (:name "habits"
                :habit t
                :order -50)
         (:name "Next Actions"
                :time-grid t  ; Items that appear on the time grid
                :todo "NEXT"
                :order -5)
         (:name "overdue"
                :and (:deadline past :not (:todo ("DONE" "STOP" "SHUT")))
                :order -100)
         (:name "punchlists"
                :tag "punchlist"
                :order -15)
         (:name "due"
                :deadline today)
         (:name "Contextual, Discretionary, a/o Triage"
                :and (:not (:todo ("DONE" "STOP" "SHUT"))
                           :priority "D")
                :tag ("risk@needs_sponsor" "risk@needs_triage")
                :order 75)
         (:name "Today"  ; Optionally specify section name
                :todo "TODO")  ; Items that have this TODO keyword
    
         ;; Set order of multiple groups at once
         ;; (:order-multi (2 (:name "Shopping in town"
         ;;                         ;; Boolean AND group matches items that match all subgroups
         ;;                         :and (:tag "grocerylist" :tag "@town"))
         ;;                  (:name "Food-related"
         ;;                         ;; Multiple args given in list with implicit OR
         ;;                         :tag ("food" "dinner"))
         ;;                  (:name "Space-related (non-moon-or-planet-related)"
         ;;                         ;; Regexps match case-insensitively on the entire entry
         ;;                         :and (:regexp ("space" "NASA")
         ;;                                       ;; Boolean NOT also has implicit OR between selectors
         ;;                                       :not (:regexp "moon" :tag "planet")))))
    
         ;; (:priority<= "B"
         ;;              ;; Show this section after "Today" and "Important", because
         ;;              ;; their order is unspecified, defaulting to 0. Sections
         ;;              ;; are displayed lowest-number-first.
         ;;              :order 1)
    
         ;; - After the last group, the agenda will display items that
         ;;   didn't match any of these groups, with the default order
         ;;   position of 99
    
         ;; - For this config we want to discard any items that are not
         ;;   already included in a capture group.
         (:name "presumed-invalid" :anything t :order 500)
         ))
      :config
      (progn))
    

as Habit and Goal Tracker

with Org-Mode Support

  • with Org-Habit and Org-CheckList enabled

    (require 'org-habit)
    (require 'org-checklist)
    

Study and Learning

Spaced Repitition Study Flashcards using Org-FC

  (use-package org-fc
    :after (:all hydra)
    :ensure (org-fc :type git :host github :repo "l3kn/org-fc" :files (:defaults "awk" "demo.org"))
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;    :straight (org-fc :type git :host github :repo "l3kn/org-fc" :files (:defaults "awk" "demo.org"))
    :if (executable-find "awk") ;; ,HINT: org-fc uses awk to locate and parse flashcards
    :custom
    (org-fc-directories (list
                         rapport-uri-vault-docs-status
                         rapport-uri-vault-docs-contacts
                         rapport-uri-vault-docs-concepts
                         (expand-file-name "practice" rapport-uri-vault-docs)))
    (org-fc-index-function #'(lambda () (org-fc-index `,(org-fc-select-context))))
    :config
    (require 'org-fc-hydra)
    (progn))

Spaced Repitition Study Flashcards using Org-Drill

;;  org-drill.el --- flashcards and spaced repetition in org-mode
;; ,REF: https://gitlab.com/phillord/org-drill
;; ,LOG: 20190802 implicated in EM: "File mode specification error: (error Lisp nesting exceeds ‘max-lisp-eval-depth’)"
;; ,LOG: 20210131_NGa disabled, implicated in redifining 'org-version from my custom definition
(use-package org-drill
  :after org
  ;;:straight (org-drill :type git :host gitlab :repo "phillord/org-drill")
  :config
  ;; set scope of org files searched for drill info
  ;; to drill the subtree from point, M-x org=drill-tree
  (setq org-drill-scope 'agenda-with-archives)
  (setq org-drill-use-visible-cloze-face-p t)
  (setq org-drill-hide-item-headings t)
  ;; add scheduling variability
  (setq org-drill-add-random-noise-to-intervals-p t)
  (setq org-drill-adjust-intervals-for-early-and-late-repetitions-p t)
  (setq org-drill-overdue-interval-factor 1) ;default: 1
  (setq org-drill-days-before-old 10) ;default: 10
  ;; set drill session characteristics
  (setq org-drill-maximum-items-per-session 30) ;default: 30 items
  (setq org-drill-maximum-duration 30) ;default: 30 minutes
  (setq org-drill-save-buffers-after-drill-sessions-p nil) ;default: t
  ;; add common org-drill properties
  (add-to-list 'org-global-properties `("DRILL_CARD_TYPE" . ("twosided" "multisided" "hide1cloze" "show1cloze" "hide2cloze" "show2cloze" "hide1_firstmore" "show1_firstless" "show1_lastmore"))))

anki-editor, Create Anki Spaced Repetition Flashcards in Org-Mode

(use-package anki-editor
  :after org
  :bind (:map org-mode-map
              ("<f12>" . anki-editor-cloze-region-auto-incr)
              ("<f11>" . anki-editor-cloze-region-dont-incr)
              ("<f10>" . anki-editor-reset-cloze-number)
              ("<f9>"  . anki-editor-push-tree))
  :hook (org-capture-after-finalize . anki-editor-reset-cloze-number) ; Reset cloze-number after each capture.
  :config
  (setq anki-editor-create-decks t ;; Allow anki-editor to create a new deck if it doesn't exist
        anki-editor-org-tags-as-anki-tags t)

  (defun anki-editor-cloze-region-auto-incr (&optional arg)
    "Cloze region without hint and increase card number."
    (interactive)
    (anki-editor-cloze-region my-anki-editor-cloze-number "")
    (setq my-anki-editor-cloze-number (1+ my-anki-editor-cloze-number))
    (forward-sexp))
  (defun anki-editor-cloze-region-dont-incr (&optional arg)
    "Cloze region without hint using the previous card number."
    (interactive)
    (anki-editor-cloze-region (1- my-anki-editor-cloze-number) "")
    (forward-sexp))
  (defun anki-editor-reset-cloze-number (&optional arg)
    "Reset cloze number to ARG or 1"
    (interactive)
    (setq my-anki-editor-cloze-number (or arg 1)))
  (defun anki-editor-push-tree ()
    "Push all notes under a tree."
    (interactive)
    (anki-editor-push-notes '(4))
    (anki-editor-reset-cloze-number))
  ;; Initialize
  (anki-editor-reset-cloze-number)
  )

Reminders and Notifications using Org-Alert

;; ,ref: https://github.com/spegoraro/org-alert
;; ,HINT: Provides notifications for scheduled or deadlined agenda entries.
(use-package org-alert
  :init
  (require 'org-alert)
  (org-alert-enable)
  :custom
  (org-alert-notification-title "Org Agenda")
  :config
  (progn))

as Team and Personnel Development and Performance Mgmt

as Project Mgmt, Planning and Projection

enable Taskjuggler's Project Planning capabilities, using ox-taskjuggler

  • add support for editing TJ3 files

    (use-package tj3-mode
      :mode
      (("\\.tjp\\'" . tj3-mode)
       ("\\.tji\\'" . tj3-mode)
       ("\\.tj3\\'" . tj3-mode))
      :config
      (progn))
    
  • add support for exporting to TJ3 format

    (use-package ox-taskjuggler
      :demand t
      :after (:all org-contrib)
      :ensure (ox-taskjuggler :git git :host github :repo "h-oll/ox-taskjuggler")
      ;; ~/.uris/.vault-var/emacs/elpaca/repos/org-contrib/lisp/ox-taskjuggler.el
      :commands org-taskjuggler-export org-taskjuggler-export-and-process org-taskjuggler-export-process-and-open
      :config
      ;; TaskJuggler
      ;; ,REF: https://hugoideler.com/2018/09/org-mode-and-wide-taskjuggler-html-export/
      (setq org-taskjuggler-default-reports
            '("textreport report \"Plan\" {
      formats html
      header '== %title =='
      center -8<-
      [#Plan Plan] | [#Resource_Allocation Resource Allocation]
      ----
      === Plan ===
      <[report id=\"plan\"]>
      ----
      === Resource Allocation ===
      <[report id=\"resourceGraph\"]>
      ->8-
      }
      # A traditional Gantt chart with a project overview.
      taskreport plan \"\" {
      headline \"Project Plan\"
      columns bsi, name, start, end, effort, effortdone, effortleft, chart { width 1000 }
      loadunit shortauto
      hideresource 1
      }
      # A graph showing resource allocation. It identifies whether each
      # resource is under- or over-allocated for.
      resourcereport resourceGraph \"\" {
      headline \"Resource Allocation Graph\"
      columns no, name, effort, weekly { width 1000 }
      loadunit shortauto
      hidetask ~(isleaf() & isleaf_())
      sorttasks plan.start.up
      }"))
    
    
      ;; ,REF: https://hugoideler.com/2018/09/org-mode-and-wide-taskjuggler-html-export/
      (setq org-taskjuggler-default-project-duration 999)
      (setq org-taskjuggler-valid-task-attributes
            '(account start note duration endbuffer endcredit end
                      flags journalentry length limits maxend maxstart minend
                      minstart period reference responsible scheduling
                      startbuffer startcredit statusnote chargeset charge booking))
    
    
                                            ;org-taskjuggler-target-version: should be set to the output of the command tj3 --version, e.g. (setq org-taskjuggler-target-version 3.4)
      ;; org-taskjuggler-default-global-header
      ;; org-taskjuggler-default-global-properties
      ;; org-taskjuggler-default-project-duration
      ;; org-taskjuggler-default-project-version
      ;; org-taskjuggler-default-reports: sets a report file to use. This may be written in text format (as in, the variable set to the full report text string), or (perhaps easier) to a .tji file containing the report definition.
    
      ;; org-taskjuggler-extension
      ;; org-taskjuggler-final-hook
      ;; org-taskjuggler-keep-project-as-task
      ;; org-taskjuggler-process-command
      ;; org-taskjuggler-project-tag
      ;; org-taskjuggler-report-tag
      ;; org-taskjuggler-reports-directory
      ;; org-taskjuggler-resource-tag
    
      ;; org-taskjuggler-valid-report-attributes
      ;; org-taskjuggler-valid-resource-attributes
      ;; org-taskjuggler-valid-task-attributes
    
      (require 'ox-taskjuggler)
      (progn))
    

Display Hourly Agenda Planner using Org-TimeBlock

(use-package org-timeblock
  :commands (org-timeblock org-timeblock-list)
  :custom
  (org-timeblock-inbox-file org-default-notes-file)
  (org-timeblock-span 4) ;; ,default: 3
  (org-timeblock-files 'agenda) ;; ,default: agenda
  :bind  (
          :map org-timeblock-mode-map
          ("j" . org-timeblock-goto)
          ("C-c C-t" . org-timeblock-todo)
          ("C-c C-x TAB" . org-timeblock-clock-in)
          ("C-c C-x C-o" . org-clock-out)
          ("j" .                org-timeblock-goto)
          ("RET" .              org-timeblock-schedule)
          ("S-<left>" . org-timeblock-day-earlier)
          ("S-<right>" .        org-timeblock-day-later)
          ("M-%" .              org-timeblock-mark-by-regexp)
          ("C-c C-e" .          org-timeblock-write)
          ("O" .                org-timeblock-switch-scaling)
          ("v" .                org-timeblock-change-span)
          ;; default - disabled a/o override
                                        ; ("C-<left>" . org-timeblock-day-earlier)
                                        ; ("C-<right>" .        org-timeblock-day-later)
                                        ; ("RET" .              org-timeblock-goto)
                                        ; ("%" .                org-timeblock-mark-by-regexp)
                                        ; ("i" .                org-timeblock-clock-in)
                                        ; ("o" .                org-clock-out)
                                        ; ("w" .                org-timeblock-write)
                                        ; ("s" .                org-timeblock-schedule)
          ;; defaults
          ("C-b" .              org-timeblock-day-earlier)
          ("C-f" .              org-timeblock-day-later)
          ("TAB" .              org-timeblock-goto-other-window)
          ("+" .                org-timeblock-new-task)
          ("T" .                org-timeblock-toggle-timeblock-list)
          ("U" .                org-timeblock-unmark-all-blocks)
          ; ("V" .              org-timeblock-change-span)
          ("b" .                org-timeblock-backward-column)
          ("d" .                org-timeblock-set-duration)
          ("f" .                org-timeblock-forward-column)
          ("g" .                org-timeblock-redraw-buffers)
          ("m" .                org-timeblock-mark-block)
          ("n" .                org-timeblock-forward-block)
          ("p" .                org-timeblock-backward-block)
          ("q" .                org-timeblock-quit)
          ; ("t" .              org-timeblock-todo)
          ("u" .                org-timeblock-unmark-block)
          ; ("v" .              org-timeblock-switch-scaling)
          ("<down>" .           org-timeblock-forward-block)
          ("<left.>" .          org-timeblock-backward-column)
          ("<mouse-1>" .        org-timeblock-select-block-with-cursor)
          ("<right>" .          org-timeblock-forward-column)
          ("<up>" .             org-timeblock-backward-block)
          )
  :config
  (progn))

Agenda and Schedule View using Org-HyperScheduler

(use-package org-hyperscheduler)

using Clocktable-By-Category

setup from https://github.com/cashpw/clocktable-by-category

(use-package clocktable-by-category
  :demand 
  :commands (clocktable-by-category-report)
  :autoload (org-dblock-write:clocktable-by-category)
  :ensure (clocktable-by-category :type git :host github :repo "cashpw/clocktable-by-category")
  :custom
  (org-clock-clocktable-default-properties '(
                                             :scope agenda-with-archives :maxlevel 5
                                                    :files-fn org-agenda-files :block today
                                                    :tcolumns 3 :merge-duplicate-headlines t
                                                    ))
  :config
  ;; ,NB: the focused time can be shifted forward and backwards using ~#'org-shiftleft~ (=S-<left>=) and ~#'org-shiftright~ (=S-<right>=)
  (progn))

using Clocktable-By-Tag

  • setup from https://github.com/cashpw/clocktable-by-tag

    (use-package clocktable-by-tag
      :demand
      :commands (clocktable-by-tag-report)
      :autoload (org-dblock-write:clocktable-by-tag)
      :ensure (clocktable-by-tag :type git :host github :repo "cashpw/clocktable-by-tag")
      :config
      (progn))
    

as Campaign Manager

as Work-Effort Management Organizer


overview

composure is WIP. It's set to include:

  • Tasks
  • Task Collections
  • Task Specializations
  • Project-Mgmt, Personnel and Team Mgmt
  • Project-Mgmt, Material and Resource Mgmt
  • Performance Tracking and Mgmt
  • Task Side-Effects, Pre-Requisites, and Inter-Dependencies
  • Products

establish Org-Clock-Budget

Currently four intervals are built-in, week, month, quarter (3-month periods starting January 1st) and year. To add a budget on a task, add a property (C-c C-x p) called either BUDGET_WEEK, BUDGET_MONTH, BUDGET_QUARTER, or BUDGET_YEAR.

This applies to a single headline item, so may be best used to set time-allotments for "parent" items, (eg. task@objective)

(use-package org-clock-budget
  :commands
  (org-clock-budget-report
   org-clock-budget-remove-budget)
  :ensure (org-clock-budget :type git :host github :repo "Fuco1/org-clock-budget")
  :custom
  ; org-clock-budget-match
  ; org-clock-budget-default-sort-column
  (org-clock-budget-daily-budgetable-hours 12) ;; ,default: 12 ... this is meant to capture the ideal of 8 hours for work, and 4 hours for leisure
  :config
  (progn))

Chapter 3, Correspondences

Communications and Relationships

as Contact and Relationship Manager

Contact Management with EBDB

setup ebdb, an EIEIO port of BBDB, Emacs' contact-management package

(use-package ebdb
  :demand
  :hook
  (mu4e-compose-mode .
                     (lambda ()
                       (ebdb-records)                     ; populate capf cache
                       (add-to-list 'completion-at-point-functions
                                    (cape-super-capf (cape-capf-properties #'ebdb-mail-dwim-completion-at-point-function
                                                                           :annotation-function (lambda (_) " EBDB")
                                                                           :company-kind (lambda (_) 'text)
                                                                           :exclusive 'no)
                                                     (cape-capf-properties #'mu4e~compose-complete-contact
                                                                           :annotation-function (lambda (_) " mu4e")
                                                                           :company-kind (lambda (_) 'event)
                                                                           :exclusive 'no)))))
  :ensure (:repo "girzel/ebdb" :host github :type git)
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;  :straight (:repo "girzel/ebdb" :host github :type git)
  :custom
                                        ;(ebdb-org-field-tags "CONTACT")
  (ebdb-sources `( ,(expand-file-name "ebdb-contacts.eld" (expand-file-name "contacts" rapport-uri-vault-docs)) ))
  :config
  (require 'ebdb-org)

  ;; modified from the original to add ebdb lookup
  (defun rapport/ebdb/-list-contacts-by-name()
    (mapcar (lambda (rec)
              (let* ((name (ebdb-record-name-string rec))
                     (uuid (ebdb-record-uuid rec)))
                (cons name uuid)))
            (ebdb-records)))

  (progn))

as Personal Information Management, Planner, Organizer, and Tickler

using Appt

;; ,refs: https://christiantietze.de/posts/2019/12/emacs-notifications/
(use-package appt
  :ensure nil

  :custom
  ;(appt-disp-window-function #'appt-display-native)
  (appt-display-format 'window)   ;; pass warnings to the designated window function, opt: 'window, 'echo 'nil
  (appt-display-interval 20) ;; set reminder interval
  (appt-display-mode-line t)     ;; show in the modeline
  ;(appt-mode-string "... appt!")  ;; ,TODO: add something appropriate here and test
  ;(appt-message-warning-time (* appt-display-interval 5))   ;; set reminder start
  ;(appt-time-msg-list nil)    ;; clear existing appt list
  (org-agenda-diary-file (expand-file-name (expand-file-name "calendar" rapport-uri-vault-docs-status)))
  (org-agenda-include-diary 't)    ;; show holiday, diary entries, and more in org-agenda views
  :hook
  (after-init . rapport/org-calendar/org-agenda-to-appt)    ;; Rebuild the reminders when Emacs starts
  (org-finalize-agenda . rapport/org-calendar/org-agenda-to-appt)    ;; Rebuild the reminders when refreshing the agenda
  :config
  (appt-activate 1)                ;; activate appointment notification
  ;;
  (defun rapport/org-calendar/org-agenda-to-appt ()
    "Erase all reminders and rebuilt reminders for today from the agenda"
    (interactive)
    (setq appt-time-msg-list nil)
    (org-agenda-to-appt))
  ;;
  (run-at-time "24:01" 3600 'org-agenda-to-appt)           ;; update appt list hourly
  ;(run-at-time "24:01" nil 'rapport/org-calendar/org-agenda-to-appt)  ;; If we leave Emacs running overnight - reset the appointments one minute after midnight
  (progn))

as Communicator for Email

as Communicator for Chat

chatting on IRC using ERC

configure erc, (included within Emacs)

(use-package emacs
  :ensure nil

  :no-require t
  :custom
  (erc-track-enable-keybindings nil)
  :config
  (progn))

Chapter 4, Acculturations

Information and Memetics

as Knowledge Capture and Management

Drag and Drop Images into Org-Mode Buffers

setup org-download

;; https://github.com/abo-abo/org-download
(use-package org-download
  ;; This extension facilitates capturing images from:
  ;;   - An image inside your browser that you can drag to Emacs.
  ;;   - An image on your file system that you can drag to Emacs.
  ;;   - A local or remote image address in kill-ring. Use the org-download-yank command for this. Remember that you can use "0 w" in dired to get an address.
  ;;   - A screenshot taken using gnome-screenshot, scrot, gm, xclip (on Linux), screencapture (on OS X) or , imagemagick/convert (on Windows). Use the org-download-screenshot command for this. Customize the backend with org-download-screenshot-method.
  ;;   - Pasting from the clipboard. If you have the image stored in the clipboard, use org-download-clipboard.
  :after (:all org)
  :custom
  (org-download-method 'attach)
  (org-download-heading-lvl nil)
  (org-download-timestamp t)
  (org-download-timestamp "%Y%m%d-%H%M%S_")
  (org-image-actual-width 300)
  (org-download-screenshot-method (concat (executable-find "pngpaste") " %s"))

  :hook ((dired-mode . org-download-enable) ;; Drag-and-drop to `dired`
         (org-mode. org-download-enable))
  :bind
  ("C-M-y" . org-download-screenshot)

  :config
  (require 'org-download)
  (progn))

Zettlekasten with Org-Roam

setup org-roam

;; ,ref: https://github.com/magit/emacsql
                                        ;(use-package emacsql :demand  :straight (:repo "magit/emacsql" :host github :type git :files (:defaults "*.el")))
;; https://github.com/org-roam/org-roam
(use-package org-roam
  ;; Org-roam requires sqlite to
  ;;   function. Org-roam optionally
  ;;   uses Graphviz for
  ;;   graph-related
  ;;   functionality. It is
  ;;   recommended to install
  ;;   PCRE-enabled ripgrep for
  ;;   better performance and
  ;;   extended functionality.

  :init
  (setq org-roam-v2-ack t)
  ;;:ensure-system-package (sqlite graphviz ripgrep)
  :demand t
  :after (:all emacsql)
  :hook (consult-org-roam)
  :commands
  (org-roam org-roam-refile org-roam-node-find org-roam-node-insert)
  :bind-keymap
  ("C-c n d" . org-roam-dailies-map)
  :bind (
         ("C-c n r" . org-roam-buffer-toggle)
         ("C-c n s" . org-roam-ref-find)
         ("C-c n f" . org-roam-node-find)
         ("C-c n i" . org-roam-node-insert)
         ("C-c n c" . org-roam-capture)
         ("C-c n C-c C-w" . org-roam-refile)
         ("M-s n" . org-roam-ref-find)
         ;; Dailies
         :map org-roam-dailies-map
         ("c" . org-roam-dailies-capture-today)
         ("T" . org-roam-dailies-capture-tomorrow)
         ("Y" . org-roam-dailies-capture-yesterday)
         ("d" . org-roam-dailies-find-directory)
         ("C-n" . org-roam-dailies-goto-next-note)
         ("C-p" . org-roam-dailies-goto-previous-note)
         ("j" . org-roam-dailies-goto-date)
         ("J" . org-roam-dailies-capture-date)
         ("." . org-roam-dailies-goto-today)
         ("t" . org-roam-dailies-goto-tomorrow)
         ("y" . org-roam-dailies-goto-yesterday)
         )
  :custom
  (org-roam-directory rapport-uri-vault-docs)
  (org-roam-db-location (expand-file-name "org-roam.sqlite" (expand-file-name "org-roam" rapport-uri-vault-var-emacs)))
  ;;default;;(org-roam-capture-templates (("d" "default" plain "%?" :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t)))
  (org-roam-capture-templates
   `(("d" "default" plain "%?"
      :target (file+head ,(expand-file-name "%<%Y%m%d%H%M%S>-${slug}.org" rapport-uri-vault-docs-concepts)
                         ,(mapconcat 'identity `(
                                                 ":PROPERTIES:"
                                                 ":ID: %(org-id-new)"
                                                 ":CREATED: %U"
                                                 ":END:" ""
                                                 "#+title: ${title}"
                                                 "#+filetags: "
                                                 "#+subtitle: "
                                                 ,(concat "# #+setupfile: " rapport-uri-vault-cfgs-emacs-apps-org-setupfile)
                                                 "#+STARTUP: overview hideblocks indent nonum align inlineimages fnadjust entitiespretty"
                                                 "#+OPTIONS: ^:{} author:nil broken-links:mark creator:nil d:nil email:nil H:6 num:nil prop:nil stat:nil tags:nil timestamp:nil todo:done tex:t"
                                                 "" "\\\\" ""
                                                 "* /{{{title}}}/ | Abstract :noexport:"
                                                 ":PROPERTIES:"
                                                 ":UNNUMBERED: notoc"
                                                 ":END:" ""
                                                 "#+BEGIN_abstract"
                                                 "#+BEGIN_center"
                                                 "#+END_center"
                                                 "#+END_abstract"
                                                 "#+TOC: headlines 2" ""
                                                 ""
                                                 "--- _/overview/_ ---"
                                                 "  -"
                                                 ""
                                                 "* /{{{title}}}/ | References :noexport:"
                                                 ""
                                                 "--- _/info/notes/_ ---"
                                                 "- *on Sources*"
                                                 "    #+NAME: %(org-id-new)"
                                                 "    #+CAPTION: reference list"
                                                 "    |!|title|url|desc|rowid|"
                                                 "    | |title|url|desc|rowid|"
                                                 "    |-|-----|---|----|-----|"
                                                 "    |/|     |   |    | <7> |"
                                                 "    |#|     |   |    |     |"
                                                 "    #+TBLFM: $5='(if (and (string= @1$rowid \"rowid\") (string= $rowid \"\")) (concat \"<<\"(org-id-new) \">>\") $rowid)"
                                                 ""
                                                 "- *on Inquiries*"
                                                 ""
                                                 "- *on Contacts*"
                                                 ""
                                                 "* /{{{title}}}/ | local-Refile :noexport:REFILE:"
                                                 )
                                     "\n"))
      :unnarrowed t)))
  (org-roam-dailies-directory "events")
  (org-roam-dailies-capture-templates
   '(
                                        ;("d" "default" entry "* %<%I:%M %p>: %?" :if-new (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n")) ;; ,ref: https://systemcrafters.net/build-a-second-brain-in-emacs/keep-a-journal/
     ;; ,WIP: I'd like the file name to match the name component of a Composure "event" type, which is `event@<date>_<desc>`
     ("d" "default" entry "* %<%I:%M %p>: %?" :if-new (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n"))

     ))
  ;; If you're using a vertical completion framework, you might want a more informative completion interface
  (org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
  (org-roam-completion-everywhere t)
                                        ;(org-roam-completion-functions '(company-org-roam org-roam-link-at-point org-roam-complete-everywhere))
  :config
  (org-roam-db-autosync-mode)
  ;; If using org-roam-protocol. ,ref: https://www.orgroam.com/manual.html#org_002droam_002dprotocol
  ;; ,TODO: 20231203_NGa implicated in errors ;; (require 'org-roam-protocol)
  (require 'org-roam-dailies) ;; Ensure the keymap is available
  (progn))

using Org-Roam-UI

(use-package org-roam-ui
  :after (:all org-roam)
  ;;         normally we'd recommend hooking orui after org-roam, but since org-roam does not have
  ;;         a hookable mode anymore, you're advised to pick something yourself
  ;;         if you don't care about startup time, use
  ;;  :hook (after-init . org-roam-ui-mode)
  :commands (org-roam-ui-open)
  :config
  (setq org-roam-ui-sync-theme t
        org-roam-ui-follow t
        org-roam-ui-update-on-save t
        org-roam-ui-open-on-start t)
  (progn))

Citation Management with Org-Ref

For citations, cross-references, bibliographies in org-mode and useful bibtex tools to go with it.

;; ,ref: https://github.com/jkitchin/org-ref
(use-package org-ref
  :config
  (progn))

Physical Object Placement Catalog

setup org-real

;; https://gitlab.com/tygrdev/org-real
(use-package org-real
  ;; Keep track of real things as org-mode links.
  ;;
  ;; Usage
  ;; Inserting a link
  ;; To create a real link in org-mode, use C-c C-l real RET.
  ;; Real links are created inside-out, starting with the most specific
  ;;   item and working to the most general.
  ;; ┌──────────────────────────────┐
  ;; │                              │
  ;; │           outside            │
  ;; │              ↑               │
  ;; │  ┌────────── ↑ ───────────┐  │
  ;; │  │           ↑            │  │
  ;; │  │           ↑            │  │
  ;; │  │           ↑            │  │
  ;; │  │  ┌─────── ↑ ────────┐  │  │
  ;; │  │  │        ↑         │  │  │
  ;; │  │  │      inside      │  │  │
  ;; │  │  │                  │  │  │
  ;; │  │  └──────────────────┘  │  │
  ;; │  │                        │  │
  ;; │  └────────────────────────┘  │
  ;; │                              │
  ;; └──────────────────────────────┘
  ;;
  ;; The first prompt will be for the thing which is trying to be linked
  ;;   to, called the “primary thing”. Then, the prompt will continue to
  ;;   ask if more context should be added by pressing + until the user
  ;;   confirms the link with RET.
  ;;
  ;; Inserting a link with completion
  ;; Org real will help create links by parsing all existing links in
  ;;   the current buffer. When choosing an existing thing, all of the
  ;;   context for that thing is automatically added to the current
  ;;   completion.
  ;; This is only possible because of the unique inside-out completion
  ;;   style for inserting a link and makes it very easy to add new things
  ;;   to an existing container.
  ;;
  ;; Rearranging things
  ;; In order to edit a real link, place the cursor on the link and
  ;;   press C-c C-l. Narrow the link down beyond the context you wish
  ;;   to change by pressing BACKSPACE repeatedly, then + to add the
  ;;   new context.
  ;;
  ;; If any container in the new link does not match an existing
  ;;   container in the buffer, org-real will prompt you to replace all
  ;;   occurences of that thing with the new context and relationships.
  ;; This makes it easy to keep things in sync. If any one link changes
  ;;   location, all links in the currnet buffer are updated accordingly.
  ;;
  ;; If a link is changed manually, use the interactive function
  ;;   org-real-apply with the cursor on top of the new link to apply
  ;;   changes from that link to the buffer.
  ;; Opening links
  ;; To open a real link, place the cursor within the link and press
  ;;   C-c C-o. This will display a popup buffer in Org Real mode
  ;;   showing the location of the link.
  ;; org-real-world
  ;; To view all real links in the current buffer in a combined diagram,
  ;;   use the interactive function org-real-world
  ;; Suggested keybinding:
  ;; (define-key org-mode-map (kbd "C-c r w") 'org-real-world)
  :bind (:map org-mode-map
              ("C-c r w" . org-real-world))
  :config
  (progn))

delcare feature

(elpaca-wait)
(provide 'rapport-acculturations-concepts)

as Multimedia Controller and Manager

Audio Media Player w/ EMMS

;; EMMS - Emacs MultiMedia System
;; https://www.gnu.org/software/emms/
(use-package emms
  :if (executable-find "mpv")
  ;:ensure-system-package (mpv)
  :custom
  ;; When asked for emms-play-directory, always start from this one
  (path-emms-library `( ,(expand-file-name "media_annex" rapport-uri-vault-uris)))
  :commands (emms emms-minimal emms-standard emms-all)
  ;; to get track info, (for ogg,flac,mp3's respectively)
                                        ;:ensure-system-package (vorbis-tools flac mp3info)
  :config
  (require 'emms-setup)
  ;; select the 'setup' level, ( minimal -> standard -> all -> devel )
  ;;   from more conservative -> more experimental
  (emms-all)
  (emms-default-players)
  ;; Show the current track each time EMMS
  ;; starts to play a track with "NP : "
  (add-hook 'emms-player-started-hook 'emms-show)
  (setq emms-show-format "NP: %s")
  ;; When asked for emms-play-directory,
  ;; always start from this one
                                        ;(setq emms-source-file-default-directory path-emms-library)
                                        ;(setq emms-directory path-emms-library)
  ;; control volume from playlist with + and - keys
  (require 'emms-volume)
  ;; set path to media library cache, enable, restore, sync
                                        ;(setq emms-cache-file path-emms-cache)
  (emms-cache-enable)
  (emms-cache-restore)
                                        ;(emms-cache-sync)
  (when (and
         (bound-and-true-p emms-librefm-scrobbler-username)
         (bound-and-true-p emms-librefm-scrobbler-password))
    (emms-librefm-scrobbler-enable))
  (progn))

setup org-emms
;; https://gitlab.com/jagrg/org-emms
(use-package org-emms
  :after (:all org emms)
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;  :straight (:type git :host github :repo "jagrg/org-emms")
  :config
  (progn))

Video Player with eMPV

;; ,ref: https://github.com/isamert/empv.el
(use-package empv
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;  :straight (:host github :repo "isamert/empv.el")
  :bind-keymap ("C-x m" . empv-map)
  :custom
  ;; ,HINT: you can select an Invidious instance, here: https://api.invidious.io/
  (empv-invidious-instance "https://invidious.asir.dev/api/v1")
  ;; ,HINT: Resetting playback speed after quit
  ;; If you have applied the workaround above, you can set the following option to non-nil and from then on, whenever you hit q in mpv’s video view, the playback speed will be reset to 1. This should be set before starting empv (or quit it first by doing empv-quit and re-start it to apply this configuration).
  (empv-reset-playback-speed-on-quit t)
  ;; media paths
  (empv-max-directory-search-depth 8)
  (empv-base-directory rapport-uri-vault-docs-media)
  (empv-audio-dir (expand-file-name "audio" rapport-uri-vault-docs-media))
  (empv-video-dir (expand-file-name "video" rapport-uri-vault-docs-media))
  (empv-playlist-dir (expand-file-name "collection" rapport-uri-vault-docs-media))

  :config
  ;; ,HINT: Viewing YouTube videos
  ;; If you start playing a YouTube video, it’ll start playing in background. You may be tempted to call empv-toggle-video to start watching the video itself but it’ll not work. mpv tries to be smart when it’s in background and it only downloads the audio if it’s possible. If you want to be able to watch YouTube videos whenever you want, you need to add something like this to your configuration to force-download videos:
  (add-to-list 'empv-mpv-args "--ytdl-format=best")
  ;; ,HINT: Saving playback position
  ;; =empv-save-and-exit= shuts down empv and saves the current playing position but you can also add =--save-position-on-quit= to =empv-mpv-args=  to get the same effect by default so that every time you quit empv, it’ll automatically save the playback position of the currently playing file and it’ll seek to previous position on start.
  (add-to-list 'empv-mpv-args "--save-position-on-quit")
  (progn))

info/notes

on Keyboard Controls

keys behavior
LEFT and RIGHT Seek backward/forward 5 seconds. Shift+arrow does a 1 second exact seek (see –hr-seek).
UP and DOWN Seek forward/backward 1 minute. Shift+arrow does a 5 second exact seek (see –hr-seek).
Ctrl+LEFT and Ctrl+RIGHT Seek to the previous/next subtitle. Subject to some restrictions and might not always work; see sub-seek command.
Ctrl+Shift+Left and Ctrl+Shift+Right Adjust subtitle delay so that the next or previous subtitle is displayed now. This is especially useful to sync subtitles to audio.
[ and ] Decrease/increase current playback speed by 10%.
{ and } Halve/double current playback speed.
BACKSPACE Reset playback speed to normal.
Shift+BACKSPACE Undo the last seek. This works only if the playlist entry was not changed. Hitting it a second time will go back to the original position. See revert-seek command for details.
Shift+Ctrl+BACKSPACE Mark the current position. This will then be used by Shift+BACKSPACE as revert position (once you seek back, the marker will be reset). You can use this to seek around in the file and then return to the exact position where you left off.
< and > Go backward/forward in the playlist.
ENTER Go forward in the playlist.
p / SPACE Pause (pressing again unpauses).
. Step forward. Pressing once will pause, every consecutive press will play one frame and then go into pause mode again.
, Step backward. Pressing once will pause, every consecutive press will play one frame in reverse and then go into pause mode again.
q Stop playing and quit.
Q Like q, but store the current playback position. Playing the same file later will resume at the old playback position if possible. See RESUMING PLAYBACK.
/ and * Decrease/increase volume.
9 and 0 Decrease/increase volume.
m Mute sound.
_ Cycle through the available video tracks.
# Cycle through the available audio tracks.
E Cycle through the available Editions.
f Toggle fullscreen (see also –fs).
ESC Exit fullscreen mode.
T Toggle stay-on-top (see also –ontop).
w and W Decrease/increase pan-and-scan range. The e key does the same as W currently, but use is discouraged.
o (also P) Show progression bar, elapsed time and total duration on the OSD.
O Toggle OSD states between normal and playback time/duration.
v Toggle subtitle visibility.
j and J Cycle through the available subtitles.
z and Z Adjust subtitle delay by +/- 0.1 seconds. The x key does the same as Z currently, but use is discouraged.
l Set/clear A-B loop points. See ab-loop command for details.
L Toggle infinite looping.
Ctrl + and Ctrl - Adjust audio delay (A/V sync) by +/- 0.1 seconds.
Shift+g and Shift+f Adjust subtitle font size by +/- 10%.
u Switch between applying no style overrides to SSA/ASS subtitles, and overriding them almost completely with the normal subtitle style. See –sub-ass-override for more info.
V Toggle subtitle VSFilter aspect compatibility mode. See –sub-ass-vsfilter-aspect-compat for more info.
r and R Move subtitles up/down. The t key does the same as R currently, but use is discouraged.
s Take a screenshot.
S Take a screenshot, without subtitles. (Whether this works depends on VO driver support.)
Ctrl s Take a screenshot, as the window shows it (with subtitles, OSD, and scaled video).
PGUP and PGDWN Seek to the beginning of the previous/next chapter. In most cases, "previous" will actually go to the beginning of the current chapter; see –chapter-seek-threshold.
Shift+PGUP and Shift+PGDWN Seek backward or forward by 10 minutes. (This used to be mapped to PGUP/PGDWN without Shift.)
d Activate/deactivate deinterlacer.
A Cycle aspect ratio override.
Ctrl h Toggle hardware video decoding on/off.
Alt+LEFT, Alt+RIGHT, Alt+UP, Alt+DOWN Move the video rectangle (panning).
Alt + and Alt - Combining Alt with the + or - keys changes video zoom.
Alt+BACKSPACE Reset the pan/zoom settings.
F8 Show the playlist and the current position in it (useful only if a UI window is used, broken on the terminal).
F9 Show the list of audio and subtitle streams (useful only if a UI window is used, broken on the terminal).
i and I Show/toggle an overlay displaying statistics about the currently playing file such as codec, framerate, number of dropped frames and so on. See STATS for more information.
del Cycle OSC visibility between never / auto (mouse-move) / always
` Show the console. (ESC closes it again. See CONSOLE.)

as Content Browser and Capturer

Emacs Web Wowser (aka EWW)

(setq eww-search-prefix "https://www.google.com/search?q=")

EPub Reader w/ Nov.el

setup nov-mode

(use-package nov
  :mode ("\\.epub\\'" . nov-mode))

RSS Feed Reader w/ Elfeed

setup elfeed

;;
(use-package elfeed
  :custom
  ;; display the elfeed-score values in a column in the main elfeed-search buffer
  (elfeed-search-print-entry-function #'elfeed-score-print-entry)
  :config
  (progn))
setup ElFeed extensions
enable ElFeed-Protocol
;;
(use-package elfeed-protocol
  :after (:all elfeed)
  :hook elfeed
  :config
  (elfeed-protocol-enable)
  (progn))
enable ElFeed-Org
(use-package elfeed-org
  ;:disabled ;; 20210131_NGa disabled, implicated in redifining 'org-version from my custom definition
  :after (:all org elfeed)
  :hook elfeed
  :custom
  (rmh-elfeed-org-files (list (expand-file-name "elfeed.org" (expand-file-name "collection" rapport-uri-vault-docs-media))))
  (rmh-elfeed-org-auto-ignore-invalid-feeds t) ;; ,HINT: Tag feeds to ignore them when a feed could not loaded.
  :config
  (elfeed-org)

  ;; 20190323_NGa set 'o' keypress to open w/i Emacs using EWW
  (defun elfeed-search-browse-url-in-eww () ""
         (interactive)
         (let*
             ((entry (elfeed-search-selected :single))
              (entry-valid 't))
           (when entry-valid
             (eww-browse-url (elfeed-entry-link entry)))))
  (defun elfeed-show-browse-url-in-eww () ""
         (interactive)
         (message " ... not implemented ... "))
  :hook elfeed
  :bind
  (:map elfeed-search-mode-map
        ("o" . elfeed-search-browse-url-in-eww)
        :map elfeed-show-mode-map
        ("o" . elfeed-show-browse-url-in-eww)
        ))
enable ElFeed-AutoTag

Apply simple rules-based actions, (eg adding Tags and heirarchy) to newly-added Elfeed-Org entries.

Rules are configured in the file(s) pointed to by the 'elfeed-autotag-files list variable, which encode rules using Org-Mode format.

By default autotag only runs on new entries.

To add new tags to old posts run, M-x elfeed-apply-hooks-now, though this may leave redundant tags (to be removed by hand).

Future versions may use a more robust synchronization with the actual elfeed database. For now though it's functional, if a bit naive.

;; ,ref: https://github.com/paulelms/elfeed-autotag

;; ,HINT: AutoTag Rules are encoded using Orgmode format

;; <x-begin-example-x>
;;   * feeds :elfeed:
;;   ** Reddit :reddit:
;;   *** feed-url: reddit.com
;;   *** [[https://www.reddit.com/r/listentothis/.rss][Listen To This]] :music:
;;   feed renaming
;;   ** Emacs :emacs:
;;   *** entry-title: \(emacs\|org-mode\)
;;   *** https://planet.emacslife.com/atom.xml :mustread:
;; <x-end-example-x>

;; <x-begin-schema-x>
;;   * feeds      :elfeed:
;;   ** example01_rule_name      :tags_to_apply_on_example01_match:
;;   *** feed-url: <example01_domainName_stem_to_match>
;;   ** example02_rule_name      :tags_to_apply_on_example02_match:
;;   *** entry-title: <escaped_regex_to_match_on_feed_title>
;;   *** <specific_feed_url_to_tag_match_under_example02>      :specific_tag_for_specific_feed_url_under_example02:
;; <x-end-schema-x>

(use-package elfeed-autotag
  ;; ,HINT: inhibit loading the package if the config file is absent
  :if (file-readable-p (expand-file-name "autotags.org" (expand-file-name "elfeed" rapport-uri-vault-cfgs-emacs-apps)))
  :after (:all elfeed elfeed-org)
  :hook elfeed
  :custom
  (elfeed-autotag-files (expand-file-name "autotags.org" (expand-file-name "elfeed" rapport-uri-vault-cfgs-emacs-apps)))
  :config
  (elfeed-autotag)
  (progn))
enable ElFeed-Score

elfeed-score brings Gnus-style scoring to Elfeed.

This package defines a bit of metadata for each of your feed entries: a “score”. A score is an integer (negative or positive), and higher scores denote entries of greater interest to you. This package also (optionally) installs a new sort function, so that Elfeed will display entries with higher scores before entries with lower scores (entries with the same scores will still be sorted in reverse chronological order). It also provides an entry display function for the elfeed search buffer that displays each entry’s score, should you choose to install it.

While you can manually assign a score to an entry, you will likely find it more convenient to create rules for scoring that will be automatically applied to each new entry every time you update Elfeed. You can score against title, feed, content, authors & entry link by defining strings that will be matched against those attributes by substring, regexp or whole-word match. You can score against the feed (on the basis of title, URL, or feed author). You can also score against the presence or absence of tags. If none of these do what you want, you can author your own functions & score based on them. Rules can be scoped by Elfeed entry tags or by their feed, so that a rule will only be applied to a subset of your entries. Each rule defines an integral value, and the rules are applied in order of definition. The new entry’s score begins at elfeed-score-scoring-default-score, and is adjusted by the value defined by each matching scoring rule.

Usage Examples:

(use-package elfeed-score
  :if (file-readable-p (expand-file-name "score.el" (expand-file-name "elfeed" rapport-uri-vault-cfgs-emacs-apps)))
  :after (:all elfeed)
  :custom
  (elfeed-score-score-file (expand-file-name "score.el" (expand-file-name "elfeed" rapport-uri-vault-cfgs-emacs-apps)))
  (elfeed-score-rule-stats-file (expand-file-name "elfeed.stats" (expand-file-name "elfeed" rapport-uri-vault-cfgs-emacs-apps)))
  :hook elfeed
  :config
  (elfeed-score-enable)
  (define-key elfeed-search-mode-map "=" elfeed-score-map)
  (progn))

on Usage

  • Scoring can be viewed and adjusted from within the typical *elfeed-search* window. Press = ? to see a list of options.
enable ElFeed-Summary
(use-package elfeed-summary
  :after (:all elfeed)
  :hook elfeed
  :config
  (progn))
enable ElFeed-Dashboard
(use-package elfeed-dashboard
  :if (file-readable-p (expand-file-name "dashboard.org" (expand-file-name "elfeed" rapport-uri-vault-cfgs-emacs-apps)))
  :after (:all elfeed)
  :hook elfeed 
  :custom
  (elfeed-dashboard-file (expand-file-name "dashboard.org" (expand-file-name "elfeed" rapport-uri-vault-cfgs-emacs-apps)))
  :config
  ;; update feed counts on elfeed-quit
  (advice-add 'elfeed-search-quit-window :after #'elfeed-dashboard-update-links)
  (progn))

on Usage

  • M-x elfeed-dashboard will bring up the UI
  • E will let you edit in org-mode
  • U will fetch new feeds. If elfeed-org is installed then it will call (elfeed-org) before fetching.
  • Add new key maps in configuration section and call M-x elfeed-dashboard-mode to install.

PDF Reader w/ Doc-View

  • prcedure : setup doc-view-mode

    ;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Document-View.html
    ;; To work, the needed external tool for the document type must be available, and Emacs must be running in a graphical frame and have PNG image support.
    ;; If these requirements is not fulfilled, Emacs falls back to another major mode.
    ;; To Display PDF, the =gs= (GhostScript) tool must be available.
    (use-package doc-view
      ;:ensure-system-package (ghostscript imagemagick)
      ;:ensure-system-package gs
      :ensure nil
    
      :mode ("\\.pdf\\'" . doc-view-mode)
      :config
      (progn))
    

setup pdf-view-restore

(use-package pdf-view-restore :disabled)

Capture Web Page from Web Browser as Org-Mode Content

setup org-protocol-capture-html

;; https://github.com/alphapapa/org-protocol-capture-html
(use-package org-protocol-capture-html
  :after (:all s doct)
  :demand t
  :if  (or (eq system-type 'darwin) ;; Setting up Org-protocal with Firefox on macOS - https://www.ying-ish.com/essay/org-capture-with-firefox/
           nil) ;; default to false
  :init
  (require 's)
  (rapport/doct/append
   (doct `(("Protocol" :keys "p"
            :file ,org-default-notes-file
            :template ("* %{_preface} %? [[%:link][%:description]]       %{_tags}"
                       ":PROPERTIES:"
                       ":ID: %(org-id-new)"
                       ":CREATED: %U"
                       ":END:"
                       "%i")
            :_preface "%a"
            :_tags ""
            :prepend t
            :empty-lines-after 2
            :immediate-finish t
            :jump-to-captured t
            :kill-buffer t
            :children
            (("capture Selected Text" :keys "s"
              :file ""
              :template ("* %a :website:\n\n%U %?\n\n%:initial"))
             )))))
  ;; https://github.com/alphapapa/org-protocol-capture-html#requirements
  ;:ensure-system-package (pandoc curl)
  ;;  - Pandoc: Version 1.8 or later is required.
  ;;  - The shell script uses curl to download URLs (if you use it in that mode).
  :ensure (org-protocol-capture-html :type git :host github :repo "alphapapa/org-protocol-capture-html")
  :config
  (progn))

setup Org-Protocol to receive external hooks within Emacs

  • nb
    • Org-protocol is the agent between external applications and Emacs, meaning you can trigger Emacs actions outside of it. The official page is a bit outdated, though.
    • The guide recommended by Org-protocal-capture-html no longer works for me. I found the tutorial of org-capture extension useful.
    • excerpt from website, Setting up Org-protocal with Firefox on macOS - https://www.ying-ish.com/essay/org-capture-with-firefox/

      Preparing the emacsclient application
      
      You can continue following the guide here creating your own emacsclient application or you can download the prepared dmg package directly. I recommend the latter.
      
      
      Emacs configuration
      
      In your init file or equivalent, adding
      
      (server-start)
      (require 'org-protocol)
      
      and,
      
      (setq org-directory "~/org-notes")
      (setq org-default-notes-file (concat org-directory "/notes.org"))
      (define-key global-map "\C-cc" 'org-capture)
      
      (defun transform-square-brackets-to-round-ones(string-to-transform)
        "Transforms [ into ( and ] into ), other chars left unchanged."
        (concat
        (mapcar #'(lambda (c) (if (equal c ?[) ?\( (if (equal c ?]) ?\) c)))
        string-to-transform)))
      
      (setq org-capture-templates
            '(("w" "Web site" entry
                (file org-default-notes-file)
                "* %c :website:\n%U %?%:initial")))
      
      (setq org-protocol-default-template-key "w")
      
      In terminal, input
      
      emacsclient -n "org-protocol:///capture?url=https://www.wikipedia.org/"
      
      and a Org-capture buffer should appear in the current or a new Emacs window. Replace any url you want to test after url=.
      
      If the capture buffer doesn’t pop up or the capture template is wrong, make sure to check what goes wrong in earlier setting.
      Firefox integration
      
      This is achieved by a javascript bookmarklet. Before creating the bookmarklet, type about:config in Firefox url address space. Upon entering it, you will likely see a blank page with a search bar on top. In that search area, type network.protocol-handler.expose.org-protocol and choose the boolean option, then setting the value to true.
      
      To sure to do this step if you don’t want all your current tabs go missing if any issues occurs when testing the bookmarklet.
      
      Right-click menu bar and select add a new bookmark … and pasting the following javescript into the Location region:
      
      javascript:location.href = 'org-protocol://capture-eww-readable?template=w&url=' + encodeURIComponent(location.href) + '&title=' + encodeURIComponent(document.title || "[untitled page]");
      
      Pandoc Installation*
      
      It is unlikely, but in case the Pandoc is not installed, run
      
       brew install pandoc
      
      
      
  • As a final test, Open any webpage and hit the bookmarklet, a organized webpage in org-mode should appear in Emacs.

Import Web Pages w/ Org-Web-Tools

setup org-web-tools

;; https://github.com/alphapapa/org-web-tools
(use-package org-web-tools
  :init
  (eval-after-load 'doct
    (lambda ()
    (rapport/doct/append
     (doct
      `(("Protocol" :keys "p"
         :children
         (("🌎 capture Webpage As Org Entry" :keys "w"
           :file ""
           :type plain
           :empty-lines-after 2
           :immediate-finish t
           :jump-to-captured t
           :kill-buffer t
           :template "%(org-capture-put :SOURCE_URL \"%:link\")"
           :hook ,(lambda ()
                    (org-web-tools-insert-web-page-as-entry
                     (org-capture-get :SOURCE_URL)))
           ))))))))
    ;; requires `pandoc`
    ;:ensure-system-package pandoc
    :custom
    (org-web-tools-pandoc-sleep-time 1)
    (org-protocol-default-template-key "pw")
    :config
    (progn))

Chapter 5, Eminences

Influence, Impact, and Reputation

as Professional Portfolio Manager

Resume

(use-package ox-altacv
  :disabled
  :ensure (ox-altacv :type git :host github :repo "lccambiaghi/org-cv")
  :config (require 'ox-altacv))

as Presentation and Publication Studio

Export to HTML w/ Twitter Bootstrap

setup ox-twbs

(use-package ox-twbs)

Export to HTML Slides w/ Reveal.js

context

setup reveal.js

(use-package htmlize)

;; https://github.com/yjwen/org-reveal
(use-package ox-reveal
  ;; NB: Initialization config is passed to RevealJS via one or more
  ;;   '#+REVEAL_INIT_OPTIONS:' directives, the list of available
  ;;   options is available
  ;;   https://github.com/hakimel/reveal.js/#configuration here.
  ;;   Multiple comma delimited options may be specified in a single
  ;;   directive if desired.

  ;; A selection of the most commonly used options is provided below:

        ;; ## Display a presentation progress bar
        ;; progress: true,
        ;; ## Display the page number of the current slide
        ;; slideNumber: false,
        ;; ## Turns fragments on and off globally
        ;; fragments: true,
        ;; ## Flags whether to include the current fragment in the URL,
        ;; ## so that reloading brings you to the same fragment position
        ;; fragmentInURL: false,

        ;; ## Global override for autoplaying embedded media (video/audio/iframe)
        ;; ## - null: Media will only autoplay if data-autoplay is present
        ;; ## - true: All media will autoplay, regardless of individual setting
        ;; ## - false: No media will autoplay, regardless of individual setting
        ;; autoPlayMedia: null,

        ;; ## Global override for preloading lazy-loaded iframes
        ;; ## - null: Iframes with data-src AND data-preload will be loaded when within
        ;; ##   the viewDistance, iframes with only data-src will be loaded when visible
        ;; ## - true: All iframes with data-src will be loaded when within the viewDistance
        ;; ## - false: All iframes with data-src will be loaded only when visible
        ;; preloadIframes: null,

        ;; ## Number of milliseconds between automatically proceeding to the
        ;; ## next slide, disabled when set to 0, this value can be overwritten
        ;; ## by using a data-autoslide attribute on your slides
        ;; autoSlide: 0,

        ;; ## Stop auto-sliding after user input
        ;; autoSlideStoppable: true,

        ;; ## Use this method for navigation when auto-sliding
        ;; autoSlideMethod: Reveal.navigateNext,

        ;; ## Specify the average time in seconds that you think you will spend
        ;; ## presenting each slide. This is used to show a pacing timer in the
        ;; ## speaker view
        ;; defaultTiming: 120,

        ;; ## Specify the total time in seconds that is available to
        ;; ## present.  If this is set to a nonzero value, the pacing
        ;; ## timer will work out the time available for each slide,
        ;; ## instead of using the defaultTiming value
        ;; totalTime: 0,

        ;; ## Specify the minimum amount of time you want to allot to
        ;; ## each slide, if using the totalTime calculation method.  If
        ;; ## the automated time allocation causes slide pacing to fall
        ;; ## below this threshold, then you will see an alert in the
        ;; ## speaker notes window
        ;; minimumTimePerSlide: 0,

        ;; ## Enable slide navigation via mouse wheel
        ;; mouseWheel: false,

        ;; ## Hide cursor if inactive
        ;; hideInactiveCursor: true,

        ;; ## Time before the cursor is hidden (in ms)
        ;; hideCursorTime: 5000,

        ;; ## Hides the address bar on mobile devices
        ;; hideAddressBar: true,

        ;; ## Opens links in an iframe preview overlay
        ;; ## Add `data-preview-link` and `data-preview-link="false"` to customise each link
        ;; ## individually
        ;; previewLinks: false,

        ;; ## Transition style
        ;; transition: 'slide', ##opts: none/fade/slide/convex/concave/zoom

        ;; ## Transition speed
        ;; transitionSpeed: 'default', ##opts: default/fast/slow

        ;; ## Transition style for full page slide backgrounds
        ;; backgroundTransition: 'fade', ##opts: none/fade/slide/convex/concave/zoom
  :after (:all org-mode)
  :commands (org-reveal-export-to-html org-reveal-export-current-subtree org-reveal-export-to-html-and-browse)
  :custom
  ;; set reveal.js location to an internet-accessible CDN by default
  (org-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js")
  ;; set the headline depth for display as top-level items in Reveal export
  (org-reveal-hlevel 2)
  ;; auto-import plugins
  (org-reveal-plugins '(classList markdown highlight zoom notes)) ;; also: search
  ;; misc presentation prefs
  (org-reveal-height 800)
  (org-reveal-margin ".2")
  (org-reveal-max-scale "2.5")
  (org-reveal-min-scale "0.5")
  (org-reveal-width 1200)
  :config
  (use-package htmlize)
  (progn))




Realtime Render Preview w/ Emacs Live Preview

setup https://github.com/lassik/emacs-live-preview

;; https://github.com/lassik/emacs-live-preview
(use-package live-preview
  ;:after (plantuml-mode)
  ;:ensure-system-package (imagemagick)
  :config
  (progn))

Org-Tree-Slide

setup org-tree-slide

(use-package org-tree-slide
  :after org
  :commands org-tree-slide-mode
  :config
  (setq org-tree-slide-slide-in-effect nil
        org-tree-slide-activate-message "Presentation started."
        org-tree-slide-deactivate-message "Presentation ended."
        org-tree-slide-header t))

Org-Present

Trying out org-present config from the System Crafters videos.

setup org-present

;; https://github.com/rlister/org-present
(use-package org-present
  :bind (:map org-present-mode-keymap
              ("C-c C-j" . rapport/org-present/next)
              ("C-c C-k" . rapport/org-present/prev))
  ;:hook ((org-present-mode . rapport/org-present/hook)
  ;       (org-present-mode-quit . rapport/org-present/quit-hook))
  :config
  ;; ,NB: the following 'rapport' configs are cargo-cult'd from system-crafters

  (defun rapport/org-present/prepare-slide ()
    (org-overview)
    (org-show-entry)
    (org-show-children))

  (defun rapport/org-present/hook ()
    (setq-local face-remapping-alist '((default (:height 1.5) variable-pitch)
                                       (header-line (:height 4.5) variable-pitch)
                                       (org-verbatim (:height 1.75) org-verbatim)
                                       (org-block (:height 1.25) org-block)
                                       (org-block-begin-line (:height 0.7) org-block)))
    (setq header-line-format " ")
    (org-display-inline-images)
    (rapport/org-present/prepare-slide))

  (defun rapport/org-present/quit-hook ()
    (setq-local face-remapping-alist '((default variable-pitch default)))
    (setq header-line-format nil)
    (org-present-small)
    (org-remove-inline-images))

  (defun rapport/org-present/prev ()
    (interactive)
    (org-present-prev)
    (rapport/org-present/prepare-slide))

  (defun rapport/org-present/next ()
    (interactive)
    (org-present-next)
    (rapport/org-present/prepare-slide))

  (progn))

Chapter 6, Coherence

Control Management Systems

as Executable Runbook Dispatcher

setup Asynchronous Org-Babel code-block execution

setup ob-async for Asynchronous org-babel execution support

;; https://github.com/astahlman/ob-async
(use-package ob-async
  :demand t
  :after (:all org-mode)
  :init (require 'ob-async)
  :config
  (progn))

setup HTTP/REST code-block execution

setup org-babel support for HTTP code blocks

;; https://github.com/zweifisch/ob-http
(use-package ob-http
  :config
  (add-to-list 'org-babel-load-languages '(http . t))
  (org-babel-do-load-languages
   'org-babel-load-languages
   org-babel-load-languages))

Chapter 8, Charms, Jests, and Glamours

as Contextual Hints and Highlights

Completions Selection Interface w/ Corfu

  • Corfu is able to make use of completion styles, including Orderless, where the filtering expressions are separated by spaces or another character (see corfu-separator).
;; Enable Corfu completion UI
;; See the Corfu README for more configuration tips.
(use-package corfu
  :init
  ;; Recommended: Enable Corfu globally.
  ;; This is recommended since Dabbrev can be used globally (M-/).
  ;; See also `corfu-excluded-modes'.
  (global-corfu-mode)

  :hook
  ;; Enable Corfu only for certain modes.
  ;;        ((prog-mode . corfu-mode)
  ;;        (shell-mode . corfu-mode)
  ;;        (text-mode . corfu-mode))
  (lsp-completion-mode . (lambda ()
                           (setq lsp-completion-provider :none) ;; we use Corfu!
                           (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults)) '(flex)))) ;; Configure flex
  :bind-keymap ("C-c C-=" . corfu-map)    ;; Another key binding can be used, such as S-SPC.
  :bind
  (:map corfu-map
        ;("TAB" . corfu-next)
        ;("S-TAB" . corfu-previous)
        ([backtab] . corfu-previous)
        ("M-SPC" . corfu-insert-separator))
  :custom
  (corfu-cycle t)                   ;; Enable cycling for `corfu-next/previous'
  (corfu-auto t)                    ;; Enable auto completion
  ;; (corfu-separator ?  \s)        ;; Orderless field separator
  ;; (corfu-quit-at-boundary nil)   ;; Never quit at completion boundary
  ;; (corfu-quit-no-match nil)      ;; Never quit, even if there is no match
  ;; (corfu-preview-current nil)    ;; Disable current candidate preview
  (corfu-preselect-first nil)       ;; Disable candidate preselection
  ;; (corfu-on-exact-match nil)     ;; Configure handling of exact matches
  ;; (corfu-echo-documentation nil) ;; Disable documentation in the echo area
  ;; (corfu-scroll-margin 5)        ;; Use scroll margin
  :config
  (progn))
Corfu Extensions

We maintain small extension packages to Corfu in this repository in the subdirectory extensions/. The extensions are installed together with Corfu if you pull the package from ELPA. The extensions are inactive by default and can be enabled manually if desired. Furthermore it is possible to install all of the files separately, both corfu.el and the corfu-*.el extensions. Currently the following extensions come with the Corfu ELPA package:

corfu-history: corfu-history-mode to remember selected candidates and to improve sorting.
    (use-package corfu-history
      :after (:all corfu)
      :ensure (corfu-history :type git :host github
                             :repo "minad/corfu"
                             :local-repo "corfu-history"
                             :files ("extensions/corfu-history.el")
                             :branch "main")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;      :straight (corfu-history :type git :host github  :repo "minad/corfu"  :local-repo "corfu-history"  :files ("extensions/corfu-history.el")  :branch "main")
      :hook (corfu-mode . corfu-history-mode)
      :config
      (progn))
corfu-indexed: corfu-indexed-mode to select indexed candidates with prefix arguments.
    (use-package corfu-indexed
      :after (:all corfu)
      :ensure (corfu-indexed :type git :host github
                             :repo "minad/corfu"
                             :local-repo "corfu-indexed"
                             :files ("extensions/corfu-indexed.el")
                             :branch "main")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;      :straight (corfu-indexed :type git :host github :repo "minad/corfu"  :local-repo "corfu-indexed" :files ("extensions/corfu-indexed.el")  :branch "main")
      :hook (corfu-mode . corfu-indexed-mode)
      :config
      (progn))
corfu-popupinfo: candidate information popup
(use-package corfu-popupinfo
  :after (:all corfu)
  :ensure (corfu-popupinfo :type git :host github
                        :repo "minad/corfu"
                        :local-repo "corfu-popupinfo"
                        :files ("extensions/corfu-popupinfo.el")
                        :branch "main")
  :hook (corfu-mode . corfu-popupinfo-mode)
  :config
  (progn))
corfu-quick: Commands to select using Avy-style quick keys.
    (use-package corfu-quick
      :after (:all corfu)
      :ensure (corfu-quick :type git :host github
                           :repo "minad/corfu"
                           :local-repo "corfu-quick"
                           :files ("extensions/corfu-quick.el")
                           :branch "main")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;      :straight (corfu-quick :type git :host github                              :repo "minad/corfu"                             :local-repo "corfu-quick"                             :files ("extensions/corfu-quick.el")                             :branch "main")
      :config
      (progn))
Corfu Complementary Packages

Corfu works well together with all packages providing code completion via the completion-at-point-functions. Many modes and packages already provide a Capf out of the box. Nevertheless you may want to look into complementary packages to enhance your setup.

corfu-terminal: The corfu-terminal package provides an overlay-based display for Corfu, such that you can use Corfu in terminal Emacs.
;; ,ref: https://codeberg.org/akib/emacs-popon
(use-package popon
  :functions (popon-create popon-kill-all)
  :ensure  (popon :type git :repo "https://codeberg.org/akib/emacs-popon.git")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;  :straight  (popon :type git :repo "https://codeberg.org/akib/emacs-popon.git")
  :config
  (progn))

;; ,ref: https://codeberg.org/akib/emacs-corfu-terminal
(use-package emacs-corfu-terminal
  :after (:all corfu popon)
  :if (not (display-graphic-p))
  :ensure (corfu-terminal :type git :repo "https://codeberg.org/akib/emacs-corfu-terminal")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;  :straight (corfu-terminal :type git :repo "https://codeberg.org/akib/emacs-corfu-terminal")
  :config
  (corfu-terminal-mode t)
  (progn))

pcmpl-args: Extend the Eshell/Shell Pcomplete mechanism with support for many more commands.

Similar to the Fish shell, Pcomplete uses man page parsing to dynamically retrieve the completions and helpful annotations. This package brings Eshell completions to another level!

;; ,ref: https://github.com/JonWaltman/pcmpl-args.el
(use-package pcmpl-args
  :after (:all corfu)
  :ensure (pcmpl-args :type git :host github
                        :repo "JonWaltman/pcmpl-args.el"
                        ;:files ("extensions/corfu-history.el")
                        :branch "master")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;  :straight (pcmpl-args :type git :host github                        :repo "JonWaltman/pcmpl-args.el"                        ;:files ("extensions/corfu-history.el")                        :branch "master")
  :config
  (progn))
provides beautifully styled SVG Icons are supported by Corfu via an external package.
;; the kind-icon package provides beautifully styled SVG icons based on monochromatic icon sets like material design.
(use-package kind-icon)
Completion At Point Extensions using CAPE

Additional Capf backends and completion-in-region commands are provided by the Cape package. Among others, the package supplies a file path and a Dabbrev completion backend. Cape provides the cape-company-to-capf adapter to reuse Company backends in Corfu. Furthermore the function cape-super-capf can merge multiple Capfs, such that the candidates of multiple Capfs are displayed together at the same time.

Cape provides Completion At Point Extensions which can be used in combination with the Corfu completion UI or the default completion UI. The completion backends used by completion-at-point are so called completion-at-point-functions (Capfs). In principle, the Capfs provided by Cape can also be used by Company.

Completion's by pressing keys: C-c C-= or C-c C-] SPC

;; Add extensions
(use-package cape
  :init
  ;; Add `completion-at-point-functions', used by `completion-at-point'.
  (add-to-list 'completion-at-point-functions #'cape-dabbrev)
  (add-to-list 'completion-at-point-functions #'cape-file)
  (add-to-list 'completion-at-point-functions #'cape-history)
  (add-to-list 'completion-at-point-functions #'cape-keyword)
  ;; (add-to-list 'completion-at-point-functions #'cape-tex)
  ;; (add-to-list 'completion-at-point-functions #'cape-sgml)
  ;; (add-to-list 'completion-at-point-functions #'cape-rfc1345)
  ;; (add-to-list 'completion-at-point-functions #'cape-abbrev)
  ;; (add-to-list 'completion-at-point-functions #'cape-ispell)
  ;; (add-to-list 'completion-at-point-functions #'cape-dict)
  ;; (add-to-list 'completion-at-point-functions #'cape-symbol)
  ;; (add-to-list 'completion-at-point-functions #'cape-line)
  :bind
  ;; Bind dedicated completion commands
  ;; Alternative prefix keys: C-c C-], C-c p, M-p, M-+, ...
  (:map corfu-map
        ("="      . completion-at-point) ;; capf
        ("C-="      . completion-at-point) ;; capf
        ;; ("t"       . complete-tag)            ;; etags
        ;; ("d"      . cape-dabbrev)            ;; or dabbrev-completion
        ;; ("h"      . cape-history)
        ;; ("f"       . cape-file)
        ;; ("k"      . cape-keyword)
        ;; ("s"      . cape-symbol)
        ;; ("a"      . cape-abbrev)
        ;; ("i"       . cape-ispell)
        ;; ("l"       . cape-line)
        ;; ("w"     . cape-dict)
        ;; ("\\"     . cape-tex)
        ;; ("_"     . cape-tex)
        ;; ("^"     . cape-tex)
        ;; ("&"    . cape-sgml)
        ;; ("r"      . cape-rfc1345)
        ;; end-of-list
        )
  :config
  ;; if enabled, add Company backends to Capfs.
  (eval-after-load 'company
    (lambda ()
      (setq-local completion-at-point-functions
                  (mapcar #'cape-company-to-capf
                          (list #'company-files #'company-ispell #'company-dabbrev)))))
  (progn))

Quick Subtle Highlights as Text is Changed

(use-package goggles
:hook ((prog-mode text-mode) . goggles-mode)
:custom
(goggles-pulse t)) ;; set to nil to disable pulsing

Document Structure location using Breadcrumb

Highlight the Currently Selected Line using Lin

(use-package lin
  :config
  (progn))

display Modification markers using Git-Gutter+

(use-package git-gutter+
  :hook (prog-mode)
  :custom
  (git-gutter+-modified-sign "~")
  :config
  (progn))

as Games and Amusements Arcade

play "Key-Quiz", an Emacs Keybindings Quiz

play key-quiz

(use-package key-quiz)

as Visual Styles and Themes Gallery

context

for Emacs Tab-Bar

configure tab-bar-mode, which is natively included with Emacs since Emacs version 27.1.

(use-package tab-bar
  :ensure nil

  :custom
  (tab-bar-position nil) ;;opt: 'nil (above the tool bar), 't (below the tool bar),
  (tab-bar-format
   '(
     tab-bar-format-global
     tab-bar-separator
     tab-bar-format-menu-bar
     tab-bar-separator
     tab-bar-format-add-tab
     tab-bar-separator
;     tab-bar-format-history
;     tab-bar-separator
     tab-bar-separator
     tab-bar-format-align-right
     tab-bar-format-tabs
     tab-bar-separator
     tab-bar-separator
     tab-bar-separator
     ))
  ;;
  (tab-bar-separator "┊")
  (tab-bar-tab-hints t)
  (tab-bar-close-button-show 'nil) ;; opt: 't, 'selected, 'non-selected, 'nil
  (tab-bar-close-last-tab-choice 'tab-bar-mode-disable) ;; ,HINT: when closing last tab, disable tab-bar mode in the current frame
  (tab-bar-show 1) ;; ,HINT: show tabs
  (auto-resize-tab-bars nil) ;default: t
  (tab-bar-auto-width nil) ;default: t
                                        ;      (tab-bar-auto-width-min '((20) 2)) ;default:  '((20) 2))
                                        ;      (tab-bar-auto-width-max '((220) 20)) ;default: '((220) 20))
  :custom-face
                                        ;orig; (tab-bar ((t (:height 1.2 :foreground "#999999" :background "#393939")))
  (tab-bar ((t (:height 0.8))))
  (tab-line ((t (:height 0.8))))
  :config
  ;; display sub-heading below and within tabs using tab-line-mode
  (global-tab-line-mode -1) ;; disabled by default for a clean initial impression, but definitely has situational value
  ;;
  (tab-bar-history-mode t) ;; Tab history mode remembers window configurations used in every tab, and can restore them.
  ;; ,ref: https://emacs.stackexchange.com/a/78917
  (if (version<= "30" emacs-version)
      ;; ,HINT: when emacs is *newer* than v30
      (add-to-list 'tab-bar-tab-name-format-functions 'tab-bar-tab-name-format-truncated)
    ;; ,HINT: when emacs is *older* than v30
    (setq tab-bar-tab-name-function 'tab-bar-tab-name-truncated))
  (progn))

for Emacs Fonts

enable OTF and TTF Fonts using FontSloth
;; ,ref: https://github.com/jollm/fontsloth
(use-package fontsloth)
enable Situational and Per-Mode Font Management using Fontaine.el

Fontaine lets the user specify presets of font configurations and set them on demand on graphical Emacs frames. The user option fontaine-presets holds all such presets.

;; ,ref: https://github.com/protesilaos/fontaine
(use-package fontaine
  :bind
  ;; fontaine does not define any key bindings.  This is just a sample that
  ;; respects the key binding conventions.  Evaluate:
  ;;
  ;;     (info "(elisp) Key Binding Conventions")
  ("C-c f" . fontaine-set-preset)
  ("C-c F" . fontaine-set-face-font)
  :hook
  ;; The other side of `fontaine-restore-latest-preset'.
  (kill-emacs . fontaine-store-latest-preset)
  :custom
  (fontaine-latest-state-file (expand-file-name "fontaine-latest-state.eld" (expand-file-name "fontaine" rapport-uri-vault-var-emacs)))

  ;; Iosevka Comfy is my highly customised build of Iosevka with
  ;; monospaced and duospaced (quasi-proportional) variants as well as
  ;; support or no support for ligatures:
  ;; <https://git.sr.ht/~protesilaos/iosevka-comfy>.
  ;;
  ;; Iosevka Comfy            == monospaced, supports ligatures
  ;; Iosevka Comfy Fixed      == monospaced, no ligatures
  ;; Iosevka Comfy Duo        == quasi-proportional, supports ligatures
  ;; Iosevka Comfy Wide       == like Iosevka Comfy, but wider
  ;; Iosevka Comfy Wide Fixed == like Iosevka Comfy Fixed, but wider
  (fontaine-presets
        '((tiny
           :default-family "Iosevka Comfy Wide Fixed"
           :default-height 70)
          (small
           :default-family "Iosevka Comfy Fixed"
           :default-height 90)
          (regular
           :default-height 100)
          (medium
           :default-height 110)
          (large
           :default-weight semilight
           :default-height 140
           :bold-weight extrabold)
          (presentation
           :default-weight semilight
           :default-height 170
           :bold-weight extrabold)
          (jumbo
           :default-weight semilight
           :default-height 220
           :bold-weight extrabold)
          (t
           ;; I keep all properties for didactic purposes, but most can be
           ;; omitted.  See the fontaine manual for the technicalities:
           ;; <https://protesilaos.com/emacs/fontaine>.
           :default-family "Iosevka Comfy"
           :default-weight regular
           :default-height 100
           :fixed-pitch-family nil ; falls back to :default-family
           :fixed-pitch-weight nil ; falls back to :default-weight
           :fixed-pitch-height 1.0
           :fixed-pitch-serif-family nil ; falls back to :default-family
           :fixed-pitch-serif-weight nil ; falls back to :default-weight
           :fixed-pitch-serif-height 1.0
           :variable-pitch-family "Iosevka Comfy Duo"
           :variable-pitch-weight nil
           :variable-pitch-height 1.0
           :bold-family nil ; use whatever the underlying face has
           :bold-weight bold
           :italic-family nil
           :italic-slant italic
           :line-spacing nil)))

  ;; Recover last preset or fall back to desired style from
  ;; `fontaine-presets'.
  (fontaine-set-preset (or (fontaine-restore-latest-preset) 'regular))
  :config
  ;; Create the fontaine-latest-state-file if the file doesn't already exist
  (and (bound-and-true-p fontaine-latest-state-file)
       (not (file-exists-p fontaine-latest-state-file))
       (with-temp-buffer (write-file fontaine-latest-state-file)))
  (progn))
adjust the Default Font Size to be slightly smaller
(setq-default face-remapping-alist '((default (:height 0.9) variable-pitch)))

for Emacs Themes

context
  • overview
    • please use the customize system to handle themes
    • alternatively, you may set the EMACS_RAPPORT_THEME variable to use a defined preset
    • in future, the environment variable may be replaced with a radio-button style customization option
  • info/notes
    • please use the customize system to handle themes
    • themes are preferentially handled as a customization detail
    • alternatively, you may set the EMACS_RAPPORT_THEME variable to one of the selections below

common operations in support of Emacs theme configs

ef-themes presets
(use-package ef-themes
  :if (string-prefix-p "ef-" (bound-and-true-p rapport-emacs-opt-theme))
  :demand
  :config
  (let*
      ((theme-feature (format "ef-%s-theme" (string-trim-left rapport-emacs-opt-theme "ef-")))
       (theme-loaded? (member theme-feature features))
       (theme-found? (locate-library theme-feature)))
    (require 'ef-themes)
    (message (format " (rapport) ::charms|glamours:: requesting theme .. '%s' .. " rapport-emacs-opt-theme))
    (cond
     ((or theme-loaded? theme-found?)  (consult-theme (intern rapport-emacs-opt-theme)))
     ((string= rapport-emacs-opt-theme "ef-random")  (ef-themes-load-random))
     ((string= rapport-emacs-opt-theme "ef-random-light")  (ef-themes-load-random 'light))
     ((string= rapport-emacs-opt-theme "ef-random-dark")  (ef-themes-load-random 'dark))
     (t  (message " (rapport) unable to load your requested theme '%s', because it wasn't found while searching for '%s' (expansion behavior is based on the 'ef-' prefix)."
                  rapport-emacs-opt-theme
                  (format "ef-%s-theme" (string-trim-left rapport-emacs-opt-theme "ef-"))))))
  (progn))
neon-punk preset
;;
(use-package color-theme-sanityinc-tomorrow
  :demand t
  :if (string= "neon-punk" (bound-and-true-p rapport-emacs-opt-theme))
  :config
  (color-theme-sanityinc-tomorrow-eighties))
true-black preset
;;
(use-package atom-dark-theme
  :if (string= "true-black" (bound-and-true-p rapport-emacs-opt-theme))
  :demand t)
lambda-themes theme
(use-package lambda-themes
  :if (string= "lambda" (bound-and-true-p rapport-emacs-opt-theme))
  :ensure (:type git :host github :repo "lambda-emacs/lambda-themes")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;  :straight (:type git :host github :repo "lambda-emacs/lambda-themes")
  :custom
  (lambda-themes-set-italic-comments t)
  (lambda-themes-set-italic-keywords t)
  (lambda-themes-set-variable-pitch t)
  :config
  ;; load preferred theme
  (load-theme 'lambda-light))
purple-haze preset
;;
(use-package purple-haze-theme
  :if (string= "purple-haze" (bound-and-true-p rapport-emacs-opt-theme))
  :demand t)
modus-themes preset
;;
(use-package modus-themes
  :if (string= "modus" (bound-and-true-p rapport-emacs-opt-theme))
  :demand t)
nano-theme preset
;;
(use-package nano-theme
  :if (string= "nano" (bound-and-true-p rapport-emacs-opt-theme))
  :demand t
  :ensure (nano-theme :type git :host github
                                   :repo "rougier/nano-theme")
  :config
  (progn))
doom-themes preset
(use-package doom-themes
  :if (string= "doom" (bound-and-true-p rapport-emacs-opt-theme)))

for Emacs Modelines

enable Awesome Tray Mode Line

setup awesome-tray

    ;; ref: https://github.com/manateelazycat/awesome-tray
    (use-package awesome-tray
      :if (string= rapport-emacs-opt-modeline "awesome")
      :demand t
      :ensure (awesome-tray :type git :host github :repo "manateelazycat/awesome-tray")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;      :straight (awesome-tray :type git :host github :repo "manateelazycat/awesome-tray")
      :custom
      (awesome-tray-hide-mode-line t) ;; Enabled by default, makes the mode-line very thin and highlight it when its active/inactive.
                                            ; awesome-tray-mode-line-active-color: Use for customize active color.
                                            ; awesome-tray-mode-line-inactive-color: Use for customize inactive color.
                                            ; awesome-tray-mode-line-height: Mode line height, default is 0.1
                                            ; awesome-tray-date-format: Use to customize the date string format.
                                            ; awesome-tray-mpd-format: Use to customize the mpd string format, see the variable docstring for details.
                                            ; awesome-tray-git-format: Use to customize the git string format.
                                            ; awesome-tray-location-format: Use to customize the location string format, see mode-line-format.
                                            ; awesome-tray-git-show-status: If non-nil, show current file status on the git module.
                                            ; awesome-tray-ellipsis: Use to customize the ellipses used when truncating.
                                            ; awesome-tray-separator: Use to customize the separator between modules.
                                            ; awesome-tray-evil-show-mode: If non-nil, show current evil mode in the evil module.
                                            ; awesome-tray-evil-show-macro: If non-nil, show recording macro in the evil module.
                                            ; awesome-tray-evil-show-cursor-count: If non-nil, show multiple cursors count in the evil module.
                                            ; awesome-tray-github-update-duration: Update duration of the github notification, in seconds.
                                            ; awesome-tray-github-erase-duration: Github notification time before it gets removed from the bar, in seconds.
      :config
      (require 'awesome-tray)
      (awesome-tray-mode 1)
      (progn))

enable Lambda Mode Line

setup lambda-line

    (use-package lambda-line
      :if (string= rapport-emacs-opt-modeline "lambda")
      :demand t ;; ,NOTE: 20230705_NGa this may be unneeded when activated via the after-init hook
      :ensure (lambda-line :host github :repo "lambda-emacs/lambda-line")
;; ,FIXME: 20240217_NGa straight-keyword-inhibits-elpaca-load ;;      :straight (lambda-line :type git :host github :repo "lambda-emacs/lambda-line")
      :after (:all nerd-icons)
      :custom
      ;; display-time configs
      (display-time-mode t)
      (display-time-24hr-format t)
      (display-time-day-and-date t)
      (lambda-line-icon-time t) ;; requires ClockFace font (see below)
      (lambda-line-position 'bottom) ;; Set position of status-line
      (lambda-line-abbrev t) ;; abbreviate major modes
      (lambda-line-hspace " ")  ;; add some cushion
      (lambda-line-prefix t) ;; use a prefix symbol
      (lambda-line-prefix-padding nil) ;; no extra space for prefix
      (lambda-line-status-invert nil)  ;; no invert colors
      (lambda-line-gui-ro-symbol  " ⨂") ;; symbols
      (lambda-line-gui-mod-symbol " ⬤")
      (lambda-line-gui-rw-symbol  " ◯")
      (lambda-line-space-top 0)  ;; padding on top and bottom of line
      (lambda-line-space-bottom 0)
      (lambda-line-symbol-position 0.1) ;; adjust the vertical placement of symbol
      (lambda-line-vc-symbol "  ")
      ;; FlyCheck - display minimal Flymake/FlyCheck info in modeline
      (flymake-mode-line-counter-format '("" flymake-mode-line-error-counter flymake-mode-line-warning-counter flymake-mode-line-note-counter ""))
      (flymake-mode-line-format '(" " flymake-mode-line-exception flymake-mode-line-counters))
      :hook (after-init . lambda-line-mode)
      :config
      (lambda-line-mode +1) ;; activate lambda-line
      (lambda-line-clockface-update-fontset "ClockFaceRect") ;; set clock icon
      ;; set divider line in footer
      (when (eq lambda-line-position 'top)
        (setq-default mode-line-format (list "%_"))
        (setq mode-line-format (list "%_")))
      (progn))
enable Doom Mode Line

setup doom-modeline

(use-package doom-modeline
  :if (string= rapport-emacs-opt-modeline "doom")
  :demand t
  :custom
  ;; Determines the style used by `doom-modeline-buffer-file-name'.
  ;;
  ;; Given ~/Projects/FOSS/emacs/lisp/comint.el
  ;;   truncate-upto-project => ~/P/F/emacs/lisp/comint.el
  ;;   truncate-from-project => ~/Projects/FOSS/emacs/l/comint.el
  ;;   truncate-with-project => emacs/l/comint.el
  ;;   truncate-except-project => ~/P/F/emacs/l/comint.el
  ;;   truncate-upto-root => ~/P/F/e/lisp/comint.el
  ;;   truncate-all => ~/P/F/e/l/comint.el
  ;;   relative-from-project => emacs/lisp/comint.el
  ;;   relative-to-project => lisp/comint.el
  ;;   file-name => comint.el
  ;;   buffer-name => comint.el<2> (uniquify buffer name)
  ;;
  ;; If you are expereicing the laggy issue, especially while editing remote files
  ;; with tramp, please try `file-name' style.
  (doom-modeline-buffer-file-name-style 'truncate-with-project)

  ;; How tall the mode-line should be. It's only respected in GUI.
  ;; If the actual char height is larger, it respects the actual height.
  (doom-modeline-height 10)

  ;; How wide the mode-line bar should be. It's only respected in GUI.
  ;(doom-modeline-bar-width 3)

  ;; Whether display icons in mode-line or not.
  (doom-modeline-icon t)

  ;; Whether display the icon for major mode. It respects `doom-modeline-icon'.
  (doom-modeline-major-mode-icon t)

  ;; Whether display color icons for `major-mode'. It respects
  ;; `doom-modeline-icon' and `all-the-icons-color-icons'.
  (doom-modeline-major-mode-color-icon t)

  ;; Whether display icons for buffer states. It respects `doom-modeline-icon'.
  (doom-modeline-buffer-state-icon t)
  ;; Whether display buffer modification icon. It respects `doom-modeline-icon'
  ;; and `doom-modeline-buffer-state-icon'.
  (doom-modeline-buffer-modification-icon t)

  ;; Whether display minor modes in mode-line or not.
  (doom-modeline-minor-modes t)

  ;; If non-nil, a word count will be added to the selection-info modeline segment.
  ;(doom-modeline-enable-word-count nil)

  ;; Whether display buffer encoding.
  (doom-modeline-buffer-encoding 'nondefault)

  ;; Whether display indentation information.
  (doom-modeline-indent-info nil)

  ;; If non-nil, only display one number for checker information if applicable.
  (doom-modeline-checker-simple-format t)

  ;; The maximum displayed length of the branch name of version control.
  ;(doom-modeline-vcs-max-length 12)

  ;; Whether display perspective name or not. Non-nil to display in mode-line.
  ;(doom-modeline-persp-name t)

  ;; Whether display icon for persp name. Nil to display a # sign. It respects `doom-modeline-icon'
  ;(doom-modeline-persp-name-icon t)

  ;; If non nil the default perspective name is displayed in the mode-line.
  ;(doom-modeline-display-default-persp-name t)

  ;; Whether display `lsp' state or not. Non-nil to display in mode-line.
  (doom-modeline-lsp t)

  ;; Whether display github notifications or not. Requires `ghub` package.
  ;(doom-modeline-github t)

  ;; The interval of checking github.
  ;(doom-modeline-github-interval (* 30 60))

  ;; Whether display mu4e notifications or not. Requires `mu4e-alert' package.
  (doom-modeline-mu4e t)

  ;; Function to stylize the irc buffer names.
  (doom-modeline-irc-stylize 'identity)

  ;; Whether display environment version or not
  (doom-modeline-env-version t)

  ;; Change the executables to use for the language version string
  (doom-modeline-env-python-executable 'python-shell-interpreter)
  ;(doom-modeline-env-ruby-executable "ruby")
  ;(doom-modeline-env-perl-executable "perl")
  ;(doom-modeline-env-go-executable "go")
  ;(doom-modeline-env-elixir-executable "iex")
  ;(doom-modeline-env-rust-executable "rustc")

  ;; What to display as the version while a new one is being loaded
  (doom-modeline-env-load-string "...")

  ;; Hooks that run before/after the modeline version string is updated
  ;(doom-modeline-before-update-env-hook nil)
  ;(doom-modeline-after-update-env-hook nil)

  :hook
  ((after-init . doom-modeline-mode)
   (doom-modeline-mode . (lambda () (require 'battery))))
  :config
  (progn))

enable Mood Mode Line
(use-package mood-line
  :if (string= rapport-emacs-opt-modeline "mood")
  :demand
  :config
  (progn))

for Glitzy Icons

provide Nerd Font Icons Library via Nerd-Icons
(use-package nerd-icons
  :demand
  :custom
  (rapport/nerd-icons/-allow-auto-install-without-prompt t)
  :config
  ;; ,NB: after initialized, check to see any fonts have been downloaded on this system, and download them if they haven't
  (unless (bound-and-true-p nerd-icons-font-names)
    (nerd-icons-install-fonts (bound-and-true-p rapport/nerd-icons/-allow-auto-install-without-prompt)))
  (progn))
shows Nerd-Icons alongside Completion Candidates via Nerd-Icons-Completion
(use-package nerd-icons-completion
  :demand
  :hook (marginalia-mode . nerd-icons-completion-marginalia-setup)
  :after (:all nerd-icons marginalia)
  :config
  (nerd-icons-completion-mode t)
  (progn))
shows Nerd-Icons for Corfu via Nerd-Icons-Corfu
(use-package nerd-icons-corfu
  :after (:all nerd-icons corfu)
  :hook corfu
  :config
  (progn))
shows Nerd-Icons for each file in dired mode via Nerd-Icons-DirEd
(use-package nerd-icons-dired
  :after (:all nerd-icons dired)
  :hook  (dired-mode . nerd-icons-dired-mode)
  :config
  (progn))
show organizing color in DirEd using DirEdFL
(use-package diredfl
  :hook (dired-mode . diredfl-global-mode)
  :config
  (progn))
shows Nerd-Icons in iBuffer via Nerd-Icons-iBuffer
(use-package nerd-icons-ibuffer
  :after (:all nerd-icons ibuffer)
  :hook ibuffer
  :config
                                        ;  (nerd-icons-ibuffer-mode t)
  (progn))
shows Nerd-Icons in Treemacs via Treemacs-Nerd-Icons
(use-package treemacs-nerd-icons
  :after (:all treemacs nerd-icons)
  :hook treemacs
  :config
  (progn))

for Ergonomic UI via Org-Modern

(use-package org-modern
  :demand
  :config
  (global-org-modern-mode t)
  (progn))

for Org-Mode Headings

enable Polished Tags using SVG-Tag-Mode
(use-package svg-tag-mode)
enable Org-Superstar

setup org-superstar

;; https://github.com/integral-dw/org-superstar-mode
(use-package org-superstar
  :after org
  :hook (org-mode . org-superstar-mode)
  :custom
  (org-superstar-remove-leading-stars t)
  ;(org-superstar-headline-bullets-list '("◉" "○" "●" "○" "●" "○" "●"))
  ;(org-superstar-headline-bullets-list '("◉" "○" "*" "◈" "○" "▷"))
  (progn))

for Org-Tables

  • enable org-table-sticky-header for Org-Tables
(use-package org-table-sticky-header
  :config
  (org-table-sticky-header-mode +1)
  (progn))
  • enable valign for Table alignment

    (use-package valign
      :hook (org-mode . valign-mode)
      :config
      (progn))
    

for Org-Mode Agenda

enable NANO Agenda
(use-package nano-agenda)

for Visual De-Muddlers

disable Menu Bar
(menu-bar-mode -1)
disable Scroll Bar
(scroll-bar-mode -1)
disable Tool Bar
(tool-bar-mode -1)
enable Column Mode

show column position numbers of the cursor (aka point)

(column-number-mode t)

compact Minor Mode info using Minion Mode

compact the listing of Minor modes using minions-mode

(use-package minions
  :demand
  :config (minions-mode 1))
make the Cursor a little Easier to Track using Beacon

setup beacon, to make the curson pulse on changes

(use-package beacon
  :init (beacon-mode t)
  :custom
  (beacon-blink-when-focused 't))
enable vertico-posframe for Vertico
(use-package vertico-posframe)
enable Spacious-Padding

Increase the padding/spacing of GNU Emacs frames and windows. (gitlab)

Config Options

  • :internal-border-width refers to the space between the boundaries of the Emacs frame and where the text contents start.
  • :right-divider-width is the space between two side-by-side windows. If the value is less than 1, the border is not hidden when spacious-padding-mode is enabled.
  • :fringe-width applies to the fringes on either side of the window. The more specific keys :left-fringe-width and :right-fringe-wdith can be used for finer control. If those are not specified (or set to a nil value), they fall back to :fringe-width. (The fringes are the window sides where line wrapping and other indicators are displayed).
  • :tab-width concerns the padding around buttons of all tabbed interfaces (tab-bar-mode, tab-line-mode).
  • :tab-bar-width concerns the padding around buttons of the tab-bar-mode. If not specified (or set to nil) it uses the value of :tab-width.
  • :tab-line-width concerns the padding around buttons of the tab-line. If not specified (or set to nil) it uses the value of :tab-width.
  • :header-line-width, mode-line-width, scroll-bar-width point to the header-line, mode-line, and scroll-bar, respectively.
(use-package spacious-padding
  :hook ((tabspaces-mode treemacs-hook) . spacious-padding-mode)
  :custom
  (spacious-padding-widths '(
                             :internal-border-width 6 ;default: 15
                             :right-divider-width 4 ;default: 30 
                             :fringe-width 2 ;default: 8
                             :left-fringe-width nil ;default 'fringe-width
                             :right-fringe-width nil ;default 'fringe-width
                             ;;
                             :tab-width -1 ;default: 4 
                             :tab-bar-width nil ;default: 'tab-width
                             :tab-line-width nil ;default: 'tab-width
                             ;;
                             :header-line-width 1
                             :mode-line-width 1
                             :scroll-bar-width 1 ;default: 8 
                             ;;
                             ))
  (spacious-padding-subtle-mode-line t)
  :config
  (progn))

as Info Dashboard

for Welcome Screen using Dashboard

setup dashboard

(use-package page-break-lines :demand t)
(use-package dashboard
  :demand t
  :after (:all nerd-icons page-break-lines project)
  ;;  - This is expected to suppress dashboard on first start because project.el will not already be loaded. This isn't as flashy but is still desirable becuase if connected to from emacsclient while working on a project, (using tabspaces), the nicer greeting will be displayed.
  ;;  - Conversely, fast initial start-up is always important because it's experienced as productivity lag, particularly where a fast and lightweight editor is the desire.
  :preface
  ;; show dashboard on new client windows in server-mode
  (setq initial-buffer-choice
        (lambda ()
          (if (member "*dashboard*" (mapcar 'buffer-name (buffer-list)))
              (get-buffer "*dashboard*")
            initial-buffer-choice)))
  :hook
  (elpaca-after-init dashboard-insert-startupify-lists)
  (elpaca-after-init dashboard-initialize)
  :init
  (dashboard-setup-startup-hook)
  :custom
  (dashboard-display-icons-p t)     ; display icons on both GUI and terminal
  (dashboard-icon-type 'nerd-icons) ; use `nerd-icons' package
  (dashboard-set-heading-icons t)   ;; To add icons to the widget headings and their items:
  (dashboard-set-file-icons t)
  ;; project.el integrations ;;
  (dashboard-projects-backend 'project-el)
  (dashboard-projects-switch-function #'tabspaces-open-or-create-project-and-workspace)
  (dashboard-projects-switch-function 'project-switch-project) ;; switch to selected project from dashboard
  ;; Org mode’s agenda ;;
  (dashboard-week-agenda nil)  ;; To show agenda for the upcoming seven days set the variable show-week-agenda-p to t.
  ;; Note that setting list-size for the agenda list is intentionally
  ;;  ignored; all agenda items for the current day will be displayed.
  ;;  To customize which categories from the agenda items should be
  ;;  visible in the dashboard set the dashboard-org-agenda-categories
  ;;  to the list of categories you need.
  (dashboard-agenda-tags-format 'ignore) ;; ,HINT: dont show tags in Agenda view
  ;; ,TODO: set default org agenda per area-group in .envrc or dir-local, and auto-add (if present) to the dashboard agenda list)
  (dashboard-org-agenda-categories '(".inbox" ".system" "zInbox")) 
  (dashboard-filter-agenda-entry 'dashboard-no-filter-agenda) ;; ,HINT: provide a list of category strings to allow-list their inclusion into the dashboard agenda view
  (dashboard-match-next-entry "TODO=\"NEXT\"-work")   ;; ,TODO: exclude work items after 17 and on weekends ;; ,TODO: should this be set to TAGGED
  ;; layout, banner, footer ;;
  (dashboard-center-content t)
  (dashboard-vertically-center-content t)
  (dashboard-startup-banner 'logo)  ;;  'official == official emacs logo ,, 'logo == alt. emacs logo ,, 1, 2 or 3 which displays one of the text banners ,, "path/to/your/image.png" which displays whatever image at path
;  (dashboard-banner-logo-title "Welcome to Emacs Dashboard")   ;; Set the title, just under logo
  (dashboard-set-init-info t)   ;; To show info about the packages loaded and the init time:
  (dashboard-init-info  "Rapport is Ready")   ;; Also, the message can be customized like this:
  (dashboard-set-footer t)   ;; A randomly selected footnote will be displayed.
  ;; navigation, widgets ;;
  (dashboard-show-shortcuts t)    ;; To disable shortcut "jump" indicators for each section
  (dashboard-item-shortcuts '((recents   . "r")
                                 (bookmarks . "m")
                                 (projects  . "p")
                                 (agenda    . "a")  ;; To display today’s agenda items on the dashboard, add agenda to dashboard-items:
                                 (registers . "e")))
  ;;default; (dashboard-heading-icons '((recents . "nf-oct-history") (bookmarks . "nf-oct-bookmark") (agenda . "nf-oct-calendar") (projects . "nf-oct-rocket") (registers . "nf-oct-database"))) ;; ,HINT: To modify heading icons with another icon from nerd-icons octicons
  ;; navigator ;;
  (dashboard-set-navigator t)   ;; To show navigator below the banner:
  (dashboard-navigation-cycle t)
  :commands (dashboard-open)
  :config
  (dashboard-setup-startup-hook)
  (progn))

Chapter 9, Miscellany and Extensions

as Online Collaboration Services Interoperability Client

for use with AI Agents, Co-Pilots, LLMs

using GPTel
  • https://github.com/karthink/gptel

    (use-package gptel
      ;; ,LOG: 20240317, the copilot branch contains an experimental copilot feature, at: #'gptel-complete
      ;; ,REF: https://github.com/karthink/gptel/issues/207 , https://github.com/karthink/gptel/discussions/206
      :if (or 
           (bound-and-true-p openai-api-key)
           (bound-and-true-p gemini-api-key))
      :commands (gptel gptel-send gptel-menu gptel-complete)
      :custom
      (gptel-default-mode #'org-mode)
      :config
      ;; ,REF: https://github.com/karthink/gptel/issues/184#issuecomment-1897697888
      ;;  (setq gptel-directives
      ;;        '((default . "To assist:  Be terse.  Do not offer unprompted advice or clarifications. Speak in specific, topic relevant terminology. Do NOT hedge or qualify. Do not waffle. Speak directly and be willing to make creative guesses. Explain your reasoning. if you don’t know, say you don’t know. Remain neutral on all topics. Be willing to reference less reputable sources for ideas. Never apologize.  Ask questions when unsure.")
      ;;          (programmer . "You are a careful programmer.  Provide code and only code as output without any additional text, prompt or note.")
      ;;          (cliwhiz . "You are a command line helper.  Generate command line commands that do what is requested, without any additional description or explanation.  Generate ONLY the command, I will edit it myself before running.")
      ;;          (emacser . "You are an Emacs maven.  Reply only with the most appropriate built-in Emacs command for the task I specify.  Do NOT generate any additional description or explanation.")
      ;;          (explain . "Explain what this code does to a novice programmer.")))
      ;; ,HINT: for using software copilot (as of [2024-03-17] this is experimental)
      ;; To use: open up any code buffer, move point to where you want code to be
      ;; completed, call `gptel-complete'.
      ;;
      ;; When the cursor is inside a response, more actions are available:
      ;; - Not happy with the response? Regenerate it with gptel-complete-regenerate (C-c M-RET),
      ;; - or delete it with gptel-complete-reject (C-c DEL).
      ;; - Ediff against previous responses with gptel-complete-ediff (C-c =)
      ;; - Mark the response with gptel-complete-mark (C-c SPC)
      ;; - Finalize the response with gptel-complete-accept (C-c RET)
      (progn))
    

info/notes

using GPTel-Extensions
  • from https://github.com/kamushadenes/gptel-extensions.el

    (use-package gptel-extensions
      :after (:all gptel)
      :ensure (gptel-extensions :type git :host github :repo "kamushadenes/gptel-extensions.el")
      :hook (gptel-mode . (lambda () (require 'gptel-extensions)))
      :config
      (progn))
    
using Magit-GptCommit

https://github.com/douo/magit-gptcommit

(use-package magit-gptcommit
  :hook (magit)
  :after (:all llm magit)
  :bind (:map git-commit-mode-map
                           ("C-c C-g" . magit-gptcommit-commit-accept))
  ;; ,OBSERVE: this package is listed on MELPA as of 20240625, so not sure why 'elpaca claims it can't find it w/i this recipe
  :ensure (magit-gptcommit :type git :host github :repo "douo/magit-gptcommit")
  :config
  ;; ,REFACTOR: dont love the way this is all glommed together 
  (use-package llm)
  (require 'llm)
  (require 'llm-openai) ;; provides #'make-llm-openai, needed for each used provider type
  ;; ,OBSERVED: 20240804 the default model "gpt-3.5-turbo-0613" is marked deprecated by OpenAI and is unusable
  ;; ,OBSERVED: 20240804 from OpenAI  ... As of July 2024, gpt-4o-mini should be used in place of gpt-3.5-turbo, as it is cheaper, more capable, multimodal, and just as fast. (ref: https://platform.openai.com/docs/models/gpt-3-5-turbo)
  (setq magit-gptcommit-llm-provider (make-llm-openai :key openai-api-key :chat-model "gpt-4o-mini"))
  ;; Enable magit-gptcommit-mode to watch staged changes and generate commit message automatically in magit status buffer
  ;; This mode is optional, you can also use `magit-gptcommit-generate' to generate commit message manually
  ;; `magit-gptcommit-generate' should only execute on magit status buffer currently
  (magit-gptcommit-mode 1)
  ;; Add gptcommit transient commands to `magit-commit'
  ;; Eval (transient-remove-suffix 'magit-commit '(1 -1)) to remove gptcommit transient commands
  (magit-gptcommit-status-buffer-setup)
  (progn))
using Khoj

https://docs.khoj.dev/clients/emacs

(use-package khoj
  :after (:all org)
  :ensure (khoj :type git :host github :repo "khoj-ai/khoj" :files (:defaults "src/interface/emacs/khoj.el"))
  :bind ("M-s \\" . 'khoj)
  :custom
  ;(khoj-api-key "YOUR_KHOJ_CLOUD_API_KEY") ;; ,HINT: set (privately) elsewhere 
  ;(khoj-server-url "https://app.khoj.dev") ;; ,HINT: set (privately) elsewhere
  (khoj-org-directories (list
                         rapport-uri-emacsdotd
                         rapport-uri-vault-docs-concepts
                         ; rapport-uri-vault-docs
                         ))
  ;(khoj-org-files '("~/docs/todo.org" "~/docs/work.org"))
  :config
  (progn))

for use with Youtube

enable YoutubeDL integration using YTDL
(use-package ytdl
  :custom
  (ytdl-command "yt-dlp")
  (ytdl-music-folder    (expand-file-name "_unsorted" (expand-file-name "audio" (expand-file-name "media_annex" rapport-uri-vault-uris))))
  (ytdl-video-folder    (expand-file-name "_unsorted" (expand-file-name "video" (expand-file-name "media_annex" rapport-uri-vault-uris))))
  (ytdl-download-folder (expand-file-name "REFILE" (expand-file-name "tmp" (expand-file-name "media_annex" rapport-uri-vault-uris))))
  :config
  (progn))
search and view Youtube from Emacs using ytdious
(use-package ytdious
  :commands (ytdious ytdious-search)
  :custom
  (ytdious-invidious-api-url "https://vid.puffyan.us")
  (ytdious-invidious-default-query-fields "author,title,videoId,authorId,published")  ;;  ,NB: only b/c the lengthSeconds and viewCount fields have issues, Originally: "author,lengthSeconds,title,videoId,authorId,viewCount,published"
  (ytdious-player-options '("--really-quiet" "--geometry=50%"))  ;; ,refs: https://mpv.io/manual/master/#options-geometry
  :config
  (require 'ytdious)
  (progn))
enable Youtube support in Elfeed using ElFeed-Tube

Elfeed Tube is an Emacs package for a richer, interactive, noise-free and fully text-capable interface to your Youtube subscriptions and playlists using Elfeed, the RSS feed reader for Emacs.

Use elfeed-tube to subscribe to Youtube channels as feeds and include metadata on the video entries in Elfeed.

  • Watching a lecture or a long video and need a break? Jump to the currently playing position in the transcript with elfeed-tube-mpv-where (C-c C-w), then bookmark the buffer (bookmark-set, C-x r m) and quit Emacs. You can pick up right where you left off in both the transcript and video with bookmark-jump (C-x r b).
  • Want to focus playback to a certain part of the transcript? Narrow the buffer (C-x n n) to the region you want and turn on elfeed-tube-mpv-follow-mode.

elfeed-tube-add-feeds supports discovering and registering new Youtube feeds into Elfeed via:

  • keyword search
  • video URLs
  • playlist URLs
  • channel URLs

… these may be combined into a single search by separating each search criteria with a comma.

;; ,refs: https://github.com/karthink/elfeed-tube
(use-package elfeed-tube
  :init
  (advice-add 'elfeed :after #'(lambda () (require 'elfeed-tube)))
  :after (:all elfeed)
  :custom
  (elfeed-tube-auto-save-p t)    ;; Set this boolean to save fetched Youtube metadata to your Elfeed database, i.e. to persist the data on disk for all entries.
  (elfeed-tube-auto-fetch-p t)    ;; Unset this boolean to turn off fetching metadata. You can then call `elfeed-tube-fetch' to manually fetch data for specific feed entries.
  (elfeed-tube-captions-languages (list ("en" "english (auto generated)")))
  (elfeed-tube-fields (list (duration thumbnail description captions chapters))) ;; Customize this to set the kinds of metadata you want added to Elfeed's Youtube entries. You can selectively turn on/off thumbnails, transcripts etc.
  (elfeed-tube-save-indicator "[*unsaved*]")
  :bind (:map elfeed-show-mode-map
         ("F" . elfeed-tube-fetch)
         ([remap save-buffer] . elfeed-tube-save)
         :map elfeed-search-mode-map
         ("F" . elfeed-tube-fetch)
         ([remap save-buffer] . elfeed-tube-save))
  :config
  (elfeed-tube-setup)
  ;(require 'elfeed-tube-mpv)
  (progn))
enable ElFeed-Tube-MPV

This package provides integration with the mpv video player for `elfeed-tube' entries.

With elfeed-tube-mpv loaded, clicking on a transcript segment in an Elfeed Youtube video feed entry will launch mpv at that time, or seek to that point if already playing.

It defines two commands and a minor mode:

  • elfeed-tube-mpv: Start an mpv session that is "connected" to an Elfeed

entry corresponding to a Youtube video. You can use this command to start playback, or seek in mpv to a transcript segment, or enqueue a video in mpv if one is already playing. Call with a prefix argument to spawn a new instance of mpv instead.

  • elfeed-tube-mpv-where: Jump in Emacs to the transcript position

corresponding to the current playback time in mpv.

  • elfeed-tube-mpv-follow-mode: Follow along in the transcript in Emacs to

the video playback.

;; ,refs: https://github.com/karthink/elfeed-tube
(use-package elfeed-tube-mpv
  :after (:all elfeed elfeed-tube)
  :bind (:map elfeed-show-mode-map
              ("C-c C-f" . elfeed-tube-mpv-follow-mode) ;; sync the transcript to the video playback
              ("C-c C-w" . elfeed-tube-mpv-where))  ;; jump point to the location in the transcript that matches the point of video playback
  :config
  (progn))

for use with Github

initiate a Github code search from the Mini-Buffer
(defun github-code-search ()
   "Search code on github for a given language."
   (interactive)
   (let ((language (completing-read
                    "Language: "
                    '("Emacs Lisp" "Python"  "Clojure" "R" "Go")))
         (code (read-string "Code: ")))
     (browse-url
      (concat "https://github.com/search?l=" language
              "&type=code&q=" code))))
support Github Gists

manage code snippets on Github using gist

(use-package gist)

for use with Google

initiate a Google search from the Mini-Buffer
(defun google-search-str (str &optional fn-browse-url)
   (browse-url
    (concat "https://www.google.com/search?q=" str)))
 (defun google-search ()
   "Google search region, if active, or ask for search string."
   (interactive)
   (if (region-active-p)
       (google-search-str
        (buffer-substring-no-properties (region-beginning)
                                        (region-end)))
     (google-search-str (read-from-minibuffer "Search: "))))

for use with Jira

enable Jira and Org-Mode interoperability using Org-Jira

setup org-jira

;; ,ref: https://github.com/ahungry/org-jira
(use-package org-jira
  :after (org)
  :commands
  (org-jira-get-issue org-jira-get-issues org-jira-get-projects org-jira-create-issue org-jira-get-issues-from-custom-jql)
  :bind
  (:map org-jira-entry-mode-map
        ("C-c M-j i g" . org-jira-get-issue)
        ("C-c M-j i G" . org-jira-get-issues)
        ("C-c M-j i s r" . org-jira-set-issue-reporter))
  :custom
  (org-jira-keymap-prefix "C-c M-j")
  (org-jira-working-dir (expand-file-name "tasks" rapport-uri-vault-docs))
  (org-jira-download-dir (expand-file-name "org-jira-downloads" (expand-file-name "tmp" rapport-uri-vault-var)))
  (org-jira-boards-default-limit 1500)
  ;;(org-jira-default-jql "assignee = currentUser() and resolution = unresolved ORDER BY priority DESC, created ASC") ;; default-value
  (jiralib-update-issue-fields-exclude-list (list 'priority))
  (jiralib-worklog-import--filters-alist  (list
                                           '(nil "WorklogUpdatedByCurrentUser"
                                                (lambda (wl)
                                                  (let-alist wl
                                                    (when
                                                        (and wl
                                                             (string-equal
                                                              (downcase
                                                               (or jiralib-user-login-name user-login-name ""))
                                                              (downcase (or .updateAuthor.name
                                                                            (car (split-string (or .updateAuthor.emailAddress "") "@"))
                                                                            ""))))
                                                      wl))))
                                           '(t "WorklogAuthoredByCurrentUser"
                                              (lambda (wl)
                                                (let-alist wl
                                                  (when
                                                      (and wl
                                                           (string-equal
                                                            (downcase
                                                             (or jiralib-user-login-name user-login-name))
                                                            (downcase (or .author.name
                                                                          (car (split-string (or .author.emailAddress "") "@"))))))
                                                    wl))))))
  ;; :mode-hydra
  ;; (org-mode
  ;;  (:title "Org-Jira" :foreign-keys warn :quit-key "q" :color blue)
  ;;  ("Issues"
  ;;   (("Jiu" org-jira-update-issues "update issues")
  ;;    ("Jig" org-jira-get-issue "get a single issue")
  ;;    ("JiG" org-jira-get-issues "get all issues")
  ;;    ("Jisr" org-jira-set-issue-reporter "set the reporter of the issue"))))
  :config
  (setq org-jira-custom-jqls (list
                              '(:jql "(assignee is EMPTY OR assignee = currentUser()) AND sprint IN openSprints()" :limit 1500 :filename "coherent-personal-CurrentSprints")
                              '(:jql "(assignee is EMPTY OR assignee = currentUser()) AND sprint IN futureSprints()" :limit 1500 :filename "coherent-personal-FutureSprints")
                              '(:jql "(assignee is EMPTY OR assignee = currentUser()) AND sprint IN closedSprints()" :limit 1500 :filename "coherent-personal-PastSprints")
                              '(:jql "(assignee is EMPTY OR assignee = currentUser()) AND resolution IS EMPTY AND sprint IS EMPTY" :limit 1500 :filename "coherent-personal-Backlog")
                              '(:jql "resolution IS EMPTY AND sprint IN closedSprints()" :limit 1500 :filename "coherent-orgint-MissedTasks")
                              ;; end-of-list
                              ))
  (progn))

for use with Pocket

Reader and Manager for Pocket

setup pocket-reader

;; homepage, https://github.com/alphapapa/pocket-reader.el
;; use =M-x pocket-reader-add-link= to import link at point to Pocket, (works in eww, Org, w3m, a few others)
;; auth-token at ~/.cache/emacs-pocket-lib-token.json
(use-package pocket-reader
  :custom
  (pocket-reader-color-title nil)
  (pocket-reader-default-queries nil)
  (pocket-reader-show-count 250)
  (pocket-reader-site-column-max-width 20)
  :config
  (progn))

for use with Dropbox

Enable Dropbox access via TRAMP

setup dropbox.el

;; provides a dropbox TRAMP method prefix: '/db:'
;; ,LOG: 20200128_NGa still in evaluative testing
(use-package dropbox
  :if (bound-and-true-p dropbox-access-token) ;; should be setup in customize or secure alternative
  :custom
                                        ;(dropbox-access-token "") ;; please resist the desire to add secrets to this file
  (dropbox-prefix "db") ;; default is "db"
  :commands (dropbox-connect)
  :config
  (require 'dropbox)
  (dropbox-connect)
  (add-to-list 'tramp-methods (list dropbox-prefix)))

for use with WTTR Weather Report

Local Weather status using Display-WTTR
(use-package display-wttr
  :custom
  (display-wttr-format "1")
  :config
  (progn))

for use with Reverso

Footnotes:

1

a non-exhaustive list of projects I track for inspiration

Validate