12 Commits

Author SHA1 Message Date
5ee760fbe8 Doom emacs config progress dump 2026-04-30 10:25:25 -04:00
c1fbe2e8d9 Script path fix 2026-04-30 10:25:10 -04:00
1a4cafa098 Added perso mail secret 2026-04-30 10:24:39 -04:00
7e48bf1b87 rclone fix 2026-04-30 10:22:28 -04:00
3101834051 Update generated emacs config 2026-03-07 18:36:36 -05:00
8ddcf1de22 Various emacs config uddates 2026-03-07 18:33:12 -05:00
15e62ed479 Markdown emacs setup 2026-03-07 18:30:35 -05:00
a8315e32f1 UI amelioration 2026-03-07 18:11:50 -05:00
9cb17ede39 New recording app 2026-03-07 18:08:45 -05:00
cd60b775f5 Nicer windows spacing for hyprland 2026-03-07 18:02:01 -05:00
da85946d6a zsh pipx path 2026-03-07 17:59:01 -05:00
24fcd48036 btop config update 2026-03-07 17:58:17 -05:00
11 changed files with 897 additions and 328 deletions

View File

@@ -1,18 +1,18 @@
#? Config file for btop v. 1.4.4 #? Config file for btop v.1.4.6
#* 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"
color_theme = "/usr/share/btop/themes/everforest-dark-medium.theme" color_theme = "/usr/share/btop/themes/everforest-dark-medium.theme"
#* If the theme set background should be shown, set to False if you want terminal background transparency. #* If the theme set background should be shown, set to False if you want terminal background transparency.
theme_background = False theme_background = false
#* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false. #* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false.
truecolor = True truecolor = true
#* Set to true to force tty mode regardless if a real tty has been detected or not. #* Set to true to force tty mode regardless if a real tty has been detected or not.
#* 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
#* 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.
@@ -22,10 +22,13 @@ presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:defaul
#* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists. #* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists.
#* 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
#* 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
#* Use terminal synchronized output sequences to reduce flickering on supported terminals.
terminal_sync = true
#* Default symbols to use for graph creation, "braille", "block" or "tty". #* Default symbols to use for graph creation, "braille", "block" or "tty".
#* "braille" offers the highest resolution but might not be included in all fonts. #* "braille" offers the highest resolution but might not be included in all fonts.
@@ -60,37 +63,40 @@ update_ms = 2000
proc_sorting = "cpu lazy" proc_sorting = "cpu lazy"
#* Reverse sorting order, True or False. #* Reverse sorting order, True or False.
proc_reversed = False proc_reversed = false
#* Show processes as a tree. #* Show processes as a tree.
proc_tree = True proc_tree = true
#* Use the cpu graph colors in the process list. #* Use the cpu graph colors in the process list.
proc_colors = True proc_colors = true
#* Use a darkening gradient in the process list. #* Use a darkening gradient in the process list.
proc_gradient = True proc_gradient = true
#* If process cpu usage should be of the core it's running on or usage of the total available cpu power. #* If process cpu usage should be of the core it's running on or usage of the total available cpu power.
proc_per_core = True proc_per_core = true
#* Show process memory as bytes instead of percent. #* Show process memory as bytes instead of percent.
proc_mem_bytes = True proc_mem_bytes = true
#* Show cpu graph for each process. #* Show cpu graph for each process.
proc_cpu_graphs = True proc_cpu_graphs = true
#* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate) #* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate)
proc_info_smaps = False proc_info_smaps = false
#* Show proc box on left side of screen instead of right. #* Show proc box on left side of screen instead of right.
proc_left = False 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
#* 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
#* Should cpu and memory usage display be preserved for dead processes when paused.
keep_dead_proc_usage = false
#* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available. #* Sets the CPU stat shown in upper half of the CPU graph, "total" is always available.
#* Select from a list of detected attributes from the options menu. #* Select from a list of detected attributes from the options menu.
@@ -104,25 +110,28 @@ cpu_graph_lower = "Auto"
show_gpu_info = "Auto" show_gpu_info = "Auto"
#* Toggles if the lower CPU graph should be inverted. #* Toggles if the lower CPU graph should be inverted.
cpu_invert_lower = True cpu_invert_lower = true
#* Set to True to completely disable the lower CPU graph. #* Set to True to completely disable the lower CPU graph.
cpu_single_graph = False cpu_single_graph = false
#* Show cpu box at bottom of screen instead of top. #* Show cpu box at bottom of screen instead of top.
cpu_bottom = False cpu_bottom = false
#* Shows the system uptime in the CPU box. #* Shows the system uptime in the CPU box.
show_uptime = True show_uptime = true
#* Shows the CPU package current power consumption in watts. Requires running `make setcap` or `make setuid` or running with sudo.
show_cpu_watts = true
#* Show cpu temperature. #* Show cpu temperature.
check_temp = True check_temp = true
#* Which sensor to use for cpu temperature, use options menu to select from list of available sensors. #* Which sensor to use for cpu temperature, use options menu to select from list of available sensors.
cpu_sensor = "Auto" cpu_sensor = "Auto"
#* Show temperatures for cpu cores also if check_temp is True and sensors has been found. #* Show temperatures for cpu cores also if check_temp is True and sensors has been found.
show_coretemp = True show_coretemp = true
#* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core. #* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core.
#* Use lm-sensors or similar to see which cores are reporting temperatures on your machine. #* Use lm-sensors or similar to see which cores are reporting temperatures on your machine.
@@ -134,17 +143,20 @@ cpu_core_map = ""
temp_scale = "celsius" temp_scale = "celsius"
#* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024. #* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024.
base_10_sizes = False base_10_sizes = false
#* Show CPU frequency. #* Show CPU frequency.
show_cpu_freq = True show_cpu_freq = true
#* How to calculate CPU frequency, available values: "first", "range", "lowest", "highest" and "average".
freq_mode = "first"
#* Draw a clock at top of screen, formatting according to strftime, empty string to disable. #* Draw a clock at top of screen, formatting according to strftime, empty string to disable.
#* Special formatting: /host = hostname | /user = username | /uptime = system uptime #* Special formatting: /host = hostname | /user = username | /uptime = system uptime
clock_format = "%X" clock_format = "%X"
#* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort. #* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort.
background_update = True background_update = true
#* Custom cpu model name, empty string to disable. #* Custom cpu model name, empty string to disable.
custom_cpu_name = "" custom_cpu_name = ""
@@ -154,43 +166,43 @@ custom_cpu_name = ""
disks_filter = "" disks_filter = ""
#* Show graphs instead of meters for memory values. #* Show graphs instead of meters for memory values.
mem_graphs = True mem_graphs = true
#* Show mem box below net box instead of above. #* Show mem box below net box instead of above.
mem_below_net = True mem_below_net = true
#* Count ZFS ARC in cached and available memory. #* Count ZFS ARC in cached and available memory.
zfs_arc_cached = True zfs_arc_cached = true
#* If swap memory should be shown in memory box. #* If swap memory should be shown in memory box.
show_swap = True show_swap = true
#* Show swap as a disk, ignores show_swap value above, inserts itself after first disk. #* Show swap as a disk, ignores show_swap value above, inserts itself after first disk.
swap_disk = True swap_disk = true
#* If mem box should be split to also show disks info. #* If mem box should be split to also show disks info.
show_disks = True show_disks = true
#* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar. #* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar.
only_physical = True only_physical = true
#* Read disks list from /etc/fstab. This also disables only_physical. #* Read disks list from /etc/fstab. This also disables only_physical.
use_fstab = True use_fstab = true
#* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool) #* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool)
zfs_hide_datasets = False zfs_hide_datasets = false
#* Set to true to show available disk space for privileged users. #* Set to true to show available disk space for privileged users.
disk_free_priv = False disk_free_priv = false
#* Toggles if io activity % (disk busy time) should be shown in regular disk usage view. #* Toggles if io activity % (disk busy time) should be shown in regular disk usage view.
show_io_stat = True show_io_stat = true
#* Toggles io mode for disks, showing big graphs for disk read/write speeds. #* Toggles io mode for disks, showing big graphs for disk read/write speeds.
io_mode = False io_mode = false
#* Set to True to show combined read/write io graphs in io mode. #* Set to True to show combined read/write io graphs in io mode.
io_graph_combined = False io_graph_combined = false
#* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ". #* Set the top speed for the io graphs in MiB/s (100 by default), use format "mountpoint:speed" separate disks with whitespace " ".
#* Example: "/mnt/media:100 /:20 /boot:1". #* Example: "/mnt/media:100 /:20 /boot:1".
@@ -202,10 +214,10 @@ net_download = 100
net_upload = 100 net_upload = 100
#* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest. #* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest.
net_auto = True net_auto = true
#* Sync the auto scaling for download and upload to whichever currently has the highest scale. #* Sync the auto scaling for download and upload to whichever currently has the highest scale.
net_sync = True net_sync = true
#* Starts with the Network Interface specified here. #* Starts with the Network Interface specified here.
net_iface = "" net_iface = ""
@@ -214,26 +226,32 @@ net_iface = ""
base_10_bitrate = "Auto" base_10_bitrate = "Auto"
#* Show battery stats in top right if battery is present. #* Show battery stats in top right if battery is present.
show_battery = True show_battery = true
#* Which battery to use if multiple are present. "Auto" for auto detection. #* Which battery to use if multiple are present. "Auto" for auto detection.
selected_battery = "Auto" selected_battery = "Auto"
#* Show power stats of battery next to charge indicator. #* Show power stats of battery next to charge indicator.
show_battery_watts = True show_battery_watts = true
#* Set loglevel for "~/.config/btop/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG". #* Set loglevel for "~/.local/state/btop.log" levels are: "ERROR" "WARNING" "INFO" "DEBUG".
#* The level set includes all lower levels, i.e. "DEBUG" will show all logging info. #* The level set includes all lower levels, i.e. "DEBUG" will show all logging info.
log_level = "WARNING" log_level = "WARNING"
#* Automatically save current settings to config file on exit.
save_config_on_exit = true
#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards. #* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards.
nvml_measure_pcie_speeds = True nvml_measure_pcie_speeds = true
#* Measure PCIe throughput on AMD cards, may impact performance on certain cards. #* Measure PCIe throughput on AMD cards, may impact performance on certain cards.
rsmi_measure_pcie_speeds = True 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"
shown_gpus = "nvidia amd intel"
#* Custom gpu0 model name, empty string to disable. #* Custom gpu0 model name, empty string to disable.
custom_gpu_name0 = "" custom_gpu_name0 = ""

View File

