Playing with some new emacs run launchers.

This commit is contained in:
Derek Taylor
2026-01-01 13:28:44 -06:00
parent 10876119b0
commit f9d798ec39

View File

@@ -50,6 +50,149 @@
(app-launcher-run-app)
(delete-frame))))
(defun dt/emacs-generic-launcher (options prompt action-fn)
"Create a minibuffer-only frame to select from OPTIONS with PROMPT.
ACTION-FN is a function that takes the selected string as an argument."
(interactive)
(with-selected-frame
(make-frame '((name . "emacs-launcher")
(minibuffer . only)
(undecorated . t)
(width . 80)
(height . 11)
(internal-border-width . 10)))
(unwind-protect
(let ((selection (completing-read prompt options)))
(funcall action-fn selection))
(delete-frame))))
;; NEW LAUNCHERS
(require 'json) ;; for bookmarks and screenshots
(require 'cl-lib) ;; for screenshots
(defun dt/get-brave-bookmarks ()
"Parse Brave bookmarks and return an alist of (name . url)."
(let* ((path "~/.config/BraveSoftware/Brave-Browser/Default/Bookmarks") ;; Adjust "Default" if using profiles
(json-object-type 'alist)
(data (json-read-file (expand-file-name path)))
(roots (cdr (assoc 'roots data)))
(bookmarks '()))
(cl-labels ((extract (node)
(let ((type (cdr (assoc 'type node)))
(children (cdr (assoc 'children node))))
(cond
((string= type "url")
(push (cons (cdr (assoc 'name node))
(cdr (assoc 'url node)))
bookmarks))
((string= type "folder")
(mapc #'extract children))))))
;; Extract from both Bookmark Bar and Other Bookmarks
(extract (cdr (assoc 'bookmark_bar roots)))
(extract (cdr (assoc 'other roots))))
bookmarks))
(defun dt/brave-bookmark-launcher ()
"Open Brave bookmarks in a dmenu-like Emacs minibuffer."
(interactive)
(let* ((bookmarks (dt/get-brave-bookmarks))
(choices (mapcar #'car bookmarks))) ; Get just the names for the menu
(with-selected-frame
(make-frame '((name . "emacs-bookmark-launcher")
(minibuffer . only)
(undecorated . t)
(width . 80)
(height . 15)
(internal-border-width . 10)))
(unwind-protect
(let* ((selection (completing-read "Search Bookmarks: " choices))
(url (cdr (assoc selection bookmarks))))
(when url
;; This uses your default browser (Brave) to open the link
(browse-url url)))
(delete-frame)))))
(defun dt/get-monitor-info ()
"Robustly parse xrandr geometry, stripping physical size data for maim."
(let ((xrandr-output (shell-command-to-string "xrandr --listactivemonitors")))
(delq nil
(mapcar (lambda (line)
;; Regex matches: Name (column 3) and Geometry (column 2)
;; Example line: 0: +*HDMI-A-0 1920/477x1080/268+1920+0
(when (string-match "[0-9]+: \\+\\*?\\([^ ]+\\) \\([0-9x/++-]+\\)" line)
(let ((name (match-string 1 line))
(geom (match-string 2 line)))
;; Remove the physical size bits (e.g., /477) that xrandr adds
(cons name (replace-regexp-in-string "/[0-9]+" "" geom)))))
(split-string xrandr-output "\n" t)))))
(defun dt/screenshot-launcher ()
"Emacs port of dm-maim with full monitor support and reliable clipboard handling."
(interactive)
(let* ((maim-dir (expand-file-name "~/Pictures/Screenshots/"))
(maim-file-prefix "screenshot")
(timestamp (format-time-string "%Y%m%d-%H%M%S"))
(monitors (dt/get-monitor-info))
(modes (append '("Fullscreen" "Active window" "Selected region")
(mapcar #'car monitors)))
(destinations '("File" "Clipboard" "Both")))
(unless (file-exists-p maim-dir)
(make-directory maim-dir t))
(with-selected-frame
(make-frame '((name . "emacs-screenshot-launcher")
(minibuffer . only)
(undecorated . t)
(width . 80)
(height . 12)
(internal-border-width . 10)))
(unwind-protect
(let* ((target (completing-read "Take screenshot of: " modes))
(maim-target-args
(cond ((string= target "Active window")
(concat "-i " (string-trim (shell-command-to-string "xdotool getactivewindow"))))
((string= target "Selected region") "-s")
((assoc target monitors)
(concat "-g " (cdr (assoc target monitors))))
(t "")))
(file-type (if (assoc target monitors) target (downcase target)))
(delay (completing-read "Delay (seconds): " '("0" "1" "2" "3" "4" "5")))
(delay-arg (if (string= delay "0") "0.5" delay))
(dest (completing-read "Destination: " destinations))
(filename (expand-file-name
(format "%s-%s-%s.png"
maim-file-prefix
(replace-regexp-in-string " " "_" file-type)
timestamp)
maim-dir))
(maim-args (format "%s --delay=%s -q" maim-target-args delay-arg))
;; USE XCLIP -LOOP 1 OR REDIRECTS TO ENSURE PERSISTENCE
(clipboard-cmd "xclip -selection clipboard -t image/png")
(full-command
(cond
((string= dest "File")
(format "maim %s %s && notify-send 'Saved Screenshot' '%s'"
maim-args filename filename))
((string= dest "Clipboard")
(format "maim %s | %s && notify-send 'Saved' 'Clipboard'"
maim-args clipboard-cmd))
((string= dest "Both")
(format "maim %s | tee %s | %s && notify-send 'Saved' 'File & Clipboard'"
maim-args filename clipboard-cmd)))))
;; Use 'call-process-shell-command' with an ampersand to truly
;; background it without Emacs waiting or killing the pipe too early.
(call-process-shell-command (concat full-command " &") nil 0))
(delete-frame)))))
(provide 'app-launchers)
;;; app-launchers.el ends here