aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/tagmail84
-rw-r--r--config/doom/config.org212
-rw-r--r--config/doom/init.el21
-rw-r--r--config/doom/snippets/notmuch-message-mode/nbg-guest23
-rw-r--r--config/doom/snippets/notmuch-message-mode/nbg-membership105
-rw-r--r--config/git/attributes2
-rw-r--r--config/guix/shell-authorized-directories2
-rw-r--r--config/khard/khard.conf4
-rw-r--r--config/pikaur.conf3
-rw-r--r--elisp/ai-query.el64
-rw-r--r--elisp/delivery-track.el81
-rw-r--r--home-dots/dot-profile5
-rwxr-xr-xinstall.scm15
-rw-r--r--mail/dot-mbsyncrc.byteplant6
-rw-r--r--mail/dot-mbsyncrc.personal43
15 files changed, 545 insertions, 125 deletions
diff --git a/bin/tagmail b/bin/tagmail
index 9febae5..ebc18fa 100755
--- a/bin/tagmail
+++ b/bin/tagmail
@@ -156,45 +156,43 @@ LD_LIBRARY_PATH=$HOME/.guix-profile/lib exec guile -e main -s "$0" "$@"
(format #t " ~a messages added to spam~%")))))))
(define tag-rules
- '(("+ci" "from:travis-ci.com or from:travis-ci.org or from:appveyor.com or from:circleci.com or from:mg.gitlab.com and subject:Pipeline")
- ("+slack" "from:slack.com")
- ("+immonews/communications" "from:nachrichten.immobilienscout24.de or subject:Kontaktaufnahme and tag:immonews")
- ("+ingrid" "from:postmaster@oscarnajera.com or from:root@oscarnajera.com" "Reports from ingrid")
- ("+Checkm-Alerts" "subject:Check_MK AND from:ingrid")
- ("+fail2ban" "subject:Fail2Ban from:oscarnajera.com" "Fail2ban report")
- ("+arsmagna +inbox" "to:arsmagna")
- ;; Toastmasters
- ("+NBG-toastmasters" "to:nuremberg.toastmasters@googlemail.com")
- ("+Isar-Speak" "to:isarspeak@gmail.com")
- ("+toastmasters" "toastmaster NOT from:info@meetup.com")
-
- ("+iohk" "from:iohk.io" "IOHK Plutus")
- ("+sms" "folder:hi_pers/SMS")
- ("+calls" "folder:hi_pers/Calls")
- ;; clearing up from newsletters
- ("+Indie-Hackers" "from:channing@indiehackers.com")
- ("+socialnews" "from:facebookmail.com or from:mail.instagram.com")
- ("+promotions" "from:newsletter")
- ("+linkedin +socialnews" "from:linkedin.com" "Linkedin")
- ("+meetups" "from:info@meetup.com or from:info@email.meetup.com" "Meetups info mails")
- ("+immonews" "from:immobilienscout24.de")
- ("+newsletter" "from:venturebeat.com")
- ("+zeihan" "from:zeihan.com")
- ("+freecodecamp" "from:freecodecamp.org")
- ;; byteplant
- ("+support" "to:support@byteplant.com")
- ("+admin" "to:admin@byteplant.com")
- ("+sent" "from:byteplant.com")
- ))
-
-(define (clear-inbox options ffi-db)
- (display "[Inbox]\n")
- (let ((sent (format #f "(~{from:~a~^ OR ~}) AND NOT (~:*~{to:~a~^ OR ~})"
- (assq-ref options 'my-emails))))
- (map (notmuch-tag options ffi-db #t)
- `(("+sent" ,sent "Emails I have sent")
- ("+inbox" "*" "Inbox for the rest")))))
-
+ (let* ((my-emails (list "hi@oscarnajera.com" "hello@oscarnajera.com" "najera.oscar@gmail.com"))
+ (sent (format #f "(~{from:~a~^ OR ~}) AND NOT (~:*~{to:~a~^ OR ~})" my-emails)))
+ `(("+sent" ,sent "Emails I have sent")
+ ("+ci" "from:travis-ci.com or from:travis-ci.org or from:appveyor.com or from:circleci.com or from:mg.gitlab.com and subject:Pipeline")
+ ("+slack" "from:slack.com")
+ ("+immonews/communications" "from:nachrichten.immobilienscout24.de or subject:Kontaktaufnahme and tag:immonews")
+ ("+ingrid" "from:postmaster@oscarnajera.com or from:root@oscarnajera.com" "Reports from ingrid")
+ ("+Checkm-Alerts" "subject:Check_MK AND from:ingrid")
+ ("+fail2ban" "subject:Fail2Ban from:oscarnajera.com" "Fail2ban report")
+ ("+arsmagna +inbox" "to:arsmagna.xyz")
+
+ ;; Toastmasters
+ ("+NBG-toastmasters" "folder:/nbgtm/")
+ ("+sent" "folder:\"/Google Mail]/Sent Mail/\"")
+ ("+Isar-Speak" "to:isarspeak@gmail.com")
+ ("+toastmasters" "toastmaster NOT from:info@meetup.com NOT from:linkedin.com" )
+
+ ("+iohk" "from:iohk.io" "IOHK Plutus")
+ ("+sms" "folder:hi_pers/SMS")
+ ("+calls" "folder:hi_pers/Calls")
+ ;; clearing up from newsletters
+ ("+Indie-Hackers" "from:channing@indiehackers.com")
+ ("+socialnews" "from:facebookmail.com or from:mail.instagram.com")
+ ("+promotions" "from:newsletter")
+ ("+linkedin +socialnews" "from:linkedin.com" "Linkedin")
+ ("+meetups" "from:info@meetup.com or from:info@email.meetup.com" "Meetups info mails")
+ ("+immonews" "from:immobilienscout24.de")
+ ("+newsletter" "from:venturebeat.com")
+ ("+zeihan" "from:zeihan.com")
+ ("+freecodecamp" "from:freecodecamp.org")
+ ;; byteplant
+ ("+support" "to:support@byteplant.com")
+ ("+admin" "to:admin@byteplant.com")
+ ("+AV" "folder:/addressvalidator/")
+ ("+EV" "folder:/addressvalidator/")
+ ("+PV" "folder:/phonevalidator/")
+ ("+sent" "folder:/Sent/"))))
(define (main args)
(let* ((mail-repo (string-append
@@ -224,11 +222,13 @@ LD_LIBRARY_PATH=$HOME/.guix-profile/lib exec guile -e main -s "$0" "$@"
(with-nm-database
(ffi-db mail-repo 'NOTMUCH_DATABASE_MODE_READ_WRITE)
- (let ((new (not (option-ref options 'all #f))))
+ (let* ((new (not (option-ref options 'all #f)))
+ (tagger (notmuch-tag options ffi-db new)))
(display "[TAG rules]\n")
- (map (notmuch-tag options ffi-db new) tag-rules)
+ (map tagger tag-rules)
(list-tag options ffi-db new)
- (clear-inbox options ffi-db)
+ (display "[Inbox]\n")
+ (tagger '("+inbox" "to:oscar@byteplant.com" "Inbox for the rest"))
(tag-spam options ffi-db "tag:inbox")))))
diff --git a/config/doom/config.org b/config/doom/config.org
index 63e6977..339dc73 100644
--- a/config/doom/config.org
+++ b/config/doom/config.org
@@ -28,11 +28,6 @@
(add-hook 'prog-mode-hook 'on/prettify-symbols)
#+end_src
-This determines the style of line numbers in effect. If set to `nil', line
-numbers are disabled. For relative line numbers, set this to `relative'.
-#+begin_src emacs-lisp
-;(setq display-line-numbers-type 'relative)
-#+end_src
** Frame title includes visited file
#+BEGIN_SRC emacs-lisp
;;http://emacs-fu.blogspot.fr/2011/01/setting-frame-title.html
@@ -41,15 +36,6 @@ numbers are disabled. For relative line numbers, set this to `relative'.
(abbreviate-file-name (buffer-file-name))
"%b"))))
#+END_SRC
-** Keybindings
-#+begin_src emacs-lisp
-(map! :leader
- :desc "M-x" "x" #'execute-extended-command
- )
-(after! evil
- (setq evil-default-state 'emacs)
- (set-evil-initial-state! '(prog-mode text-mode fundamental-mode conf-mode pass-view-mode) 'normal))
-#+end_src
** Package Manager
Doom manages packages separately. Keep that file separate
#+begin_src emacs-lisp :tangle "packages.el"
@@ -60,6 +46,35 @@ Doom manages packages separately. Keep that file separate
#+begin_src emacs-lisp
(setenv "SSH_AUTH_SOCK" (concat (getenv "XDG_RUNTIME_DIR")"/gnupg/S.gpg-agent.ssh"))
#+end_src
+** Auth mechanisms
+#+begin_src emacs-lisp :tangle "packages.el"
+(package! pass)
+(package! password-store)
+(package! password-store-otp)
+#+end_src
+
+#+begin_src emacs-lisp
+(use-package! pass
+ :init
+ (require 'auth-source)
+ (auth-source-pass-enable)
+ (defun on/fetch-password (&rest params)
+ (if-let* ((match (car (apply #'auth-source-search params)))
+ (secret (plist-get match :secret)))
+ (if (functionp secret)
+ (funcall secret)
+ secret)
+ (user-error "Password not found for %S" params))))
+#+end_src
+** Keybindings
+#+begin_src emacs-lisp
+;; (map! :leader
+;; :desc "M-x" "x" #'execute-extended-command
+;; )
+(after! evil
+ (setq evil-default-state 'emacs)
+ (set-evil-initial-state! '(prog-mode text-mode fundamental-mode conf-mode pass-view-mode) 'normal))
+#+end_src
** Avy
This allows me to jump to buffer positions using my home row ordering
#+begin_src emacs-lisp
@@ -71,7 +86,6 @@ This allows me to jump to buffer positions using my home row ordering
** Ace window
#+begin_src emacs-lisp
(after! ace-window
- (global-set-key (kbd "s-w") 'evil-window-map)
(setq aw-keys '(?r ?t ?i ?e ?a ?o ?n ?s)))
#+end_src
** Which-key
@@ -107,6 +121,20 @@ Because I always need help and it should come up quickly
#+begin_src emacs-lisp
(add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)
#+end_src
+** AI queries
+#+begin_src emacs-lisp
+(use-package! ai-query
+ :load-path "~/dev/dotfiles/elisp/"
+ :commands (ai-query-request))
+#+end_src
+
+** Track Deliveries
+#+begin_src emacs-lisp
+(use-package! delivery-track
+ :load-path "~/dev/dotfiles/elisp/"
+ :commands (delivery-track-update-dhl))
+#+end_src
+
* Dictionary
#+begin_src emacs-lisp :tangle "packages.el"
(package! lexic)
@@ -157,6 +185,15 @@ Shamelessly copied from https://tecosaur.github.io/emacs-config/#dictionary
`("e" "Event" entry (file ,(expand-file-name
"caldav.org" org-directory))
"* %?\n%^T\n%i\n%a"))
+ (add-to-list 'org-capture-templates
+ `("m" "NBG-TM Contact" entry
+ (file+headline ,(expand-file-name "toastmasters/NBG-membership.org" org-directory) "Guest")
+ "* INTRS [[notmuch-search:%:reply-to][%:fromname]]
+:PROPERTIES:
+:EMAIL: %:reply-to
+:END:
+Invited: %^t
+"))
(setq org-roam-capture-templates '(("d" "default" plain "%i\n%?"
:target (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
@@ -203,8 +240,10 @@ this new window.
(call-process "org_agenda_sync"
nil (list :file (expand-file-name "~/org/caldav.org")) nil
"--format" "org"))
- (setq cal-sync-url "https://oscar@cloud.oscarnajera.com/remote.php/dav/calendars/oscar"
- cal-sync-calendar-id "personal-1"
+ (setq cal-sync-connection
+ (cal-sync-calendar-create
+ "https://cloud.oscarnajera.com/remote.php/dav/calendars/oscar/personal-1/"
+ "oscar" "~/org/caldav.org")
org-icalendar-date-time-format ":%Y%m%dT%H%M%SZ"))
#+end_src
** References
@@ -265,6 +304,7 @@ this new window.
"http://feeds.feedburner.com/TroyHunt"
"http://kitchingroup.cheme.cmu.edu/blog/feed/index.xml"
"http://www.howardism.org/index.xml"
+ "https://www.reddit.com/r/Common_Lisp/.rss"
"https://ag91.github.io/rss.xml"
"https://architectelevator.com/feed.xml"
"https://bitcoinops.org/feed.xml"
@@ -291,7 +331,7 @@ this new window.
#+begin_src emacs-lisp :tangle "packages.el"
(package! notmuch :pin "c769658360e10a6d01a4134e680e2f498741bc5c")
(package! org-mime :pin "cc00afcf0291633324364c1c83bfe2833cfdc1bf")
-(package! ol-notmuch :pin "781c3518a537da2a8b5e8a4424f9441df463a147")
+(package! ol-notmuch :pin "2704345ac8c4558c7c787d2ea0a4777607789a62")
#+end_src
#+BEGIN_SRC emacs-lisp
(use-package! notmuch
@@ -328,7 +368,7 @@ this new window.
(:name "Isar-Speak" :query "(tag:Isar-Speak or tag:lists/isar-speak-officers) and tag:unread" :key "t")
(:name "flagged" :query "tag:flagged" :key "f")
(:name "sent" :query "tag:sent" :key "s")
- (:name "unread" :query "tag:unread" :key "u")
+ (:name "unread" :query "tag:unread and not tag:fail2ban and not tag:Checkm-Alerts" :key "u")
(:name "drafts" :query "tag:draft" :key "d")))
(setq notmuch-show-all-tags-list t
@@ -425,12 +465,9 @@ this new window.
"Read mbsync config to extract IMAPAccounts."
(with-temp-buffer
(insert-file-contents (expand-file-name "~/.mbsyncrc"))
- (let ((pick (thread-last
- (cl-loop while (search-forward-regexp (rx bol "IMAPAccount " (group (+ any)) eol) nil t)
- collect (match-string 1))
- (cons "all")
- (completing-read "Which mailbox"))))
- (if (string= pick "all") nil (list pick)))))
+ (cl-loop while (search-forward-regexp (rx bol "IMAPAccount " (group (+ any)) eol) nil t)
+ collect (match-string 1))))
+
(define-derived-mode mail-sync-log-mode comint-mode "mail-sync-log"
"Major mode for reading mail sync."
@@ -439,16 +476,21 @@ this new window.
(,(rx bol " [mv]") . font-lock-constant-face)
(,(rx bol " [rm]") . font-lock-keyword-face)))))
-(defun on/fetch-all-email ()
- "Start tagmail fetch on a subprocess."
- (interactive)
+(defun on/fetch-all-email (mailbox)
+ "Start tagmail fetch on a subprocess for MAILBOX."
+ (interactive (list (completing-read
+ "Which mailbox? "
+ (on/registered-mail-accounts)
+ nil nil nil nil "all")))
(with-current-buffer (get-buffer-create "*E-mail fetch*")
(pop-to-buffer (current-buffer))
(mail-sync-log-mode)
(make-process
:name "E-mail fetch"
:buffer (current-buffer)
- :command (cons "tagmail" (on/registered-mail-accounts))
+ :command (thread-last
+ (if (string= mailbox "all") nil (list mailbox))
+ (cons "tagmail"))
:filter #'comint-output-filter)))
#+END_SRC
** Sending email
@@ -467,6 +509,7 @@ this new window.
(string-split "@")))
(smtp-servers '("oscarnajera.com" "mail.oscarnajera.com"
"gmail.com" "smtp.googlemail.com"
+ "googlemail.com" "smtp.googlemail.com"
"byteplant.com" "smtp.byteplant.com"))
((&plist :host :user :port :secret)
(car
@@ -489,21 +532,27 @@ this new window.
(package! khardel)
#+end_src
#+begin_src emacs-lisp
-(use-package! khardel)
+(use-package! khardel
+ :config
+ (after! tree-sitter-langs
+ (add-to-list 'tree-sitter-major-mode-language-alist '(khardel-edit-mode . yaml)))
+ (add-hook 'khardel-edit-mode-hook
+ (lambda ()
+ (tree-sitter-mode)
+ (setq imenu-create-index-function #'on/imenu-nested-path-elements))))
#+end_src
* IRC
#+begin_src emacs-lisp
-(set-irc-server! "irc.libera.chat"
- `(:tls t
- :port 6697
- :nick "titan-c"
- :sasl-username ,(+pass-get-user "Social/freenode/titan-c")
- :sasl-password (lambda (&rest _) (+pass-get-secret "Social/freenode/titan-c"))
- :channels ("#emacs" "#guix")))
+(after! circe
+ (set-irc-server! "irc.libera.chat"
+ '(:tls t
+ :port 6697
+ :nick "titan-c"
+ :sasl-username "titan-c"
+ :sasl-password (lambda (&rest _) (on/fetch-password :user "titan-c" :host "freenode"))
+ :channels ("#emacs" "#guix"))))
#+end_src
-#+RESULTS:
-
* Ledger
Emacs mode for managing ledger text files
#+BEGIN_SRC emacs-lisp
@@ -592,13 +641,83 @@ Emacs mode for managing ledger text files
:load-path "~/dev/emacs-lisp/emacs-libyaml/")
(use-package! yaml)
-#+end_src
-** Databases
-#+begin_src emacs-lisp :tangle "packages.el"
-(package! emacsql-psql)
+(after! yaml-mode
+ ;; Inspired by this blog post to use tree sitter to create a imenu list.
+ ;; https://blog.meain.io/2022/navigating-config-files-using-tree-sitter/
+ (defun on/ts-elements ()
+ "Tree sitter matches for all entries in data buffer."
+ (let ((query (thread-last
+ (cond
+ ((derived-mode-p 'json-mode)
+ "(object (pair (string (string_content) @key) (_)) @item)")
+ ((derived-mode-p 'yaml-mode)
+ "(block_mapping_pair (flow_node) @key (_)) @item"))
+ (tsc-make-query tree-sitter-language)))
+ (root-node (tsc-root-node tree-sitter-tree)))
+ (tsc-query-matches query root-node #'tsc--buffer-substring-no-properties)))
+
+ (defun on/pos-items (ts-match)
+ "From a TS-MATCH get element key name and region in buffer."
+ (pcase-let ((`[(_ . ,item) (_ . ,key)] (cdr ts-match)))
+ (list
+ (tsc-node-text key)
+ (tsc-node-byte-range item)
+ ;; (destructuring-bind (s . e) (tsc-node-byte-range key)
+ ;; (cons (byte-to-position s) (byte-to-position e)))
+ )))
+
+ (defun on/nested-item-names (items)
+ "From named ITEMS figure out the nested hierarchy for names."
+ (let ((node-stack '(("" 0)))
+ result)
+ (dolist (item items (nreverse result))
+ (pcase-let ((`(,item-name (,item-start . ,item-end)) item)
+ (`((_ ,parent-end)) node-stack))
+ (when (< parent-end item-end)
+ (setq node-stack (seq-filter (lambda (y)
+ (<= item-end (cadr y)))
+ node-stack)))
+ (push (list item-name item-end) node-stack)
+ (push (list (nreverse (mapcar #'car node-stack))
+ item-start)
+ result)))))
+
+ (defun on/imenu-nested-path-elements ()
+ "On a yaml or json buffer get the element positions for imenu."
+ (thread-last
+ (seq-map #'on/pos-items (on/ts-elements))
+ (on/nested-item-names)
+ (seq-map (lambda (item)
+ (seq-let (name-chain start) item
+ (cons (string-join name-chain ".") (byte-to-position start)))))))
+
+ (remove-hook 'yaml-mode-hook 'yaml-set-imenu-generic-expression) ;; don't use default one
+ (add-hook 'yaml-mode-hook
+ (lambda ()
+ (setq imenu-create-index-function #'on/imenu-nested-path-elements)))
+
+ (ert-deftest on/tree-sitter-imenu ()
+ "Test the imenu generation."
+ (with-temp-buffer
+ (yaml-mode)
+ (tree-sitter-mode)
+ (insert "one: Ñaño
+skills:
+ run: 3
+ jump:
+ high: 7
+ low: 2
+
+")
+ (should
+ (equal '(("one" . 1) ("skills" . 13) ("skills.run" . 23) ("skills.jump" . 32) ("skills.jump.high" . 43) ("skills.jump.low" . 55))
+ (on/imenu-nested-path-elements)))
+ ))
+ )
#+end_src
+** Databases
#+begin_src emacs-lisp
(after! format-all
(define-format-all-formatter sqlformat
@@ -694,15 +813,12 @@ Emacs mode for managing ledger text files
(user "crazy")
(port (plist-get networks
(intern (completing-read "Pick network: " networks))))
- (secret (-some->
- (auth-source-search :host host)
- (car)
- (plist-get :secret))))
+ (secret (on/fetch-password :host host)))
(when (and btc-explorer-bitcoind
(json-rpc-live-p btc-explorer-bitcoind))
(json-rpc-close btc-explorer-bitcoind))
(setq btc-explorer-bitcoind
- (json-rpc-connect host port user (funcall secret))))))
+ (json-rpc-connect host port user secret)))))
(use-package! lnd
:load-path "~/dev/emacs-lisp/btc-explorer/"
diff --git a/config/doom/init.el b/config/doom/init.el
index cd9d65d..7394840 100644
--- a/config/doom/init.el
+++ b/config/doom/init.el
@@ -22,17 +22,18 @@
:completion
company ; the ultimate code completion backend
+ ;; (corfu +orderless) ; complete with cap(f), cape and a flying feather!
;; helm ; the *other* search engine for love and life
- ;;ido ; the other *other* search engine...
- ivy ; a search engine for love and life
- ;; vertico ; the search engine of the future
+ ;; ido ; the other *other* search engine...
+ ;; ivy ; a search engine for love and life
+ vertico ; the search engine of the future
:ui
;;deft ; notational velocity for Emacs
doom ; what makes DOOM look the way it does
;; doom-dashboard ; a nifty splash screen for Emacs
;;doom-quit ; DOOM quit-message prompts when you quit Emacs
- ;;(emoji +unicode) ; 🙂
+ (emoji +unicode) ; 🙂
hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW
;;hydra
;;indent-guides ; highlighted indent columns
@@ -45,7 +46,7 @@
(popup +defaults) ; tame sudden yet inevitable temporary windows
;;tabs ; a tab bar for Emacs
;;treemacs ; a project drawer, like neotree but cooler
- ;;unicode ; extended unicode support for various languages
+ unicode ; extended unicode support for various languages
vc-gutter ; vcs diff in the fringe
vi-tilde-fringe ; fringe tildes to mark beyond EOB
window-select ; visually switch windows
@@ -98,7 +99,7 @@
lsp
magit ; a git porcelain for Emacs
;;make ; run make tasks from Emacs
- (pass +auth) ; password manager for nerds
+ ;; (pass +auth) ; password manager for nerds
pdf ; pdf enhancements
;;prodigy ; FIXME managing external services & code builders
;;rgb ; creating color strings
@@ -109,7 +110,7 @@
;;upload ; map local to remote projects via ssh/ftp
:os
- (:if IS-MAC macos) ; improve compatibility with macOS
+ (:if (featurep :system 'macos) macos) ; improve compatibility with macOS
;;tty ; improve the terminal Emacs experience
:lang
@@ -154,7 +155,7 @@
nix ; I hereby declare "nix geht mehr!"
;;ocaml ; an objective camel
(org +roam2 +hugo +present +gnuplot +pomodoro) ; organize your plain life in plain text
- ;;php ; perl's insecure younger brother
+ php ; perl's insecure younger brother
;;plantuml ; diagrams for confusing people more
;;purescript ; javascript, but functional
(python +lsp +ipython +pyright +tree-sitter) ; beautiful is better than ugly
@@ -172,8 +173,8 @@
;;solidity ; do you need a blockchain? No.
;;swift ; who asked for emoji variables?
;;terra ; Earth and Moon in alignment for performance.
- (web +lsp +tree-sitter) ; the tubes
- yaml ; JSON, but readable
+ (web +lsp +tree-sitter) ; the tubes
+ (yaml +lsp +tree-sitter) ; JSON, but readable
;;zig ; C, but simpler
:email
diff --git a/config/doom/snippets/notmuch-message-mode/nbg-guest b/config/doom/snippets/notmuch-message-mode/nbg-guest
index dff6b79..b3131d6 100644
--- a/config/doom/snippets/notmuch-message-mode/nbg-guest
+++ b/config/doom/snippets/notmuch-message-mode/nbg-guest
@@ -4,21 +4,25 @@
# --
Dear ${1:`(-> (message-fetch-field "to") (mail-extract-address-components) (car))`},
-Glad to hear you are interested. You can always attend our meetings as guest to see if this club is beneficial for you.
+Glad to hear you are interested in our Toastmasters club. You can always attend our meetings as guest to see if this club is beneficial for you.
-Feel free to join us in our next meeting on ${2:MeetingDate}.
+Feel free to join us in our next meeting on Monday, ${2:MeetingDate} @ 19:00 CEST.
We will meet at:
DAI
Gleißbühlstraße 9
-90402 Nuremberg.
+90402 Nuremberg
If you like, I can also add you to our guest list so you always get an invite before the next meeting.
-Our meetings normally begin with a warm up section that includes an impromptu speech session guests also can participate in. Then we have two to four prepared speeches. Finally, there is the speech and meeting evaluations that give us feedback on what we can improve and more importantly, what was done well.
+Our meetings normally begin with a warm up section that includes an impromptu speech session where guests can also participate. Then we have two to four prepared speeches. Finally, there is the speech and meeting evaluations that give us feedback on what we can improve and more importantly, what was done well.
-There is no cost for coming as guest. To participate fully, give prepared speeches, and profit from Toastmasters learning materials, you need to become a member though. There is a one-time registration fee of 25€ and a monthly cost of 12,5€ that is paid in advance by you for a six month period, though when you join you only pay the remaining months until the next renewal period (these start in October and April).
+There is no cost for coming as guest. To participate fully, give prepared speeches, and profit from Toastmasters learning materials, you need to become a member though. There is a one-time registration fee of 25€ and a monthly cost of 15€ that is paid in advance by you for a six month period, though when you join you only pay the remaining months until the next renewal period (these start in October and April).
+
+You'll find more information in our 2 page pdf under this link:
+
+https://drive.google.com/file/d/1IwSBHFqNUaNJKBF9wmhXtPjbC3r7mEel/view?usp=sharing
Feel free to come back to me should you have any more questions.
@@ -26,3 +30,12 @@ Kind regards
Oscar
VP Membership
Nuremberg Toastmasters Club
+
+Club 00008040, Area 4, Division D, District 95
+Join us at 7pm every 1st & 3rd Monday of the month
+DAI, Gleißbühlstr. 9, 90402 Nuremberg
+
+www.nuremberg-toastmasters.de
+
+This message was sent to you because you have provided us with your e-mail address.
+If you no longer wish to receive emails from Nuremberg Toastmasters, please reply to this email with "unsubscribe".
diff --git a/config/doom/snippets/notmuch-message-mode/nbg-membership b/config/doom/snippets/notmuch-message-mode/nbg-membership
new file mode 100644
index 0000000..96c3b89
--- /dev/null
+++ b/config/doom/snippets/notmuch-message-mode/nbg-membership
@@ -0,0 +1,105 @@
+# -*- mode: snippet -*-
+# name: nbg-membership
+# key: nbg-membership
+# --
+Dear ${1:`(-> (message-fetch-field "to") (mail-extract-address-components) (car))`},
+
+${2:some context of how we met}
+
+The simple version to membership is:
+
+- Money:
+
+The club collects a monthly membership fee of 15 €. We pay it in 6
+months intervals, for the periods October-March and April-September at
+90 € each. When you join as a new member, you only pay for the months
+until the next period begin, in your case would you join in August, you
+would pay 30 €, for August-September.
+
+There is a one time registration fee of 25 €, to register you with
+Toastmasters International. That registration is life-long and world
+wide valid. Were you to join other clubs in other cities, or countries
+later on in life. You would only need to pay that club's corresponding
+fees, and skip the new member fee.
+
+- Bureaucracy:
+
+You need to fill the membership form, and send it back to me. I have
+pre-filled some fields regarding the club, and its fees. Don't worry
+about page 3: Payment Information. We don't take your money, you send us
+your membership fees via bank transfer to the club treasurer.
+
+The bank details are as follows:
+Bank Name: Raiffeisenbank im Nürnberger Land eG
+Account Holder Name: Nuremberg Toastmasters
+IBAN: DE35 7606 1482 0004 3987 26
+Please include your full name and "TM Membership" in the payment reference.
+
+Once that is cleared with the treasurer. You get 2 online accounts. One
+for Toastmaster International, where you keep track of your learning
+path and your public speaking manuals(called Pathways). And one for
+EasySpeak which is the system we use to organize each of the club
+meeting roles.
+
+If you want to join as a member at a later time(like September, October,
+etc) it is OK, mention it on the membership form, do the corresponding
+math to calculate your fee and pay.
+
+You don't have a membership contract with the club, no german 2-year
+contract. We don't charge your bank account for the membership fees. You
+have to send us the money every half year to remain a member. If you
+stop, your membership runs out. If you change cities and join other
+club, you just worry about their membership, ours will run out. You
+don't need to cancel anything with us.
+
+If you want to join more than one club, maybe for more practice ours.
+You will have to pay the fees of each club.
+
+- Where does the money go?
+
+Most of your membership fee goes directly to Toastmaster International,
+to give you access to the "franchise", and all the learning material on
+their website as your individual learning program (the manuals called
+pathways). You also need to be a registered member to participate at the
+Speech contests and conferences.
+
+A second chunk goes to pay the German VAT,(Umsatzsteuer) that the German
+Government forces Toastmasters International(TMI) to collect on the
+membership fees they request. It didn't use to be like that, because we
+are all simple volunteer organizations, and TMI is a US non-profit. But
+since last year it became a point of "discussion" among all german clubs
+and other concerned parties, and now became mandatory since July this
+year, even for the german toastmasters clubs that are e.V.
+
+The remaining money is to pay for club expenses, like the venue, those
+simple drinks and snacks offered at the end of the meeting and whatever
+else that we might need. The rest of the benefits are part of the club
+life and we are a volunteer organization.
+
+- Final considerations:
+
+I consider that joining a club(any kind) requires a life style change.
+You have to take time to go to the club, practice whatever it offers, at
+the club and by yourself and you have to deal with the people in the
+club. For that you should choose somewhere that is most compatible with
+your lifestyle.
+
+Toastmasters International is a global "franchise". In the Nürnberg area
+there are some other clubs.
+
+Noris Toastmasters Nuremberg www.noris-toastmasters.de
+Bamberg Toastmasters Bamberg www.bamberg-toastmasters.de
+Erlangen Toastmasters Erlangen www.erlangen-toastmasters.de
+Nürnberger Rhetoriker Nuremberg www.nuernberger-rhetoriker.de
+(German speaking club)
+
+If you haven't, you should give them a try. Maybe you like their venue,
+meeting schedule or people better. Or maybe not and you'll be happier
+with us, in which case we'll be happy to have you as a member.
+
+Feel free to contact me if you have any further questions.
+
+Best regards,
+Óscar
+VP Membership
+Nuremberg Toastmasters Club \ No newline at end of file
diff --git a/config/git/attributes b/config/git/attributes
index 1f901af..81fde0f 100644
--- a/config/git/attributes
+++ b/config/git/attributes
@@ -3,6 +3,8 @@
*.lisp diff=lisp
*.el diff=lisp
*.scm diff=lisp
+tagmail diff=lisp
+habit diff=lisp
*.pdf diff=pdf
*.svg binary
*.png binary
diff --git a/config/guix/shell-authorized-directories b/config/guix/shell-authorized-directories
index 20cfaa6..7db1a2c 100644
--- a/config/guix/shell-authorized-directories
+++ b/config/guix/shell-authorized-directories
@@ -1,2 +1,4 @@
/home/titan/dev/cardano/emacs-wallet
/home/titan/dev/emacs-lisp/btc-explorer/ln-pay
+/home/oscar/bytegit/FW
+/home/oscar/bytegit/AddressValidator
diff --git a/config/khard/khard.conf b/config/khard/khard.conf
index 7bf6197..0bc9e06 100644
--- a/config/khard/khard.conf
+++ b/config/khard/khard.conf
@@ -22,9 +22,9 @@ group_by_addressbook = no
# reverse table ordering: yes / no
reverse = no
# append nicknames to name column: yes / no
-show_nicknames = no
+show_nicknames = yes
# show uid table column: yes / no
-show_uids = yes
+show_uids = no
# sort by first or last name: first_name / last_name / formatted_name
sort = last_name
# localize dates: yes / no
diff --git a/config/pikaur.conf b/config/pikaur.conf
index 6c8e171..3727c18 100644
--- a/config/pikaur.conf
+++ b/config/pikaur.conf
@@ -35,6 +35,7 @@ displaylastupdated = no
groupbyrepository = yes
reversesearchsorting = no
warnaboutpackageupdates =
+warnaboutnondefaultprivilegeescalationtool = yes
[misc]
sudoloopinterval = 59
@@ -43,6 +44,8 @@ privilegeescalationtool = sudo
privilegeescalationtarget = pikaur
userid = 0
preserveenv = PKGDEST,VISUAL,EDITOR,http_proxy,https_proxy,ftp_proxy,HTTP_PROXY,HTTPS_PROXY,FTP_PROXY,ALL_PROXY
+cachepath = /home/titan/.cache
+datapath = /home/titan/.local/share
[network]
aururl = https://aur.archlinux.org
diff --git a/elisp/ai-query.el b/elisp/ai-query.el
new file mode 100644
index 0000000..3bc621c
--- /dev/null
+++ b/elisp/ai-query.el
@@ -0,0 +1,64 @@
+;;; ai-query.el --- Query an AI over the lakera gandalf game -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2024 Óscar Nájera
+;;
+;; Author: Óscar Nájera <hi@oscarnajera.com>
+;; Maintainer: Óscar Nájera <hi@oscarnajera.com>
+;; Created: July 22, 2024
+;; Modified: July 22, 2024
+;; Version: 0.0.1
+;; Package-Requires: ((emacs "27.1"))
+;;
+;; This file is not part of GNU Emacs.
+;;
+;;; Commentary:
+;;
+;; Query an AI over the lakera gandalf game
+;;
+;;; Code:
+
+(require 'subr-x)
+(require 'markdown-mode)
+
+;; Silence byte-compiler.
+(defvar url-http-end-of-headers)
+
+(defconst ai-query-api
+ "https://gandalf.lakera.ai/api/send-message"
+ "AI security endpoint, use it for queries.")
+
+(defun ai-query--request (prompt callback)
+ "Async request to API using PROMPT and process with CALLBACK."
+ (let ((url-request-method "POST")
+ (url-request-extra-headers
+ '(("Content-Type" . "application/x-www-form-urlencoded")))
+ (url-request-data
+ (thread-first
+ (list 'prompt prompt)
+ (cons '((defender "baseline")))
+ (url-build-query-string))))
+ (url-retrieve ai-query-api callback)))
+
+(defun ai-query--process-response (_status)
+ "Callback function to process response."
+ (goto-char url-http-end-of-headers)
+ (let ((response (json-parse-buffer)))
+ (with-current-buffer (get-buffer-create "*AI reply*")
+ (markdown-mode)
+ (erase-buffer)
+ (insert "# Question\n" (gethash "prompt" response))
+ (insert "\n\n# Answer\n\n" (gethash "answer" response))
+ (display-buffer (current-buffer)))))
+
+(defun ai-query-request (prompt)
+ "Query the API with this PROMPT."
+ (thread-first
+ (if (use-region-p)
+ (buffer-substring-no-properties (region-beginning) (region-end))
+ (read-string "What is your question? "))
+ (list)
+ (interactive))
+ (ai-query--request prompt #'ai-query--process-response))
+
+(provide 'ai-query)
+;;; ai-query.el ends here
diff --git a/elisp/delivery-track.el b/elisp/delivery-track.el
new file mode 100644
index 0000000..ec24417
--- /dev/null
+++ b/elisp/delivery-track.el
@@ -0,0 +1,81 @@
+;;; delivery-track.el --- Track packages -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2024 Óscar Nájera
+;;
+;; Author: Óscar Nájera <hi@oscarnajera.com>
+;; Maintainer: Óscar Nájera <hi@oscarnajera.com>
+;; Created: August 28, 2024
+;; Modified: August 28, 2024
+;; Version: 0.0.1
+;; Keywords: abbrev bib c calendar comm convenience data docs emulations extensions faces files frames games hardware help hypermedia i18n internal languages lisp local maint mail matching mouse multimedia news outlines processes terminals tex tools unix vc wp
+;; Homepage: https://github.com/titan/delivery-track
+;; Package-Requires: ((emacs "27.1"))
+;;
+;; This file is not part of GNU Emacs.
+;;
+;;; Commentary:
+;;
+;; Track packages
+;;
+;;; Code:
+
+(require 'org)
+(require 'org-id)
+(require 'url)
+
+(defvar url-http-end-of-headers)
+
+(defun delivery-track--dhl-de (track-id buffer callback)
+ "Async request to API using TRACK-ID and process with CALLBACK.
+It writes into the org-node in BUFFER."
+ (let* ((url-request-method "GET")
+ (params `((piececode ,track-id)
+ ("noRedirect" true)
+ (language "en"))))
+ (thread-first
+ "https://www.dhl.de/int-verfolgen/data/search?"
+ (concat (url-build-query-string params))
+ (url-retrieve callback (list buffer)))))
+
+(defun delivery-track-entry--dhl (_request-status buffer)
+ "Parse response from DHL and write in in BUFFER."
+ (goto-char url-http-end-of-headers)
+ (let* ((shipment-info (thread-last
+ (json-parse-buffer)
+ (gethash "sendungen")
+ (seq-find
+ (lambda (item)
+ (eq t (gethash "hasCompleteDetails" item))))))
+ (history (thread-last
+ shipment-info
+ (gethash "sendungsdetails")
+ (gethash "sendungsverlauf")))
+ (id (gethash "id" shipment-info))
+ (status (gethash "kurzStatus" history))
+ (events (reverse (gethash "events" history))))
+ (with-current-buffer buffer
+ (goto-char (org-find-entry-with-id id))
+ (org-entry-put nil "status" status)
+ (org-next-visible-heading 1)
+ (seq-let (level _rlevel _todo _prio headline)
+ (org-heading-components)
+ (when (and (= level 2)
+ (string= "Shipment reverse history" headline))
+ (org-cut-subtree))
+
+ (insert "** Shipment reverse history\n")
+ (seq-doseq (event events)
+ (thread-first
+ (gethash "datum" event)
+ (parse-time-string)
+ (encode-time)
+ (org-insert-timestamp t t))
+ (insert " " (gethash "status" event) "\n"))))))
+
+(defun delivery-track-update-dhl (track-id)
+ "Update tracking information for DHL TRACK-ID."
+ (interactive (list (read-string "What is the tracking id? " (org-id-get))))
+ (delivery-track--dhl-de track-id (current-buffer) #'delivery-track-entry--dhl))
+
+(provide 'delivery-track)
+;;; delivery-track.el ends here
diff --git a/home-dots/dot-profile b/home-dots/dot-profile
index 084d096..9cc54fb 100644
--- a/home-dots/dot-profile
+++ b/home-dots/dot-profile
@@ -1,4 +1,5 @@
#!/bin/sh
export PATH="$HOME/.local/bin:$HOME/dev/dotfiles/bin:$PATH"
-[ -f "$HOME/.ghcup/env" ] && source "$HOME/.ghcup/env"
-[ -f "$HOME/.cargo/env" ] && source "$HOME/.cargo/env"
+[ -f "$HOME/.ghcup/env" ] && . "$HOME/.ghcup/env"
+[ -f "$HOME/.cargo/env" ] && . "$HOME/.cargo/env"
+[ -d "$HOME/.config/composer/vendor/bin" ] && export PATH="$HOME/.config/composer/vendor/bin:$PATH"
diff --git a/install.scm b/install.scm
index acabf6e..68c1533 100755
--- a/install.scm
+++ b/install.scm
@@ -20,17 +20,16 @@
((_ value (f ...) rest ...) (->> (f ... value) rest ...))
((_ value f rest ...) (->> (f value) rest ...))))
-(define (ansi-color-log-formatter lvl time str)
+(define* (ansi-color-log-formatter lvl time str #:key proc-name #:allow-other-keys)
(let ((color (case lvl
((CRITICAL) 'RED)
((WARN) 'YELLOW)
((OK) 'GREEN))))
- (string-append
- (strftime "%F %H:%M:%S" (localtime time))
- (colorize-string
- (string-append " (" (symbol->string lvl) "): ") color 'BOLD)
- str "\n")))
-
+ (format #f "~a ~a: ~a ~@[(proc: ~a)~]~%"
+ (strftime "%F %H:%M:%S" (localtime time))
+ (colorize-string (symbol->string lvl) color 'BOLD)
+ str
+ proc-name)))
(define (setup-logging)
(let ((lgr (make <logger>))
@@ -187,6 +186,8 @@
"hello@oscarnajera.com"
"najera.oscar@gmail.com"
"oscar@byteplant.com"
+ "nuremberg.toastmasters@googlemail.com"
+ "nuremberg.toastmasters@gmail.com"
))
(user-mail
(if (string=? (gethostname) "obp")
diff --git a/mail/dot-mbsyncrc.byteplant b/mail/dot-mbsyncrc.byteplant
index 16a2867..98374ed 100644
--- a/mail/dot-mbsyncrc.byteplant
+++ b/mail/dot-mbsyncrc.byteplant
@@ -5,7 +5,7 @@ Host imap.byteplant.com
User oscar
PassCmd "pass show byteplant.com/imap"
AuthMechs LOGIN
-SSLType IMAPS
+TLSType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore oscar-remote
@@ -31,7 +31,7 @@ Host imap.byteplant.com
User admin
PassCmd "pass show byteplant.com/admin-email"
AuthMechs LOGIN
-SSLType IMAPS
+TLSType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore admin-remote
@@ -59,7 +59,7 @@ Host imap.byteplant.com
User support
PassCmd "pass show byteplant.com/support-mail"
AuthMechs LOGIN
-SSLType IMAPS
+TLSType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore support-remote
diff --git a/mail/dot-mbsyncrc.personal b/mail/dot-mbsyncrc.personal
index 527cd52..5a21887 100644
--- a/mail/dot-mbsyncrc.personal
+++ b/mail/dot-mbsyncrc.personal
@@ -8,7 +8,7 @@ User najera.oscar@gmail.com
PassCmd "pass show google/googlemail.com/najera.oscar"
AuthMechs LOGIN
# Use SSL
-SSLType IMAPS
+TLSType IMAPS
# The following line should work. If get certificate errors, uncomment the two following lines and read the "Troubleshooting" section.
CertificateFile /etc/ssl/certs/ca-certificates.crt
#CertificateFile ~/.cert/imap.gmail.com.pem
@@ -43,7 +43,7 @@ Host mail.oscarnajera.com
User hi@oscarnajera.com
PassCmd "pass show Correos/mail.oscarnajera.com"
AuthMechs LOGIN
-SSLType IMAPS
+TLSType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore hi_pers-remote
@@ -69,7 +69,7 @@ Host mail.oscarnajera.com
User kindle@oscarnajera.com
PassCmd "pass show Correos/kindle@oscarnajera.com"
AuthMechs LOGIN
-SSLType IMAPS
+TLSType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore kindle-remote
@@ -95,7 +95,7 @@ Host mail.oscarnajera.com
User oscar.najera@delightfuldying.com
PassCmd "pass show WebSites/delightfuldying.com/mailbox/julie"
AuthMechs LOGIN
-SSLType IMAPS
+TLSType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore dd-remote
@@ -121,7 +121,7 @@ Host mail.oscarnajera.com
User sarah@fallforward.space
PassCmd "pass show WebSites/fallforward.space/mailbox/sarah"
AuthMechs LOGIN
-SSLType IMAPS
+TLSType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore ff-remote
@@ -147,7 +147,7 @@ Host mail.oscarnajera.com
User hi@arsmagna.xyz
PassCmd "pass show WebSites/arsmagna.xyz/mailbox/hello"
AuthMechs LOGIN
-SSLType IMAPS
+TLSType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore am-remote
@@ -166,6 +166,37 @@ Create Both
SyncState *
Expunge Both
+###############################################################################
+# GMAIL for Nuremberg Toastmasters
+
+IMAPAccount nbgtm
+# Address to connect to
+Host imap.gmail.com
+User nuremberg.toastmasters@googlemail.com
+PassCmd "pass show orgs/NBG-TM/smtp.googlemail.com"
+AuthMechs LOGIN
+# Use SSL
+TLSType IMAPS
+# The following line should work. If get certificate errors, uncomment the two following lines and read the "Troubleshooting" section.
+CertificateFile /etc/ssl/certs/ca-certificates.crt
+
+IMAPStore nbgtm-remote
+Account nbgtm
+
+MaildirStore nbgtm-local
+# The trailing "/" is important
+Path ~/.mail/nbgtm/
+Inbox ~/.mail/nbgtm/Inbox
+SubFolders Verbatim
+
+Channel nbgtm
+Far :nbgtm-remote:
+Near :nbgtm-local:
+Patterns "INBOX" "[Google Mail]/Sent Mail"
+Create Both
+Expunge Both
+SyncState *
+
# Local Variables:
# mode: conf-unix
# End: