doc-view: C-j/C-k page navigation (same as pdf-tools)

This commit is contained in:
2026-09-10 12:30:45 -04:00
parent eeb77245c2
commit 9001c45e8b
4 changed files with 201 additions and 36 deletions

View File

@@ -1,4 +1,4 @@
#? Config file for btop v.1.4.6 #? Config file for btop v.1.4.7
#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes. #* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes" #* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
@@ -14,6 +14,11 @@ truecolor = true
#* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols. #* Will force 16-color mode and TTY theme, set all graph symbols to "tty" and swap out other non tty friendly symbols.
force_tty = false force_tty = false
#* Option to disable presets. Either the default preset, custom presets, or all presets.
#* "Off" All presets are enabled.
#* "Default" preset is disabled.#* "Custom" presets are disabled.#* "All" presets are disabled.
disable_presets = "Off"
#* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets. #* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets.
#* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box. #* Format: "box_name:P:G,box_name:P:G" P=(0 or 1) for alternate positions, G=graph symbol to use for box.
#* Use whitespace " " as separator between different presets. #* Use whitespace " " as separator between different presets.
@@ -24,6 +29,9 @@ presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:defaul
#* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift. #* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift.
vim_keys = true vim_keys = true
#* Disable all mouse events.
disable_mouse = false
#* Rounded corners on boxes, is ignored if TTY mode is ON. #* Rounded corners on boxes, is ignored if TTY mode is ON.
rounded_corners = true rounded_corners = true
@@ -92,6 +100,9 @@ proc_left = false
#* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop). #* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop).
proc_filter_kernel = false proc_filter_kernel = false
#* Should the process list follow the selected process when detailed view is open.
proc_follow_detailed = true
#* In tree-view, always accumulate child process resources in the parent process. #* In tree-view, always accumulate child process resources in the parent process.
proc_aggregate = true proc_aggregate = true
@@ -208,6 +219,9 @@ io_graph_combined = false
#* Example: "/mnt/media:100 /:20 /boot:1". #* Example: "/mnt/media:100 /:20 /boot:1".
io_graph_speeds = "" io_graph_speeds = ""
#* Swap the positions of the upload and download speed graphs. When true, upload will be on top.
swap_upload_download = false
#* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False. #* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False.
net_download = 100 net_download = 100
@@ -250,7 +264,7 @@ rsmi_measure_pcie_speeds = true
#* Horizontally mirror the GPU graph. #* Horizontally mirror the GPU graph.
gpu_mirror_graph = true gpu_mirror_graph = true
#* Set which GPU vendors to show. Available values are "nvidia amd intel" #* Set which GPU vendors to show. Available values are "nvidia amd intel apple"
shown_gpus = "nvidia amd intel" shown_gpus = "nvidia amd intel"
#* Custom gpu0 model name, empty string to disable. #* Custom gpu0 model name, empty string to disable.

View File

@@ -703,26 +703,27 @@ org-agenda-files (seq-uniq org-agenda-files)
(setq (setq
org-capture-templates org-capture-templates
'( '(
("t" "TODO" entry (file+olp +org-capture-todo-file "Tasks") ("t" "Tasks")
("ti" "Idea" entry (file+olp +org-capture-todo-file "Tasks")
"* IDEA %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :prepend t) "* IDEA %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :prepend t)
("c" "Code TODO" entry ("tt" "Todo" entry (file+olp +org-capture-todo-file "Tasks")
(file+olp +org-capture-todo-file "Tasks") "* TODO %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :prepend t)
"* TODO %a\n:PROPERTIES:\n:CREATED: %U\n:END:\n":prepend t) ("tw" "Wait" entry (file+olp +org-capture-todo-file "Tasks")
"* WAIT %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :prepend t)
("tp" "Task at point" entry (file+olp +org-capture-todo-file "Tasks")
"* TODO %? %a\n:PROPERTIES:\n:CREATED: %U\n:END:\n" :prepend t)
("te" "Emails")
("tef" "Follow Up" entry (file+olp +org-capture-todo-file "Tasks") "* TODO Follow up with %:fromname on %a\nSCHEDULED:%t\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("ter" "Read Later" entry (file+olp +org-capture-todo-file "Tasks") "* TODO Read: %a\nSCHEDULED:%t\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("tew" "Waiting Response" entry
(file+olp +org-capture-todo-file "Tasks") "* WAIT Waiting response from %:toname on %a\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("n" "Note" entry (file+olp +org-capture-notes-file "Notes") ("n" "Note" entry (file+olp +org-capture-notes-file "Notes")
"* %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i") "* %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i")
("w" "Question" entry (file+olp +org-capture-notes-file "Questions") ("w" "Question" entry (file+olp +org-capture-notes-file "Questions")
"* [?] %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i") "* [?] %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i")
("j" "Journal" entry (file+olp +org-capture-journal-file "Journal") ("e" "Event" entry (file+olp +org-capture-todo-file "Events")
"* %?\n%a\n%i") "* %? %^t\n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i")
("m" "Meeting" entry (file+olp +org-capture-notes-file "Meetings") ("C" "Contact" entry (file+olp +org-capture-todo-file "Contacts") "* %?\n:PROPERTIES:\n:EMAIL: %:fromemail\n:ROLE: \n:END:\n%a\n%i")
"* %? %U :meeting:\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n/Met with: /")
("a" "Appointment" entry (file+olp +org-capture-journal-file "Appointments")
"* %? :appointment:\n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :time-prompt t)
("e" "Email Workflow")
("ef" "Follow Up" entry (file+olp +org-capture-emails-file "Mails" "Follow Up") "* TODO Follow up with %:fromname on %a\nSCHEDULED:%t\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("er" "Read Later" entry (file+olp +org-capture-emails-file "Mails" "Read Later") "* TODO Read: %a\nSCHEDULED:%t\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("ew" "Waiting Response" entry
(file+olp +org-capture-emails-file "Mails" "Waiting Response") "* WAIT Waiting response from %:toname on %a\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
) )
) )
) )
@@ -1434,7 +1435,7 @@ Let me write like a broken engineer, thank you.
;; Fold bindings ;; Fold bindings
(after! evil (after! evil
(define-key evil-motion-state-map (kbd "z C") #'hs-hide-level)) (define-key evil-motion-state-map (kbd "z M") #'hs-hide-level))
;; Disable global bindings for C-j and C-k ;; Disable global bindings for C-j and C-k
(global-unset-key (kbd "C-j")) (global-unset-key (kbd "C-j"))
@@ -2394,6 +2395,10 @@ Make org task, agenda, tables look nicer, but you need to deactivate it sometime
:config :config
(global-org-modern-mode) (global-org-modern-mode)
(setq org-modern-star 'replace) (setq org-modern-star 'replace)
;; U+2733 (✳) isn't in JetBrainsMono Nerd Font -> font fallback renders it green.
;; r/emacs favorite headline list, flower ✿ swapped for hollow ◇ in level 5 (filled ◆ was too big).
;; NOTE: ✸⁖ may need font fallback in the GUI frame (JetBrainsMono Nerd lacks them).
(setq org-modern-replace-stars "⁖◉○◇✸")
(setq org-modern-todo-faces (setq org-modern-todo-faces
'( '(
;; Framework ;; Framework
@@ -2569,7 +2574,7 @@ Cordialement,
(setq mu4e-icalendar-diary-file nil) (setq mu4e-icalendar-diary-file nil)
(setq gnus-icalendar-org-capture-file +org-capture-journal-file (setq gnus-icalendar-org-capture-file +org-capture-journal-file
gnus-icalendar-org-capture-headline '("Journal")) gnus-icalendar-org-capture-headline '("Events"))
(gnus-icalendar-org-setup) (gnus-icalendar-org-setup)
@@ -2883,6 +2888,17 @@ Really useful to be able to have a buffer with notes, and another with the offic
:n "C-k" #'pdf-roll-previous-page)) :n "C-k" #'pdf-roll-previous-page))
#+end_src #+end_src
* Doc-View (docx/odt)
Same page navigation as PDF-Tools (C-j / C-k) for doc-view buffers (renders .docx/.odt via PDF).
#+begin_src emacs-lisp
(use-package! doc-view
:config
(map! :map doc-view-mode-map
:n "C-j" #'doc-view-next-page
:n "C-k" #'doc-view-previous-page))
#+end_src
* Custom functions * Custom functions
** Refile to datetree ** Refile to datetree
@@ -3803,6 +3819,67 @@ Optional PROJECT-TAG and CONTEXT-TAG can be given to create .projectile and .dir
(message "Successfully batch-converted %d directories to ExoKortex nodes!" count)))) (message "Successfully batch-converted %d directories to ExoKortex nodes!" count))))
#+end_src #+end_src
** ExoKortex Archive / Restore
Moves node(s) between categories. Operates on marked Dired items, or the
item at cursor when nothing is marked.
#+begin_src emacs-lisp
(defun gortium/dired-node-dirs ()
"Return marked Dired subdirectories, or the cursor dir if nothing marked."
(when (derived-mode-p 'dired-mode)
(let* ((elements (dired-get-marked-files nil nil nil t))
(has-marks (or (and (listp elements) (> (length elements) 1))
(and (consp elements) (eq (car elements) t))))
(marked (when has-marks
(cl-remove-if-not #'file-directory-p
(if (eq (car-safe elements) t)
(cdr elements)
elements)))))
(or marked
(let ((cursor (dired-get-filename nil t)))
(when (and cursor (file-directory-p cursor))
(list cursor)))))))
(defun gortium/move-node (src-category dst-category node-dirs)
"Move NODE-DIRS (absolute paths) from SRC-CATEGORY to DST-CATEGORY.
Markers (.projectile/.dir-locals/.hermes-sessions/.git) move with each dir."
(let ((root (expand-file-name gortium/exokortex-root))
(moved 0))
(dolist (dir node-dirs)
(let* ((name (file-name-nondirectory (directory-file-name dir)))
(src (expand-file-name name (expand-file-name src-category root)))
(dst (expand-file-name name (expand-file-name dst-category root))))
(unless (file-directory-p src)
(user-error "No node '%s' in %s" name src-category))
(when (file-exists-p dst)
(user-error "%s already has a node named '%s'" dst-category name))
(make-directory (file-name-directory dst) t)
(rename-file src dst)
;; Stale path: drop from the Projectile cache so the switch-list cleans up.
(when (fboundp 'projectile-remove-known-project)
(projectile-remove-known-project src))
(cl-incf moved)))
(message "Archived/restored %d node(s): %s → %s" moved src-category dst-category)))
(defun gortium/archive-node ()
"Move marked (or cursor) nodes from 1-Projects to 4-Archives."
(interactive)
(let ((dirs (gortium/dired-node-dirs)))
(unless dirs
(user-error "No node under Dired cursor / no marked directories"))
(gortium/move-node "1-Projects" "4-Archives" dirs)))
(defun gortium/restore-node (category)
"Move marked (or cursor) archived nodes back into CATEGORY."
(interactive
(list (completing-read "Restore to category: "
'("1-Projects" "2-Areas" "3-Resources"))))
(let ((dirs (gortium/dired-node-dirs)))
(unless dirs
(user-error "No node under Dired cursor / no marked directories"))
(gortium/move-node "4-Archives" category dirs)))
#+end_src
** Project-Aware Agenda ** Project-Aware Agenda
Reads =.dir-locals.el= from the current Projectile root and injects the Reads =.dir-locals.el= from the current Projectile root and injects the

View File

@@ -548,26 +548,27 @@ org-agenda-files (seq-uniq org-agenda-files)
(setq (setq
org-capture-templates org-capture-templates
'( '(
("t" "TODO" entry (file+olp +org-capture-todo-file "Tasks") ("t" "Tasks")
("ti" "Idea" entry (file+olp +org-capture-todo-file "Tasks")
"* IDEA %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :prepend t) "* IDEA %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :prepend t)
("c" "Code TODO" entry ("tt" "Todo" entry (file+olp +org-capture-todo-file "Tasks")
(file+olp +org-capture-todo-file "Tasks") "* TODO %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :prepend t)
"* TODO %a\n:PROPERTIES:\n:CREATED: %U\n:END:\n":prepend t) ("tw" "Wait" entry (file+olp +org-capture-todo-file "Tasks")
"* WAIT %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :prepend t)
("tp" "Task at point" entry (file+olp +org-capture-todo-file "Tasks")
"* TODO %? %a\n:PROPERTIES:\n:CREATED: %U\n:END:\n" :prepend t)
("te" "Emails")
("tef" "Follow Up" entry (file+olp +org-capture-todo-file "Tasks") "* TODO Follow up with %:fromname on %a\nSCHEDULED:%t\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("ter" "Read Later" entry (file+olp +org-capture-todo-file "Tasks") "* TODO Read: %a\nSCHEDULED:%t\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("tew" "Waiting Response" entry
(file+olp +org-capture-todo-file "Tasks") "* WAIT Waiting response from %:toname on %a\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("n" "Note" entry (file+olp +org-capture-notes-file "Notes") ("n" "Note" entry (file+olp +org-capture-notes-file "Notes")
"* %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i") "* %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i")
("w" "Question" entry (file+olp +org-capture-notes-file "Questions") ("w" "Question" entry (file+olp +org-capture-notes-file "Questions")
"* [?] %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i") "* [?] %? \n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i")
("j" "Journal" entry (file+olp +org-capture-journal-file "Journal") ("e" "Event" entry (file+olp +org-capture-todo-file "Events")
"* %?\n%a\n%i") "* %? %^t\n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i")
("m" "Meeting" entry (file+olp +org-capture-notes-file "Meetings") ("C" "Contact" entry (file+olp +org-capture-todo-file "Contacts") "* %?\n:PROPERTIES:\n:EMAIL: %:fromemail\n:ROLE: \n:END:\n%a\n%i")
"* %? %U :meeting:\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n/Met with: /")
("a" "Appointment" entry (file+olp +org-capture-journal-file "Appointments")
"* %? :appointment:\n:PROPERTIES:\n:CREATED: %U\n:END:\n%a\n%i" :time-prompt t)
("e" "Email Workflow")
("ef" "Follow Up" entry (file+olp +org-capture-emails-file "Mails" "Follow Up") "* TODO Follow up with %:fromname on %a\nSCHEDULED:%t\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("er" "Read Later" entry (file+olp +org-capture-emails-file "Mails" "Read Later") "* TODO Read: %a\nSCHEDULED:%t\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
("ew" "Waiting Response" entry
(file+olp +org-capture-emails-file "Mails" "Waiting Response") "* WAIT Waiting response from %:toname on %a\nDEADLINE:%(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i" :immediate-finish t)
) )
) )
) )
@@ -908,7 +909,7 @@ Handles org-clock and context link capture for tasks."
;; Fold bindings ;; Fold bindings
(after! evil (after! evil
(define-key evil-motion-state-map (kbd "z C") #'hs-hide-level)) (define-key evil-motion-state-map (kbd "z M") #'hs-hide-level))
;; Disable global bindings for C-j and C-k ;; Disable global bindings for C-j and C-k
(global-unset-key (kbd "C-j")) (global-unset-key (kbd "C-j"))
@@ -1562,6 +1563,10 @@ If SESSION-ID is empty, show a menu of recent sessions to browse."
:config :config
(global-org-modern-mode) (global-org-modern-mode)
(setq org-modern-star 'replace) (setq org-modern-star 'replace)
;; U+2733 (✳) isn't in JetBrainsMono Nerd Font -> font fallback renders it green.
;; r/emacs favorite headline list, flower ✿ swapped for hollow ◇ in level 5 (filled ◆ was too big).
;; NOTE: ✸⁖ may need font fallback in the GUI frame (JetBrainsMono Nerd lacks them).
(setq org-modern-replace-stars "⁖◉○◇✸")
(setq org-modern-todo-faces (setq org-modern-todo-faces
'( '(
;; Framework ;; Framework
@@ -1719,7 +1724,7 @@ Cordialement,
(setq mu4e-icalendar-diary-file nil) (setq mu4e-icalendar-diary-file nil)
(setq gnus-icalendar-org-capture-file +org-capture-journal-file (setq gnus-icalendar-org-capture-file +org-capture-journal-file
gnus-icalendar-org-capture-headline '("Journal")) gnus-icalendar-org-capture-headline '("Events"))
(gnus-icalendar-org-setup) (gnus-icalendar-org-setup)
@@ -1988,6 +1993,12 @@ only injects when the project's context-tag matches current mu4e context."
:n "C-j" #'pdf-roll-next-page :n "C-j" #'pdf-roll-next-page
:n "C-k" #'pdf-roll-previous-page)) :n "C-k" #'pdf-roll-previous-page))
(use-package! doc-view
:config
(map! :map doc-view-mode-map
:n "C-j" #'doc-view-next-page
:n "C-k" #'doc-view-previous-page))
;;Refile in datetree function ;;Refile in datetree function
(defun org-refile-to-datetree (&optional file) (defun org-refile-to-datetree (&optional file)
"Refile a subtree to a datetree corresponding to its timestamp. "Refile a subtree to a datetree corresponding to its timestamp.
@@ -2874,6 +2885,61 @@ Optional PROJECT-TAG and CONTEXT-TAG can be given to create .projectile and .dir
(message "Directory successfully converted to ExoKortex node.") (message "Directory successfully converted to ExoKortex node.")
(message "Successfully batch-converted %d directories to ExoKortex nodes!" count)))) (message "Successfully batch-converted %d directories to ExoKortex nodes!" count))))
(defun gortium/dired-node-dirs ()
"Return marked Dired subdirectories, or the cursor dir if nothing marked."
(when (derived-mode-p 'dired-mode)
(let* ((elements (dired-get-marked-files nil nil nil t))
(has-marks (or (and (listp elements) (> (length elements) 1))
(and (consp elements) (eq (car elements) t))))
(marked (when has-marks
(cl-remove-if-not #'file-directory-p
(if (eq (car-safe elements) t)
(cdr elements)
elements)))))
(or marked
(let ((cursor (dired-get-filename nil t)))
(when (and cursor (file-directory-p cursor))
(list cursor)))))))
(defun gortium/move-node (src-category dst-category node-dirs)
"Move NODE-DIRS (absolute paths) from SRC-CATEGORY to DST-CATEGORY.
Markers (.projectile/.dir-locals/.hermes-sessions/.git) move with each dir."
(let ((root (expand-file-name gortium/exokortex-root))
(moved 0))
(dolist (dir node-dirs)
(let* ((name (file-name-nondirectory (directory-file-name dir)))
(src (expand-file-name name (expand-file-name src-category root)))
(dst (expand-file-name name (expand-file-name dst-category root))))
(unless (file-directory-p src)
(user-error "No node '%s' in %s" name src-category))
(when (file-exists-p dst)
(user-error "%s already has a node named '%s'" dst-category name))
(make-directory (file-name-directory dst) t)
(rename-file src dst)
;; Stale path: drop from the Projectile cache so the switch-list cleans up.
(when (fboundp 'projectile-remove-known-project)
(projectile-remove-known-project src))
(cl-incf moved)))
(message "Archived/restored %d node(s): %s → %s" moved src-category dst-category)))
(defun gortium/archive-node ()
"Move marked (or cursor) nodes from 1-Projects to 4-Archives."
(interactive)
(let ((dirs (gortium/dired-node-dirs)))
(unless dirs
(user-error "No node under Dired cursor / no marked directories"))
(gortium/move-node "1-Projects" "4-Archives" dirs)))
(defun gortium/restore-node (category)
"Move marked (or cursor) archived nodes back into CATEGORY."
(interactive
(list (completing-read "Restore to category: "
'("1-Projects" "2-Areas" "3-Resources"))))
(let ((dirs (gortium/dired-node-dirs)))
(unless dirs
(user-error "No node under Dired cursor / no marked directories"))
(gortium/move-node "4-Archives" category dirs)))
(defun gortium/read-dir-local (var) (defun gortium/read-dir-local (var)
"Read variable VAR from .dir-locals.el in `default-directory'. "Read variable VAR from .dir-locals.el in `default-directory'.
Returns nil if file doesn't exist or VAR isn't set." Returns nil if file doesn't exist or VAR isn't set."

View File

@@ -17,6 +17,14 @@ if [ ${#TARGETS[@]} -eq 0 ]; then
exit 0 exit 0
fi fi
# Root ExoKortex repo (root-level org files only; see ~/ExoKortex/.gitignore)
if git -C "$HOME/ExoKortex" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
if [ -n "$(git -C "$HOME/ExoKortex" status --porcelain)" ]; then
git -C "$HOME/ExoKortex" add -A
git -C "$HOME/ExoKortex" commit -m "System: Automated background sweep $(date +'%Y-%m-%d %H:%M')"
fi
fi
# Execute strict structural scanning on active paths only # Execute strict structural scanning on active paths only
find "${TARGETS[@]}" -mindepth 2 -maxdepth 2 -type d -name ".git" | while read -r gitdir; do find "${TARGETS[@]}" -mindepth 2 -maxdepth 2 -type d -name ".git" | while read -r gitdir; do
repo_dir=$(dirname "$gitdir") repo_dir=$(dirname "$gitdir")