@@ -156,7 +156,6 @@ My current workflow consist in having the 3-5 files I work on open in vertical s
#+end_src #+end_src
* Org Mode * Org Mode
If you use ~org~ and don't want your org files in the default location below, If you use ~org~ and don't want your org files in the default location below,
change ~org-directory~. It must be set before org loads! change ~org-directory~. It must be set before org loads!
@@ -164,12 +163,11 @@ change ~org-directory~. It must be set before org loads!
#+begin_src emacs-lisp #+begin_src emacs-lisp
(setq (setq
org-directory "~/ExoKortex/" org-directory "~/ExoKortex/"
+org-capture-todo-file "~/ExoKortex/2-Areas/Meta-Planning/Org/Core/master_list.org" +org-capture-todo-file "~/ExoKortex/3-Telos/5-Kernel/inbox.org"
+org-capture-notes-file "~/ExoKortex/2-Areas/Meta-Planning/Org/Core/master_list.org" +org-capture-notes-file "~/ExoKortex/3-Telos/5-Kernel/inbox.org"
+org-capture-journal-file "~/ExoKortex/2-Areas/Meta-Planning/Org/Core/master_list.org" +org-capture-journal-file "~/ExoKortex/3-Telos/5-Kernel/inbox.org"
+org-capture-emails-file "~/ExoKortex/2-Areas/Meta-Planning/Org/Core/master_list.org" +org-capture-emails-file "~/ExoKortex/3-Telos/5-Kernel/inbox.org"
;; +org-capture-central-project-todo-file '"refile.org" ;; +org-capture-central-project-todo-file '"refile.org"
;; +org-capture-project-todo-file '"refile.org" ;; +org-capture-project-todo-file '"refile.org"
org-agenda-files (directory-files-recursively "~/ExoKortex/" "\\.org$") org-agenda-files (directory-files-recursively "~/ExoKortex/" "\\.org$")
@@ -366,15 +364,34 @@ change ~org-directory~. It must be set before org loads!
("p" . "Personal commands") ("p" . "Personal commands")
("wg" "GTD view" ("wg" "GTD view"
( (
(agenda "" ((org-agenda-span 'week))) (agenda "" ((org-agenda-span 'week)
(todo "STRT" ((org-agenda-overriding-header gtd/started-head))) (org-agenda-prefix-format " %12t") ;; reserve time space
(todo "NEXT" ((org-agenda-overriding-header gtd/next-action-head))) (org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
(todo "WAIT" ((org-agenda-overriding-header gtd/waiting-head))) ))
(todo "STRT" ((org-agenda-overriding-header gtd/started-head)
(org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
(todo "NEXT" ((org-agenda-overriding-header gtd/next-action-head)
(org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
(todo "WAIT" ((org-agenda-overriding-header gtd/waiting-head)
(org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
;; (todo "DONE" ((org-agenda-overriding-header gtd/complete-head))) ;; (todo "DONE" ((org-agenda-overriding-header gtd/complete-head)))
(stuck "" ((org-stuck-projects '("TODO=\"PROJ\"" ("NEXT" "STRT") nil "")) (stuck "" ((org-stuck-projects '("TODO=\"PROJ\"" ("NEXT" "STRT") nil ""))
(org-agenda-overriding-header gtd/project-head))) (org-agenda-overriding-header gtd/project-head)
(todo "IDEA" ((org-agenda-overriding-header gtd/someday-head))) (org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
(todo "IDEA" ((org-agenda-overriding-header gtd/someday-head)
(org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
) )
((org-agenda-tag-filter-preset '("+work"))) ((org-agenda-tag-filter-preset '("+work")))
) )
("pg" "GTD view" ("pg" "GTD view"
@@ -466,7 +483,7 @@ change ~org-directory~. It must be set before org loads!
) )
("wP" "Installation Bombardier" ("wP" "Installation Bombardier"
((agenda "" ((agenda ""
((org-agenda-span 60) ((org-agenda-span 90)
(org-agenda-start-day "2026-01-29") (org-agenda-start-day "2026-01-29")
(org-agenda-overriding-header "📅 Installation Bombardier") (org-agenda-overriding-header "📅 Installation Bombardier")
(org-agenda-prefix-format " %12t") ;; reserve time space (org-agenda-prefix-format " %12t") ;; reserve time space
@@ -479,7 +496,7 @@ change ~org-directory~. It must be set before org loads!
) )
) )
) )
) )
#+end_src #+end_src
** Rust ** Rust
@@ -492,20 +509,64 @@ change ~org-directory~. It must be set before org loads!
#+end_src #+end_src
** Latex ** Latex
#+begin_src emacs-lisp #+begin_src emacs-lisp
(after! org (after! org
(setq (setq org-format-latex-options (plist-put org-format-latex-options :scale 2.0))
;; LaTeX math preview ;; 1. Use XeLaTeX to generate the intermediate file for dvisvgm
org-format-latex-options '(:foreground default :background default :scale 2 :html-foreground "Black" ;; This handles UTF-8 (like long dashes) which standard 'latex' crashes on.
:html-background "Transparent" :html-scale 1.0 (setq org-preview-latex-process-alist
:matchers ("begin" "$1" "$" "$$" "\\(" "\\[")) '((dvisvgm
) :programs ("xelatex" "dvisvgm")
:description "xdv to svg"
:message "rendering %f via xelatex..."
:image-input-type "xdv"
:image-output-type "svg"
:image-size-adjust (1.0 . 1.0)
:latex-compiler ("xelatex -interaction nonstopmode -no-pdf -output-directory %o %f")
:image-converter ("dvisvgm %f --no-fonts --exact-bbox --scale=%S --output=%O"))))
(setq org-preview-latex-default-process 'dvisvgm)
(defun gortium/org-latex-preview-all ()
"Render all LaTeX fragments in the buffer."
(interactive)
(when (derived-mode-p 'org-mode)
(org-latex-preview '(16))))
;; 1.5s delay to ensure Doom font-colors load first
;; (add-hook 'org-mode-hook
;; (lambda ()
;; (run-with-idle-timer 1.5 nil #'gortium/org-latex-preview-all)))
) )
(after! ox-latex (after! ox-latex
(setq org-latex-compiler "xelatex")) (setq org-latex-src-block-backend 'listings)
(add-to-list 'org-latex-packages-alist '("" "listings") t)
(add-to-list 'org-latex-packages-alist '("" "xcolor") t)
(add-to-list 'org-latex-listings-langs '(text ""))
(setq org-latex-listings-options
'(("breaklines" "true")
("basicstyle" "\\small\\ttfamily")
("frame" "single")
("backgroundcolor" "\\color{gray!10}"))))
#+end_src
** Fragtog
#+begin_src emacs-lisp
(use-package! org-fragtog
:hook (org-mode . org-fragtog-mode))
(defun gortium/org-latex-refresh-on-zoom (&rest _)
(when (derived-mode-p 'org-mode)
(let ((new-scale (+ 2 (* 0.5 (if (boundp 'text-scale-mode-amount) text-scale-mode-amount 0)))))
(setq org-format-latex-options
(plist-put org-format-latex-options :scale new-scale))
(org-clear-latex-preview)
(gortium/org-latex-preview-all))))
(advice-add 'text-scale-increase :after #'gortium/org-latex-refresh-on-zoom)
(advice-add 'text-scale-decrease :after #'gortium/org-latex-refresh-on-zoom)
#+end_src #+end_src
** Org Capture ** Org Capture
@@ -539,6 +600,14 @@ change ~org-directory~. It must be set before org loads!
) )
) )
#+end_src #+end_src
** Default apps
#+begin_src emacs-lisp
(after! org
;; Ensure exported HTML opens in the system browser, not inside Emacs
(setq org-file-apps
(append '(("\\.x?html?\\'" . default))
(assq-delete-all "\\.x?html?\\'" org-file-apps))))
#+end_src
** +Org Superstar mode+ ** +Org Superstar mode+
org-modern instead org-modern instead
@@ -546,7 +615,53 @@ org-modern instead
(add-hook 'org-mode-hook (lambda () (org-superstar-mode 1))) (add-hook 'org-mode-hook (lambda () (org-superstar-mode 1)))
#+end_src #+end_src
* Markdown
#+begin_src emacs-lisp
(after! grip-mode
(setq grip-binary-path "/home/tpouplier/.local/bin/grip")
)
#+end_src
#+begin_src emacs-lisp
(after! markdown-mode
(setq markdown-header-scaling t)
(custom-set-faces
'(markdown-header-face-1 ((t
:inherit markdown-header-face
:foreground "#fabd2f"
:height 1.8
:weight extra-bold)))
'(markdown-header-face-2 ((t
:inherit markdown-header-face
:foreground "#fe8019"
:height 1.4
:weight extra-bold)))
'(markdown-header-face-3 ((t
:inherit markdown-header-face
:foreground "#fb4934"
:height 1.2
:weight bold)))
'(markdown-header-face-4 ((t
:inherit markdown-header-face
:foreground "#b8bb26"
:height 1.1
:weight bold)))
'(markdown-header-face-5 ((t
:inherit markdown-header-face
:foreground "#83a598"
:height 1.0
:weight bold)))
'(markdown-header-face-6 ((t
:inherit markdown-header-face
:foreground "#d3869b"
:height 1.0
:weight bold))))
)
#+end_src
* PlantUML * PlantUML
#+begin_src emacs-lisp #+begin_src emacs-lisp
;; Enable plantuml-mode for PlantUML files ;; Enable plantuml-mode for PlantUML files
(add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode)) (add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode))
@@ -571,6 +686,7 @@ fc --> UC3
[[/tmp/babel-pg1Nry/plantuml-SHtP1g.png][/tmp/babel-pg1Nry/plantuml-SHtP1g.png]] [[/tmp/babel-pg1Nry/plantuml-SHtP1g.png][/tmp/babel-pg1Nry/plantuml-SHtP1g.png]]
* Elgantt * Elgantt
Broken for now.. Broken for now..
#+begin_src emacs-lisp :tangle no #+begin_src emacs-lisp :tangle no
(require 'cl-lib) (require 'cl-lib)
@@ -790,12 +906,11 @@ Broken for now..
: elgantt-open-current-org-file : elgantt-open-current-org-file
* Org Roam * Org Roam
** Static Path ** Static Path
#+begin_src emacs-lisp #+begin_src emacs-lisp
(setq org-roam-directory (file-truename "~/ExoKortex/") (setq org-roam-directory (file-truename "~/ExoKortex/")
org-roam-db-location (file-truename "~/ExoKortex/2-Areas/IT/Roam/org-roam.db") org-roam-db-location (file-truename "~/ExoKortex/1-Soma/2-Areas/IT/Roam/org-roam.db")
org-attach-id-dir "assets/" org-attach-id-dir "assets/"
org-roam-dailies-directory "~/ExoKortex/2-Areas/Meta-Planning/Org/Journal/Daily") org-roam-dailies-directory "~/ExoKortex/2-Areas/Meta-Planning/Org/Journal/Daily")
#+end_src #+end_src
@@ -1004,7 +1119,6 @@ Handles org-clock and context link capture for tasks."
#+end_src #+end_src
* IDE * IDE
** Dap Mode ** Dap Mode
#+begin_src emacs-lisp #+begin_src emacs-lisp
@@ -1127,14 +1241,14 @@ Now I can write x) (spellchecking)
(after! ispell (after! ispell
(setq ispell-program-name "hunspell" (setq ispell-program-name "hunspell"
ispell-dictionary "en_CA,fr_CA" ispell-dictionary "en_CA,fr_CA"
ispell-personal-dictionary "/home/tpouplier/ExoKortex/2-Areas/IT/Dictionaries/perso.dic") ispell-personal-dictionary "/home/tpouplier/ExoKortex/1-Soma/2-Areas/IT/Dictionaries/perso.dic")
;; Set the dictionary path environment variable ;; Set the dictionary path environment variable
(setenv "DICPATH" "/home/tpouplier/ExoKortex/2-Areas/IT/Dictionaries") (setenv "DICPATH" "/home/tpouplier/ExoKortex/1-Soma/2-Areas/IT/Dictionaries")
(setq ispell-hunspell-dict-paths-alist (setq ispell-hunspell-dict-paths-alist
'(("fr_CA" "/home/tpouplier/ExoKortex/2-Areas/IT/Dictionaries/fr_CA.aff") '(("fr_CA" "/home/tpouplier/ExoKortex/1-Soma/2-Areas/IT/Dictionaries/fr_CA.aff")
("en_CA" "/home/tpouplier/ExoKortex/2-Areas/IT/Dictionaries/en_CA.aff"))) ("en_CA" "/home/tpouplier/ExoKortex/1-Soma/2-Areas/IT/Dictionaries/en_CA.aff")))
(setq ispell-hunspell-dictionary-alist (setq ispell-hunspell-dictionary-alist
'(("fr_CA" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "fr_CA") nil utf-8) '(("fr_CA" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "fr_CA") nil utf-8)
@@ -1296,33 +1410,6 @@ I'm a formatting nazi now xD
) )
#+end_src #+end_src
** Fragtog
#+begin_src emacs-lisp
;; Hook fragtog to org-mode to have editable latex preview
(use-package! org-fragtog
:hook (org-mode . org-fragtog-mode))
;; Rescale latex preview when changing font size
(defun gortium/org-latex-refresh-on-zoom (&rest _)
"Dynamically rescale and refresh all LaTeX previews after text zoom."
(when (derived-mode-p 'org-mode)
;; Dynamically update scale relative to zoom level
(setq org-format-latex-options
(plist-put org-format-latex-options
:scale (+ 2 (* 0.5 text-scale-mode-amount))
))
;; Clear all previews
(org-clear-latex-preview)
;; Re-render all previews
(org-latex-preview '(16))
))
(advice-add 'text-scale-increase :after #'gortium/org-latex-refresh-on-zoom)
(advice-add 'text-scale-decrease :after #'gortium/org-latex-refresh-on-zoom)
(advice-add 'text-scale-set :after #'gortium/org-latex-refresh-on-zoom)
#+end_src
** Age ** Age
Allow me to edit encryted age file directly in emacs buffer. Allow me to edit encryted age file directly in emacs buffer.
@@ -1397,11 +1484,11 @@ Allow retrieval of password from age file formatted like passwordstore
;; rebind function value for pass to passage ;; rebind function value for pass to passage
(fset #'pass (lambda () (interactive) (passage))) (fset #'pass (lambda () (interactive) (passage)))
(setq age-program "rage") (setq age-program "rage")
(setq auth-source-passage-filename (expand-file-name "~/ExoKortex/2-Areas/IT/dotfiles/secrets")) (setq auth-source-passage-filename (expand-file-name "~/ExoKortex/4-Automata/dotfiles/secrets"))
(setenv "PASSAGE_IDENTITIES_FILE" (expand-file-name age-default-identity)) (setenv "PASSAGE_IDENTITIES_FILE" (expand-file-name age-default-identity))
(setenv "PASSAGE_RECIPIENTS_FILE" (expand-file-name age-default-recipient)) (setenv "PASSAGE_RECIPIENTS_FILE" (expand-file-name age-default-recipient))
(setenv "PASSAGE_AGE" "rage") (setenv "PASSAGE_AGE" "rage")
(setenv "PASSAGE_DIR" (expand-file-name "~/ExoKortex/2-Areas/IT/dotfiles/secrets")) (setenv "PASSAGE_DIR" (expand-file-name "~/ExoKortex/4-Automata/dotfiles/secrets"))
) )
#+end_src #+end_src
** Diff HL Mode ** Diff HL Mode
@@ -1412,7 +1499,6 @@ Show git changes in the sidebar
#+end_src #+end_src
* Terminal * Terminal
** +EEE+ ** +EEE+
#+begin_src emacs-lisp :tangle no #+begin_src emacs-lisp :tangle no
@@ -1467,7 +1553,8 @@ The best LLM integration I found. Works with MCP server for more functionnalitie
deepseek/deepseek-chat-v3-0324:free deepseek/deepseek-chat-v3-0324:free
meta-llama/llama-4-maverick:free meta-llama/llama-4-maverick:free
mistralai/devstral-2512:free mistralai/devstral-2512:free
qwen/qwen3-coder:free)) qwen/qwen3-coder:free
nvidia/nemotron-3-nano-30b-a3b:free))
(gptel-make-gemini "Gemini" (gptel-make-gemini "Gemini"
:key (auth-source-passage-get 'secret "gemini") :key (auth-source-passage-get 'secret "gemini")
:stream t :stream t
@@ -1772,7 +1859,9 @@ Recently added the quick access entries. Game changer.
#+begin_src emacs-lisp #+begin_src emacs-lisp
;; Dirvish config ;; Dirvish config
(after! dirvish (after! (dirvish dired)
(require 'async)
(dired-async-mode 1)
;; Display icons, file size, timestamps, etc. ;; Display icons, file size, timestamps, etc.
(setq dirvish-attributes (setq dirvish-attributes
'(nerd-icons '(nerd-icons
@@ -1805,13 +1894,15 @@ Recently added the quick access entries. Game changer.
("d" "~/Downloads/" "Downloads") ("d" "~/Downloads/" "Downloads")
("u" "/run/media" "Mounted drives") ("u" "/run/media" "Mounted drives")
("t" "~/.local/share/Trash/files/" "Trash") ("t" "~/.local/share/Trash/files/" "Trash")
))) ))
(setq dirvish-yank-use-rsync t)
(setq dirvish-yank-rsync-args '("-ah" "--info=progress2"))
)
;; Use `p` to open the yank menu ;; Use `p` to open the yank menu
(map! :after dirvish-yank (map! :after dirvish-yank
:map dirvish-mode-map :map dirvish-mode-map
:n "p" #'dirvish-yank-menu) :n "p" #'dirvish-yank-menu)
#+end_src #+end_src
#+RESULTS: #+RESULTS:
@@ -1905,7 +1996,6 @@ Useful for the user, but also when you have someone over your shoulder trying to
#+end_src #+end_src
* Email * Email
** Org-Msg ** Org-Msg
#+begin_src emacs-lisp #+begin_src emacs-lisp
@@ -1915,14 +2005,54 @@ Useful for the user, but also when you have someone over your shoulder trying to
(setq org-msg-options "html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil \\n:t" (setq org-msg-options "html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil \\n:t"
org-msg-startup "hidestars indent inlineimages" org-msg-startup "hidestars indent inlineimages"
org-msg-greeting-fmt "\nBonjour%s,\n\n" org-msg-greeting-fmt "\nBonjour%s,\n\n"
;; org-msg-recipient-names '(("jeremy.compostella@gmail.com" . "Jérémy"))
org-msg-greeting-name-limit 1 org-msg-greeting-name-limit 1
org-msg-default-alternatives '((new . (text html)) org-msg-default-alternatives '((new . (text html))
(reply-to-html . (text html)) (reply-to-html . (text html))
(reply-to-text . (text))) (reply-to-text . (text)))
org-msg-convert-citation t org-msg-convert-citation t)
org-msg-signature " )
#+end_src
** Mu4e
#+begin_src emacs-lisp
(after! mu4e
(setq mu4e-maildir-shortcuts mu4e-maildir-list mu4e-maildir-initial-input mu4e-maildir-info-delimiter)
(setq mu4e-contexts
(list
;; --- CONTEXT: TDNDE ---
(make-mu4e-context
:name "TDNDE"
:match-func (lambda (msg)
(when msg
(string-prefix-p "/TDNDE/" (mu4e-message-field msg :maildir))))
:vars
'((user-mail-address . "tpouplier@tdnde.com")
(user-full-name . "Thierry Pouplier")
;; Folders
(mu4e-sent-folder . "/TDNDE/Sent")
(mu4e-drafts-folder . "/TDNDE/Drafts")
(mu4e-trash-folder . "/TDNDE/Trash")
(mu4e-refile-folder . "/TDNDE/Archive")
;; Shortcuts
(mu4e-maildir-shortcuts . (("/TDNDE/Inbox" . ?i)
("/TDNDE/Sent" . ?s)
("/TDNDE/Drafts" . ?d)
("/TDNDE/Trash" . ?t)
("/TDNDE/Archive" . ?a)))
;; SMTP
(smtpmail-smtp-user . "tpouplier@tdnde.com")
(smtpmail-stream-type . ssl)
(smtpmail-smtp-server . "smtp.hostinger.com")
(smtpmail-smtp-service . 465)
(mu4e-sent-messages-behavior . sent)
;; Context-specific signature
(org-msg-signature . "
Cdlt, Cdlt,
,#+begin_signature ,#+begin_signature
@@ -1936,97 +2066,66 @@ Tél. : +1 (450) 667-1884 \\\\
Cell. : +1 (514) 887-1674 \\\\ Cell. : +1 (514) 887-1674 \\\\
tpouplier@tdnde.com \\\\ tpouplier@tdnde.com \\\\
www.tdnde.com \\\\ www.tdnde.com \\\\
,#+end_signature") ,#+end_signature")))
)
#+end_src
** Mu4e ;; --- CONTEXT: Perso ---
#+begin_src emacs-lisp
(after! mu4e
(setq mu4e-maildir-shortcuts mu4e-maildir-list mu4e-maildir-initial-input mu4e-maildir-info-delimiter)
(setq mu4e-contexts
(list
(make-mu4e-context (make-mu4e-context
:name "TDNDE" :name "Perso"
:match-func :match-func (lambda (msg)
(lambda (msg)
(when msg (when msg
(string-prefix-p (string-prefix-p "/Perso/" (mu4e-message-field msg :maildir))))
"/TDNDE/" :vars `((user-mail-address . "thierrypouplier@gmail.com")
(mu4e-message-field msg :maildir))))
:vars
'((user-mail-address . "tpouplier@tdnde.com")
(user-full-name . "Thierry Pouplier") (user-full-name . "Thierry Pouplier")
(mu4e-sent-folder . "/Perso/Sent")
(mu4e-drafts-folder . "/Perso/Drafts")
(mu4e-trash-folder . "/Perso/Trash")
(mu4e-refile-folder . "/Perso/Archive")
;; Folders (mu4e-maildir-shortcuts . (("/Perso/Inbox" . ?i)
(mu4e-sent-folder . "/TDNDE/Sent") ("/Perso/Sent" . ?s)
(mu4e-drafts-folder . "/TDNDE/Drafts") ("/Perso/Trash" . ?t)
(mu4e-trash-folder . "/TDNDE/Trash") ("/Perso/Drafts" . ?d)
(mu4e-refile-folder . "/TDNDE/Archive") ("/Perso/Archive" . ?a)))
;; Shortcuts (smtpmail-smtp-user . "thierrypouplier@gmail.com")
(mu4e-maildir-shortcuts (smtpmail-smtp-server . "smtp.gmail.com")
. (smtpmail-smtp-service . 587)
(("/TDNDE/Inbox" . ?i) (smtpmail-stream-type . starttls)
("/TDNDE/Sent" . ?s) (mu4e-sent-messages-behavior . sent)
("/TDNDE/Drafts" . ?d) (org-msg-signature . "
("/TDNDE/Trash" . ?t) Cordialement,
("/TDNDE/Archive" . ?a)))
;; Bookmarks ,#+begin_signature
(mu4e-bookmarks --
. ,*Thierry Pouplier* \\
((:name "Airbus-6825" (514) 887-1674 | thierrypouplier@gmail.com
:query "maildir:/TDNDE/* AND label:proj:6825 AND label:client:airbus" ,#+end_signature"))))) ;; End of mu4e-contexts list
:key ?A)
(:name "Bombardier-3154"
:query "maildir:/TDNDE/* AND label:proj:3154 AND label:client:bombardier"
:key ?B)
(:name "Daher-5304"
:query "maildir:/TDNDE/* AND label:proj:5304 AND label:client:daher"
:key ?D)
(:name "TDNDE"
:query "maildir:/TDNDE/* AND label:tdnde"
:key ?T)))
;; SMTP
(smtpmail-smtp-user . "tpouplier@tdnde.com")
(smtpmail-stream-type . ssl)
(smtpmail-smtp-server . "smtp.hostinger.com")
(smtpmail-smtp-service . 465)))
;; Other context here
;; (make-mu4e-context ...)
)
)
(setq mu4e-context-policy 'pick-first (setq mu4e-context-policy 'pick-first
mu4e-compose-context-policy 'ask) mu4e-compose-context-policy 'ask)
(require 'mu4e-icalendar) (require 'mu4e-icalendar)
(mu4e-icalendar-setup) (mu4e-icalendar-setup)
(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 '("Journal"))
(gnus-icalendar-org-setup) (gnus-icalendar-org-setup)
)
;; Separate after! blocks for clarity
(after! mu4e (after! mu4e
(setq mu4e-modeline-support nil)) (setq mu4e-modeline-support nil))
(after! mu4e (after! mu4e
;; restore label key ;; restore label key
(evil-define-key 'normal mu4e-headers-mode-map"l" #'mu4e-headers-mark-for-label) (evil-define-key 'normal mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label)
(evil-define-key 'visual mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label) (evil-define-key 'visual mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label)
(evil-define-key 'emacs mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label) (evil-define-key 'emacs mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label)
(evil-define-key 'normal mu4e-view-mode-map "l" #'mu4e-view-mark-for-label) (evil-define-key 'normal mu4e-view-mode-map "l" #'mu4e-view-mark-for-label)
(evil-define-key 'visual mu4e-view-mode-map "l" #'mu4e-view-mark-for-label) (evil-define-key 'visual mu4e-view-mode-map "l" #'mu4e-view-mark-for-label)
(evil-define-key 'emacs mu4e-view-mode-map "l" #'mu4e-view-mark-for-label) (evil-define-key 'emacs mu4e-view-mode-map "l" #'mu4e-view-mark-for-label)))
)
#+end_src #+end_src
* IRC * IRC
@@ -2192,7 +2291,7 @@ If FILE is nil, refile in the current file."
(add-hook 'ediff-prepare-buffer-hook 'org-ediff-prepare-buffer) (add-hook 'ediff-prepare-buffer-hook 'org-ediff-prepare-buffer)
#+end_src #+end_src
* Custom function for reschedulling * Custom function for scheduling
#+begin_src emacs-lisp #+begin_src emacs-lisp
;;; ============================================================ ;;; ============================================================
@@ -2342,7 +2441,7 @@ Returns nil if no range found (safe, non-blocking)."
(all-resolved t)) (all-resolved t))
(when (and (string-match "ids(\\(.*?\\))" clean) (when (and (string-match "ids(\\(.*?\\))" clean)
(not (string-empty-p (s-trim (match-string 1 clean))))) (not (string-empty-p (s-trim (match-string 1 clean)))))
(dolist (tid (split-string (match-string 1 clean) "[ ,]+" t)) (dolist (tid (split-string (match-string 1 clean) "[[:space:],]+" t))
(let* ((clean-id (replace-regexp-in-string "[\"']\\|id: " "" tid)) (let* ((clean-id (replace-regexp-in-string "[\"']\\|id: " "" tid))
(pos (org-id-find clean-id t)) (pos (org-id-find clean-id t))
(computed-end (gethash clean-id task-end-map)) (computed-end (gethash clean-id task-end-map))
@@ -2364,6 +2463,9 @@ Returns nil if no range found (safe, non-blocking)."
;; Priority 2: Use range end if FIXED ;; Priority 2: Use range end if FIXED
((string-equal "t" (org-entry-get nil "FIXED")) ((string-equal "t" (org-entry-get nil "FIXED"))
(gortium/org--get-range-end m)) (gortium/org--get-range-end m))
;; Priority 3: Fallback to existing range end if it exists
((gortium/org--get-range-end m)
(gortium/org--get-range-end m))
(t nil)))))) (t nil))))))
(t nil))) (t nil)))
@@ -2574,10 +2676,27 @@ Returns list of task IDs involved in cycles, or nil if no cycles found."
(push task done-this-loop)))))))) (push task done-this-loop))))))))
(setq remaining (cl-set-difference remaining done-this-loop)))) (setq remaining (cl-set-difference remaining done-this-loop))))
;; --- DIAGNOSTICS FOR UNSCHEDULED TASKS ---
(if remaining
(progn
(message "!!! WARNING: %d tasks were NOT scheduled !!!" (length remaining))
(dolist (task remaining)
(pcase-let ((`(,_buf ,pos ,id ,_eff ,blocker ,_fix ,_sch ,_off) task))
(let* ((blocker-string (format "%s" blocker))
(clean-blocker (if (string-match "ids(\\(.*?\\))" blocker-string)
(match-string 1 blocker-string)
"None")))
(message " -> Task [%s] at pos %s is BLOCKED by: %s"
id (marker-position pos) clean-blocker)))))
(message "=== All tasks scheduled successfully! ==="))
;; 3. CLEANUP ;; 3. CLEANUP
(setq org-element-use-cache t) (setq org-element-use-cache t)
(org-element-cache-reset 'all) (org-element-cache-reset 'all)
(message "=== Scheduler completed (%d tasks, %d iterations) ===" (length all-tasks) iter)))) (message "=== Scheduler completed (%d tasks, %d iterations) ===" (length all-tasks) iter)
;; (gortium/org-rollup-parent-ranges)
;; (message "=== All Scheduling and Roll-ups Complete ===")
)))
;; --------------------------------------------- ;; ---------------------------------------------
(defun gortium/org-ensure-task-properties () (defun gortium/org-ensure-task-properties ()
@@ -2621,6 +2740,143 @@ and ensure the standard property drawer exists without overwriting existing data
#+RESULTS: #+RESULTS:
: gortium/add-ids-to-subtree : gortium/add-ids-to-subtree
* Custom function for maintenance
#+begin_src emacs-lisp
(after! org
;; ---------------------------------------------------------
;; 1. THE REUSABLE ENGINE (Domain Agnostic)
;; ---------------------------------------------------------
(defun my/org-metric-sync-engine (&key prop-name value-current prop-last-done prop-interval target-tag log-label)
"Core logic to sync parent metrics to sub-tasks and log changes.
PROP-NAME: The property triggering the change (e.g., LAST_KM).
VALUE-CURRENT: The new value being set.
PROP-LAST-DONE: Sub-task property for 'baseline' (e.g., LAST_DONE_KM).
PROP-INTERVAL: Sub-task property for 'frequency' (e.g., INTERVAL_KM).
TARGET-TAG: Filter for specific sub-tasks (e.g., SERVICE).
LOG-LABEL: The prefix used in the Logbook entry."
(save-excursion
;; A. Log the update to the Logbook with a timestamp
(when log-label
(org-add-log-setup 'note (format "%s: %s" log-label value-current) nil 'findpos))
;; B. Narrow scope to current header and scan sub-tasks
(org-narrow-to-subtree)
(org-map-entries
(lambda ()
(let* ((last-done (string-to-number (or (org-entry-get nil prop-last-done) "0")))
(interval (string-to-number (or (org-entry-get nil prop-interval) "0")))
(current (string-to-number value-current)))
;; Only process tasks that have an interval set
(when (> interval 0)
(if (>= current (+ last-done interval))
(org-todo "TODO")
(org-todo "HOLD")))))
target-tag)
(widen)))
(defun my/org-metric-prompt-engine (&key state tag prop-parent-metric prop-task-done label-prompt)
"Core logic to prompt for values when a task is marked DONE.
STATE: The new TODO state (e.g., DONE).
TAG: The tag identifying relevant tasks.
PROP-PARENT-METRIC: The property on the parent to update (e.g., LAST_KM).
PROP-TASK-DONE: The property on the task to update (e.g., LAST_DONE_KM).
LABEL-PROMPT: The text shown in the minibuffer."
(when (string= state "DONE")
(let ((tags (org-get-tags)))
(when (member tag tags)
(save-excursion
;; Inherit parent metric as the default value for the prompt
(let* ((current-val (org-entry-get nil prop-parent-metric t))
(input-val (read-string (format "%s (default %s): " label-prompt (or current-val "0"))
nil nil current-val)))
;; 1. Update the task property
(org-set-property prop-task-done input-val)
;; 2. Update the parent property (triggers the sync engine)
(save-excursion
(when (org-up-heading-safe)
(org-set-property prop-parent-metric input-val)))
(message "Synchronized %s to %s" label-prompt input-val)))))))
;; ---------------------------------------------------------
;; 2. THE DISPATCHERS (The Switchboard)
;; ---------------------------------------------------------
(defun my/org-property-change-handler (prop value)
"Routes property changes to the correct sync parameters."
(cond
;; Case: F-150 Odometer
((string= prop "LAST_KM")
(my/org-metric-sync-engine
:prop-name prop :value-current value :prop-last-done "LAST_DONE_KM"
:prop-interval "INTERVAL_KM" :target-tag "SERVICE" :log-label "Odometer Update"))))
;; Case: Equipment/Industrial Hours
;; ((string= prop "LAST_HOURS")
;; (my/org-metric-sync-engine
;; :prop-name prop :value-current value :prop-last-done "LAST_DONE_HOURS"
;; :prop-interval "INTERVAL_HOURS" :target-tag "MAINTENANCE" :log-label "Usage Hours Logged"))))
(defun my/org-todo-state-handler ()
"Safely routes DONE completions, catching any argument errors."
(interactive)
(condition-case err
(when (string= org-state "DONE")
(my/org-metric-prompt-engine
:state "DONE"
:tag "SERVICE"
:prop-parent-metric "LAST_KM"
:prop-task-done "LAST_DONE_KM"
:label-prompt "Current Odometer"))
(error (message "Handler suppressed error: %s" (error-message-string err)))))
)
;; (my/org-metric-prompt-engine
;; :state org-state :tag "MAINTENANCE" :prop-parent-metric "LAST_HOURS"
;; :prop-task-done "LAST_DONE_HOURS" :label-prompt "Equipment Hours"))
;; ---------------------------------------------------------
;; 3. THE HOOKS
;; ---------------------------------------------------------
(add-hook 'org-after-prop-change-hook #'my/org-property-change-handler)
(add-hook 'org-after-todo-state-change-hook #'my/org-todo-state-handler)
#+end_src
* Custom for rescheduling task later
#+begin_src emacs-lisp
(defun my/org-smart-advance-date ()
"Jump to next repeater occurrence or add 1 day.
Suppresses all logging, notes, and custom odometer hooks."
(interactive)
(let ((org-log-done nil)
(org-log-repeat nil)
(org-todo-repeat-to-state "LOOP")
(org-after-todo-state-change-hook nil)
(org-treat-insert-todo-log-note nil)
(inhibit-modification-hooks t))
(let ((is-agenda (derived-mode-p 'org-agenda-mode)))
(cond
;; Case 1: Task has a repeater (teleport to next date)
((if is-agenda
(org-agenda-with-point-at-orig-entry nil (org-get-repeat))
(org-get-repeat))
;; This surgical strike prevents the Logbook entry entirely
(cl-letf (((symbol-function 'org-add-log-setup) (lambda (&rest _args) nil)))
(if is-agenda (org-agenda-todo "DONE") (org-todo "DONE")))
(message "Silently jumped to next occurrence."))
;; Case 2: No repeater, fallback to standard +1 day shift
(t
(if is-agenda
(org-agenda-date-later 1)
(org-timestamp-change 1 'day))
(message "No repeater found: Added 1 day."))))))
(map! :after org
(:map org-mode-map
:localleader "L" #'my/org-smart-advance-date)
(:map org-agenda-mode-map
:localleader "L" #'my/org-smart-advance-date))
#+end_src
* Custom function Open link in other frame * Custom function Open link in other frame
@@ -2935,7 +3191,7 @@ Need chrome... :(
* +Org-Edna+ * +Org-Edna+
#+begin_src emacs-lisp #+begin_src emacs-lisp :tangle no
;; Org-edna for advanced task dependencies ;; Org-edna for advanced task dependencies
(use-package! org-edna (use-package! org-edna
:after org :after org
@@ -2946,4 +3202,3 @@ Need chrome... :(
:localleader :localleader
:desc "Edit Edna rules" "E" #'org-edna-edit)) :desc "Edit Edna rules" "E" #'org-edna-edit))
#+end_src #+end_src

View File

@@ -50,12 +50,11 @@
(defalias 'getf #'cl-getf)) (defalias 'getf #'cl-getf))
(setq (setq
org-directory "~/ExoKortex/" org-directory "~/ExoKortex/"
+org-capture-todo-file "~/ExoKortex/2-Areas/Meta-Planning/Org/Core/master_list.org" +org-capture-todo-file "~/ExoKortex/3-Telos/5-Kernel/inbox.org"
+org-capture-notes-file "~/ExoKortex/2-Areas/Meta-Planning/Org/Core/master_list.org" +org-capture-notes-file "~/ExoKortex/3-Telos/5-Kernel/inbox.org"
+org-capture-journal-file "~/ExoKortex/2-Areas/Meta-Planning/Org/Core/master_list.org" +org-capture-journal-file "~/ExoKortex/3-Telos/5-Kernel/inbox.org"
+org-capture-emails-file "~/ExoKortex/2-Areas/Meta-Planning/Org/Core/master_list.org" +org-capture-emails-file "~/ExoKortex/3-Telos/5-Kernel/inbox.org"
;; +org-capture-central-project-todo-file '"refile.org" ;; +org-capture-central-project-todo-file '"refile.org"
;; +org-capture-project-todo-file '"refile.org" ;; +org-capture-project-todo-file '"refile.org"
org-agenda-files (directory-files-recursively "~/ExoKortex/" "\\.org$") org-agenda-files (directory-files-recursively "~/ExoKortex/" "\\.org$")
@@ -236,15 +235,34 @@
("p" . "Personal commands") ("p" . "Personal commands")
("wg" "GTD view" ("wg" "GTD view"
( (
(agenda "" ((org-agenda-span 'week))) (agenda "" ((org-agenda-span 'week)
(todo "STRT" ((org-agenda-overriding-header gtd/started-head))) (org-agenda-prefix-format " %12t") ;; reserve time space
(todo "NEXT" ((org-agenda-overriding-header gtd/next-action-head))) (org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
(todo "WAIT" ((org-agenda-overriding-header gtd/waiting-head))) ))
(todo "STRT" ((org-agenda-overriding-header gtd/started-head)
(org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
(todo "NEXT" ((org-agenda-overriding-header gtd/next-action-head)
(org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
(todo "WAIT" ((org-agenda-overriding-header gtd/waiting-head)
(org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
;; (todo "DONE" ((org-agenda-overriding-header gtd/complete-head))) ;; (todo "DONE" ((org-agenda-overriding-header gtd/complete-head)))
(stuck "" ((org-stuck-projects '("TODO=\"PROJ\"" ("NEXT" "STRT") nil "")) (stuck "" ((org-stuck-projects '("TODO=\"PROJ\"" ("NEXT" "STRT") nil ""))
(org-agenda-overriding-header gtd/project-head))) (org-agenda-overriding-header gtd/project-head)
(todo "IDEA" ((org-agenda-overriding-header gtd/someday-head))) (org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
(todo "IDEA" ((org-agenda-overriding-header gtd/someday-head)
(org-agenda-prefix-format " %12t") ;; reserve time space
(org-agenda-todo-keyword-format " %-5s") ;; fixed-width TODO
))
) )
((org-agenda-tag-filter-preset '("+work"))) ((org-agenda-tag-filter-preset '("+work")))
) )
("pg" "GTD view" ("pg" "GTD view"
@@ -336,7 +354,7 @@
) )
("wP" "Installation Bombardier" ("wP" "Installation Bombardier"
((agenda "" ((agenda ""
((org-agenda-span 60) ((org-agenda-span 90)
(org-agenda-start-day "2026-01-29") (org-agenda-start-day "2026-01-29")
(org-agenda-overriding-header "📅 Installation Bombardier") (org-agenda-overriding-header "📅 Installation Bombardier")
(org-agenda-prefix-format " %12t") ;; reserve time space (org-agenda-prefix-format " %12t") ;; reserve time space
@@ -349,7 +367,7 @@
) )
) )
) )
) )
(after! org (after! org
;; Rust code block setting ;; Rust code block setting
@@ -357,17 +375,59 @@
) )
(after! org (after! org
(setq (setq org-format-latex-options (plist-put org-format-latex-options :scale 2.0))
;; LaTeX math preview ;; 1. Use XeLaTeX to generate the intermediate file for dvisvgm
org-format-latex-options '(:foreground default :background default :scale 2 :html-foreground "Black" ;; This handles UTF-8 (like long dashes) which standard 'latex' crashes on.
:html-background "Transparent" :html-scale 1.0 (setq org-preview-latex-process-alist
:matchers ("begin" "$1" "$" "$$" "\\(" "\\[")) '((dvisvgm
) :programs ("xelatex" "dvisvgm")
:description "xdv to svg"
:message "rendering %f via xelatex..."
:image-input-type "xdv"
:image-output-type "svg"
:image-size-adjust (1.0 . 1.0)
:latex-compiler ("xelatex -interaction nonstopmode -no-pdf -output-directory %o %f")
:image-converter ("dvisvgm %f --no-fonts --exact-bbox --scale=%S --output=%O"))))
(setq org-preview-latex-default-process 'dvisvgm)
(defun gortium/org-latex-preview-all ()
"Render all LaTeX fragments in the buffer."
(interactive)
(when (derived-mode-p 'org-mode)
(org-latex-preview '(16))))
;; 1.5s delay to ensure Doom font-colors load first
;; (add-hook 'org-mode-hook
;; (lambda ()
;; (run-with-idle-timer 1.5 nil #'gortium/org-latex-preview-all)))
) )
(after! ox-latex (after! ox-latex
(setq org-latex-compiler "xelatex")) (setq org-latex-src-block-backend 'listings)
(add-to-list 'org-latex-packages-alist '("" "listings") t)
(add-to-list 'org-latex-packages-alist '("" "xcolor") t)
(add-to-list 'org-latex-listings-langs '(text ""))
(setq org-latex-listings-options
'(("breaklines" "true")
("basicstyle" "\\small\\ttfamily")
("frame" "single")
("backgroundcolor" "\\color{gray!10}"))))
(use-package! org-fragtog
:hook (org-mode . org-fragtog-mode))
(defun gortium/org-latex-refresh-on-zoom (&rest _)
(when (derived-mode-p 'org-mode)
(let ((new-scale (+ 2 (* 0.5 (if (boundp 'text-scale-mode-amount) text-scale-mode-amount 0)))))
(setq org-format-latex-options
(plist-put org-format-latex-options :scale new-scale))
(org-clear-latex-preview)
(gortium/org-latex-preview-all))))
(advice-add 'text-scale-increase :after #'gortium/org-latex-refresh-on-zoom)
(advice-add 'text-scale-decrease :after #'gortium/org-latex-refresh-on-zoom)
(after! org (after! org
(setq (setq
@@ -397,11 +457,56 @@
) )
) )
(after! org
;; Ensure exported HTML opens in the system browser, not inside Emacs
(setq org-file-apps
(append '(("\\.x?html?\\'" . default))
(assq-delete-all "\\.x?html?\\'" org-file-apps))))
(after! grip-mode
(setq grip-binary-path "/home/tpouplier/.local/bin/grip")
)
(after! markdown-mode
(setq markdown-header-scaling t)
(custom-set-faces
'(markdown-header-face-1 ((t
:inherit markdown-header-face
:foreground "#fabd2f"
:height 1.8
:weight extra-bold)))
'(markdown-header-face-2 ((t
:inherit markdown-header-face
:foreground "#fe8019"
:height 1.4
:weight extra-bold)))
'(markdown-header-face-3 ((t
:inherit markdown-header-face
:foreground "#fb4934"
:height 1.2
:weight bold)))
'(markdown-header-face-4 ((t
:inherit markdown-header-face
:foreground "#b8bb26"
:height 1.1
:weight bold)))
'(markdown-header-face-5 ((t
:inherit markdown-header-face
:foreground "#83a598"
:height 1.0
:weight bold)))
'(markdown-header-face-6 ((t
:inherit markdown-header-face
:foreground "#d3869b"
:height 1.0
:weight bold))))
)
;; Enable plantuml-mode for PlantUML files ;; Enable plantuml-mode for PlantUML files
(add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode)) (add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode))
(setq org-roam-directory (file-truename "~/ExoKortex/") (setq org-roam-directory (file-truename "~/ExoKortex/")
org-roam-db-location (file-truename "~/ExoKortex/2-Areas/IT/Roam/org-roam.db") org-roam-db-location (file-truename "~/ExoKortex/1-Soma/2-Areas/IT/Roam/org-roam.db")
org-attach-id-dir "assets/" org-attach-id-dir "assets/"
org-roam-dailies-directory "~/ExoKortex/2-Areas/Meta-Planning/Org/Journal/Daily") org-roam-dailies-directory "~/ExoKortex/2-Areas/Meta-Planning/Org/Journal/Daily")
@@ -630,14 +735,14 @@ Handles org-clock and context link capture for tasks."
(after! ispell (after! ispell
(setq ispell-program-name "hunspell" (setq ispell-program-name "hunspell"
ispell-dictionary "en_CA,fr_CA" ispell-dictionary "en_CA,fr_CA"
ispell-personal-dictionary "/home/tpouplier/ExoKortex/2-Areas/IT/Dictionaries/perso.dic") ispell-personal-dictionary "/home/tpouplier/ExoKortex/1-Soma/2-Areas/IT/Dictionaries/perso.dic")
;; Set the dictionary path environment variable ;; Set the dictionary path environment variable
(setenv "DICPATH" "/home/tpouplier/ExoKortex/2-Areas/IT/Dictionaries") (setenv "DICPATH" "/home/tpouplier/ExoKortex/1-Soma/2-Areas/IT/Dictionaries")
(setq ispell-hunspell-dict-paths-alist (setq ispell-hunspell-dict-paths-alist
'(("fr_CA" "/home/tpouplier/ExoKortex/2-Areas/IT/Dictionaries/fr_CA.aff") '(("fr_CA" "/home/tpouplier/ExoKortex/1-Soma/2-Areas/IT/Dictionaries/fr_CA.aff")
("en_CA" "/home/tpouplier/ExoKortex/2-Areas/IT/Dictionaries/en_CA.aff"))) ("en_CA" "/home/tpouplier/ExoKortex/1-Soma/2-Areas/IT/Dictionaries/en_CA.aff")))
(setq ispell-hunspell-dictionary-alist (setq ispell-hunspell-dictionary-alist
'(("fr_CA" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "fr_CA") nil utf-8) '(("fr_CA" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "fr_CA") nil utf-8)
@@ -760,29 +865,6 @@ Handles org-clock and context link capture for tasks."
(add-to-list 'auto-mode-alist '("\\.hledger\\'" . hledger-mode)) (add-to-list 'auto-mode-alist '("\\.hledger\\'" . hledger-mode))
) )
;; Hook fragtog to org-mode to have editable latex preview
(use-package! org-fragtog
:hook (org-mode . org-fragtog-mode))
;; Rescale latex preview when changing font size
(defun gortium/org-latex-refresh-on-zoom (&rest _)
"Dynamically rescale and refresh all LaTeX previews after text zoom."
(when (derived-mode-p 'org-mode)
;; Dynamically update scale relative to zoom level
(setq org-format-latex-options
(plist-put org-format-latex-options
:scale (+ 2 (* 0.5 text-scale-mode-amount))
))
;; Clear all previews
(org-clear-latex-preview)
;; Re-render all previews
(org-latex-preview '(16))
))
(advice-add 'text-scale-increase :after #'gortium/org-latex-refresh-on-zoom)
(advice-add 'text-scale-decrease :after #'gortium/org-latex-refresh-on-zoom)
(advice-add 'text-scale-set :after #'gortium/org-latex-refresh-on-zoom)
(use-package! age (use-package! age
:demand t :demand t
:config :config
@@ -846,11 +928,11 @@ Handles org-clock and context link capture for tasks."
;; rebind function value for pass to passage ;; rebind function value for pass to passage
(fset #'pass (lambda () (interactive) (passage))) (fset #'pass (lambda () (interactive) (passage)))
(setq age-program "rage") (setq age-program "rage")
(setq auth-source-passage-filename (expand-file-name "~/ExoKortex/2-Areas/IT/dotfiles/secrets")) (setq auth-source-passage-filename (expand-file-name "~/ExoKortex/4-Automata/dotfiles/secrets"))
(setenv "PASSAGE_IDENTITIES_FILE" (expand-file-name age-default-identity)) (setenv "PASSAGE_IDENTITIES_FILE" (expand-file-name age-default-identity))
(setenv "PASSAGE_RECIPIENTS_FILE" (expand-file-name age-default-recipient)) (setenv "PASSAGE_RECIPIENTS_FILE" (expand-file-name age-default-recipient))
(setenv "PASSAGE_AGE" "rage") (setenv "PASSAGE_AGE" "rage")
(setenv "PASSAGE_DIR" (expand-file-name "~/ExoKortex/2-Areas/IT/dotfiles/secrets")) (setenv "PASSAGE_DIR" (expand-file-name "~/ExoKortex/4-Automata/dotfiles/secrets"))
) )
(diff-hl-mode +1) (diff-hl-mode +1)
@@ -889,7 +971,8 @@ Handles org-clock and context link capture for tasks."
deepseek/deepseek-chat-v3-0324:free deepseek/deepseek-chat-v3-0324:free
meta-llama/llama-4-maverick:free meta-llama/llama-4-maverick:free
mistralai/devstral-2512:free mistralai/devstral-2512:free
qwen/qwen3-coder:free)) qwen/qwen3-coder:free
nvidia/nemotron-3-nano-30b-a3b:free))
(gptel-make-gemini "Gemini" (gptel-make-gemini "Gemini"
:key (auth-source-passage-get 'secret "gemini") :key (auth-source-passage-get 'secret "gemini")
:stream t :stream t
@@ -988,7 +1071,9 @@ DIFF:
) )
;; Dirvish config ;; Dirvish config
(after! dirvish (after! (dirvish dired)
(require 'async)
(dired-async-mode 1)
;; Display icons, file size, timestamps, etc. ;; Display icons, file size, timestamps, etc.
(setq dirvish-attributes (setq dirvish-attributes
'(nerd-icons '(nerd-icons
@@ -1021,7 +1106,10 @@ DIFF:
("d" "~/Downloads/" "Downloads") ("d" "~/Downloads/" "Downloads")
("u" "/run/media" "Mounted drives") ("u" "/run/media" "Mounted drives")
("t" "~/.local/share/Trash/files/" "Trash") ("t" "~/.local/share/Trash/files/" "Trash")
))) ))
(setq dirvish-yank-use-rsync t)
(setq dirvish-yank-rsync-args '("-ah" "--info=progress2"))
)
;; Use `p` to open the yank menu ;; Use `p` to open the yank menu
(map! :after dirvish-yank (map! :after dirvish-yank
@@ -1100,14 +1188,50 @@ DIFF:
(setq org-msg-options "html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil \\n:t" (setq org-msg-options "html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil \\n:t"
org-msg-startup "hidestars indent inlineimages" org-msg-startup "hidestars indent inlineimages"
org-msg-greeting-fmt "\nBonjour%s,\n\n" org-msg-greeting-fmt "\nBonjour%s,\n\n"
;; org-msg-recipient-names '(("jeremy.compostella@gmail.com" . "Jérémy"))
org-msg-greeting-name-limit 1 org-msg-greeting-name-limit 1
org-msg-default-alternatives '((new . (text html)) org-msg-default-alternatives '((new . (text html))
(reply-to-html . (text html)) (reply-to-html . (text html))
(reply-to-text . (text))) (reply-to-text . (text)))
org-msg-convert-citation t org-msg-convert-citation t)
org-msg-signature " )
(after! mu4e
(setq mu4e-maildir-shortcuts mu4e-maildir-list mu4e-maildir-initial-input mu4e-maildir-info-delimiter)
(setq mu4e-contexts
(list
;; --- CONTEXT: TDNDE ---
(make-mu4e-context
:name "TDNDE"
:match-func (lambda (msg)
(when msg
(string-prefix-p "/TDNDE/" (mu4e-message-field msg :maildir))))
:vars
'((user-mail-address . "tpouplier@tdnde.com")
(user-full-name . "Thierry Pouplier")
;; Folders
(mu4e-sent-folder . "/TDNDE/Sent")
(mu4e-drafts-folder . "/TDNDE/Drafts")
(mu4e-trash-folder . "/TDNDE/Trash")
(mu4e-refile-folder . "/TDNDE/Archive")
;; Shortcuts
(mu4e-maildir-shortcuts . (("/TDNDE/Inbox" . ?i)
("/TDNDE/Sent" . ?s)
("/TDNDE/Drafts" . ?d)
("/TDNDE/Trash" . ?t)
("/TDNDE/Archive" . ?a)))
;; SMTP
(smtpmail-smtp-user . "tpouplier@tdnde.com")
(smtpmail-stream-type . ssl)
(smtpmail-smtp-server . "smtp.hostinger.com")
(smtpmail-smtp-service . 465)
(mu4e-sent-messages-behavior . sent)
;; Context-specific signature
(org-msg-signature . "
Cdlt, Cdlt,
#+begin_signature #+begin_signature
@@ -1121,93 +1245,66 @@ Tél. : +1 (450) 667-1884 \\\\
Cell. : +1 (514) 887-1674 \\\\ Cell. : +1 (514) 887-1674 \\\\
tpouplier@tdnde.com \\\\ tpouplier@tdnde.com \\\\
www.tdnde.com \\\\ www.tdnde.com \\\\
#+end_signature") #+end_signature")))
)
(after! mu4e ;; --- CONTEXT: Perso ---
(setq mu4e-maildir-shortcuts mu4e-maildir-list mu4e-maildir-initial-input mu4e-maildir-info-delimiter)
(setq mu4e-contexts
(list
(make-mu4e-context (make-mu4e-context
:name "TDNDE" :name "Perso"
:match-func :match-func (lambda (msg)
(lambda (msg)
(when msg (when msg
(string-prefix-p (string-prefix-p "/Perso/" (mu4e-message-field msg :maildir))))
"/TDNDE/" :vars `((user-mail-address . "thierrypouplier@gmail.com")
(mu4e-message-field msg :maildir))))
:vars
'((user-mail-address . "tpouplier@tdnde.com")
(user-full-name . "Thierry Pouplier") (user-full-name . "Thierry Pouplier")
(mu4e-sent-folder . "/Perso/Sent")
(mu4e-drafts-folder . "/Perso/Drafts")
(mu4e-trash-folder . "/Perso/Trash")
(mu4e-refile-folder . "/Perso/Archive")
;; Folders (mu4e-maildir-shortcuts . (("/Perso/Inbox" . ?i)
(mu4e-sent-folder . "/TDNDE/Sent") ("/Perso/Sent" . ?s)
(mu4e-drafts-folder . "/TDNDE/Drafts") ("/Perso/Trash" . ?t)
(mu4e-trash-folder . "/TDNDE/Trash") ("/Perso/Drafts" . ?d)
(mu4e-refile-folder . "/TDNDE/Archive") ("/Perso/Archive" . ?a)))
;; Shortcuts (smtpmail-smtp-user . "thierrypouplier@gmail.com")
(mu4e-maildir-shortcuts (smtpmail-smtp-server . "smtp.gmail.com")
. (smtpmail-smtp-service . 587)
(("/TDNDE/Inbox" . ?i) (smtpmail-stream-type . starttls)
("/TDNDE/Sent" . ?s) (mu4e-sent-messages-behavior . sent)
("/TDNDE/Drafts" . ?d) (org-msg-signature . "
("/TDNDE/Trash" . ?t) Cordialement,
("/TDNDE/Archive" . ?a)))
;; Bookmarks #+begin_signature
(mu4e-bookmarks --
. *Thierry Pouplier* \\
((:name "Airbus-6825" (514) 887-1674 | thierrypouplier@gmail.com
:query "maildir:/TDNDE/* AND label:proj:6825 AND label:client:airbus" #+end_signature"))))) ;; End of mu4e-contexts list
:key ?A)
(:name "Bombardier-3154"
:query "maildir:/TDNDE/* AND label:proj:3154 AND label:client:bombardier"
:key ?B)
(:name "Daher-5304"
:query "maildir:/TDNDE/* AND label:proj:5304 AND label:client:daher"
:key ?D)
(:name "TDNDE"
:query "maildir:/TDNDE/* AND label:tdnde"
:key ?T)))
;; SMTP
(smtpmail-smtp-user . "tpouplier@tdnde.com")
(smtpmail-stream-type . ssl)
(smtpmail-smtp-server . "smtp.hostinger.com")
(smtpmail-smtp-service . 465)))
;; Other context here
;; (make-mu4e-context ...)
)
)
(setq mu4e-context-policy 'pick-first (setq mu4e-context-policy 'pick-first
mu4e-compose-context-policy 'ask) mu4e-compose-context-policy 'ask)
(require 'mu4e-icalendar) (require 'mu4e-icalendar)
(mu4e-icalendar-setup) (mu4e-icalendar-setup)
(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 '("Journal"))
(gnus-icalendar-org-setup) (gnus-icalendar-org-setup)
)
;; Separate after! blocks for clarity
(after! mu4e (after! mu4e
(setq mu4e-modeline-support nil)) (setq mu4e-modeline-support nil))
(after! mu4e (after! mu4e
;; restore label key ;; restore label key
(evil-define-key 'normal mu4e-headers-mode-map"l" #'mu4e-headers-mark-for-label) (evil-define-key 'normal mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label)
(evil-define-key 'visual mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label) (evil-define-key 'visual mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label)
(evil-define-key 'emacs mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label) (evil-define-key 'emacs mu4e-headers-mode-map "l" #'mu4e-headers-mark-for-label)
(evil-define-key 'normal mu4e-view-mode-map "l" #'mu4e-view-mark-for-label) (evil-define-key 'normal mu4e-view-mode-map "l" #'mu4e-view-mark-for-label)
(evil-define-key 'visual mu4e-view-mode-map "l" #'mu4e-view-mark-for-label) (evil-define-key 'visual mu4e-view-mode-map "l" #'mu4e-view-mark-for-label)
(evil-define-key 'emacs mu4e-view-mode-map "l" #'mu4e-view-mark-for-label) (evil-define-key 'emacs mu4e-view-mode-map "l" #'mu4e-view-mark-for-label)))
)
(defun gortium-circe-nickserv-password (server) (defun gortium-circe-nickserv-password (server)
(auth-source-passage-get 'secret "irc")) (auth-source-passage-get 'secret "irc"))
@@ -1475,7 +1572,7 @@ Returns nil if no range found (safe, non-blocking)."
(all-resolved t)) (all-resolved t))
(when (and (string-match "ids(\\(.*?\\))" clean) (when (and (string-match "ids(\\(.*?\\))" clean)
(not (string-empty-p (s-trim (match-string 1 clean))))) (not (string-empty-p (s-trim (match-string 1 clean)))))
(dolist (tid (split-string (match-string 1 clean) "[ ,]+" t)) (dolist (tid (split-string (match-string 1 clean) "[[:space:],]+" t))
(let* ((clean-id (replace-regexp-in-string "[\"']\\|id: " "" tid)) (let* ((clean-id (replace-regexp-in-string "[\"']\\|id: " "" tid))
(pos (org-id-find clean-id t)) (pos (org-id-find clean-id t))
(computed-end (gethash clean-id task-end-map)) (computed-end (gethash clean-id task-end-map))
@@ -1497,6 +1594,9 @@ Returns nil if no range found (safe, non-blocking)."
;; Priority 2: Use range end if FIXED ;; Priority 2: Use range end if FIXED
((string-equal "t" (org-entry-get nil "FIXED")) ((string-equal "t" (org-entry-get nil "FIXED"))
(gortium/org--get-range-end m)) (gortium/org--get-range-end m))
;; Priority 3: Fallback to existing range end if it exists
((gortium/org--get-range-end m)
(gortium/org--get-range-end m))
(t nil)))))) (t nil))))))
(t nil))) (t nil)))
@@ -1707,10 +1807,27 @@ Returns list of task IDs involved in cycles, or nil if no cycles found."
(push task done-this-loop)))))))) (push task done-this-loop))))))))
(setq remaining (cl-set-difference remaining done-this-loop)))) (setq remaining (cl-set-difference remaining done-this-loop))))
;; --- DIAGNOSTICS FOR UNSCHEDULED TASKS ---
(if remaining
(progn
(message "!!! WARNING: %d tasks were NOT scheduled !!!" (length remaining))
(dolist (task remaining)
(pcase-let ((`(,_buf ,pos ,id ,_eff ,blocker ,_fix ,_sch ,_off) task))
(let* ((blocker-string (format "%s" blocker))
(clean-blocker (if (string-match "ids(\\(.*?\\))" blocker-string)
(match-string 1 blocker-string)
"None")))
(message " -> Task [%s] at pos %s is BLOCKED by: %s"
id (marker-position pos) clean-blocker)))))
(message "=== All tasks scheduled successfully! ==="))
;; 3. CLEANUP ;; 3. CLEANUP
(setq org-element-use-cache t) (setq org-element-use-cache t)
(org-element-cache-reset 'all) (org-element-cache-reset 'all)
(message "=== Scheduler completed (%d tasks, %d iterations) ===" (length all-tasks) iter)))) (message "=== Scheduler completed (%d tasks, %d iterations) ===" (length all-tasks) iter)
;; (gortium/org-rollup-parent-ranges)
;; (message "=== All Scheduling and Roll-ups Complete ===")
)))
;; --------------------------------------------- ;; ---------------------------------------------
(defun gortium/org-ensure-task-properties () (defun gortium/org-ensure-task-properties ()
@@ -1751,6 +1868,138 @@ and ensure the standard property drawer exists without overwriting existing data
(lambda () (org-id-get-create)) (lambda () (org-id-get-create))
nil 'tree))) nil 'tree)))
(after! org
;; ---------------------------------------------------------
;; 1. THE REUSABLE ENGINE (Domain Agnostic)
;; ---------------------------------------------------------
(defun my/org-metric-sync-engine (&key prop-name value-current prop-last-done prop-interval target-tag log-label)
"Core logic to sync parent metrics to sub-tasks and log changes.
PROP-NAME: The property triggering the change (e.g., LAST_KM).
VALUE-CURRENT: The new value being set.
PROP-LAST-DONE: Sub-task property for 'baseline' (e.g., LAST_DONE_KM).
PROP-INTERVAL: Sub-task property for 'frequency' (e.g., INTERVAL_KM).
TARGET-TAG: Filter for specific sub-tasks (e.g., SERVICE).
LOG-LABEL: The prefix used in the Logbook entry."
(save-excursion
;; A. Log the update to the Logbook with a timestamp
(when log-label
(org-add-log-setup 'note (format "%s: %s" log-label value-current) nil 'findpos))
;; B. Narrow scope to current header and scan sub-tasks
(org-narrow-to-subtree)
(org-map-entries
(lambda ()
(let* ((last-done (string-to-number (or (org-entry-get nil prop-last-done) "0")))
(interval (string-to-number (or (org-entry-get nil prop-interval) "0")))
(current (string-to-number value-current)))
;; Only process tasks that have an interval set
(when (> interval 0)
(if (>= current (+ last-done interval))
(org-todo "TODO")
(org-todo "HOLD")))))
target-tag)
(widen)))
(defun my/org-metric-prompt-engine (&key state tag prop-parent-metric prop-task-done label-prompt)
"Core logic to prompt for values when a task is marked DONE.
STATE: The new TODO state (e.g., DONE).
TAG: The tag identifying relevant tasks.
PROP-PARENT-METRIC: The property on the parent to update (e.g., LAST_KM).
PROP-TASK-DONE: The property on the task to update (e.g., LAST_DONE_KM).
LABEL-PROMPT: The text shown in the minibuffer."
(when (string= state "DONE")
(let ((tags (org-get-tags)))
(when (member tag tags)
(save-excursion
;; Inherit parent metric as the default value for the prompt
(let* ((current-val (org-entry-get nil prop-parent-metric t))
(input-val (read-string (format "%s (default %s): " label-prompt (or current-val "0"))
nil nil current-val)))
;; 1. Update the task property
(org-set-property prop-task-done input-val)
;; 2. Update the parent property (triggers the sync engine)
(save-excursion
(when (org-up-heading-safe)
(org-set-property prop-parent-metric input-val)))
(message "Synchronized %s to %s" label-prompt input-val)))))))
;; ---------------------------------------------------------
;; 2. THE DISPATCHERS (The Switchboard)
;; ---------------------------------------------------------
(defun my/org-property-change-handler (prop value)
"Routes property changes to the correct sync parameters."
(cond
;; Case: F-150 Odometer
((string= prop "LAST_KM")
(my/org-metric-sync-engine
:prop-name prop :value-current value :prop-last-done "LAST_DONE_KM"
:prop-interval "INTERVAL_KM" :target-tag "SERVICE" :log-label "Odometer Update"))))
;; Case: Equipment/Industrial Hours
;; ((string= prop "LAST_HOURS")
;; (my/org-metric-sync-engine
;; :prop-name prop :value-current value :prop-last-done "LAST_DONE_HOURS"
;; :prop-interval "INTERVAL_HOURS" :target-tag "MAINTENANCE" :log-label "Usage Hours Logged"))))
(defun my/org-todo-state-handler ()
"Safely routes DONE completions, catching any argument errors."
(interactive)
(condition-case err
(when (string= org-state "DONE")
(my/org-metric-prompt-engine
:state "DONE"
:tag "SERVICE"
:prop-parent-metric "LAST_KM"
:prop-task-done "LAST_DONE_KM"
:label-prompt "Current Odometer"))
(error (message "Handler suppressed error: %s" (error-message-string err)))))
)
;; (my/org-metric-prompt-engine
;; :state org-state :tag "MAINTENANCE" :prop-parent-metric "LAST_HOURS"
;; :prop-task-done "LAST_DONE_HOURS" :label-prompt "Equipment Hours"))
;; ---------------------------------------------------------
;; 3. THE HOOKS
;; ---------------------------------------------------------
(add-hook 'org-after-prop-change-hook #'my/org-property-change-handler)
(add-hook 'org-after-todo-state-change-hook #'my/org-todo-state-handler)
(defun my/org-smart-advance-date ()
"Jump to next repeater occurrence or add 1 day.
Suppresses all logging, notes, and custom odometer hooks."
(interactive)
(let ((org-log-done nil)
(org-log-repeat nil)
(org-todo-repeat-to-state "LOOP")
(org-after-todo-state-change-hook nil)
(org-treat-insert-todo-log-note nil)
(inhibit-modification-hooks t))
(let ((is-agenda (derived-mode-p 'org-agenda-mode)))
(cond
;; Case 1: Task has a repeater (teleport to next date)
((if is-agenda
(org-agenda-with-point-at-orig-entry nil (org-get-repeat))
(org-get-repeat))
;; This surgical strike prevents the Logbook entry entirely
(cl-letf (((symbol-function 'org-add-log-setup) (lambda (&rest _args) nil)))
(if is-agenda (org-agenda-todo "DONE") (org-todo "DONE")))
(message "Silently jumped to next occurrence."))
;; Case 2: No repeater, fallback to standard +1 day shift
(t
(if is-agenda
(org-agenda-date-later 1)
(org-timestamp-change 1 'day))
(message "No repeater found: Added 1 day."))))))
(map! :after org
(:map org-mode-map
:localleader "L" #'my/org-smart-advance-date)
(:map org-agenda-mode-map
:localleader "L" #'my/org-smart-advance-date))
;; Open link in another frame ;; Open link in another frame
(defun gortium/org-open-link-in-other-frame () (defun gortium/org-open-link-in-other-frame ()
"Open the Org link at point in another frame." "Open the Org link at point in another frame."
@@ -1937,13 +2186,3 @@ fallback to today's daily note. Ensures the daily has an Org-roam ID."
(message "Task refiled under '%s' in %s" (message "Task refiled under '%s' in %s"
headline headline
(file-name-nondirectory daily-file))))) (file-name-nondirectory daily-file)))))
;; Org-edna for advanced task dependencies
(use-package! org-edna
:after org
:config
(setq org-edna-use-inheritance t)
(org-edna-mode 1)
(map! :map org-mode-map
:localleader
:desc "Edit Edna rules" "E" #'org-edna-edit))

View File

@@ -150,7 +150,9 @@
;;lean ; for folks with too much to prove ;;lean ; for folks with too much to prove
ledger ; be audit you can be ledger ; be audit you can be
lua ; one-based indices? one-based indices lua ; one-based indices? one-based indices
markdown ; writing docs for people to ignore (markdown ; writing docs for people to ignore
+grip
+tree-sitter)
;;nim ; python + lisp at the speed of c ;;nim ; python + lisp at the speed of c
(nix ; I hereby declare "nix geht mehr!" (nix ; I hereby declare "nix geht mehr!"
+lsp +lsp

View File

@@ -101,8 +101,8 @@ env = WLR_RENDERER_ALLOW_SOFTWARE,1
# https://wiki.hyprland.org/Configuring/Variables/#general # https://wiki.hyprland.org/Configuring/Variables/#general
general { general {
gaps_in = 4.5 gaps_in = 7.5
gaps_out = 9 gaps_out = 15
border_size = 2 border_size = 2
@@ -148,7 +148,12 @@ animations {
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
dwindle { dwindle {
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
# This prevents the layout from collapsing if you close one window
preserve_split = true # You probably want this preserve_split = true # You probably want this
# 0 -> follow mouse, 1 -> always left/top, 2 -> always right/bottom
force_split = 2
} }
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
@@ -208,7 +213,7 @@ $mainMod = SUPER # Sets "Windows" key as main modifier
bind = $mainMod, T, exec, $terminal bind = $mainMod, T, exec, $terminal
bind = $mainMod, D, killactive, bind = $mainMod, D, killactive,
bind = $mainMod SHIFT, Q, exit, bind = $mainMod SHIFT, Q, exit,
bind = $mainMod, U, exec, ~/ExoKortex/2-Areas/IT/dotfiles/scripts/make_all.sh bind = $mainMod, U, exec, ~/ExoKortex/4-Automata/dotfiles/scripts/make_all.sh
bind = $mainMod, M, exec, $monitoring bind = $mainMod, M, exec, $monitoring
bind = $mainMod, E, exec, $editor bind = $mainMod, E, exec, $editor
bind = $mainMod, V, togglefloating, bind = $mainMod, V, togglefloating,
@@ -219,8 +224,8 @@ bind = $mainMod, P, togglesplit, # dwindle
bind = $mainMod, N, movecurrentworkspacetomonitor, -1 bind = $mainMod, N, movecurrentworkspacetomonitor, -1
bind = $mainMod SHIFT, N, movecurrentworkspacetomonitor, +1 bind = $mainMod SHIFT, N, movecurrentworkspacetomonitor, +1
bind = $mainMod, X, swapwindow bind = $mainMod, X, swapwindow
bind = $mainMod, B, exec, nerd-dictation begin bind = $mainMod, B, exec, python /home/tpouplier/ExoKortex/4-Automata/recordntrans/record_transcribe.py
bind = $mainMod, G, exec, nerd-dictation end # bind = $mainMod, G, exec, nerd-dictation end
bind = $mainMod, A, exec, $music bind = $mainMod, A, exec, $music
# Full screen # Full screen
@@ -287,8 +292,8 @@ bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10 bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Example special workspace (scratchpad) # Example special workspace (scratchpad)
bind = $mainMod, S, togglespecialworkspace, magic bind = $mainMod, S, togglespecialworkspace, tools
bind = $mainMod SHIFT, S, movetoworkspace, special:magic bind = $mainMod SHIFT, S, movetoworkspace, special:tools
# Scroll through existing workspaces with mainMod + scroll # Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1 bind = $mainMod, mouse_down, workspace, e+1
@@ -376,4 +381,42 @@ workspace = 3, name:long-1, monitor:DP-5 # Right screen
workspace = 4, name:long-2, monitor:DP-5 # Right screen workspace = 4, name:long-2, monitor:DP-5 # Right screen
workspace = 5, name:smoll, monitor:eDP-1 # Laptop screen workspace = 5, name:smoll, monitor:eDP-1 # Laptop screen
#workspace = 4, name:windows, monitor:DP-4, on-created-empty:VBoxManage startvm "Windows 11" #workspace = 4, name:windows, monitor:DP-4, on-created-empty:VBoxManage startvm "Windows 11"
#workspace = special:scratchpad, on-created-empty:kitty workspace = special:tools, layout:dwindle, gapsin:0
# Top Left: btop
windowrule {
name = dashboard-btop
match:class = ^(btop)$
tile = true
workspace = special:tools
}
# Top Right: ncspot
windowrule {
name = dashboard-ncspot
match:class = ^(ncspot)$
tile = true
workspace = special:tools
}
# Bottom Left: ncpamixer
windowrule {
name = dashboard-ncpamixer
match:class = ^(ncpamixer)$
tile = true
workspace = special:tools
}
# Bottom Right: bluetuith
windowrule {
name = dashboard-bluetuith
match:class = ^(bluetuith)$
tile = true
workspace = special:tools
}
# Bind to launch the suite (Run this once)
bind = $mainMod, grave, exec, kitty --class btop btop
bind = $mainMod, grave, exec, kitty --class ncspot ncspot
bind = $mainMod, grave, exec, kitty --class ncpamixer ncpamixer
bind = $mainMod, grave, exec, kitty --class bluetuith bluetuith

View File

@@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
cd ~/ExoKortex/2-Areas/IT/dotfiles/ cd ~/ExoKortex/4-Automata/dotfiles/
make all make all
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
notify-send "Dotfiles" "Configuration reloaded successfully!" notify-send "Dotfiles" "Configuration reloaded successfully!"

View File

@@ -33,7 +33,7 @@ if systemctl --user is-active --quiet rclone_ftp_mount.service; then
echo "Rclone service is already running." echo "Rclone service is already running."
else else
echo "Starting the rclone service." echo "Starting the rclone service."
systemctl start rclone_ftp_mount.service || { echo "Failed to start the service"; exit 1; } systemctl --user start rclone_ftp_mount.service || { echo "Failed to start the service"; exit 1; }
fi fi
echo "Post-installation steps for rclone completed successfully." echo "Post-installation steps for rclone completed successfully."

9
secrets/perso-mail.age Normal file
View File

@@ -0,0 +1,9 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEdoTUQ4QSBSTnZa
REtrM2FwSngxY2FRWkdsWWNUU0JETW81eWYwUE9Ndy9TT096UFRnClRzbTJnWEhG
WlAvVlhicjA0Um45TFZNL3VQaDBSMHNaWG1TOEthN1RrVlkKLT4gUXFLVUQ9Xnwt
Z3JlYXNlIDIiIDdnPmZfQCBEClVpYVcxSEMvbnp0VFptdWtENmdQZUtYK05uUVFO
ZWRtCi0tLSBIcGNFcXVKOWhjS3lGZUdNaDd3N2dMN21KT2JhUzIrWHc0UHFOcFlq
TWRzClWaMFgCPM9T0pLoh/HyXVwAALd3fPUKll/VFjHa4eJIGjGa36g5lxU7BxTa
39fa8FNrSHU=
-----END AGE ENCRYPTED FILE-----

View File

@@ -4,11 +4,11 @@
// general settings // general settings
"position": "top", "position": "top",
"margin-top": 8, "margin-top": 15,
"margin-bottom": 0, "margin-bottom": 0,
"layer": "top", "layer": "top",
"margin-left": 8, "margin-left": 15,
"margin-right": 8, "margin-right": 15,
"spacing": 10, "spacing": 10,
"fixed-center": true, "fixed-center": true,
"exclusive": true, "exclusive": true,

View File

@@ -110,7 +110,7 @@
"car": "", "car": "",
"default": ["", "", ""] "default": ["", "", ""]
}, },
"on-click": "pwvucontrol" "on-click": "kitty ncpamixer"
}, },
// bluetooth // bluetooth

View File

@@ -125,3 +125,6 @@ export HYPRSHOT_DIR="Images"
# Atuin # Atuin
#eval "$(atuin init zsh)" #eval "$(atuin init zsh)"
# Created by `pipx` on 2026-03-03 16:51:31
export PATH="$PATH:/home/tpouplier/.local/bin"