diff options
49 files changed, 2121 insertions, 474 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c0318a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/elisp/*.elc +__pycache__ diff --git a/bin/backup.sh b/bin/backup.sh index 8a27847..9f53249 100755 --- a/bin/backup.sh +++ b/bin/backup.sh @@ -1,11 +1,12 @@ #! /bin/bash +set -e backup_local() { # external program to supply the passphrase: export BORG_PASSCOMMAND="pass show $1" # repo pass first arg # Create Local Backups - echo $(date) "Creating Local Backups ..." + echo "$(date) -- Creating Local Backups ..." REPOSITORY=$2 # repo vault path second arg shift 2 # consume the first 2 arguments borg create --list --filter AME --stats --compression=lz4 \ @@ -28,22 +29,34 @@ backup_local() { --exclude '*/mpd/log' \ --exclude '*/elpa' \ --exclude '*.elc' \ + --exclude '*/*.o' \ + --exclude '*/guix/*/*.go' \ + --exclude '*/guix/*/*.Po' \ + --exclude '*/guix/*/*.m4' \ --exclude '*/.local/straight' \ --exclude '*/phd/simulation_data' \ - $REPOSITORY::'{hostname}-{user}-{utcnow:%Y-%m-%dT%H:%M:%S}' \ - $@ # all the dirs to bac + --exclude '*/semantic-roam' \ + "$REPOSITORY::{hostname}-{user}-{utcnow:%Y-%m-%dT%H:%M:%S}" \ + "$@" # all the dirs to bac # Prune Local Backups - echo $(date) "Pruning local repository ..." + echo "$(date) -- Pruning local repository ..." borg prune --verbose --stats --list \ --glob-archives='{hostname}-{user}-*' \ --keep-daily 7 \ --keep-weekly 4 \ - --keep-monthly 6 $REPOSITORY + --keep-monthly 6 "$REPOSITORY" } +BASIC_PATHS=(~/dev/ ~/org/ ~/.mail/ ~/.bogofilter/ ~/Nextcloud/) +backup_local Admin/sarah/borg/ingrid ssh://borgbackup@sarah/./repos/ingrid "${BASIC_PATHS[@]}" + DISK=/run/media/titan/ext_backup -# backup_local borgbackup ssh://backup/media/Backup/daily_backup/ ~/dev/ ~/.mail/ ~/.bogofilter/ ~/Nextcloud/ ~/org/ "$DISK/personal/Pictures/" "$DISK/personal/Libros/" "$DISK/personal/dev/" "$DISK/Archives/" -backup_local Admin/sarah/borg/ingrid ssh://borgbackup@173.212.211.30/./repos/ingrid ~/dev/ ~/org/ ~/.mail/ ~/.bogofilter/ ~/Nextcloud/ -backup_local Admin/sarah/borg/oscar ssh://borgbackup@173.212.211.30/./repos/oscar "$DISK/personal/Pictures/" "$DISK/personal/Libros/" "$DISK/personal/dev/" "$DISK/Archives/" +if [ -d "$DISK" ]; then + LARGER_PATHS=("$DISK/personal/Pictures/" "$DISK/personal/Libros/" "$DISK/personal/dev/" "$DISK/Archives/") + backup_local Admin/sarah/borg/oscar ssh://borgbackup@sarah/./repos/oscar "${LARGER_PATHS[@]}" + if ping -c 1 -W 1 192.168.178.128 >/dev/null; then + backup_local borgbackup ssh://backup/media/Backup/daily_backup/ "${BASIC_PATHS[@]}" "${LARGER_PATHS[@]}" + fi +fi @@ -2,7 +2,10 @@ -e main-rofi -s !# -(add-to-load-path "/home/titan/dev/dotfiles/lib/guile/") +(add-to-load-path + (string-append + (passwd:dir (getpwuid (geteuid))) + "/dev/dotfiles/lib/guile/")) (use-modules (ice-9 rdelim) (ice-9 popen) @@ -17,24 +20,24 @@ (scandir dir (lambda (file) (string-suffix? ".dat" file)))) (define (prepare-options files) - (string-join (map (lambda (name) (string-drop-right name 4)) files) "\n")) + (string-join (map (lambda (f) (basename f ".dat")) files) "\n")) -(define (rofi-capture-option options) - (let* ((cmd (format #f "echo -e ~s | rofi -dmenu" options)) - (port (open-input-pipe cmd)) - (option (read-line port))) +(define (over-shell cmd) + (let* ((port (open-input-pipe cmd)) + (result (read-line port))) (close-pipe port) - (if (eof-object? option) #f option))) + (if (eof-object? result) #f result))) + +(define (rofi-capture-option options) + (over-shell (format #f "echo -e ~s | rofi -dmenu" options))) (define (rofi-capture-habit-quantity habit) - (let* ((cmd (format #f "echo 1 | rofi -dmenu -p 'Add to ~a'" habit)) - (port (open-input-pipe cmd)) - (quantity (read-line port))) - (close-pipe port) - (if (eof-object? quantity) #f quantity))) + (over-shell (format #f "echo 1 | rofi -dmenu -p 'Add to ~a'" habit))) (define (main-rofi args) - (and-let* ((habit (rofi-capture-option (prepare-options (get-habit-files habits-dir)))) + (and-let* ((habit (-> (get-habit-files habits-dir) + (prepare-options) + (rofi-capture-option))) (quantity (rofi-capture-habit-quantity habit)) (file-out (open-file (string-append habits-dir habit ".dat") "a"))) (format file-out "~d:~a\n" (current-time) quantity) diff --git a/bin/kindlenotes2org.py b/bin/kindlenotes2org.py new file mode 100644 index 0000000..1769c8c --- /dev/null +++ b/bin/kindlenotes2org.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +r""" +extract book highlights to orgmode +================================== + +Extracts from exported html notes from kindle to org subtree +""" +# Created: Sat Jul 14 02:10:24 2018 +# Author: Óscar Nájera +# License: GPL-3 + +import argparse +from textwrap import fill as filltxt + +from bs4 import BeautifulSoup + + +def html_notes2org(page): + soup = BeautifulSoup(page, "lxml") + + docs = "" + for div in soup.find_all("div"): + hcl = div.attrs.get("class") + if "bookTitle" in hcl: + docs += "* {}".format(div.text.strip()) + if "authors" in hcl: + docs += " -- {}\n".format(div.text.strip()) + if "sectionHeading" in hcl: + docs += "** " + div.text.lstrip() + if "noteText" in hcl: + docs += "#+begin_quote\n{}\n#+end_quote\n\n".format( + filltxt(div.text.strip()) + ) + + return docs + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("file", help="HTML file from kindle export") + args = parser.parse_args() + + with open(args.file, "rb") as fid: + page = fid.read() + + docs = html_notes2org(page) + + with open("sub.org", "w") as fid: + fid.write(docs) + + +if __name__ == "__main__": + main() diff --git a/bin/tagmail b/bin/tagmail index 52bcc7c..9febae5 100755 --- a/bin/tagmail +++ b/bin/tagmail @@ -38,9 +38,9 @@ LD_LIBRARY_PATH=$HOME/.guix-profile/lib exec guile -e main -s "$0" "$@" (define (delete-email-files! options) (define (logged-delete file-path) - (let ((do? (not (option-ref options 'dry-run #f)))) - (simple-format #t " [rm] ~a~%" file-path) - (if do? (delete-file file-path)))) + (simple-format #t " [rm] ~a~%" file-path) + (unless (option-ref options 'dry-run #f) + (delete-file file-path))) (with-nm-database (ffi-db (assq-ref options 'mail-repo) 0) (with-nm-query @@ -53,14 +53,14 @@ LD_LIBRARY_PATH=$HOME/.guix-profile/lib exec guile -e main -s "$0" "$@" (define (move-mail! options account query start-dir end-dir) (define (move-file uidvalidity target-folder) - (lambda (file) - (let* ((target-file (new-path (rename-higher file uidvalidity) target-folder)) - (sub-len (string-prefix-length file target-file)) - (do? (not (option-ref options 'dry-run #f)))) - (simple-format #t " [mv] ~a -> ~a~%" - (substring file sub-len) - (substring target-file sub-len)) - (when do? (rename-file file target-file))))) + (let ((dry-run? (option-ref options 'dry-run #f))) + (lambda (file) + (let* ((target-file (new-path (rename-higher file uidvalidity) target-folder)) + (sub-len (string-prefix-length file target-file))) + (simple-format #t " [mv] ~a -> ~a~%" + (substring file sub-len) + (substring target-file sub-len)) + (unless dry-run? (rename-file file target-file)))))) (let* ((mail-repo (assq-ref options 'mail-repo)) (target-folder (format #f "~a~a/~a" mail-repo account end-dir)) @@ -78,10 +78,11 @@ LD_LIBRARY_PATH=$HOME/.guix-profile/lib exec guile -e main -s "$0" "$@" (on-all-messages-filenames to-move (move-file uidvalidity target-folder)))))) (define (apply-tags-to-message options tags) - (lambda (message) - (simple-format #t " ~a~%" (nm-header message "subject")) - (unless (option-ref options 'dry-run #f) - (nm-apply-tags message tags)) #t)) + (let ((dry-run? (option-ref options 'dry-run #f))) + (lambda (message) + (simple-format #t " ~a~%" (nm-header message "subject")) + (unless dry-run? + (nm-apply-tags message tags)) #t))) (define (log-msg-tag count rule new) (let* ((query-str (query-with-new rule new)) @@ -178,7 +179,12 @@ LD_LIBRARY_PATH=$HOME/.guix-profile/lib exec guile -e main -s "$0" "$@" ("+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) @@ -201,7 +207,7 @@ LD_LIBRARY_PATH=$HOME/.guix-profile/lib exec guile -e main -s "$0" "$@" (dry-run (single-char #\n) (value #f)))) (options (append (list (cons 'mail-repo mail-repo) (cons 'my-emails my-emails)) - (getopt-long args option-spec))) + (getopt-long args option-spec))) (account (assq-ref options '()) )) (delete-email-files! options) diff --git a/config/alacritty.toml b/config/alacritty.toml new file mode 100644 index 0000000..e2bafee --- /dev/null +++ b/config/alacritty.toml @@ -0,0 +1,47 @@ +[colors.bright] +black = "#928374" +blue = "#83a598" +cyan = "#8ec07c" +green = "#b8bb26" +magenta = "#d3869b" +red = "#fb4934" +white = "#ebdbb2" +yellow = "#fabd2f" + +[colors.cursor] +cursor = "CellForeground" +text = "CellBackground" + +[colors.dim] +black = "#32302f" +blue = "#076678" +cyan = "#427b58" +green = "#79740e" +magenta = "#8f3f71" +red = "#9d0006" +white = "#928374" +yellow = "#b57614" + +[colors.normal] +black = "#282828" +blue = "#458588" +cyan = "#689d6a" +green = "#98971a" +magenta = "#b16286" +red = "#cc241d" +white = "#a89984" +yellow = "#d79921" + +[colors.primary] +background = "#282828" +bright_foreground = "#fbf1c7" +dim_foreground = "#a89984" +foreground = "#ebdbb2" + +[colors.selection] +background = "CellForeground" +text = "CellBackground" + +[colors.vi_mode_cursor] +cursor = "CellForeground" +text = "CellBackground" diff --git a/config/alacritty.yml b/config/alacritty.yml deleted file mode 100644 index bc8e2e7..0000000 --- a/config/alacritty.yml +++ /dev/null @@ -1,59 +0,0 @@ -# Colors (Gruvbox dark) -colors: - primary: - # hard contrast background - '#1d2021' - background: &gruvbox_dark_bg "#282828" - # soft contrast background - '#32302f' - foreground: "#ebdbb2" - bright_foreground: "#fbf1c7" - dim_foreground: "#a89984" - cursor: - text: CellBackground - cursor: CellForeground - vi_mode_cursor: - text: CellBackground - cursor: CellForeground - # search: - # matches: - # foreground: '#000000' - # background: '#ffffff' - # focused_match: - # foreground: CellBackground - # background: CellForeground - # bar: - # background: '' - # foreground: '' - # line_indicator: - # foreground: None - # background: None - selection: - text: CellBackground - background: CellForeground - bright: - black: "#928374" - red: "#fb4934" - green: "#b8bb26" - yellow: "#fabd2f" - blue: "#83a598" - magenta: "#d3869b" - cyan: "#8ec07c" - white: "#ebdbb2" - normal: - black: *gruvbox_dark_bg - red: "#cc241d" - green: "#98971a" - yellow: "#d79921" - blue: "#458588" - magenta: "#b16286" - cyan: "#689d6a" - white: "#a89984" - dim: - black: "#32302f" - red: "#9d0006" - green: "#79740e" - yellow: "#b57614" - blue: "#076678" - magenta: "#8f3f71" - cyan: "#427b58" - white: "#928374" - # indexed_colors: [] diff --git a/config/awesome/rc.lua b/config/awesome/rc.lua index 08a5794..f085979 100644 --- a/config/awesome/rc.lua +++ b/config/awesome/rc.lua @@ -44,14 +44,21 @@ local hostname = io.popen("uname -n"):read() -- Setup laptop screen -- awful.spawn.with_shell("nvidia-settings -a [gpu:0]/GPUPowerMizerMode=1") -- load the gpu performance profile saved in home -- awful.spawn.with_shell("xrandr --output eDP-1 --mode 1920x1080 --pos 0x0 --output HDMI-2 --primary --mode 1920x1080 --pos 1920x0") -awful.spawn.with_shell("xrandr --output eDP-1 --mode 1920x1080 --pos 0x360 --output HDMI-2 --primary --mode 3440x1440 --pos 1920x0") -awful.spawn.with_shell("xinput --set-prop \"SYN1B7E:01 06CB:2970 Touchpad\" \"Synaptics Two-Finger Scrolling\" 1 1") +-- awful.spawn.with_shell("xrandr --output eDP-1 --mode 1920x1080 --pos 0x360 --output HDMI-2 --primary --mode 3440x1440 --pos 1920x0") +-- awful.spawn.with_shell("xrandr --output HDMI-A-0 --mode 1920x1080 --rotate right --output DisplayPort-0 --mode 3440x1440 --pos 1080x0") -- vertical +if "obp" == hostname then + awful.spawn.with_shell("xrandr --output eDP --primary --mode 1920x1200 --pos 0x240 --rotate normal --output HDMI-A-0 --mode 3440x1440 --pos 1920x0 --rotate normal") +else + awful.spawn.with_shell("xrandr --output HDMI-A-0 --mode 1920x1080 --pos 0x0 --output DisplayPort-0 --primary --mode 3440x1440 --pos 1920x0") +end +if "titanroam" then + awful.spawn.with_shell("xinput --set-prop \"SYN1B7E:01 06CB:2970 Touchpad\" \"Synaptics Two-Finger Scrolling\" 1 1") +end -- {{{ Variable definitions -- Themes define colours, icons, font and wallpapers. -beautiful.init(gears.filesystem.get_themes_dir() .. "zenburn/theme.lua") - +beautiful.init(string.format("%s/.config/awesome/%s.lua", os.getenv("HOME"), "zenburn-theme")) -- This is used later as the default software to run local tools = { terminal = "alacritty", @@ -63,7 +70,7 @@ local tools = { video = "vlc", pass = "passmenu", rofi_run = "rofi -show combi", - habit = "/home/titan/dev/helpful_scripts/guile/habit.scm", + habit = string.format("%s/dev/dotfiles/bin/habit", os.getenv("HOME")), } -- Default modkey. @@ -80,7 +87,7 @@ awful.layout.layouts = { -- awful.layout.suit.tile.left, -- awful.layout.suit.tile.bottom, -- awful.layout.suit.tile.top, - -- awful.layout.suit.fair.horizontal, + awful.layout.suit.fair.horizontal, awful.layout.suit.spiral, -- awful.layout.suit.spiral.dwindle, -- awful.layout.suit.max, @@ -155,7 +162,7 @@ local tasklist_buttons = gears.table.join( local function set_wallpaper(s) local wallpaper = awful.util.getdir("config") .. "brown-hair-brunette-green-eyes.jpg" - gears.wallpaper.maximized(wallpaper, s, true) + gears.wallpaper.maximized(wallpaper, s, false) end -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution) @@ -611,12 +618,15 @@ local function run_once(cmd) awful.spawn.with_shell("pgrep -u $USER -x " .. findme .. " > /dev/null || (" .. cmd .. ")") end -run_once("nextcloud") run_once("light-locker") run_once("redshift-gtk") -run_once("udisksctl mount -b /dev/disk/by-label/ext_backup") run_once("nm-applet") -run_once("aw-qt") + +if ("obp" ~= hostname) then + run_once("nextcloud") + run_once("udisksctl mount -b /dev/disk/by-label/ext_backup") + run_once("aw-qt") +end -- Autostart script for keymaps awful.spawn.with_shell("setxkbmap -I~/.config/xkb/ oscar -option caps:escape -print | xkbcomp -I$HOME/.config/xkb/ - $DISPLAY") diff --git a/config/awesome/zenburn-theme.lua b/config/awesome/zenburn-theme.lua new file mode 100644 index 0000000..89aa37c --- /dev/null +++ b/config/awesome/zenburn-theme.lua @@ -0,0 +1,142 @@ +------------------------------- +-- "Zenburn" awesome theme -- +-- By Adrian C. (anrxc) -- +------------------------------- + +local themes_path = require("gears.filesystem").get_themes_dir() +local dpi = require("beautiful.xresources").apply_dpi + +-- {{{ Main +local theme = {} +theme.wallpaper = themes_path .. "zenburn/zenburn-background.png" +-- }}} + +-- {{{ Styles +theme.font = "sans 8" + +-- {{{ Colors +theme.fg_normal = "#DCDCCC" +theme.fg_focus = "#F0DFAF" +theme.fg_urgent = "#CC9393" +theme.bg_normal = "#3F3F3F" +theme.bg_focus = "#1E2320" +theme.bg_urgent = "#3F3F3F" +theme.bg_systray = theme.bg_normal +-- }}} + +-- {{{ Borders +theme.useless_gap = dpi(0) +theme.border_width = dpi(2) +theme.border_normal = "#3F3F3F" +theme.border_focus = "#6F6F6F" +theme.border_marked = "#CC9393" +-- }}} + +-- {{{ Titlebars +theme.titlebar_bg_focus = "#3F3F3F" +theme.titlebar_bg_normal = "#3F3F3F" +-- }}} + +-- There are other variable sets +-- overriding the default one when +-- defined, the sets are: +-- [taglist|tasklist]_[bg|fg]_[focus|urgent|occupied|empty|volatile] +-- titlebar_[normal|focus] +-- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color] +-- Example: +--theme.taglist_bg_focus = "#CC9393" +-- }}} + +-- {{{ Widgets +-- You can add as many variables as +-- you wish and access them by using +-- beautiful.variable in your rc.lua +--theme.fg_widget = "#AECF96" +--theme.fg_center_widget = "#88A175" +--theme.fg_end_widget = "#FF5656" +--theme.bg_widget = "#494B4F" +--theme.border_widget = "#3F3F3F" +-- }}} + +-- {{{ Mouse finder +theme.mouse_finder_color = "#CC9393" +-- mouse_finder_[timeout|animate_timeout|radius|factor] +-- }}} + +-- {{{ Menu +-- Variables set for theming the menu: +-- menu_[bg|fg]_[normal|focus] +-- menu_[border_color|border_width] +theme.menu_height = dpi(15) +theme.menu_width = dpi(100) +-- }}} + +-- {{{ Icons +-- {{{ Taglist +theme.taglist_squares_sel = themes_path .. "zenburn/taglist/squarefz.png" +theme.taglist_squares_unsel = themes_path .. "zenburn/taglist/squarez.png" +--theme.taglist_squares_resize = "false" +-- }}} + +-- {{{ Misc +theme.awesome_icon = themes_path .. "zenburn/awesome-icon.png" +theme.menu_submenu_icon = themes_path .. "default/submenu.png" +-- }}} + +-- Variables set for theming notifications: +theme.notification_font = "DejaVu Sans 18" +-- notification_[bg|fg] +-- notification_[width|height|margin] +-- notification_[border_color|border_width|shape|opacity] + +-- {{{ Layout +theme.layout_tile = themes_path .. "zenburn/layouts/tile.png" +theme.layout_tileleft = themes_path .. "zenburn/layouts/tileleft.png" +theme.layout_tilebottom = themes_path .. "zenburn/layouts/tilebottom.png" +theme.layout_tiletop = themes_path .. "zenburn/layouts/tiletop.png" +theme.layout_fairv = themes_path .. "zenburn/layouts/fairv.png" +theme.layout_fairh = themes_path .. "zenburn/layouts/fairh.png" +theme.layout_spiral = themes_path .. "zenburn/layouts/spiral.png" +theme.layout_dwindle = themes_path .. "zenburn/layouts/dwindle.png" +theme.layout_max = themes_path .. "zenburn/layouts/max.png" +theme.layout_fullscreen = themes_path .. "zenburn/layouts/fullscreen.png" +theme.layout_magnifier = themes_path .. "zenburn/layouts/magnifier.png" +theme.layout_floating = themes_path .. "zenburn/layouts/floating.png" +theme.layout_cornernw = themes_path .. "zenburn/layouts/cornernw.png" +theme.layout_cornerne = themes_path .. "zenburn/layouts/cornerne.png" +theme.layout_cornersw = themes_path .. "zenburn/layouts/cornersw.png" +theme.layout_cornerse = themes_path .. "zenburn/layouts/cornerse.png" +-- }}} + +-- {{{ Titlebar +theme.titlebar_close_button_focus = themes_path .. "zenburn/titlebar/close_focus.png" +theme.titlebar_close_button_normal = themes_path .. "zenburn/titlebar/close_normal.png" + +theme.titlebar_minimize_button_normal = themes_path .. "default/titlebar/minimize_normal.png" +theme.titlebar_minimize_button_focus = themes_path .. "default/titlebar/minimize_focus.png" + +theme.titlebar_ontop_button_focus_active = themes_path .. "zenburn/titlebar/ontop_focus_active.png" +theme.titlebar_ontop_button_normal_active = themes_path .. "zenburn/titlebar/ontop_normal_active.png" +theme.titlebar_ontop_button_focus_inactive = themes_path .. "zenburn/titlebar/ontop_focus_inactive.png" +theme.titlebar_ontop_button_normal_inactive = themes_path .. "zenburn/titlebar/ontop_normal_inactive.png" + +theme.titlebar_sticky_button_focus_active = themes_path .. "zenburn/titlebar/sticky_focus_active.png" +theme.titlebar_sticky_button_normal_active = themes_path .. "zenburn/titlebar/sticky_normal_active.png" +theme.titlebar_sticky_button_focus_inactive = themes_path .. "zenburn/titlebar/sticky_focus_inactive.png" +theme.titlebar_sticky_button_normal_inactive = themes_path .. "zenburn/titlebar/sticky_normal_inactive.png" + +theme.titlebar_floating_button_focus_active = themes_path .. "zenburn/titlebar/floating_focus_active.png" +theme.titlebar_floating_button_normal_active = themes_path .. "zenburn/titlebar/floating_normal_active.png" +theme.titlebar_floating_button_focus_inactive = themes_path .. "zenburn/titlebar/floating_focus_inactive.png" +theme.titlebar_floating_button_normal_inactive = themes_path .. "zenburn/titlebar/floating_normal_inactive.png" + +theme.titlebar_maximized_button_focus_active = themes_path .. "zenburn/titlebar/maximized_focus_active.png" +theme.titlebar_maximized_button_normal_active = themes_path .. "zenburn/titlebar/maximized_normal_active.png" +theme.titlebar_maximized_button_focus_inactive = themes_path .. "zenburn/titlebar/maximized_focus_inactive.png" +theme.titlebar_maximized_button_normal_inactive = themes_path .. "zenburn/titlebar/maximized_normal_inactive.png" +-- }}} +-- }}} + +return theme + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/calendars.conf b/config/calendars.conf index 7362346..f09945f 100644 --- a/calendars.conf +++ b/config/calendars.conf @@ -1,16 +1,10 @@ [DEFAULT] -agenda_outfile=~/org/caldav.org -contacts_outfile=~/org/contacts.org ahead=90 back=28 - -[contacts] -outfile=~/org/contacts.org -user = oscar -passwordstore=CS_storage/cloud.oscarnajera.com/oscar -url=https://cloud.oscarnajera.com/remote.php/dav/addressbooks/users/oscar/{}?export -addressbooks=contacts +[catalyst] +url=https://calendar.google.com/calendar/ical/c_jvsrkmkigu6ibgkmk5dr86bd7g@group.calendar.google.com/public/{}.ics +calendars = basic [personal] user = oscar @@ -18,6 +12,3 @@ passwordstore=CS_storage/cloud.oscarnajera.com/oscar url=https://cloud.oscarnajera.com/remote.php/dav/calendars/oscar/{}?export calendars = habitual personal-1 -[catalyst] -url=https://calendar.google.com/calendar/ical/c_jvsrkmkigu6ibgkmk5dr86bd7g@group.calendar.google.com/public/{}.ics -calendars = basic diff --git a/config/doom/config.org b/config/doom/config.org index 3d203aa..577f1f9 100644 --- a/config/doom/config.org +++ b/config/doom/config.org @@ -11,6 +11,22 @@ #+begin_src emacs-lisp (setq doom-font (font-spec :family "DejaVu Sans Mono" :size 18 :weight 'semi-light)) (setq doom-theme 'doom-gruvbox) +(add-hook 'prog-mode-hook 'prettify-symbols-mode) + +(defun on/prettify-symbols () + "Common added symbols." + (mapc (lambda (p) + (cl-pushnew p prettify-symbols-alist :test #'equal)) + '(("<=" . ?≤) + (">=" . ?≥) + ("->" . ?→) + ("->>" . ?↠) + ("=>" . ?⇒) + ("/=" . ?≠) ("!=" . ?≠) + ("::" . ?∷) + ("lambda" . ?λ)))) + +(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'. @@ -88,6 +104,9 @@ Because I always need help and it should come up quickly (emacs-lisp-mode) (display-buffer (current-buffer)))) #+end_src +#+begin_src emacs-lisp + (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p) +#+end_src * Dictionary #+begin_src emacs-lisp :tangle "packages.el" (package! lexic) @@ -110,6 +129,7 @@ Shamelessly copied from https://tecosaur.github.io/emacs-config/#dictionary * Orgmode #+begin_src emacs-lisp (after! org + (setq org-tags-column (- fill-column)) (setcdr (assoc "j" org-capture-templates) '("Journal" entry (file+olp+datetree +org-capture-journal-file) "* %(format-time-string \"%H:%M\") %?\n%a\n%i" @@ -119,20 +139,19 @@ 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 - `("i" "Isar-Speak Contact" - entry (file ,(expand-file-name "Isar-Speak.org" org-directory)) - "* INTRS [[notmuch-search:%:fromaddress][%:fromname]] -:PROPERTIES: -:EMAIL: %:fromaddress -:END: -Invited: %^t -")) + (setq org-roam-capture-templates '(("d" "default" plain "%i\n%?" :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}") :unnarrowed t)) org-roam-capture-ref-templates org-roam-capture-templates)) + +(use-package! semantic-search + :after org + :load-path "~/dev/dotfiles/scratch/semgrep" + :commands (semantic-search) + :config + (setq semantic-server-url "http://localhost:8080")) #+end_src ** Alerts This is to set the reminders of calendar events. @@ -155,13 +174,18 @@ this new window. #+begin_src emacs-lisp (use-package! cal-sync :load-path "~/dev/org-caldav" - :commands (cal-sync-push cal-sync-import-file cal-sync-delete) + :commands (cal-sync-push cal-sync-import-file cal-sync-delete on/calendar-fetch) :init (map! :leader (:prefix-map "mc" "p" #'cal-sync-push "f" #'cal-sync-import-file)) :config - (setq cal-sync-url "https://cloud.oscarnajera.com/remote.php/dav/calendars/oscar" + (defun on/calendar-fetch () + (interactive) + (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" org-icalendar-date-time-format ":%Y%m%dT%H%M%SZ")) #+end_src @@ -219,23 +243,37 @@ this new window. #+begin_src emacs-lisp (after! elfeed (setq elfeed-feeds - '("https://sachachua.com/blog/feed" + '("http://feeds.feedburner.com/MeltingAsphalt" + "http://feeds.feedburner.com/TroyHunt" + "http://kitchingroup.cheme.cmu.edu/blog/feed/index.xml" "http://www.howardism.org/index.xml" - "https://reyify.com/api/rss" - "https://guix.gnu.org/feeds/blog.atom" "https://ag91.github.io/rss.xml" + "https://architectelevator.com/feed.xml" + "https://bitcoinops.org/feed.xml" + "https://cyberwardog.blogspot.com/feeds/posts/default" "https://daryl.wakatara.com/rss.xml" + "https://guix.gnu.org/feeds/blog.atom" + "https://hboeck.de/rss.xml" + "https://jackrusher.com/feed.xml" "https://nullprogram.com/feed/" + "https://oscarnajera.com/post/index.xml" + "https://paulstamatiou.com/posts.xml" + "https://planet.archlinux.org/atom.xml" + "https://reyify.com/api/rss" + "https://sachachua.com/blog/feed" + "https://serokell.io/blog.rss.xml" + "https://stevelosh.com/rss.xml" + "https://www.archlinux.org/feeds/news/" + "https://www.n16f.net/blog/index.xml" "https://www.schneier.com/feed/atom" - "https://stevelosh.com/rss.xml"))) - + "https://www.tweag.io/rss.xml"))) #+end_src * Email ** Notmuch #+begin_src emacs-lisp :tangle "packages.el" -(package! notmuch :pin "7b5921877e748338359a25dae578771f768183af") -(package! org-mime :pin "a7bf07316f93015e4f853ea0fc5b8d05b4a7695d") -(package! ol-notmuch :pin "126fb446d8fa9e54cf21103afaf506fd81273c02") +(package! notmuch :pin "c769658360e10a6d01a4134e680e2f498741bc5c") +(package! org-mime :pin "cc00afcf0291633324364c1c83bfe2833cfdc1bf") +(package! ol-notmuch :pin "781c3518a537da2a8b5e8a4424f9441df463a147") #+end_src #+BEGIN_SRC emacs-lisp (use-package! notmuch @@ -367,18 +405,14 @@ this new window. (defun on/registered-mail-accounts () "Read mbsync config to extract IMAPAccounts." - (let ((buffer (find-file-noselect - (expand-file-name - "~/dev/dotfiles/mail/dot-mbsyncrc.personal")))) - (with-current-buffer buffer - (goto-char (point-min)) - (let ((pick (prog1 (->> - (cl-loop while (search-forward-regexp (rx bol "IMAPAccount " (group (+ any)) eol) nil t) - collect (match-string 1)) - (cons "all") - (completing-read "Which mailbox"))))) - (kill-buffer buffer) - (if (string= pick "all") nil (list pick)))))) + (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))))) (define-derived-mode mail-sync-log-mode comint-mode "mail-sync-log" "Major mode for reading mail sync." @@ -407,21 +441,27 @@ this new window. smtpmail-local-domain "oscarnajera.com") (defun set-smtp-server () - (let* ((default-smtp-conf '("mail.oscarnajera.com" 587 starttls "hi")) - (smtp-from-server-alist - '(("Oscar Najera <najera.oscar@gmail.com>" - "smtp.googlemail.com" 587 starttls "najera.oscar"))) - (smtp-conf (alist-get (save-restriction - (message-narrow-to-headers) - (message-fetch-field "from")) - smtp-from-server-alist default-smtp-conf - nil #'string=))) - (-let [(server port protocol user) smtp-conf] - (setq smtpmail-smtp-server server - smtpmail-smtp-service port - smtpmail-stream-type protocol - smtpmail-smtp-user user) - (message "SMTP server changed to %s in port %s by %s" server port protocol)))) + (-let* (((user host) + (thread-first + (message-field-value "from" ) + (mail-extract-address-components) + (cadr) + (string-split "@"))) + (smtp-servers '("oscarnajera.com" "mail.oscarnajera.com" + "gmail.com" "smtp.googlemail.com" + "byteplant.com" "smtp.byteplant.com")) + ((&plist :host :user :port :secret) + (car + (auth-source-search :host + (or (plist-get smtp-servers host #'string=) + "mail.oscarnajera.com") + :user user + :max 1)))) + (setq smtpmail-smtp-server host + smtpmail-smtp-service (string-to-number port) + smtpmail-stream-type 'starttls + smtpmail-smtp-user user) + (message "SMTP server changed to %s %s %s" host port user))) (add-hook 'message-send-mail-hook 'set-smtp-server)) #+end_src @@ -433,6 +473,19 @@ this new window. #+begin_src emacs-lisp (use-package! khardel) #+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"))) +#+end_src + +#+RESULTS: + * Ledger Emacs mode for managing ledger text files #+BEGIN_SRC emacs-lisp @@ -442,20 +495,21 @@ Emacs mode for managing ledger text files (defun on/ledger-link-invoice () "Attach an invoice file to this posting." (interactive) + (ledger-navigate-beginning-of-xact) + (end-of-line) (when-let* ((date (ledger-xact-date)) - (payee (replace-regexp-in-string " " "_" (string-trim-right (ledger-xact-payee)))) - (src-file (read-file-name "Attach: " "~/dev/journal/Empresa_DE/")) + (payee (thread-last + (ledger-xact-payee) + (string-trim) + (replace-regexp-in-string (rx (+ (or space punctuation))) "_"))) + (src-file (read-file-name "Attach: ")) (file-name (concat "Empresa_DE/" date "_" payee "." (file-name-extension src-file)))) - (ledger-navigate-beginning-of-xact) - (end-of-line) - (rename-file src-file (expand-file-name file-name "/home/titan/dev/journal/")) - (newline) - (insert " ; Invoice: " file-name)))) + (insert "\n ; Invoice: " file-name) + (rename-file src-file (expand-file-name file-name))))) #+end_src ** CSV #+begin_src emacs-lisp :tangle "packages.el" (package! parse-csv) -(package! emacsql-sqlite3) #+end_src ** Crypto #+begin_src emacs-lisp @@ -465,8 +519,8 @@ Emacs mode for managing ledger text files :init (defun on/cardano-set-network () (interactive) - (let* ((networks '((:mainnet "/tmp/nina-mn.socket" "http://localhost:8090" "--mainnet") - (:preview "/tmp/nina-pr.socket" "http://localhost:8091" "--testnet-magic" "2"))) + (let* ((networks '((:mainnet "/run/cardano-node-mainnet/socket" "http://localhost:8090" "--mainnet") + (:preview "/run/cardano-node-preview/socket" "http://localhost:8091" "--testnet-magic" "2"))) (pick (alist-get (completing-read "Pick network" networks) @@ -485,7 +539,7 @@ Emacs mode for managing ledger text files cardano-wallet-tx-log-mode))))) (setq cardano-tx-log-level 'debug) ;; (setq cardano-cli-command (expand-file-name "~/dev/cardano/cardano-node/cli")) - (setq cardano-tx-cli-command "/home/titan/dev/cardano/cardano-node/dist-newstyle/build/x86_64-linux/ghc-8.10.7/cardano-cli-1.35.3/x/cardano-cli/build/cardano-cli/cardano-cli") + (setq cardano-tx-cli-command "/usr/bin/cardano-cli") (setq cardano-tx-db-keyring-dir "~/dev/cardano/emacs-wallet/keys/demo")) (use-package! cardano-wallet @@ -526,10 +580,33 @@ Emacs mode for managing ledger text files #+begin_src emacs-lisp :tangle "packages.el" (package! emacsql-psql) #+end_src + +#+begin_src emacs-lisp +(after! format-all + (define-format-all-formatter sqlformat + (:executable "pg_format") + (:install) + (:modes sql-mode) + (:format + (format-all--buffer-easy + executable + "-s2" "-g" "-U2" + "-")))) +#+end_src ** WEB +#+begin_src emacs-lisp :tangle "packages.el" +(package! impatient-mode) +#+end_src #+begin_src emacs-lisp -(after! web-mode - (setq-hook! 'web-mode-hook +format-with :none)) +(after! skewer-mode + (setq httpd-port 8095)) + +(use-package! impatient-mode + :commands impatient-mode) + +(use-package! trident-mode + :commands trident-mode + :load-path "~/dev/emacs-lisp/trident-mode.el/") #+end_src ** Haskell #+begin_src emacs-lisp @@ -542,6 +619,36 @@ Emacs mode for managing ledger text files #+begin_src emacs-lisp (setq-hook! 'clojure-mode-hook +format-with :none) #+end_src +** Common Lisp +#+begin_src emacs-lisp +(after! sly + (setq sly-lisp-implementations + '((sbcl-large ("sbcl" "--dynamic-space-size" "2048")) + (sbcl ("sbcl"))))) +#+end_src +** C +#+begin_src emacs-lisp +(after! lsp-clangd + (setq lsp-clients-clangd-args + '("-j=3" + "--background-index" + "--clang-tidy" + "--completion-style=detailed" + "--header-insertion=never" + "--header-insertion-decorators=0")) + (set-lsp-priority! 'clangd 2)) +#+end_src + +* Video Editing +#+begin_src emacs-lisp :tangle "packages.el" +(package! subed + :recipe (:host github :repo "sachac/subed" :files ("subed/*.el"))) +#+end_src + +#+begin_src emacs-lisp +(use-package! subed) +#+end_src + * Admin #+begin_src emacs-lisp :tangle "packages.el" (package! guix) @@ -553,8 +660,43 @@ Emacs mode for managing ledger text files (package! json-rpc) #+end_src #+begin_src emacs-lisp -(use-package! json-rpc) +(use-package! btc-explorer + :load-path "~/dev/emacs-lisp/btc-explorer/" + :commands (on/bitcoin-rpc-connect) + :config + (use-package json-rpc) + (defun on/bitcoin-rpc-connect () + (interactive) + (let* ((networks '(:mainnet 8332 + :mainnet-r 8335 + :testnet 18332 + :testnet-r 18335 + :regtest 18443)) + (host "localhost") + (user "crazy") + (port (plist-get networks + (intern (completing-read "Pick network: " networks)))) + (secret (-some-> + (auth-source-search :host host) + (car) + (plist-get :secret)))) + (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)))))) + +(use-package! lnd + :load-path "~/dev/emacs-lisp/btc-explorer/" + :commands (lnd-pick-node) + :config + (setq lnd-nodes '(("local" "https://localhost:8480/v1/" + "/run/media/titan/ext_backup/personal/bitcoin/lnd/data/chain/bitcoin/testnet/admin.macaroon") + ("remote" "https://localhost:8481/v1/" + "~/dev/emacs-lisp/btc-explorer/admin.macaroon")))) + #+end_src + #+begin_src emacs-lisp (use-package! shepherd :load-path "~/dev/dotfiles/elisp/" @@ -564,3 +706,12 @@ Emacs mode for managing ledger text files #+begin_src emacs-lisp (use-package! mpc) #+end_src + +#+begin_src emacs-lisp +(use-package! journalctl + :load-path "~/dev/dotfiles/elisp" + :commands (journalctl)) +#+end_src +#+begin_src emacs-lisp +(setq netstat-program-options '("-aptu")) +#+end_src diff --git a/config/doom/custom.el b/config/doom/custom.el index 9ea349e..7ba527d 100644 --- a/config/doom/custom.el +++ b/config/doom/custom.el @@ -3,12 +3,76 @@ ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. + '(auth-source-save-behavior nil) '(ignored-local-variable-values '((grep-find-ignored-directories ".git" ".venv" "node_modules" ".mypy_cache" ".pytest_cache" "SCCS" "RCS" "CVS" "MCVS" ".src" ".svn" ".git" ".hg" ".bzr" "_MTN" "_darcs" "{arch}") (grep-find-ignored-files "*.min.js" "*.standalone.js" "*.map" "*.gz" ".#*" "*.o" "*~" "*.bin" "*.lbin" "*.so" "*.a" "*.ln" "*.blg" "*.bbl" "*.elc" "*.lof" "*.glo" "*.idx" "*.lot" "*.fmt" "*.tfm" "*.class" "*.fas" "*.lib" "*.mem" "*.x86f" "*.sparcf" "*.dfsl" "*.pfsl" "*.d64fsl" "*.p64fsl" "*.lx64fsl" "*.lx32fsl" "*.dx64fsl" "*.dx32fsl" "*.fx64fsl" "*.fx32fsl" "*.sx64fsl" "*.sx32fsl" "*.wx64fsl" "*.wx32fsl" "*.fasl" "*.ufsl" "*.fsl" "*.dxl" "*.lo" "*.la" "*.gmo" "*.mo" "*.toc" "*.aux" "*.cp" "*.fn" "*.ky" "*.pg" "*.tp" "*.vr" "*.cps" "*.fns" "*.kys" "*.pgs" "*.tps" "*.vrs" "*.pyc" "*.pyo"))) - '(package-selected-packages '(youtube-sub-extractor elpher adoc-mode logview)) + '(package-selected-packages + '(graphviz-dot-mode elfeed-tube flycheck-elsa elpher adoc-mode logview)) '(safe-local-variable-values - '((cider-default-cljs-repl . shadow) + '((eval let + ((root-dir-unexpanded + (locate-dominating-file default-directory ".dir-locals.el"))) + (when root-dir-unexpanded + (let* + ((root-dir + (file-local-name + (expand-file-name root-dir-unexpanded))) + (root-dir* + (directory-file-name root-dir))) + (unless + (boundp 'geiser-guile-load-path) + (defvar geiser-guile-load-path 'nil)) + (make-local-variable 'geiser-guile-load-path) + (require 'cl-lib) + (cl-pushnew root-dir* geiser-guile-load-path :test #'string-equal)))) + (eval with-eval-after-load 'yasnippet + (let + ((guix-yasnippets + (expand-file-name "etc/snippets/yas" + (locate-dominating-file default-directory ".dir-locals.el")))) + (unless + (member guix-yasnippets yas-snippet-dirs) + (add-to-list 'yas-snippet-dirs guix-yasnippets) + (yas-reload-all)))) + (eval setq-local guix-directory + (locate-dominating-file default-directory ".dir-locals.el")) + (eval add-to-list 'completion-ignored-extensions ".go") + (google-translate-default-source-language . "de") + (google-translate-default-target-language . "en") + (vc-prepare-patches-separately) + (diff-add-log-use-relative-names . t) + (vc-git-annotate-switches . "-w") + (eval eval-after-load "yapfify" + '(defun yapfify-call-bin + (input-buffer output-buffer start-line end-line) + "Call process yapf on INPUT-BUFFER saving the output to OUTPUT-BUFFER. + +Return the exit code. START-LINE and END-LINE specify region to +format." + (with-current-buffer input-buffer + (call-process-region + (point-min) + (point-max) + (concat + (projectile-locate-dominating-file default-directory dir-locals-file) + "scripts/run-pipenv") + nil output-buffer nil "run" "yapf" "-l" + (concat + (number-to-string start-line) + "-" + (number-to-string end-line)))))) + (eval setq flycheck-python-pylint-executable + (concat + (projectile-locate-dominating-file default-directory dir-locals-file) + "scripts/run-pylint")) + (eval setq flycheck-python-mypy-executable + (concat + (projectile-locate-dominating-file default-directory dir-locals-file) + "scripts/run-mypy")) + (grep-find-ignored-directories ".git" ".venv" "node_modules" ".mypy_cache" ".pytest_cache" "SCCS" "RCS" "CVS" "MCVS" ".src" ".svn" ".git" ".hg" ".bzr" "_MTN" "_darcs" "{arch}") + (grep-find-ignored-files "*.min.js" "*.standalone.js" "*.map" "*.gz" ".#*" "*.o" "*~" "*.bin" "*.lbin" "*.so" "*.a" "*.ln" "*.blg" "*.bbl" "*.elc" "*.lof" "*.glo" "*.idx" "*.lot" "*.fmt" "*.tfm" "*.class" "*.fas" "*.lib" "*.mem" "*.x86f" "*.sparcf" "*.dfsl" "*.pfsl" "*.d64fsl" "*.p64fsl" "*.lx64fsl" "*.lx32fsl" "*.dx64fsl" "*.dx32fsl" "*.fx64fsl" "*.fx32fsl" "*.sx64fsl" "*.sx32fsl" "*.wx64fsl" "*.wx32fsl" "*.fasl" "*.ufsl" "*.fsl" "*.dxl" "*.lo" "*.la" "*.gmo" "*.mo" "*.toc" "*.aux" "*.cp" "*.fn" "*.ky" "*.pg" "*.tp" "*.vr" "*.cps" "*.fns" "*.kys" "*.pgs" "*.tps" "*.vrs" "*.pyc" "*.pyo") + (cider-default-cljs-repl . shadow) (cider-shadow-cljs-default-options . "app") (cider-preferred-build-tool . clojure-cli) (cider-clojure-cli-global-options . "-A:dev") diff --git a/config/doom/init.el b/config/doom/init.el index 2bce639..cd9d65d 100644 --- a/config/doom/init.el +++ b/config/doom/init.el @@ -21,49 +21,49 @@ ;;layout ; auie,ctsrnm is the superior home row :completion - company ; the ultimate code completion backend - ;;helm ; the *other* search engine for love and life + company ; the ultimate code completion backend + ;; helm ; the *other* search engine for love and life ;;ido ; the other *other* search engine... - ivy ; a search engine for love and life + 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 + 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) ; 🙂 - ;;fill-column ; a `fill-column' indicator - hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW + hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW ;;hydra ;;indent-guides ; highlighted indent columns ;;ligatures ; ligatures and symbols to make your code pretty again ;;minimap ; show a map of the code on the side - modeline ; snazzy, Atom-inspired modeline, plus API + modeline ; snazzy, Atom-inspired modeline, plus API ;;nav-flash ; blink cursor line after big motions ;;neotree ; a project drawer, like NERDTree for vim - ophints ; highlight the region an operation acts on + ophints ; highlight the region an operation acts on (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 - vc-gutter ; vcs diff in the fringe - vi-tilde-fringe ; fringe tildes to mark beyond EOB - window-select ; visually switch windows - workspaces ; tab emulation, persistence & separate workspaces + vc-gutter ; vcs diff in the fringe + vi-tilde-fringe ; fringe tildes to mark beyond EOB + window-select ; visually switch windows + ;;workspaces ; tab emulation, persistence & separate workspaces ;;zen ; distraction-free coding or writing :editor - evil; come to the dark side, we have cookies - file-templates ; auto-snippets for empty files + evil ; come to the dark side, we have cookies + file-templates ; auto-snippets for empty files ;; fold ; (nigh) universal code folding - (format +onsave) ; automated prettiness + (format +onsave) ; automated prettiness ;;god ; run Emacs commands without modifier keys ;;lispy ; vim for lisp, for people who don't like vim ;;multiple-cursors ; editing in many places at once ;;objed ; text object editing for the innocent ;;parinfer ; turn lisp into python, sort of ;;rotate-text ; cycle region at point between text candidates - snippets ; my elves. They type so I don't have to + snippets ; my elves. They type so I don't have to ;;word-wrap ; soft wrapping with language-aware indent :emacs @@ -74,15 +74,15 @@ vc ; version-control and Emacs, sitting in a tree :term - eshell ; the elisp shell that works everywhere + eshell ; the elisp shell that works everywhere ;;shell ; simple shell REPL for Emacs ;;term ; basic terminal emulator for Emacs ;;vterm ; the best terminal emulation in Emacs :checkers - syntax ; tasing you for every semicolon you forget - (spell +flyspell +hunspell) ; tasing you for misspelling mispelling - grammar ; tasing grammar mistake every you make + syntax ; tasing you for every semicolon you forget + (spell +flyspell +hunspell) ; tasing you for misspelling mispelling + grammar ; tasing grammar mistake every you make :tools ;;ansible @@ -92,41 +92,41 @@ ;;docker ;;editorconfig ; let someone else argue about tabs vs spaces ;;ein ; tame Jupyter notebooks with emacs - (eval +overlay) ; run code, run (also, repls) + (eval +overlay) ; run code, run (also, repls) ;;gist ; interacting with github gists - lookup ; navigate your code and its documentation + lookup ; navigate your code and its documentation lsp - magit ; a git porcelain for Emacs + magit ; a git porcelain for Emacs ;;make ; run make tasks from Emacs - (pass +auth) ; password manager for nerds - pdf ; pdf enhancements + (pass +auth) ; password manager for nerds + pdf ; pdf enhancements ;;prodigy ; FIXME managing external services & code builders ;;rgb ; creating color strings ;;taskrunner ; taskrunner for all your projects ;;terraform ; infrastructure as code ;;tmux ; an API for interacting with tmux - tree-sitter ; syntax and parsing, sitting in a tree... + tree-sitter ; syntax and parsing, sitting in a tree... ;;upload ; map local to remote projects via ssh/ftp :os - (:if IS-MAC macos) ; improve compatibility with macOS + (:if IS-MAC macos) ; improve compatibility with macOS ;;tty ; improve the terminal Emacs experience :lang ;;agda ; types of types of types of types... ;;beancount ; mind the GAAP - ;;cc ; C > C++ == 1 + (cc +lsp +tree-sitter) ; C > C++ == 1 clojure ; java with a lisp common-lisp ; if you've seen one lisp, you've seen them all ;;coq ; proofs-as-programs ;;crystal ; ruby at the speed of c ;;csharp ; unity, .NET, and mono shenanigans - data ; config/data formats + data ; config/data formats ;;(dart +flutter) ; paint ui and not much else ;;dhall - ;;elixir ; erlang done right + (elixir +tree-sitter +lsp) ; erlang done right ;;elm ; care for a cup of TEA? - emacs-lisp ; drown in parentheses + emacs-lisp ; drown in parentheses ;;erlang ; an elegant language for a more civilized age ;;ess ; emacs speaks statistics ;;factor @@ -137,27 +137,27 @@ ;;gdscript ; the language you waited for ;;(go +lsp) ; the hipster dialect ;;(graphql +lsp) ; Give queries a REST - (haskell +lsp) ; a language that's lazier than I am + (haskell +lsp) ; a language that's lazier than I am ;;hy ; readability of scheme w/ speed of python ;;idris ; a language you can depend on - ;;json ; At least it ain't XML + (json +lsp +tree-sitter) ; At least it ain't XML ;;(java +lsp) ; the poster child for carpal tunnel syndrome - (javascript +lsp) ; all(hope(abandon(ye(who(enter(here)))))) - ;;julia ; a better, faster MATLAB + (javascript +lsp +tree-sitter) ; all(hope(abandon(ye(who(enter(here)))))) + (julia +lsp +tree-sitter) ; a better, faster MATLAB ;;kotlin ; a better, slicker Java(Script) ;;latex ; writing papers in Emacs has never been so fun ;;lean ; for folks with too much to prove - ledger ; be audit you can be - lua ; one-based indices? one-based indices - markdown ; writing docs for people to ignore + ledger ; be audit you can be + lua ; one-based indices? one-based indices + markdown ; writing docs for people to ignore ;;nim ; python + lisp at the speed of c - nix ; I hereby declare "nix geht mehr!" + nix ; I hereby declare "nix geht mehr!" ;;ocaml ; an objective camel - (org +roam2 +hugo +present) ; organize your plain life in plain text + (org +roam2 +hugo +present +gnuplot +pomodoro) ; organize your plain life in plain text ;;php ; perl's insecure younger brother ;;plantuml ; diagrams for confusing people more ;;purescript ; javascript, but functional - (python +lsp +ipython) ; beautiful is better than ugly + (python +lsp +ipython +pyright +tree-sitter) ; beautiful is better than ugly ;;qt ; the 'cutest' gui framework ever ;;racket ; a DSL for DSLs ;;raku ; the artist formerly known as perl6 @@ -166,14 +166,14 @@ ;;(ruby +rails) ; 1.step {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"} (rust +lsp) ; Fe2O3.unwrap().unwrap().unwrap().unwrap() ;;scala ; java, but good - (scheme +guile) ; a fully conniving family of lisps - sh ; she sells {ba,z,fi}sh shells on the C xor + (scheme +guile) ; a fully conniving family of lisps + sh ; she sells {ba,z,fi}sh shells on the C xor ;;sml ;;solidity ; do you need a blockchain? No. ;;swift ; who asked for emoji variables? ;;terra ; Earth and Moon in alignment for performance. - web ; the tubes - yaml ; JSON, but readable + (web +lsp +tree-sitter) ; the tubes + yaml ; JSON, but readable ;;zig ; C, but simpler :email @@ -184,8 +184,8 @@ :app ;;calendar ;;emms - ;;everywhere ; *leave* Emacs!? You must be joking - irc ; how neckbeards socialize + ;; everywhere ; *leave* Emacs!? You must be joking + irc ; how neckbeards socialize rss ; emacs as an RSS reader ;;twitter ; twitter client https://twitter.com/vnought diff --git a/config/doom/snippets/org-mode/daily b/config/doom/snippets/org-mode/daily index f0f24fd..57e60c2 100644 --- a/config/doom/snippets/org-mode/daily +++ b/config/doom/snippets/org-mode/daily @@ -2,17 +2,18 @@ # name: daily # key: daily # -- -- Amazing things that happened yesterday -- How could I have made yesterday even better? -- Daily affirmations -- What would make today great - -- What am I *happy* about in my life now? What about that makes me happy? How does that make me feel? -- What am I *excited* about in my life now? What about that makes me excited? How does that make me feel? -- What am I *proud* about in my life now? What about that makes me proud? How does that make me feel? -- What am I *grateful* for in my life now? what about that makes me grateful? how does that make me feel? -- What am I *enjoying most* in my life right now? what about that do I enjoy? How does that make me feel? -- What am I *committed to* in my life right now? What about that make me committed? How does that make me feel? -- Who do I love? Who loves me? What about that makes me loving? How does that make me feel? +* Routine Review +** Amazing things that happened yesterday +** How could I have made yesterday even better? +** Daily affirmations +** What would make today great +** What makes me feel? And what about that makes me feel that way? :feelings: +- happy :: about in my life now? What about that makes me happy? How does that make me feel? +- excited :: about in my life now? What about that makes me excited? How does that make me feel? +- proud :: about in my life now? What about that makes me proud? How does that make me feel? +- grateful :: for in my life now? what about that makes me grateful? how does that make me feel? +- enjoying most :: in my life right now? what about that do I enjoy? How does that make me feel? +- committed :: to in my life right now? What about that make me committed? How does that make me feel? +- love :: Who do I love? Who loves me? What about that makes me loving? How does that make me feel? - [ ] Timebox day
\ No newline at end of file diff --git a/config/git/attributes b/config/git/attributes index 761502e..1f901af 100644 --- a/config/git/attributes +++ b/config/git/attributes @@ -1,4 +1,5 @@ *.org diff=org +*.ledger diff=ledger *.lisp diff=lisp *.el diff=lisp *.scm diff=lisp diff --git a/config/guix/shell-authorized-directories b/config/guix/shell-authorized-directories new file mode 100644 index 0000000..20cfaa6 --- /dev/null +++ b/config/guix/shell-authorized-directories @@ -0,0 +1,2 @@ +/home/titan/dev/cardano/emacs-wallet +/home/titan/dev/emacs-lisp/btc-explorer/ln-pay diff --git a/config/mpd/mpd.conf b/config/mpd/mpd.conf index 30119e2..5d88caa 100644 --- a/config/mpd/mpd.conf +++ b/config/mpd/mpd.conf @@ -11,6 +11,7 @@ # file:// protocol) or streaming files over an accepted protocol. # music_directory "/run/media/titan/ext_backup/personal/cleaned_music/" +# music_directory "/mnt/disk/personal/cleaned_music/" # # This setting sets the MPD internal playlist directory. The purpose of this # directory is storage for playlists created by MPD. The server will use @@ -26,6 +27,7 @@ playlist_directory "~/.config/mpd/playlists" # files over an accepted protocol. # db_file "/run/media/titan/ext_backup/personal/mpd_database" +# db_file "/mnt/disk/personal/mpd_database" # # These settings are the locations for the daemon log files for the daemon. # These logs are great for troubleshooting, depending on your log_level diff --git a/config/pikaur.conf b/config/pikaur.conf index bf0b064..6c8e171 100644 --- a/config/pikaur.conf +++ b/config/pikaur.conf @@ -10,9 +10,9 @@ keepbuilddir = no keepdevbuilddir = yes keepbuilddeps = no skipfailedbuild = no -alwaysusedynamicusers = no ignorearch = no gpgdir = +dynamicusers = root [review] noedit = no @@ -40,6 +40,9 @@ warnaboutpackageupdates = sudoloopinterval = 59 pacmanpath = pacman privilegeescalationtool = sudo +privilegeescalationtarget = pikaur +userid = 0 +preserveenv = PKGDEST,VISUAL,EDITOR,http_proxy,https_proxy,ftp_proxy,HTTP_PROXY,HTTPS_PROXY,FTP_PROXY,ALL_PROXY [network] aururl = https://aur.archlinux.org diff --git a/config/shepherd/init.d/bitcoin.scm b/config/shepherd/init.d/bitcoin.scm index d576eef..2805b57 100644 --- a/config/shepherd/init.d/bitcoin.scm +++ b/config/shepherd/init.d/bitcoin.scm @@ -1,31 +1,33 @@ +(use-modules (ice-9 popen) + (ice-9 rdelim)) + (define (make-dir-parents dir-path) (unless (access? dir-path F_OK) (make-dir-parents (dirname dir-path)) (mkdir dir-path))) + +(define (bitcoin-rpc-pass) + (let* ((port + (open-input-pipe + "pass show Development/bitcoin/testnet/localhost")) + (result (read-line port))) + (close-pipe port) + result)) + ;; TESTNET ;; Requires the running node which is now under systemd (register-services (make <service> - #:docstring "Electrs testnet" - #:provides '(electrs-testnet) - #:start (make-forkexec-constructor - (list "/home/titan/dev/bitcoin/electrs/target/release/electrs" - "--conf" "/home/titan/dev/bitcoin/electrs/testnet-conf.toml") - #:log-file "/tmp/electrs.log") - #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C - #:respawn? #t)) - -(register-services - (make <service> #:docstring "Bitcoin testnet index" #:provides '(index-testnet) #:start (make-forkexec-constructor (list "/home/titan/dev/bitcoin/rust-bitcoin-indexer/target/release/bitcoin-indexer") - #:directory "/home/titan/dev/bitcoin/rust-bitcoin-indexer/" + #:environment-variables `("DATABASE_URL=postgres://titan@%2Frun%2Fpostgresql/btc-testnet-idx" + ,(format #f "NODE_RPC_URL=http://crazy:~a@127.0.0.1:18332/" (bitcoin-rpc-pass)) + "RUST_LOG=bitcoin_indexer=info") #:log-file "/tmp/btc-indexer.log") #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C - #:requires '(bitcoin-testnet) #:respawn? #t)) (register-services @@ -33,39 +35,27 @@ #:docstring "Bitcoin testnet lnd lightning" #:provides '(lnd-testnet) #:start (make-forkexec-constructor - (list "lnd" + (list "/home/titan/.local/bin/lnd" "--lnddir=/run/media/titan/ext_backup/personal/bitcoin/lnd/" "--noseedbackup")) #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C - #:requires '(bitcoin-testnet) #:respawn? #t)) -;; Mainnet +;; ssh (register-services (make <service> - #:docstring "Sarah tunnel btc" + #:docstring "Sarah ssh tunnel" #:provides '(sarah-ssh) #:start (make-forkexec-constructor (list "ssh" "-NTv" "-o" "ServerAliveInterval=60" "-o" "ExitOnForwardFailure=yes" "-o" "StreamLocalBindUnlink=yes" - "-L" "8332:localhost:8332" - "-L" "8333:localhost:8333" - "sarah") - #:log-file "/tmp/sarah-ssh.log") - #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C - #:respawn? #t)) - -(register-services - (make <service> - #:docstring "Electrs mainnet" - #:provides '(electrs-mainnet) - #:start (make-forkexec-constructor - (list "/home/titan/dev/bitcoin/electrs/target/release/electrs" - "--conf" "/home/titan/dev/bitcoin/electrs/mainnet-conf.toml") - #:log-file "/tmp/electrs-m.log") + "-L" "8335:localhost:8332" ;; btcm + "-L" "18335:localhost:18332" ;; btct + "-L" "8481:localhost:8480" ;; LNDT + "orchest@sarah") + #:log-file "/tmp/sarah-ssh.log" + #:environment-variables '("SSH_AUTH_SOCK=/run/user/1000/gnupg/S.gpg-agent.ssh")) #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C - #:requires '(sarah-ssh) #:respawn? #t)) - diff --git a/config/shepherd/init.d/cardano.scm b/config/shepherd/init.d/cardano.scm index b8efbca..1c5b731 100644 --- a/config/shepherd/init.d/cardano.scm +++ b/config/shepherd/init.d/cardano.scm @@ -19,7 +19,8 @@ "-L" "50001:localhost:50001" ;; electrs "-L" "24224:localhost:24224" ;; electrs monitoring "cardano@nina") - #:log-file "/tmp/nina-ssh.log") + #:log-file "/tmp/nina-ssh.log" + #:environment-variables '("SSH_AUTH_SOCK=/run/user/1000/gnupg/S.gpg-agent.ssh")) #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C #:respawn? #t)) @@ -29,7 +30,7 @@ #:provides '(preview-wallet) #:start (make-forkexec-constructor (list "cardano-wallet" - ;;(string-append (getenv "HOME") "/.cabal/bin/cardano-wallet") + ;;(string-append (getenv "HOME") "/.cabal/bin/cardano-wallet") "serve" "--port" "8091" "--node-socket" "/tmp/nina-pr.socket" @@ -47,11 +48,10 @@ #:start (make-forkexec-constructor (list ;;(string-append (getenv "HOME") "/.cabal/bin/cardano-wallet") "cardano-wallet" - "serve" - "+RTS" "-T" "-RTS" - "--node-socket" "/tmp/nina-mn.socket" - "--database" (string-append (getenv "HOME") "/test-cardano/main/wallet") - "--mainnet") + "serve" + "--node-socket" "/run/cardano-node-mainnet/socket" + "--database" (string-append (getenv "HOME") "/test-cardano/main/wallet") + "--mainnet") #:log-file (string-append (getenv "HOME") "/test-cardano/main/log/wallet.log")) #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C - #:requires '(nina-ssh))) + #:requires '())) diff --git a/config/shepherd/init.d/cmk.scm b/config/shepherd/init.d/cmk.scm index 4c98f1c..97ced9f 100644 --- a/config/shepherd/init.d/cmk.scm +++ b/config/shepherd/init.d/cmk.scm @@ -9,6 +9,7 @@ "-o" "StreamLocalBindUnlink=yes" "-L" "/tmp/ingridcmk.socket:/omd/sites/ingrid/tmp/run/live" "ingrid@ingrid") - #:log-file "/tmp/ingrid-cmk.log") + #:log-file "/tmp/ingrid-cmk.log" + #:environment-variables '("SSH_AUTH_SOCK=/run/user/1000/gnupg/S.gpg-agent.ssh")) #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C #:respawn? #t)) diff --git a/config/shepherd/init.d/my-daemons.scm b/config/shepherd/init.d/my-daemons.scm new file mode 100644 index 0000000..1b5daf8 --- /dev/null +++ b/config/shepherd/init.d/my-daemons.scm @@ -0,0 +1,32 @@ + +(register-services + (make <service> + #:docstring "Habit tracker" + #:provides '(habit-logs) + #:start (make-forkexec-constructor + (list "sbcl" + "--load" + (string-append (getenv "HOME") "/dev/common-lisp/todo-demo/habit.asd") + "--eval" "(asdf:load-system :habit)" + "--eval" "(habit-log::main)" + "--non-interactive") + #:directory (string-append (getenv "HOME") "/dev/common-lisp/todo-demo/") + #:environment-variables (list (string-append "HABIT_DIR=" (getenv "HOME") "/org/habits/") + "PORT=4242") + #:log-file "/tmp/habits.log") + #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C + #:respawn? #t)) + +(let ((workdir (string-append (getenv "HOME") "/dev/dotfiles/scratch/semgrep/"))) + (register-services + (make <service> + #:docstring "Roam semantic DB" + #:provides '(roam-semantic-db) + #:start (make-forkexec-constructor + (list "python" + (string-append workdir "server.py")) + #:directory workdir + #:environment-variables (list (string-append "PATH=" (getenv "HOME") "/.virtualenvs/language/bin")) + #:log-file "/tmp/roam-semantic.log") + #:stop (make-kill-destructor 2) ;; 2 is SIGINT - interupt process stream, ctrl-C + #:respawn? #t))) diff --git a/config/shepherd/init.scm b/config/shepherd/init.scm index 7b548e9..3d47bd4 100644 --- a/config/shepherd/init.scm +++ b/config/shepherd/init.scm @@ -1,14 +1,14 @@ ;; init.scm -- default shepherd configuration file. -(use-modules ((ice-9 ftw) #:select (scandir))) +(use-modules ((ice-9 ftw) #:select (scandir)) + (srfi srfi-26)) ;; Load all the files in the directory 'init.d' with a suffix '.scm'. (for-each (lambda (file) (load (string-append "init.d/" file))) (scandir (string-append (dirname (current-filename)) "/init.d") - (lambda (file) - (string-suffix? ".scm" file)))) + (cut string-suffix? ".scm" <>))) ;; Services known to shepherd: @@ -22,4 +22,4 @@ ;; Services to start when shepherd starts: ;; Add the name of each service that should be started to the list ;; below passed to 'for-each'. -(for-each start '()) +(for-each start '(habit-logs roam-semantic-db)) diff --git a/config/systemd/user/default.target.wants/shepherd.service b/config/systemd/user/default.target.wants/shepherd.service new file mode 120000 index 0000000..f25096b --- /dev/null +++ b/config/systemd/user/default.target.wants/shepherd.service @@ -0,0 +1 @@ +/home/titan/.config/systemd/user/shepherd.service
\ No newline at end of file diff --git a/config/systemd/user/shepherd.service b/config/systemd/user/shepherd.service new file mode 100644 index 0000000..b57d7ec --- /dev/null +++ b/config/systemd/user/shepherd.service @@ -0,0 +1,26 @@ +# -*- mode: conf-unix; -*- +[Unit] +Description=GNU Shepherd Daemon +After=network.target +Wants=guix-daemon.service + +[Service] +Type=forking +ExecStart=/usr/bin/bash -c "source $GUIX_PROFILE/etc/profile && shepherd" +ExecStop=herd stop root +ExecStopPost=rm %t/shepherd/socket -v +# disallow writing to /usr, /bin, /sbin, ... +# ProtectSystem=yes +Environment="GUIX_PROFILE=%h/.guix-profile" +Environment="GUIX_LOCPATH=%h/.guix-profile/lib/locale" + +# # more paranoid security settings +# NoNewPrivileges=yes +# ProtectKernelTunables=yes +# ProtectControlGroups=yes +# # AF_NETLINK is required by libsmbclient, or it will exit() .. *sigh* +# RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK +# RestrictNamespaces=yes + +[Install] +WantedBy=default.target diff --git a/config/systemd/user/sockets.target.wants/mpd.socket b/config/systemd/user/sockets.target.wants/mpd.socket new file mode 120000 index 0000000..ac109b9 --- /dev/null +++ b/config/systemd/user/sockets.target.wants/mpd.socket @@ -0,0 +1 @@ +/usr/lib/systemd/user/mpd.socket
\ No newline at end of file diff --git a/elisp/borgbackup.el b/elisp/borgbackup.el new file mode 100644 index 0000000..52c64cd --- /dev/null +++ b/elisp/borgbackup.el @@ -0,0 +1,88 @@ +;;; borgbackup.el --- Borg backup client -*- lexical-binding: t; -*- +;; +;; Copyright (C) 2023 Óscar Nájera +;; +;; Author: Óscar Nájera <hi@oscarnajera.com> +;; Maintainer: Óscar Nájera <hi@oscarnajera.com> +;; Created: October 26, 2023 +;; Modified: October 26, 2023 +;; Version: 0.0.1 +;; Homepage: https://git.oscarnajera.com/dotfiles/tree/elisp/borgbackup.el +;; Package-Requires: ((emacs "27.1")) +;; +;; This file is not part of GNU Emacs. +;; +;;; Commentary: +;; +;; Description +;; +;;; Code: + +(require 'dash) + +(defcustom borgbackup-repos '(("ssh://borgbackup@sarah/./repos/ingrid" "Admin/sarah/borg/ingrid") + ("ssh://borgbackup@sarah/./repos/oscar" "Admin/sarah/borg/oscar") + ("ssh://backup/media/Backup/daily_backup/" "borgbackup")) + "List of lists where each entry has the repo path and then the pass entry." + :type list + :group 'borgbackup) + +(defun borgbackup--cmd (cmd repo pass-path &rest args) + (let ((process-environment (list (concat "BORG_PASSCOMMAND=pass show " pass-path) + (concat "SSH_AUTH_SOCK=" (getenv "SSH_AUTH_SOCK")) + (concat "HOME=" (getenv "HOME")))) + (err-file (make-temp-file "borg-err"))) + (with-temp-buffer + (apply #'call-process "borg" nil (list (current-buffer) err-file) nil + cmd repo args) + (if (= 0 (file-attribute-size (file-attributes err-file))) ;; no error + (buffer-string) + (user-error (find-file err-file)))))) + +(-let (((&plist :archives) + (json-parse-string + (borgbackup--cmd "list" + "ssh://borgbackup@sarah/./repos/ingrid" + "Admin/sarah/borg/ingrid" "--json") + :object-type 'plist))) + archives) + +(defun borgbackup-info (repo pass-path) + (interactive + (thread-first + (completing-read "Which repo do you want: " borgbackup-repos) + (assoc borgbackup-repos #'string=))) + (message + (borgbackup--cmd "info" repo pass-path))) + +(defun borgbackup--list (repo pass-path) + (-let (((&plist :archives) + (json-parse-string + (borgbackup--cmd "list" repo pass-path "--json") + :object-type 'plist))) + + (with-current-buffer (get-buffer-create "*borg*") + (tabulated-list-mode) + (setq tabulated-list-format [("Archive" 40 t) + ("Date" 27 t) + ("ID" 64 t)]) + (setq tabulated-list-padding 2) + (setq tabulated-list-entries + (cl-map 'list + (lambda (row) + (-let (((&plist :archive :time :id) row)) + (list row (vector archive time id)))) + archives)) + (tabulated-list-init-header) + (tabulated-list-print) + (display-buffer (current-buffer))))) + +(defun borgbackup-list (repo pass-path) + (interactive + (thread-first + (completing-read "Which repo do you want: " borgbackup-repos) + (assoc borgbackup-repos #'string=))) + (borgbackup--list repo pass-path)) + +(provide 'borgbackup) +;;; borgbackup.el ends here diff --git a/elisp/cmk.el b/elisp/cmk.el index 61b71df..6023cf0 100644 --- a/elisp/cmk.el +++ b/elisp/cmk.el @@ -21,6 +21,8 @@ (require 'subr-x) (require 'cl-lib) (require 'dash) +(require 'company) +(require 'csv-mode) (defun cmk-state-coloring (state) "Font color for numeric STATE input as string." @@ -67,41 +69,49 @@ Default is \"%Y-%m-%d %H:%M\"." " "))) (defconst cmk-problem-col-spec - '(("STATE" 5 t :column "service_state" :parser cmk-state-coloring ) + `(("STATE" 5 t :column "service_state" :parser cmk-state-coloring ) ("Host" 9 t :column "host_name") ("Service" 20 t :column "service_description") - ("Since" 16 nil :column "service_last_state_change" :parser cmk-timestamp-to-date) + ("Since" 16 ,(lambda (a b) + (time-less-p + (encode-time (parse-time-string (elt (cadr a) 3))) + (encode-time (parse-time-string (elt (cadr b) 3))))) + :column "service_last_state_change" :parser cmk-timestamp-to-date) ("Check output" 18 t :column "service_plugin_output" :parser cmk-purge-bangs))) (defconst cmk-log-col-spec - '(("host_state" 5 t :column "host_state" :parser cmk-state-coloring) + '(;("host_state" 5 t :column "host_state" :parser cmk-state-coloring) + ("STATE" 5 t :column "log_state" :parser cmk-state-coloring) + ;; ("lsttype" 8 t :column "log_state_type") ("Host" 9 t :column "host_name") ("Service" 12 t :column "service_description") ("log_time" 16 t :column "log_time" :parser cmk-timestamp-to-date) - ("log_command_name" 10 t :column "log_command_name") - ("log_comment" 15 t :column "log_comment") - ("lineno" 8 t :column "log_lineno") - ("lstate" 8 t :column "log_state") - ("lsttype" 8 t :column "log_state_type") - ("log_type" 8 t :column "log_type") - ("host_scheduled_downtime_depth" 5 t :column "host_scheduled_downtime_depth") - ("host_has_been_checked" 5 t :column "host_has_been_checked") + ;; ("log_command_name" 10 t :column "log_command_name") + ;; ("log_comment" 15 t :column "log_comment") + ;; ("lineno" 8 t :column "log_lineno") + ("log_type" 16 t :column "log_type") + ;; ("host_scheduled_downtime_depth" 5 t :column "host_scheduled_downtime_depth") + ;; ("host_has_been_checked" 5 t :column "host_has_been_checked") ("log_plugin_output" 5 t :column "log_plugin_output"))) (defun cmk-parse-rows (buffer column-spec) "Return tabulated entries from BUFFER according to COLUMN-SPEC." (with-current-buffer buffer (goto-char (point-min)) - (cl-loop until (eobp) - collect - (list (count-lines 1 (point)) - (cl-map 'vector - (lambda (entry spec) - (let ((parser (or (plist-get (cdddr spec) :parser) #'identity))) - (funcall parser entry))) - (split-string (buffer-substring-no-properties (point) (line-end-position)) ";") - column-spec)) - do (forward-line)))) + (let (rows + (parsers (mapcar (lambda (spec) + (or (plist-get (cdddr spec) :parser) #'identity)) + column-spec))) + (while (not (eobp)) + (push + (list (count-lines 1 (point)) + (cl-map 'vector + (lambda (parser entry) (funcall parser entry)) + parsers + (split-string (thing-at-point 'line t) ";" nil "\n"))) + rows) + (forward-line)) + (nreverse rows)))) (defun cmk-livestatus-query (query) "One shot livestatus QUERY, return network process." @@ -120,14 +130,63 @@ Default is \"%Y-%m-%d %H:%M\"." (setq tabulated-list-entries (cmk-parse-rows (process-buffer cmks) tabulated-list-format)) (tabulated-list-print 'remember))) +(defun cmk-timestamp-eldoc-documentation () + (when-let ((number (thing-at-point 'number))) + (format-time-string "%Y-%m-%d %H:%M" (seconds-to-time number)))) + +(defconst cmk-livestatus-headers + '("Filter" "Columns" "Stats" "Limit" "ColumnHeaders" "OutputFormat")) + (define-derived-mode cmk-livestatus-mode prog-mode "livestatus" "Major mode for viewing journalctl output." + (add-function :before-until (local 'eldoc-documentation-function) + #'cmk-timestamp-eldoc-documentation) + ;; (setq-local company-backends (cons 'company-cmk-lq company-backends)) + ;; (setq-local completion-at-point-functions '(cmk-lq-capf)) + (add-hook 'completion-at-point-functions 'cmk-lq-capf nil 'local) ;; code for syntax highlighting (setq font-lock-defaults `(((,(rx bol "GET" eow) . font-lock-keyword-face) (,(rx word-start (or "hosts" "services") word-end) . font-lock-constant-face) - (,(rx bol (or "Filter" "Columns" "Stats" "Limit") ":" whitespace) . font-lock-function-name-face) + (,(concat "^" (regexp-opt cmk-livestatus-headers 'words) ":[[:space:]]") . font-lock-function-name-face) (,(rx bol (or "And" "Or" "Negate") ":" whitespace) . font-lock-keyword-face) (,(rx whitespace (or "~" "=" "=~" "~~" "<" ">" "<=" ">=") whitespace) . font-lock-keyword-face))))) +(defun cmk-custom-livestatus-query () + (interactive) + (let ((query cmk-livestatus-query) + (edit-buffer (get-buffer-create "*LQ*"))) + (with-current-buffer edit-buffer + (cmk-livestatus-mode) + (if (string-blank-p query) (insert "GET ") (insert query)) + (local-set-key "\C-c\C-c" + (lambda () + (interactive) + (let ((new-query (-> (buffer-string) (string-trim) (concat "\n\n")))) + (kill-buffer) + (let ((cmk (cmk-livestatus-query new-query))) + (switch-to-buffer (process-buffer cmk)) + (setq csv-separators '(";") + csv-separator-regexp "[;]" + csv-separator-chars '(59)) + (csv-align-mode) + (setq-local cmk-livestatus-query new-query)))))) + (switch-to-buffer edit-buffer))) + +(defun company-cmk-lq (command &optional arg &rest ignored) + (interactive (list 'interactive)) + (cl-case command + (interactive (company-begin-backend 'company-cmk-lq)) + (prefix (company-grab-word)) + (candidates (cl-loop for header in cmk-livestatus-headers + when (string-prefix-p arg header t) collect header)) + (meta (format "This value is named %s" arg)))) + +(defun cmk-lq-capf () + (when (looking-back (rx bol (+ alpha)) 1) + (list (match-beginning 0) + (match-end 0) + (cl-loop for header in cmk-livestatus-headers + when (string-prefix-p (match-string-no-properties 0) header t) + collect (concat header ": "))))) (defun cmk-edit-lq (buffer) "Open window to edit the livestatus query of current BUFFER." @@ -195,10 +254,11 @@ Negate:")) Filter: class = 1 Filter: class = 3 Filter: class = 8 -Or: 3" +Or: 3 +Filter: log_state_type = HARD" (floor (- (time-to-seconds (current-time)) - (* 4 3600)))))) + (* 24 3600)))))) ;;; Get a different csv diff --git a/elisp/journalctl.el b/elisp/journalctl.el index 2d16240..84ec1e1 100644 --- a/elisp/journalctl.el +++ b/elisp/journalctl.el @@ -7,8 +7,8 @@ ;; Created: September 07, 2022 ;; Modified: September 07, 2022 ;; Version: 0.0.1 -;; Homepage: https://github.com/titan/journalctl -;; Package-Requires: ((emacs "27.1")) +;; Homepage: https://git.oscarnajera.com/dotfiles/tree/elisp/journalctl.el +;; Package-Requires: ((emacs "28.1")) ;; ;; This file is not part of GNU Emacs. ;; @@ -19,18 +19,13 @@ ;;; Code: (require 'org) (require 'cl-extra) +(require 'transient) (defvar-local journalctl-current-host nil - "Keeps the optetes of the last call of journalctl.") + "Keeps the optetes of the last call to journalctl.") (defvar-local journalctl-current-opts nil - "Keeps the optetes of the last call of journalctl.") - -(defcustom journalctl-error-keywords - '("Failed" "failed" "Error" "error" "critical" "couldn't" "Can't" "not" "Not" "unreachable" "FATAL") - "Keywords that mark errors in journalctl output." - :group 'journalctl - :type 'string) + "Keeps the optetes of the last call to journalctl.") (defcustom journalctl-warn-keywords '("Warning" "warn" "debug") @@ -38,6 +33,12 @@ :group 'journalctl :type 'string) +(defcustom journalctl-error-keywords + '("Failed" "failed" "Error" "error" "critical" "couldn't" "Can't" "not" "Not" "unreachable" "FATAL") + "Keywords that mark errors in journalctl output." + :group 'journalctl + :type 'string) + (defcustom journalctl-starting-keywords '("Starting" "Activating" "Listening" "Reloading" "connect") "Keywords that mark start of processes or steps in journalctl output." @@ -52,16 +53,16 @@ :type 'string) ;;; faces -(defface journalctl-error-face - '((t :inherit error)) - "Face to mark errors in journalctl's output." - :group 'journalctl) - (defface journalctl-warning-face '((t :inherit warning)) "Face to mark warnings in journalctl's output." :group 'journalctl) +(defface journalctl-error-face + '((t :inherit error)) + "Face to mark errors in journalctl's output." + :group 'journalctl) + (defface journalctl-starting-face '((t :inherit success)) "Face to mark starting units in journalctl's output." @@ -88,30 +89,24 @@ :group 'journalctl) (defvar journalctl-font-lock-keywords - (let ( - ;; generate regex string for each category of keywords - (error-keywords-regexp (regexp-opt journalctl-error-keywords 'words)) - (warn-keywords-regexp (regexp-opt journalctl-warn-keywords 'words)) - (starting-keywords-regexp (regexp-opt journalctl-starting-keywords 'words)) - (finished-keywords-regexp (regexp-opt journalctl-finished-keywords 'words))) - `( - (,warn-keywords-regexp . 'journalctl-warning-face) - (,error-keywords-regexp . 'journalctl-error-face) - (,starting-keywords-regexp . 'journalctl-starting-face) - (,finished-keywords-regexp . 'journalctl-finished-face) - ("^\\([A-Z][a-z]+ [0-9]+ [0-9:]+\\) \\(\\(?:[[:alnum:]]\\|\\.\\)+\\) \\(.*?:\\)" - (1 'journalctl-timestamp-face) - (2 'journalctl-host-face) - (3 'journalctl-process-face)) - - ;; note: order above matters, because once colored, that part won't change. - ;; in general, put longer words first - ))) + ;; note: order matters, because once colored, that part won't change. + ;; in general, put longer words first + `((,(regexp-opt journalctl-warn-keywords 'words) . 'journalctl-warning-face) + (,(regexp-opt journalctl-error-keywords 'words) . 'journalctl-error-face) + (,(regexp-opt journalctl-starting-keywords 'words) . 'journalctl-starting-face) + (,(regexp-opt journalctl-finished-keywords 'words) . 'journalctl-finished-face) + (,(rx bol (group (= 3 alpha) " " (= 2 digit) " " (1+ (in digit ":"))) " " ; timestamp + (group (+ (in alphanumeric ?.))) " " ; host + (group (+? not-newline)) "[" (group (+ digit)) "]:") ; service[PID] + (1 'journalctl-timestamp-face) + (2 'journalctl-host-face) + (3 'journalctl-process-face) + (4 'font-lock-comment-face)))) (defcustom journalctl-hosts - '("/ssh:alina|sudo::" - "/ssh:nina|sudo::" - "/sudo::") + '("/sudo::" + "/ssh:ingrid|sudo::" + "/ssh:sarah|sudo::") "Valid hosts to connect for journal data." :type (list 'string) :group 'file) @@ -121,6 +116,8 @@ "--follow" "--lines" "--reverse" + "--pager-end" + "--catalog" "--grep" "--boot" "--since" @@ -129,6 +126,18 @@ "--priority") "List of possible options to be given to journalctl." ) +(transient-define-prefix journalct-opts () + "Prefix for opts." + ["infixes" + ("f" "follow" "--follow") + ("h" "host" "--host=" :choices journalctl-hosts :prompt "hus: ") + ("u" "unit" "--unit=" + :prompt "a unit: " + :reader journalctl-read-system-units + ;; :always-read t + )]) +;; (journalct-opts) + (defun journalctl--clean-buffer () "Produce a clean buffer for the log. It seems I must kill the buffer for tramp to behave correctly on the new calls." @@ -138,17 +147,21 @@ It seems I must kill the buffer for tramp to behave correctly on the new calls." (kill-buffer buffer)) (get-buffer-create name-buffer))) -(defun journalctl-system-units (host-location) +(defun journalctl--system-units (host-location) "Query HOST-LOCATION (a tramp path) for its systemd units." - (interactive (list (completing-read "Tramp host: " journalctl-hosts))) (let ((default-directory host-location)) (with-temp-buffer (start-file-process "units" (current-buffer) "systemctl" "list-units" "--all" "--quiet" "--full") (sit-for 0.1) (thread-last (split-string (buffer-string) "\n") (mapcar (lambda (line) (car (split-string line)) )) - (delq nil) - (completing-read "Unit: "))))) + (delq nil))))) + +(defun journalctl-read-system-units (_prompt host-location history) + "Query HOST-LOCATION (a tramp path) for its systemd units, given command HISTORY." + (completing-read "Unit: " + (journalctl--system-units host-location) + nil nil nil history)) (defun journalctl-remove-opt (opt) "Remove an OPT flag from the journal query." @@ -167,8 +180,8 @@ If OPT is set, remove this option." (thread-last (pcase opt ((or "--since" "--until") (org-read-date t)) - ((or "--follow" "--reverse" "--user")) - ("--unit" (journalctl-system-units host)) + ((or "--follow" "--reverse" "--user" "--pager-end" "--catalog")) + ("--unit" (journalctl-read-system-units nil host nil)) (_ (read-string (concat opt "= ")))) (list opt) (list) @@ -176,7 +189,7 @@ If OPT is set, remove this option." (journalctl host)))) (defun journalctl-edit-opts () - "Edit the value of 'journalctl-current-opts'." + "Edit the value of `journalctl-current-opts'." (interactive) (let* ((host journalctl-current-host) (opts journalctl-current-opts) @@ -188,8 +201,7 @@ If OPT is set, remove this option." (lambda () (interactive) (goto-char (point-min)) - (let ((standard-input (current-buffer))) - (journalctl host (read))) + (journalctl host (read (current-buffer))) (kill-buffer edit-buff))) (switch-to-buffer (current-buffer))))) @@ -209,9 +221,10 @@ If OPT is set, remove this option." (defun journalctl (host options) "Query the log of HOST given OPTIONS." (interactive - (let* ((picked-host (completing-read "Tramp host: " journalctl-hosts)) - (default-options `(("--unit" ,(journalctl-system-units picked-host)) ("--follow")))) - (list picked-host default-options))) + (let ((picked-host (completing-read "Tramp host: " journalctl-hosts))) + (list picked-host + `(("--unit" ,(journalctl-read-system-units nil picked-host nil)) ("--follow") + ("--lines" "100"))))) (let ((buffer (journalctl--clean-buffer)) (default-directory host)) (apply #'start-file-process "Journal" buffer "journalctl" (flatten-tree options)) diff --git a/elisp/shepherd.el b/elisp/shepherd.el index 1141d31..48a1aa8 100644 --- a/elisp/shepherd.el +++ b/elisp/shepherd.el @@ -63,7 +63,7 @@ `(,name . (lambda (service) (message (shepherd-command ,name service)))))) - '(status start stop restart enable))))) + '(start status stop restart enable))))) (provide 'shepherd) ;;; shepherd.el ends here diff --git a/gnupg/gpg.conf b/gnupg/gpg.conf index 8c9535b..372be0a 100644 --- a/gnupg/gpg.conf +++ b/gnupg/gpg.conf @@ -1,4 +1,7 @@ -with-keygrip +#with-keygrip +with-fingerprint +with-subkey-fingerprint +keyid-format 0xshort ## SHA1 is too weak. ## https://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html personal-digest-preferences SHA256 diff --git a/home-dots/dot-bash_profile b/home-dots/dot-bash_profile deleted file mode 100644 index ea2a147..0000000 --- a/home-dots/dot-bash_profile +++ /dev/null @@ -1,6 +0,0 @@ -# -# ~/.bash_profile -# -[[ -f ~/.bashrc ]] && . ~/.bashrc -# [ -f "$HOME/.ghcup/env" ] && source "$HOME/.ghcup/env" # ghcup-env -# source "$HOME/.cargo/env" diff --git a/home-dots/dot-bashrc b/home-dots/dot-bashrc index aefd08b..5488946 100644 --- a/home-dots/dot-bashrc +++ b/home-dots/dot-bashrc @@ -5,17 +5,17 @@ # If not running interactively, don't do anything [[ $- != *i* ]] && return +# If emacs tramp or eshell, don't execute any of this +[[ $TERM == "dumb" ]] && return HISTSIZE=-1 HISTFILESIZE=-1 +HISTCONTROL=ignorespace # enable color support of ls and also add handy aliases if [ -x /usr/bin/dircolors ]; then - test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" + # test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" alias ls='ls --color=auto' - #alias dir='dir --color=auto' - #alias vdir='vdir --color=auto' - alias grep='grep --color=auto' alias fgrep='fgrep --color=auto' alias egrep='egrep --color=auto' @@ -34,10 +34,11 @@ git_current_branch() { echo " ${ref#refs/heads/}" } +[[ -f /usr/bin/virtualenvwrapper_lazy.sh ]] && source /usr/bin/virtualenvwrapper_lazy.sh python_current_venv() { local orange="\[\e[0;91m\]" - if [[ -n ${VIRTUAL_ENV_PROMPT} ]]; then - echo " ${orange}${VIRTUAL_ENV_PROMPT}" + if [[ -n ${VIRTUAL_ENV} ]]; then + echo " ${orange} $(basename "${VIRTUAL_ENV}")" fi } @@ -66,9 +67,12 @@ PROMPT_COMMAND=__prompt_command export EDITOR='emacsclient' # GPG agent with ssh -unset SSH_AGENT_PID -if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then - export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" +if [ -z "$SSH_CLIENT" ]; then + unset SSH_AGENT_PID + if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then + SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" + export SSH_AUTH_SOCK + fi fi # For python lsp @@ -78,5 +82,6 @@ alias isrun='ps -ae | grep' alias gdimg='git difftool -t image_diff' alias G='grep -i' alias lar='ls -lahrt' +alias ssh='TERM=xterm-256color ssh' alias emacs='TERM=xterm-direct emacs' alias mykeys='setxkbmap -I$HOME/.config/xkb/ oscar -option caps:escape -print | xkbcomp -I$HOME/.config/xkb/ - $DISPLAY' diff --git a/home-dots/dot-gitconfig b/home-dots/dot-gitconfig index 4370974..cacdd3e 100644 --- a/home-dots/dot-gitconfig +++ b/home-dots/dot-gitconfig @@ -1,5 +1,6 @@ +# -*- mode: conf-unix; -*- [user] - name = Óscar Nájera + name = Oscar Najera email = hi@oscarnajera.com [pull] rebase = true @@ -14,7 +15,19 @@ xfuncname = "^(\\*+ +.*)$" [diff "lisp"] xfuncname = "^[ \t]*(((;+ )|\\((cl-|el-patch-|ert-)?def(un|var|macro|method|custom|ine|test)).*)$" +[diff "ledger"] + xfuncname = "^([0-9]{4}-[0-9]+-[0-9]+ .*)$" + [difftool "image_diff"] cmd = compare $REMOTE $LOCAL png:- | montage -font Liberation-Sans -tile 3x -geometry 400x -label "reference" $LOCAL -label "diff" - -label "current--%f" $REMOTE x: [diff] algorithm = histogram + +[sendemail] + smtpEncryption = tls + smtpServer = mail.oscarnajera.com + smtpUser = hi@oscarnajera.com + smtpServerPort = 587 + +[includeIf "gitdir:~/bytegit/**"] + path = ~/bytegit/.gitconfig diff --git a/home-dots/dot-profile b/home-dots/dot-profile index f156b80..084d096 100644 --- a/home-dots/dot-profile +++ b/home-dots/dot-profile @@ -1,8 +1,4 @@ #!/bin/sh export PATH="$HOME/.local/bin:$HOME/dev/dotfiles/bin:$PATH" -[ -f "$HOME/.ghcup/env" ] && source "$HOME/.ghcup/env" # ghcup-env -source "$HOME/.cargo/env" -# GUIX_PROFILE="$HOME/.guix-profile" && [ -e "$GUIX_PROFILE" ] && . "$GUIX_PROFILE/etc/profile" && export GUIX_LOCPATH=$GUIX_PROFILE/lib/locale -# GUIX_PROFILE="$HOME/.config/guix/current" && [ -e "$GUIX_PROFILE" ] && . "$GUIX_PROFILE/etc/profile" -# export SSL_CERT_DIR="$HOME/.guix-profile/etc/ssl/certs" -# export SSL_CERT_FILE="$HOME/.guix-profile/etc/ssl/certs/ca-certificates.crt" +[ -f "$HOME/.ghcup/env" ] && source "$HOME/.ghcup/env" +[ -f "$HOME/.cargo/env" ] && source "$HOME/.cargo/env" diff --git a/home-dots/dot-sbclrc b/home-dots/dot-sbclrc index a9569d3..035c861 100644 --- a/home-dots/dot-sbclrc +++ b/home-dots/dot-sbclrc @@ -2,7 +2,9 @@ ;;; The following lines added by ql:add-to-init-file: #-quicklisp -(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp" +(let ((quicklisp-init (merge-pathnames ".quicklisp/setup.lisp" (user-homedir-pathname)))) (when (probe-file quicklisp-init) (load quicklisp-init))) + +(push (merge-pathnames "dev/bitcoin/bp/" (user-homedir-pathname)) asdf:*central-registry*) diff --git a/install.scm b/install.scm index fe0dc2d..acabf6e 100755 --- a/install.scm +++ b/install.scm @@ -4,6 +4,7 @@ (use-modules (ice-9 and-let-star) + (ice-9 format) (ice-9 ftw) (ice-9 match) (ice-9 popen) @@ -20,9 +21,10 @@ ((_ value f rest ...) (->> (f value) rest ...)))) (define (ansi-color-log-formatter lvl time str) - (let ((color (cond ((eq? lvl 'CRITICAL) 'RED) - ((eq? lvl 'WARN) 'YELLOW) - ((eq? lvl 'OK) 'GREEN)))) + (let ((color (case lvl + ((CRITICAL) 'RED) + ((WARN) 'YELLOW) + ((OK) 'GREEN)))) (string-append (strftime "%F %H:%M:%S" (localtime time)) (colorize-string @@ -167,21 +169,29 @@ file-name)) (define (format-config-entry item) - (format #t "[~a]~%" (car item)) - (format #t "~:{~a=~@{~a~^;~}~%~}~%" (cdr item))) + (format #t "[~a]~%" (car item)) + (format #t "~:{~a=~@{~a~^;~}~%~}~%" (cdr item))) (define (mail-config) (log-msg 'INFO "Configuring mail") (log-msg 'INFO " Symlink mbsync") - (config-links "mail/dot-mbsyncrc.personal" "~/.mbsyncrc" #f) + (config-links + (if (string=? (gethostname) "obp") + "mail/dot-mbsyncrc.byteplant" + "mail/dot-mbsyncrc.personal") + "~/.mbsyncrc" #f) (let* ((notmuch-config-file (expand-file "~/.notmuch-config")) (emails (list "hi@oscarnajera.com" "hello@oscarnajera.com" "najera.oscar@gmail.com" + "oscar@byteplant.com" )) - (user-mail "hi@oscarnajera.com") + (user-mail + (if (string=? (gethostname) "obp") + "oscar@byteplant.com" + "hi@oscarnajera.com")) ;; setting up notmuch config (config `((database (path ,(expand-file "~/.mail"))) @@ -203,11 +213,13 @@ (define (main args) (setup-logging) (log-msg 'INFO "Symlink PIM") - (config-links "calendars.conf" "~/.calendars.conf" #f) (symlink-tree "home-dots" "~/") (config-links "gnupg/gpg.conf" "~/.gnupg/gpg.conf" #f) (config-links "gnupg/gpg-agent.conf" "~/.gnupg/gpg-agent.conf" #f) (symlink-tree "config" "~/.config") + (when (string=? (gethostname) "obp") + (config-links "other_configs/byte-gitconfig" + "~/bytegit/.gitconfig" #f)) (mail-config) (shutdown-logging)) diff --git a/lib/guile/ffi/notmuch.ffi b/lib/guile/ffi/notmuch.ffi index 1f8bfce..e404510 100644 --- a/lib/guile/ffi/notmuch.ffi +++ b/lib/guile/ffi/notmuch.ffi @@ -1,4 +1,5 @@ +;; -*- mode: scheme; -*- (define-ffi-module (ffi notmuch) - ; #:pkg-config "notmuch" - #:library '("libnotmuch") + ;; #:pkg-config "notmuch" + #:library '("libnotmuch") #:include '("notmuch.h")) diff --git a/lib/guile/ffi/notmuch.scm b/lib/guile/ffi/notmuch.scm index 42c3ab3..5c6fb6e 100644 --- a/lib/guile/ffi/notmuch.scm +++ b/lib/guile/ffi/notmuch.scm @@ -8,17 +8,11 @@ (define ffi-notmuch-llibs (delay (list (dynamic-link "libnotmuch")))) -(cond-expand - (guile-2.2) - (guile-2 - (define intptr_t long) - (define uintptr_t unsigned-long))) - ;; typedef int notmuch_bool_t; (define-public notmuch_bool_t-desc int) -;; typedef enum _notmuch_status { +;; typedef enum { ;; NOTMUCH_STATUS_SUCCESS = 0, ;; NOTMUCH_STATUS_OUT_OF_MEMORY, ;; NOTMUCH_STATUS_READ_ONLY_DATABASE, @@ -38,6 +32,12 @@ ;; NOTMUCH_STATUS_MALFORMED_CRYPTO_PROTOCOL, ;; NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION, ;; NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL, +;; NOTMUCH_STATUS_NO_CONFIG, +;; NOTMUCH_STATUS_NO_DATABASE, +;; NOTMUCH_STATUS_DATABASE_EXISTS, +;; NOTMUCH_STATUS_BAD_QUERY_SYNTAX, +;; NOTMUCH_STATUS_NO_MAIL_ROOT, +;; NOTMUCH_STATUS_CLOSED_DATABASE, ;; NOTMUCH_STATUS_LAST_STATUS, ;; } notmuch_status_t; (define notmuch_status_t-enum-nvl @@ -62,7 +62,13 @@ . 17) (NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL . 18) - (NOTMUCH_STATUS_LAST_STATUS . 19)) + (NOTMUCH_STATUS_NO_CONFIG . 19) + (NOTMUCH_STATUS_NO_DATABASE . 20) + (NOTMUCH_STATUS_DATABASE_EXISTS . 21) + (NOTMUCH_STATUS_BAD_QUERY_SYNTAX . 22) + (NOTMUCH_STATUS_NO_MAIL_ROOT . 23) + (NOTMUCH_STATUS_CLOSED_DATABASE . 24) + (NOTMUCH_STATUS_LAST_STATUS . 25)) ) (define notmuch_status_t-enum-vnl (map (lambda (pair) (cons (cdr pair) (car pair))) @@ -70,36 +76,12 @@ (define-public (unwrap-notmuch_status_t n) (cond ((symbol? n) - (or (assq-ref notmuch_status_t-enum-nvl n) (error "bad arg"))) + (or (assq-ref notmuch_status_t-enum-nvl n) + (throw 'ffi-help-error "bad arg: ~A" n))) ((integer? n) n) (else (error "bad arg")))) (define-public (wrap-notmuch_status_t v) (assq-ref notmuch_status_t-enum-vnl v)) -(define-public unwrap-enum-_notmuch_status unwrap-notmuch_status_t) -(define-public wrap-enum-_notmuch_status wrap-notmuch_status_t) - -;; enum _notmuch_status { -;; NOTMUCH_STATUS_SUCCESS = 0, -;; NOTMUCH_STATUS_OUT_OF_MEMORY, -;; NOTMUCH_STATUS_READ_ONLY_DATABASE, -;; NOTMUCH_STATUS_XAPIAN_EXCEPTION, -;; NOTMUCH_STATUS_FILE_ERROR, -;; NOTMUCH_STATUS_FILE_NOT_EMAIL, -;; NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID, -;; NOTMUCH_STATUS_NULL_POINTER, -;; NOTMUCH_STATUS_TAG_TOO_LONG, -;; NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW, -;; NOTMUCH_STATUS_UNBALANCED_ATOMIC, -;; NOTMUCH_STATUS_UNSUPPORTED_OPERATION, -;; NOTMUCH_STATUS_UPGRADE_REQUIRED, -;; NOTMUCH_STATUS_PATH_ERROR, -;; NOTMUCH_STATUS_IGNORED, -;; NOTMUCH_STATUS_ILLEGAL_ARGUMENT, -;; NOTMUCH_STATUS_MALFORMED_CRYPTO_PROTOCOL, -;; NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION, -;; NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL, -;; NOTMUCH_STATUS_LAST_STATUS, -;; }; ;; const char *notmuch_status_to_string(notmuch_status_t status); (define notmuch_status_to_string @@ -215,6 +197,28 @@ (export notmuch_config_list_t* notmuch_config_list_t*? make-notmuch_config_list_t*) +;; typedef struct _notmuch_config_values notmuch_config_values_t; +(define-public notmuch_config_values_t-desc 'void) +(define-fh-type-alias notmuch_config_values_t fh-void) +(define-public notmuch_config_values_t? fh-void?) +(define-public make-notmuch_config_values_t make-fh-void) +(define-public notmuch_config_values_t*-desc (fh:pointer notmuch_config_values_t-desc)) +(define-fh-pointer-type notmuch_config_values_t* notmuch_config_values_t*-desc + notmuch_config_values_t*? make-notmuch_config_values_t*) +(export notmuch_config_values_t* notmuch_config_values_t*? + make-notmuch_config_values_t*) + +;; typedef struct _notmuch_config_pairs notmuch_config_pairs_t; +(define-public notmuch_config_pairs_t-desc 'void) +(define-fh-type-alias notmuch_config_pairs_t fh-void) +(define-public notmuch_config_pairs_t? fh-void?) +(define-public make-notmuch_config_pairs_t make-fh-void) +(define-public notmuch_config_pairs_t*-desc (fh:pointer notmuch_config_pairs_t-desc)) +(define-fh-pointer-type notmuch_config_pairs_t* notmuch_config_pairs_t*-desc + notmuch_config_pairs_t*? make-notmuch_config_pairs_t*) +(export notmuch_config_pairs_t* notmuch_config_pairs_t*? + make-notmuch_config_pairs_t*) + ;; typedef struct _notmuch_indexopts notmuch_indexopts_t; (define-public notmuch_indexopts_t-desc 'void) (define-fh-type-alias notmuch_indexopts_t fh-void) @@ -277,7 +281,8 @@ (define-public (unwrap-notmuch_database_mode_t n) (cond ((symbol? n) - (or (assq-ref notmuch_database_mode_t-enum-nvl n) (error "bad arg"))) + (or (assq-ref notmuch_database_mode_t-enum-nvl n) + (throw 'ffi-help-error "bad arg: ~A" n))) ((integer? n) n) (else (error "bad arg")))) (define-public (wrap-notmuch_database_mode_t v) @@ -326,6 +331,109 @@ ~error_message)))))) (export notmuch_database_open_verbose) +;; notmuch_status_t notmuch_database_open_with_config(const char *database_path +;; , notmuch_database_mode_t mode, const char *config_path, const char * +;; profile, notmuch_database_t **database, char **error_message); +(define notmuch_database_open_with_config + (let ((~notmuch_database_open_with_config + (delay (fh-link-proc + ffi:int + "notmuch_database_open_with_config" + (list ffi-void* + ffi:int + ffi-void* + ffi-void* + ffi-void* + ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (database_path + mode + config_path + profile + database + error_message) + (let ((~database_path (unwrap~pointer database_path)) + (~mode (unwrap-notmuch_database_mode_t mode)) + (~config_path (unwrap~pointer config_path)) + (~profile (unwrap~pointer profile)) + (~database (unwrap~pointer database)) + (~error_message (unwrap~pointer error_message))) + (wrap-notmuch_status_t + ((force ~notmuch_database_open_with_config) + ~database_path + ~mode + ~config_path + ~profile + ~database + ~error_message)))))) +(export notmuch_database_open_with_config) + +;; notmuch_status_t notmuch_database_load_config(const char *database_path, +;; const char *config_path, const char *profile, notmuch_database_t ** +;; database, char **error_message); +(define notmuch_database_load_config + (let ((~notmuch_database_load_config + (delay (fh-link-proc + ffi:int + "notmuch_database_load_config" + (list ffi-void* + ffi-void* + ffi-void* + ffi-void* + ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (database_path + config_path + profile + database + error_message) + (let ((~database_path (unwrap~pointer database_path)) + (~config_path (unwrap~pointer config_path)) + (~profile (unwrap~pointer profile)) + (~database (unwrap~pointer database)) + (~error_message (unwrap~pointer error_message))) + (wrap-notmuch_status_t + ((force ~notmuch_database_load_config) + ~database_path + ~config_path + ~profile + ~database + ~error_message)))))) +(export notmuch_database_load_config) + +;; notmuch_status_t notmuch_database_create_with_config(const char * +;; database_path, const char *config_path, const char *profile, +;; notmuch_database_t **database, char **error_message); +(define notmuch_database_create_with_config + (let ((~notmuch_database_create_with_config + (delay (fh-link-proc + ffi:int + "notmuch_database_create_with_config" + (list ffi-void* + ffi-void* + ffi-void* + ffi-void* + ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (database_path + config_path + profile + database + error_message) + (let ((~database_path (unwrap~pointer database_path)) + (~config_path (unwrap~pointer config_path)) + (~profile (unwrap~pointer profile)) + (~database (unwrap~pointer database)) + (~error_message (unwrap~pointer error_message))) + (wrap-notmuch_status_t + ((force ~notmuch_database_create_with_config) + ~database_path + ~config_path + ~profile + ~database + ~error_message)))))) +(export notmuch_database_create_with_config) + ;; const char *notmuch_database_status_string(const notmuch_database_t *notmuch ;; ); (define notmuch_database_status_string @@ -397,6 +505,32 @@ ~closure)))))) (export notmuch_database_compact) +;; notmuch_status_t notmuch_database_compact_db(notmuch_database_t *database, +;; const char *backup_path, notmuch_compact_status_cb_t status_cb, void * +;; closure); +(define notmuch_database_compact_db + (let ((~notmuch_database_compact_db + (delay (fh-link-proc + ffi:int + "notmuch_database_compact_db" + (list ffi-void* ffi-void* ffi-void* ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (database backup_path status_cb closure) + (let ((~database + ((fht-unwrap notmuch_database_t*) database)) + (~backup_path (unwrap~pointer backup_path)) + (~status_cb + ((fht-unwrap notmuch_compact_status_cb_t) + status_cb)) + (~closure (unwrap~pointer closure))) + (wrap-notmuch_status_t + ((force ~notmuch_database_compact_db) + ~database + ~backup_path + ~status_cb + ~closure)))))) +(export notmuch_database_compact_db) + ;; notmuch_status_t notmuch_database_destroy(notmuch_database_t *database); (define notmuch_database_destroy (let ((~notmuch_database_destroy @@ -673,6 +807,22 @@ ((force ~notmuch_database_get_all_tags) ~db)))))) (export notmuch_database_get_all_tags) +;; notmuch_status_t notmuch_database_reopen(notmuch_database_t *db, +;; notmuch_database_mode_t mode); +(define notmuch_database_reopen + (let ((~notmuch_database_reopen + (delay (fh-link-proc + ffi:int + "notmuch_database_reopen" + (list ffi-void* ffi:int) + (force ffi-notmuch-llibs))))) + (lambda (db mode) + (let ((~db ((fht-unwrap notmuch_database_t*) db)) + (~mode (unwrap-notmuch_database_mode_t mode))) + (wrap-notmuch_status_t + ((force ~notmuch_database_reopen) ~db ~mode)))))) +(export notmuch_database_reopen) + ;; notmuch_query_t *notmuch_query_create(notmuch_database_t *database, const ;; char *query_string); (define notmuch_query_create @@ -693,6 +843,51 @@ (export notmuch_query_create) ;; typedef enum { +;; NOTMUCH_QUERY_SYNTAX_XAPIAN, +;; NOTMUCH_QUERY_SYNTAX_SEXP, +;; } notmuch_query_syntax_t; +(define notmuch_query_syntax_t-enum-nvl + '((NOTMUCH_QUERY_SYNTAX_XAPIAN . 0) + (NOTMUCH_QUERY_SYNTAX_SEXP . 1)) + ) +(define notmuch_query_syntax_t-enum-vnl + (map (lambda (pair) (cons (cdr pair) (car pair))) + notmuch_query_syntax_t-enum-nvl)) +(define-public (unwrap-notmuch_query_syntax_t n) + (cond + ((symbol? n) + (or (assq-ref notmuch_query_syntax_t-enum-nvl n) + (throw 'ffi-help-error "bad arg: ~A" n))) + ((integer? n) n) + (else (error "bad arg")))) +(define-public (wrap-notmuch_query_syntax_t v) + (assq-ref notmuch_query_syntax_t-enum-vnl v)) + +;; notmuch_status_t notmuch_query_create_with_syntax(notmuch_database_t * +;; database, const char *query_string, notmuch_query_syntax_t syntax, +;; notmuch_query_t **output); +(define notmuch_query_create_with_syntax + (let ((~notmuch_query_create_with_syntax + (delay (fh-link-proc + ffi:int + "notmuch_query_create_with_syntax" + (list ffi-void* ffi-void* ffi:int ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (database query_string syntax output) + (let ((~database + ((fht-unwrap notmuch_database_t*) database)) + (~query_string (unwrap~pointer query_string)) + (~syntax (unwrap-notmuch_query_syntax_t syntax)) + (~output (unwrap~pointer output))) + (wrap-notmuch_status_t + ((force ~notmuch_query_create_with_syntax) + ~database + ~query_string + ~syntax + ~output)))))) +(export notmuch_query_create_with_syntax) + +;; typedef enum { ;; NOTMUCH_SORT_OLDEST_FIRST, ;; NOTMUCH_SORT_NEWEST_FIRST, ;; NOTMUCH_SORT_MESSAGE_ID, @@ -710,7 +905,8 @@ (define-public (unwrap-notmuch_sort_t n) (cond ((symbol? n) - (or (assq-ref notmuch_sort_t-enum-nvl n) (error "bad arg"))) + (or (assq-ref notmuch_sort_t-enum-nvl n) + (throw 'ffi-help-error "bad arg: ~A" n))) ((integer? n) n) (else (error "bad arg")))) (define-public (wrap-notmuch_sort_t v) @@ -762,7 +958,8 @@ (define-public (unwrap-notmuch_exclude_t n) (cond ((symbol? n) - (or (assq-ref notmuch_exclude_t-enum-nvl n) (error "bad arg"))) + (or (assq-ref notmuch_exclude_t-enum-nvl n) + (throw 'ffi-help-error "bad arg: ~A" n))) ((integer? n) n) (else (error "bad arg")))) (define-public (wrap-notmuch_exclude_t v) @@ -1409,7 +1606,7 @@ ~indexopts)))))) (export notmuch_message_reindex) -;; typedef enum _notmuch_message_flag { +;; typedef enum { ;; NOTMUCH_MESSAGE_FLAG_MATCH, ;; NOTMUCH_MESSAGE_FLAG_EXCLUDED, ;; NOTMUCH_MESSAGE_FLAG_GHOST, @@ -1425,19 +1622,12 @@ (define-public (unwrap-notmuch_message_flag_t n) (cond ((symbol? n) - (or (assq-ref notmuch_message_flag_t-enum-nvl n) (error "bad arg"))) + (or (assq-ref notmuch_message_flag_t-enum-nvl n) + (throw 'ffi-help-error "bad arg: ~A" n))) ((integer? n) n) (else (error "bad arg")))) (define-public (wrap-notmuch_message_flag_t v) (assq-ref notmuch_message_flag_t-enum-vnl v)) -(define-public unwrap-enum-_notmuch_message_flag unwrap-notmuch_message_flag_t) -(define-public wrap-enum-_notmuch_message_flag wrap-notmuch_message_flag_t) - -;; enum _notmuch_message_flag { -;; NOTMUCH_MESSAGE_FLAG_MATCH, -;; NOTMUCH_MESSAGE_FLAG_EXCLUDED, -;; NOTMUCH_MESSAGE_FLAG_GHOST, -;; }; ;; notmuch_bool_t notmuch_message_get_flag(notmuch_message_t *message, ;; notmuch_message_flag_t flag); @@ -2293,6 +2483,324 @@ ~config_list))))) (export notmuch_config_list_destroy) +;; typedef enum { +;; NOTMUCH_CONFIG_FIRST, +;; NOTMUCH_CONFIG_DATABASE_PATH = NOTMUCH_CONFIG_FIRST, +;; NOTMUCH_CONFIG_MAIL_ROOT, +;; NOTMUCH_CONFIG_HOOK_DIR, +;; NOTMUCH_CONFIG_BACKUP_DIR, +;; NOTMUCH_CONFIG_EXCLUDE_TAGS, +;; NOTMUCH_CONFIG_NEW_TAGS, +;; NOTMUCH_CONFIG_NEW_IGNORE, +;; NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS, +;; NOTMUCH_CONFIG_PRIMARY_EMAIL, +;; NOTMUCH_CONFIG_OTHER_EMAIL, +;; NOTMUCH_CONFIG_USER_NAME, +;; NOTMUCH_CONFIG_AUTOCOMMIT, +;; NOTMUCH_CONFIG_EXTRA_HEADERS, +;; NOTMUCH_CONFIG_INDEX_AS_TEXT, +;; NOTMUCH_CONFIG_LAST, +;; } notmuch_config_key_t; +(define notmuch_config_key_t-enum-nvl + '((NOTMUCH_CONFIG_FIRST . 0) + (NOTMUCH_CONFIG_DATABASE_PATH . 0) + (NOTMUCH_CONFIG_MAIL_ROOT . 1) + (NOTMUCH_CONFIG_HOOK_DIR . 2) + (NOTMUCH_CONFIG_BACKUP_DIR . 3) + (NOTMUCH_CONFIG_EXCLUDE_TAGS . 4) + (NOTMUCH_CONFIG_NEW_TAGS . 5) + (NOTMUCH_CONFIG_NEW_IGNORE . 6) + (NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS . 7) + (NOTMUCH_CONFIG_PRIMARY_EMAIL . 8) + (NOTMUCH_CONFIG_OTHER_EMAIL . 9) + (NOTMUCH_CONFIG_USER_NAME . 10) + (NOTMUCH_CONFIG_AUTOCOMMIT . 11) + (NOTMUCH_CONFIG_EXTRA_HEADERS . 12) + (NOTMUCH_CONFIG_INDEX_AS_TEXT . 13) + (NOTMUCH_CONFIG_LAST . 14)) + ) +(define notmuch_config_key_t-enum-vnl + (map (lambda (pair) (cons (cdr pair) (car pair))) + notmuch_config_key_t-enum-nvl)) +(define-public (unwrap-notmuch_config_key_t n) + (cond + ((symbol? n) + (or (assq-ref notmuch_config_key_t-enum-nvl n) + (throw 'ffi-help-error "bad arg: ~A" n))) + ((integer? n) n) + (else (error "bad arg")))) +(define-public (wrap-notmuch_config_key_t v) + (assq-ref notmuch_config_key_t-enum-vnl v)) + +;; const char *notmuch_config_get(notmuch_database_t *notmuch, +;; notmuch_config_key_t key); +(define notmuch_config_get + (let ((~notmuch_config_get + (delay (fh-link-proc + ffi-void* + "notmuch_config_get" + (list ffi-void* ffi:int) + (force ffi-notmuch-llibs))))) + (lambda (notmuch key) + (let ((~notmuch + ((fht-unwrap notmuch_database_t*) notmuch)) + (~key (unwrap-notmuch_config_key_t key))) + ((force ~notmuch_config_get) ~notmuch ~key))))) +(export notmuch_config_get) + +;; notmuch_status_t notmuch_config_set(notmuch_database_t *notmuch, +;; notmuch_config_key_t key, const char *val); +(define notmuch_config_set + (let ((~notmuch_config_set + (delay (fh-link-proc + ffi:int + "notmuch_config_set" + (list ffi-void* ffi:int ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (notmuch key val) + (let ((~notmuch + ((fht-unwrap notmuch_database_t*) notmuch)) + (~key (unwrap-notmuch_config_key_t key)) + (~val (unwrap~pointer val))) + (wrap-notmuch_status_t + ((force ~notmuch_config_set) ~notmuch ~key ~val)))))) +(export notmuch_config_set) + +;; notmuch_config_values_t *notmuch_config_get_values(notmuch_database_t * +;; notmuch, notmuch_config_key_t key); +(define notmuch_config_get_values + (let ((~notmuch_config_get_values + (delay (fh-link-proc + ffi-void* + "notmuch_config_get_values" + (list ffi-void* ffi:int) + (force ffi-notmuch-llibs))))) + (lambda (notmuch key) + (let ((~notmuch + ((fht-unwrap notmuch_database_t*) notmuch)) + (~key (unwrap-notmuch_config_key_t key))) + ((fht-wrap notmuch_config_values_t*) + ((force ~notmuch_config_get_values) + ~notmuch + ~key)))))) +(export notmuch_config_get_values) + +;; notmuch_config_values_t *notmuch_config_get_values_string(notmuch_database_t +;; *notmuch, const char *key); +(define notmuch_config_get_values_string + (let ((~notmuch_config_get_values_string + (delay (fh-link-proc + ffi-void* + "notmuch_config_get_values_string" + (list ffi-void* ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (notmuch key) + (let ((~notmuch + ((fht-unwrap notmuch_database_t*) notmuch)) + (~key (unwrap~pointer key))) + ((fht-wrap notmuch_config_values_t*) + ((force ~notmuch_config_get_values_string) + ~notmuch + ~key)))))) +(export notmuch_config_get_values_string) + +;; notmuch_bool_t notmuch_config_values_valid(notmuch_config_values_t *values); +;; +(define notmuch_config_values_valid + (let ((~notmuch_config_values_valid + (delay (fh-link-proc + ffi:int + "notmuch_config_values_valid" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (values) + (let ((~values + ((fht-unwrap notmuch_config_values_t*) values))) + ((force ~notmuch_config_values_valid) ~values))))) +(export notmuch_config_values_valid) + +;; const char *notmuch_config_values_get(notmuch_config_values_t *values); +(define notmuch_config_values_get + (let ((~notmuch_config_values_get + (delay (fh-link-proc + ffi-void* + "notmuch_config_values_get" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (values) + (let ((~values + ((fht-unwrap notmuch_config_values_t*) values))) + ((force ~notmuch_config_values_get) ~values))))) +(export notmuch_config_values_get) + +;; void notmuch_config_values_move_to_next(notmuch_config_values_t *values); +(define notmuch_config_values_move_to_next + (let ((~notmuch_config_values_move_to_next + (delay (fh-link-proc + ffi:void + "notmuch_config_values_move_to_next" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (values) + (let ((~values + ((fht-unwrap notmuch_config_values_t*) values))) + ((force ~notmuch_config_values_move_to_next) + ~values))))) +(export notmuch_config_values_move_to_next) + +;; void notmuch_config_values_start(notmuch_config_values_t *values); +(define notmuch_config_values_start + (let ((~notmuch_config_values_start + (delay (fh-link-proc + ffi:void + "notmuch_config_values_start" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (values) + (let ((~values + ((fht-unwrap notmuch_config_values_t*) values))) + ((force ~notmuch_config_values_start) ~values))))) +(export notmuch_config_values_start) + +;; void notmuch_config_values_destroy(notmuch_config_values_t *values); +(define notmuch_config_values_destroy + (let ((~notmuch_config_values_destroy + (delay (fh-link-proc + ffi:void + "notmuch_config_values_destroy" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (values) + (let ((~values + ((fht-unwrap notmuch_config_values_t*) values))) + ((force ~notmuch_config_values_destroy) ~values))))) +(export notmuch_config_values_destroy) + +;; notmuch_config_pairs_t *notmuch_config_get_pairs(notmuch_database_t *notmuch +;; , const char *prefix); +(define notmuch_config_get_pairs + (let ((~notmuch_config_get_pairs + (delay (fh-link-proc + ffi-void* + "notmuch_config_get_pairs" + (list ffi-void* ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (notmuch prefix) + (let ((~notmuch + ((fht-unwrap notmuch_database_t*) notmuch)) + (~prefix (unwrap~pointer prefix))) + ((fht-wrap notmuch_config_pairs_t*) + ((force ~notmuch_config_get_pairs) + ~notmuch + ~prefix)))))) +(export notmuch_config_get_pairs) + +;; notmuch_bool_t notmuch_config_pairs_valid(notmuch_config_pairs_t *pairs); +(define notmuch_config_pairs_valid + (let ((~notmuch_config_pairs_valid + (delay (fh-link-proc + ffi:int + "notmuch_config_pairs_valid" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (pairs) + (let ((~pairs + ((fht-unwrap notmuch_config_pairs_t*) pairs))) + ((force ~notmuch_config_pairs_valid) ~pairs))))) +(export notmuch_config_pairs_valid) + +;; void notmuch_config_pairs_move_to_next(notmuch_config_pairs_t *pairs); +(define notmuch_config_pairs_move_to_next + (let ((~notmuch_config_pairs_move_to_next + (delay (fh-link-proc + ffi:void + "notmuch_config_pairs_move_to_next" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (pairs) + (let ((~pairs + ((fht-unwrap notmuch_config_pairs_t*) pairs))) + ((force ~notmuch_config_pairs_move_to_next) + ~pairs))))) +(export notmuch_config_pairs_move_to_next) + +;; const char *notmuch_config_pairs_key(notmuch_config_pairs_t *pairs); +(define notmuch_config_pairs_key + (let ((~notmuch_config_pairs_key + (delay (fh-link-proc + ffi-void* + "notmuch_config_pairs_key" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (pairs) + (let ((~pairs + ((fht-unwrap notmuch_config_pairs_t*) pairs))) + ((force ~notmuch_config_pairs_key) ~pairs))))) +(export notmuch_config_pairs_key) + +;; const char *notmuch_config_pairs_value(notmuch_config_pairs_t *pairs); +(define notmuch_config_pairs_value + (let ((~notmuch_config_pairs_value + (delay (fh-link-proc + ffi-void* + "notmuch_config_pairs_value" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (pairs) + (let ((~pairs + ((fht-unwrap notmuch_config_pairs_t*) pairs))) + ((force ~notmuch_config_pairs_value) ~pairs))))) +(export notmuch_config_pairs_value) + +;; void notmuch_config_pairs_destroy(notmuch_config_pairs_t *pairs); +(define notmuch_config_pairs_destroy + (let ((~notmuch_config_pairs_destroy + (delay (fh-link-proc + ffi:void + "notmuch_config_pairs_destroy" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (pairs) + (let ((~pairs + ((fht-unwrap notmuch_config_pairs_t*) pairs))) + ((force ~notmuch_config_pairs_destroy) ~pairs))))) +(export notmuch_config_pairs_destroy) + +;; notmuch_status_t notmuch_config_get_bool(notmuch_database_t *notmuch, +;; notmuch_config_key_t key, notmuch_bool_t *val); +(define notmuch_config_get_bool + (let ((~notmuch_config_get_bool + (delay (fh-link-proc + ffi:int + "notmuch_config_get_bool" + (list ffi-void* ffi:int ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (notmuch key val) + (let ((~notmuch + ((fht-unwrap notmuch_database_t*) notmuch)) + (~key (unwrap-notmuch_config_key_t key)) + (~val (unwrap~pointer val))) + (wrap-notmuch_status_t + ((force ~notmuch_config_get_bool) + ~notmuch + ~key + ~val)))))) +(export notmuch_config_get_bool) + +;; const char *notmuch_config_path(notmuch_database_t *notmuch); +(define notmuch_config_path + (let ((~notmuch_config_path + (delay (fh-link-proc + ffi-void* + "notmuch_config_path" + (list ffi-void*) + (force ffi-notmuch-llibs))))) + (lambda (notmuch) + (let ((~notmuch + ((fht-unwrap notmuch_database_t*) notmuch))) + ((force ~notmuch_config_path) ~notmuch))))) +(export notmuch_config_path) + ;; notmuch_indexopts_t *notmuch_database_get_default_indexopts( ;; notmuch_database_t *db); (define notmuch_database_get_default_indexopts @@ -2327,7 +2835,8 @@ (define-public (unwrap-notmuch_decryption_policy_t n) (cond ((symbol? n) - (or (assq-ref notmuch_decryption_policy_t-enum-nvl n) (error "bad arg"))) + (or (assq-ref notmuch_decryption_policy_t-enum-nvl n) + (throw 'ffi-help-error "bad arg: ~A" n))) ((integer? n) n) (else (error "bad arg")))) (define-public (wrap-notmuch_decryption_policy_t v) @@ -2408,6 +2917,38 @@ (NOTMUCH_DECRYPT_AUTO . 2) (NOTMUCH_DECRYPT_TRUE . 1) (NOTMUCH_DECRYPT_FALSE . 0) + (NOTMUCH_CONFIG_LAST . 14) + (NOTMUCH_CONFIG_INDEX_AS_TEXT . 13) + (NOTMUCH_CONFIG_EXTRA_HEADERS . 12) + (NOTMUCH_CONFIG_AUTOCOMMIT . 11) + (NOTMUCH_CONFIG_USER_NAME . 10) + (NOTMUCH_CONFIG_OTHER_EMAIL . 9) + (NOTMUCH_CONFIG_PRIMARY_EMAIL . 8) + (NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS . 7) + (NOTMUCH_CONFIG_NEW_IGNORE . 6) + (NOTMUCH_CONFIG_NEW_TAGS . 5) + (NOTMUCH_CONFIG_EXCLUDE_TAGS . 4) + (NOTMUCH_CONFIG_BACKUP_DIR . 3) + (NOTMUCH_CONFIG_HOOK_DIR . 2) + (NOTMUCH_CONFIG_MAIL_ROOT . 1) + (NOTMUCH_CONFIG_DATABASE_PATH . 0) + (NOTMUCH_CONFIG_FIRST . 0) + (NOTMUCH_CONFIG_LAST . 14) + (NOTMUCH_CONFIG_INDEX_AS_TEXT . 13) + (NOTMUCH_CONFIG_EXTRA_HEADERS . 12) + (NOTMUCH_CONFIG_AUTOCOMMIT . 11) + (NOTMUCH_CONFIG_USER_NAME . 10) + (NOTMUCH_CONFIG_OTHER_EMAIL . 9) + (NOTMUCH_CONFIG_PRIMARY_EMAIL . 8) + (NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS . 7) + (NOTMUCH_CONFIG_NEW_IGNORE . 6) + (NOTMUCH_CONFIG_NEW_TAGS . 5) + (NOTMUCH_CONFIG_EXCLUDE_TAGS . 4) + (NOTMUCH_CONFIG_BACKUP_DIR . 3) + (NOTMUCH_CONFIG_HOOK_DIR . 2) + (NOTMUCH_CONFIG_MAIL_ROOT . 1) + (NOTMUCH_CONFIG_DATABASE_PATH . 0) + (NOTMUCH_CONFIG_FIRST . 0) (NOTMUCH_MESSAGE_FLAG_GHOST . 2) (NOTMUCH_MESSAGE_FLAG_EXCLUDED . 1) (NOTMUCH_MESSAGE_FLAG_MATCH . 0) @@ -2430,11 +2971,21 @@ (NOTMUCH_SORT_MESSAGE_ID . 2) (NOTMUCH_SORT_NEWEST_FIRST . 1) (NOTMUCH_SORT_OLDEST_FIRST . 0) + (NOTMUCH_QUERY_SYNTAX_SEXP . 1) + (NOTMUCH_QUERY_SYNTAX_XAPIAN . 0) + (NOTMUCH_QUERY_SYNTAX_SEXP . 1) + (NOTMUCH_QUERY_SYNTAX_XAPIAN . 0) (NOTMUCH_DATABASE_MODE_READ_WRITE . 1) (NOTMUCH_DATABASE_MODE_READ_ONLY . 0) (NOTMUCH_DATABASE_MODE_READ_WRITE . 1) (NOTMUCH_DATABASE_MODE_READ_ONLY . 0) - (NOTMUCH_STATUS_LAST_STATUS . 19) + (NOTMUCH_STATUS_LAST_STATUS . 25) + (NOTMUCH_STATUS_CLOSED_DATABASE . 24) + (NOTMUCH_STATUS_NO_MAIL_ROOT . 23) + (NOTMUCH_STATUS_BAD_QUERY_SYNTAX . 22) + (NOTMUCH_STATUS_DATABASE_EXISTS . 21) + (NOTMUCH_STATUS_NO_DATABASE . 20) + (NOTMUCH_STATUS_NO_CONFIG . 19) (NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL . 18) (NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION . @@ -2456,7 +3007,13 @@ (NOTMUCH_STATUS_READ_ONLY_DATABASE . 2) (NOTMUCH_STATUS_OUT_OF_MEMORY . 1) (NOTMUCH_STATUS_SUCCESS . 0) - (NOTMUCH_STATUS_LAST_STATUS . 19) + (NOTMUCH_STATUS_LAST_STATUS . 25) + (NOTMUCH_STATUS_CLOSED_DATABASE . 24) + (NOTMUCH_STATUS_NO_MAIL_ROOT . 23) + (NOTMUCH_STATUS_BAD_QUERY_SYNTAX . 22) + (NOTMUCH_STATUS_DATABASE_EXISTS . 21) + (NOTMUCH_STATUS_NO_DATABASE . 20) + (NOTMUCH_STATUS_NO_CONFIG . 19) (NOTMUCH_STATUS_UNKNOWN_CRYPTO_PROTOCOL . 18) (NOTMUCH_STATUS_FAILED_CRYPTO_CONTEXT_CREATION . @@ -2480,7 +3037,7 @@ (NOTMUCH_STATUS_SUCCESS . 0) (NOTMUCH_TAG_MAX . 200) (LIBNOTMUCH_MICRO_VERSION . 0) - (LIBNOTMUCH_MINOR_VERSION . 3) + (LIBNOTMUCH_MINOR_VERSION . 6) (LIBNOTMUCH_MAJOR_VERSION . 5) (TRUE . 1) (FALSE . 0))) @@ -2505,6 +3062,8 @@ "notmuch_tags_t" (pointer . "notmuch_directory_t") "notmuch_directory_t" (pointer . "notmuch_filenames_t") "notmuch_filenames_t" (pointer . "notmuch_config_list_t") "notmuch_config_list_t" (pointer . + "notmuch_config_values_t") "notmuch_config_values_t" (pointer . + "notmuch_config_pairs_t") "notmuch_config_pairs_t" (pointer . "notmuch_indexopts_t") "notmuch_indexopts_t" "notmuch_compact_status_cb_t" (pointer . "notmuch_message_properties_t") "notmuch_message_properties_t")) (export ffi-notmuch-types) diff --git a/lib/guile/makefile b/lib/guile/makefile new file mode 100644 index 0000000..50b7bbe --- /dev/null +++ b/lib/guile/makefile @@ -0,0 +1,16 @@ +## +# Build my guile libraries +# +# @file +# @version 0.1 + +LD_LIBRARY_PATH=$HOME/.guix-profile/lib + +notmuch: ffi/notmuch.ffi + C_INCLUDE_PATH=$(HOME)/.guix-profile/include/ guild compile-ffi $< + +clean: + rm ffi/notmuch.scm + + +# end diff --git a/lib/guile/read-habit.scm b/lib/guile/read-habit.scm index 7ba7002..7c04422 100755 --- a/lib/guile/read-habit.scm +++ b/lib/guile/read-habit.scm @@ -2,37 +2,41 @@ --listen -s !# -(add-to-load-path "/home/titan/dev/helpful_scripts/guile/") +(add-to-load-path "/home/titan/dev/dotfiles/lib/guile/") -(use-modules (ice-9 rdelim) - (ice-9 popen) +(use-modules (ice-9 format) (ice-9 ftw) - (ice-9 format) + (ice-9 popen) + (ice-9 rdelim) + (json) (term ansi-color) + (utils) (web request) - (json) (web response) (web server) - (web uri) - (utils)) + (web uri)) (define habits-dir (expand-file "~/org/habits/")) -(define (parse-file port) - (let loop ((values '()) - (line (read-line port))) - (if (eof-object? line) - (reverse values) - (loop (cons (map string->number (string-split line #\:)) values) - (read-line port))))) +(define (iter-lines filename proc) + (call-with-input-file filename + (lambda (port) + (let loop ((values '()) + (line (read-line port))) + (if (eof-object? line) + (reverse values) + (loop (cons (proc line) values) + (read-line port))))))) (define (cli-print file-name) - (map (lambda (row) - (format #t "~a -> ~d~%" - (colorize-string (strftime "%c" (localtime (car row))) 'CYAN 'BOLD) - (cadr row))) - (call-with-input-file (string-append habits-dir file-name) - parse-file))) + (iter-lines + (string-append habits-dir file-name) + (lambda (line) + (let ((row (map string->number (string-split line #\:)))) + (format #t "~a -> ~d~%" + (colorize-string (strftime "%c" (localtime (car row))) 'CYAN 'BOLD) + (cadr row)) + row)))) (define (request-path-components request) (split-and-decode-uri-path (uri-path (request-uri request)))) @@ -53,9 +57,10 @@ ((file-exists? (string-append habits-dir (car path))) (values '((content-type . (application/json))) (scm->json-string (list->vector - (map (lambda (row) (list->vector row)) - (call-with-input-file (string-append habits-dir (car path)) - parse-file)))))) + (iter-lines + (string-append habits-dir (car path)) + (lambda (line) + (list->vector (map string->number (string-split line #\:))))))))) ((string=? "hi" (car path)) (values '((content-type . (application/json))) '(hi))) @@ -64,5 +69,5 @@ (cli-print "pull-ups.dat") (display "pu\n") -(cli-print "push-ups.dat") +(cli-print "poop.dat") ;(run-server (lambda (request request-body) (handle-request request request-body))) diff --git a/mail/dot-mbsyncrc.byteplant b/mail/dot-mbsyncrc.byteplant new file mode 100644 index 0000000..16a2867 --- /dev/null +++ b/mail/dot-mbsyncrc.byteplant @@ -0,0 +1,85 @@ +############################################################################### +# byteplant +IMAPAccount oscar +Host imap.byteplant.com +User oscar +PassCmd "pass show byteplant.com/imap" +AuthMechs LOGIN +SSLType IMAPS +CertificateFile /etc/ssl/certs/ca-certificates.crt + +IMAPStore oscar-remote +Account oscar + +MaildirStore oscar-local +Path ~/.mail/oscar/ +Inbox ~/.mail/oscar/Inbox +SubFolders Verbatim + +Channel oscar +Far :oscar-remote: +Near :oscar-local: +Patterns * +Create Both +SyncState * +Expunge Both + +############################################################################### +# byteplant +IMAPAccount admin +Host imap.byteplant.com +User admin +PassCmd "pass show byteplant.com/admin-email" +AuthMechs LOGIN +SSLType IMAPS +CertificateFile /etc/ssl/certs/ca-certificates.crt + +IMAPStore admin-remote +Account admin + +MaildirStore admin-local +Path ~/.mail/admin/ +Inbox ~/.mail/admin/Inbox +SubFolders Verbatim + +Channel admin +Far :admin-remote: +Near :admin-local: +Patterns % !history !Trash +MaxMessages 1000 +Sync Pull +Create Both +SyncState * +Expunge Both + +############################################################################### +# byteplant +IMAPAccount support +Host imap.byteplant.com +User support +PassCmd "pass show byteplant.com/support-mail" +AuthMechs LOGIN +SSLType IMAPS +CertificateFile /etc/ssl/certs/ca-certificates.crt + +IMAPStore support-remote +Account support + +MaildirStore support-local +Path ~/.mail/support/ +Inbox ~/.mail/support/Inbox +SubFolders Verbatim + +Channel support +Far :support-remote: +Near :support-local: +Patterns % !history !Trash +MaxMessages 1000 +Sync Pull +Create Both +SyncState * +Expunge Both + +# Local Variables: +# mode: conf-unix +# End: diff --git a/other_configs/byte-gitconfig b/other_configs/byte-gitconfig new file mode 100644 index 0000000..9f0dfa3 --- /dev/null +++ b/other_configs/byte-gitconfig @@ -0,0 +1,3 @@ +# -*- mode: conf-unix; -*- +[user] + email = oscar@byteplant.com @@ -1,8 +1,14 @@ #+TITLE: Managing my dotfiles * Installation -Be sure to have Guile and guile-lib installed on the system. Then execute the install -script +Be sure to have Guile and guile-lib installed on the system. +The best way is with GUIX, follow their install instructions. + +#+begin_src bash +guix install guile guile-lib +#+end_src + +Then execute the install script #+begin_src bash ./install.scm #+end_src diff --git a/scratch/semgrep/requirements.txt b/scratch/semgrep/requirements.txt new file mode 100644 index 0000000..3e493ea --- /dev/null +++ b/scratch/semgrep/requirements.txt @@ -0,0 +1,2 @@ +sentence-transformers +chromadb diff --git a/scratch/semgrep/semantic-search.el b/scratch/semgrep/semantic-search.el new file mode 100644 index 0000000..e1692d0 --- /dev/null +++ b/scratch/semgrep/semantic-search.el @@ -0,0 +1,148 @@ +;;; semantic-search.el --- Search for semantic similarity of text -*- lexical-binding: t; -*- +;; +;; Copyright (C) 2024 Óscar Nájera +;; +;; Author: Óscar Nájera <hi@oscarnajera.com> +;; Maintainer: Óscar Nájera <hi@oscarnajera.com> +;; Created: February 04, 2024 +;; Modified: February 04, 2024 +;; Version: 0.1.0 +;; Keywords: convenience data docs files hypermedia i18n matching tools +;; Homepage: https://github.com/titan/semantic-search +;; Package-Requires: ((emacs "27.1")) +;; +;; This file is not part of GNU Emacs. +;; +;;; Commentary: +;; +;; Search for semantic similarity of documents at a paragraph level +;; +;;; Code: + + +(require 'url) +(require 'org-element) +(require 'org-roam-db) +(require 'dash) + +;; Silence byte-compiler. +(defvar url-http-end-of-headers) + +(defcustom semantic-search-server-url "http://localhost:8080" + "Address where the Chromadb server is listening." + :type 'url + :group 'semantic-search) + +(defun semantic-search--connect (method data) + "Synchronous query to the server." + (let ((url-request-method "POST") + (url-request-extra-headers '(("Content-Type" . "application/json"))) + (url-request-data (encode-coding-string + (json-serialize `(,method ,data)) + 'utf-8))) + (with-current-buffer + (url-retrieve-synchronously semantic-search-server-url) + (goto-char url-http-end-of-headers) + (json-read)))) + +(defun semantic-search--org-id (paragraph &optional default) + (--> + (org-element-map + (org-element-property :parent paragraph) + 'node-property + (lambda (np) + (cons + (org-element-property :key np) + (org-element-property :value np)))) + (assoc 'ID it #'string=) + (cdr it) + (org-string-nw-p it) + (or it default))) + +(defun semantic-search--prepare-paragraph (file-id) + (lambda (paragraph) + (list + :document (substring-no-properties (org-element-interpret-data paragraph)) + :metadata (list :start-point + (org-element-property :begin paragraph) + :node-id + (semantic-search--org-id paragraph file-id))))) + +(defun semantic-search--add-buffer () + (interactive) + (if (eq major-mode 'org-mode) + (-some--> + (org-element-map + (org-element-parse-buffer) + 'paragraph + (semantic-search--prepare-paragraph (org-id-get (point-min) 'create))) + (cl-coerce it 'vector) + ;; (json-serialize it) + ;; (f-write it 'utf-8 "/tmp/out.json") + ;; (message "%S" it) + (semantic-search--connect :insert it)) + (user-error "This only works on org-mode"))) + +(defun semantic-search--roam-data (entries) + (thread-last + (cl-mapcar (lambda (meta) + (alist-get 'node-id meta)) + entries) + (delete-dups) + (vconcat) + (org-roam-db-query [:select [id title file] + :from nodes + :where (in id $v1)]))) + +(defun semantic-search--del-buffer (org-ids) + (interactive (list (org-id-get))) + (unless (null org-ids) + (semantic-search--connect :delete org-ids))) + +(defun semantic-search-pick-org-element () + (when-let ((context (ignore-errors (org-element-context)))) + (filter-buffer-substring (org-element-property :begin context) + (org-element-property :end context)))) + +(defun semantic-search--sync-db () + (org-roam-dolist-with-progress (file (nreverse (org-roam-list-files))) + "importing to semantic search" + (org-roam-with-file file nil + (semantic-search--add-buffer)))) + +;; (semantic-search--sync-db) +(defun semantic-search (text) + (interactive (list (or (semantic-search-pick-org-element) + (read-from-minibuffer "What are you looking for? ")))) + (-let (((&alist 'distances 'documents 'metadatas) + (semantic-search--connect :query text))) + (with-current-buffer (get-buffer-create "*Semantic Search*") + (erase-buffer) + (org-mode) + (insert "#+title: Looking for:\n" text "\n") + (cl-mapc + (lambda (entry-distances entry-document entry-metadatas) + (let ((data (semantic-search--roam-data entry-metadatas))) + (cl-mapc + (lambda (d paragraph meta) + (unless (zerop d) + (-let* ((node-id (alist-get 'node-id meta)) + ((_ title file) (assoc node-id data #'string=)) + (pos + (if file + (with-temp-buffer + (insert-file-contents file) + (line-number-at-pos (or (alist-get 'start-point meta) 1))) + 1))) + (insert + (format "* [[file:%s::%d][%s]]\n" file pos title) + "- Distance :: " (number-to-string d) "\n" + paragraph ?\n) + (org-fill-paragraph)))) + entry-distances entry-document entry-metadatas))) + distances documents metadatas) + (goto-char (point-min)) + (display-buffer (current-buffer))))) + +(provide 'semantic-search) +;;; semantic-search.el ends here diff --git a/scratch/semgrep/server.py b/scratch/semgrep/server.py new file mode 100644 index 0000000..becabbb --- /dev/null +++ b/scratch/semgrep/server.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +import argparse +import collections +import hashlib +import json +from http.server import BaseHTTPRequestHandler, HTTPServer + +import chromadb + + +def checksum(string: str): + sha256 = hashlib.sha256() + sha256.update(string.encode("utf-8")) + return sha256.hexdigest()[:32] + + +def ensure_list(data): + if isinstance(data, str): + return [data] + if isinstance(data, list): + if all(isinstance(l, str) for l in data): + return data + raise ValueError("Data must be a list of strings") + + +def delete_nodes(nodes): + for node in nodes: + collection.delete(where={"node-id": node}) + + +class MyRequestHandler(BaseHTTPRequestHandler): + def do_POST(self): + content_length = int(self.headers["Content-Length"]) + post_data = self.rfile.read(content_length).decode("utf-8") + + try: + data = json.loads(post_data) + response_message = f"Received POST request with data: '{data}'\n" + self.log_message(response_message) + except ValueError: + response_message = "Invalid JSON data" + self.send_response(400) + + if query := data.get("query"): + self.log_message("Processing query '%s'", query.replace("\n", " ").strip()) + response = collection.query(query_texts=ensure_list(query)) + elif delete_set := data.get("delete"): + delete_nodes(ensure_list(delete_set)) + response = f"Deleted nodes {delete_set}" + elif paragraphs := data.get("insert"): + data, metadata = drop_duplicates(paragraphs) + nodes = set(m.get("node-id") for m in metadata) + self.log_message("Processing metadata %s", nodes) + delete_nodes(nodes) + collection.add( + documents=data, metadatas=metadata, ids=list(map(checksum, data)) + ) + response = f"Successfully inserted {nodes}" + else: + raise ValueError(f"Used wrong method. Sent: {data.keys()}") + + response_message = json.dumps(response) + + self.send_response(200) + self.send_header("Content-type", "text/plain") + self.end_headers() + self.wfile.write(response_message.encode("utf-8")) + + +def run_server(port=8080): + server_address = ("", port) + httpd = HTTPServer(server_address, MyRequestHandler) + print(f"Server running on port {port}") + httpd.serve_forever() + + +def drop_duplicates(paragraphs): + data = [data["document"].replace("\n", " ").strip() for data in paragraphs] + metadata = [data["metadata"] for data in paragraphs] + dups = (x for x, count in collections.Counter(data).items() if count > 1) + to_drop = [] + for no in dups: + to_drop.extend([i for i, d in enumerate(data) if d == no][1:]) + to_drop.sort(reverse=True) + for index in to_drop: + data.pop(index) + metadata.pop(index) + return data, metadata + + +def parse_arguments(args=None): + parser = argparse.ArgumentParser( + description="Run Semantic database server", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "-db", "--database", default="org-roam", help="Name of the collection" + ) + parser.add_argument( + "-D", + "--database-dir", + default="semantic-roam", + help="Directory where to store database files", + ) + parser.add_argument( + "-p", "--port", default=8080, type=int, help="Port where server listens" + ) + + return parser.parse_args(args) + + +if __name__ == "__main__": + args = parse_arguments() + client = chromadb.PersistentClient(path=args.database_dir) + collection = client.get_or_create_collection(args.database) + run_server(args.port) diff --git a/scratch/semgrep/tests.py b/scratch/semgrep/tests.py new file mode 100644 index 0000000..0e5d233 --- /dev/null +++ b/scratch/semgrep/tests.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +import server as s + + +def test_drop_dup(): + sample = [ + {"document": "Hello", "metadata": 5}, + {"document": "World", "metadata": 8}, + {"document": "Hello", "metadata": 6}, + {"document": "Good", "metadata": 3}, + {"document": "World", "metadata": 9}, + {"document": "World\n\n", "metadata": 9}, + ] + + assert s.drop_duplicates(sample) == (["Hello", "World", "Good"], [5, 8, 3]) diff --git a/scratch/semgrep/utils.py b/scratch/semgrep/utils.py new file mode 100644 index 0000000..66ee410 --- /dev/null +++ b/scratch/semgrep/utils.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# This functions don't necessarily stand alone. I used on debug process +import uuid + +response = collection.query( + query_texts="machines scale", + where={"node-id": "496d4874-be24-4601-8a87-214d55e11297"}, +) +collection.query(query_texts="machines scale") + + +def get_node(node_id): + return collection.get(where={"node-id": node_id}) + + +def get_data(amount): + nodeid = str(uuid.uuid4()) + data = ["heelo" for _ in range(amount)] + metadata = [{"node-id": nodeid, "point": i} for i in range(amount)] + ids = [str(uuid.uuid4()) for _ in range(amount)] + return {"documents": data, "metadatas": metadata, "ids": ids} |