From c8ab813232bc743ef5e428d14f5092917893e7bb Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Sun, 22 Dec 2024 12:45:23 +0100 Subject: [PATCH] update dwim-shell-command Signed-off-by: Andreas Gerler --- .../dwim-shell-command-autoloads.el | 35 - .../dwim-shell-command-pkg.el | 12 - .../dwim-shell-command-autoloads.el | 335 ++++++++++ .../dwim-shell-command-pkg.el | 7 + .../dwim-shell-command.el | 109 ++-- .../dwim-shell-commands.el | 606 +++++++++++++++++- 6 files changed, 1002 insertions(+), 102 deletions(-) delete mode 100644 elpa/dwim-shell-command-20230709.2129/dwim-shell-command-autoloads.el delete mode 100644 elpa/dwim-shell-command-20230709.2129/dwim-shell-command-pkg.el create mode 100644 elpa/dwim-shell-command-20241115.845/dwim-shell-command-autoloads.el create mode 100644 elpa/dwim-shell-command-20241115.845/dwim-shell-command-pkg.el rename elpa/{dwim-shell-command-20230709.2129 => dwim-shell-command-20241115.845}/dwim-shell-command.el (91%) rename elpa/{dwim-shell-command-20230709.2129 => dwim-shell-command-20241115.845}/dwim-shell-commands.el (66%) diff --git a/elpa/dwim-shell-command-20230709.2129/dwim-shell-command-autoloads.el b/elpa/dwim-shell-command-20230709.2129/dwim-shell-command-autoloads.el deleted file mode 100644 index 12956bb8..00000000 --- a/elpa/dwim-shell-command-20230709.2129/dwim-shell-command-autoloads.el +++ /dev/null @@ -1,35 +0,0 @@ -;;; dwim-shell-command-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- -;; -;;; Code: - -(add-to-list 'load-path (directory-file-name - (or (file-name-directory #$) (car load-path)))) - - -;;;### (autoloads nil "dwim-shell-command" "dwim-shell-command.el" -;;;;;; (0 0 0 0)) -;;; Generated autoloads from dwim-shell-command.el - -(register-definition-prefixes "dwim-shell-command" '("dwim-shell-command")) - -;;;*** - -;;;### (autoloads nil "dwim-shell-commands" "dwim-shell-commands.el" -;;;;;; (0 0 0 0)) -;;; Generated autoloads from dwim-shell-commands.el - -(register-definition-prefixes "dwim-shell-commands" '("dwim-shell-commands-")) - -;;;*** - -;;;### (autoloads nil nil ("dwim-shell-command-pkg.el") (0 0 0 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; coding: utf-8 -;; End: -;;; dwim-shell-command-autoloads.el ends here diff --git a/elpa/dwim-shell-command-20230709.2129/dwim-shell-command-pkg.el b/elpa/dwim-shell-command-20230709.2129/dwim-shell-command-pkg.el deleted file mode 100644 index 49355d5d..00000000 --- a/elpa/dwim-shell-command-20230709.2129/dwim-shell-command-pkg.el +++ /dev/null @@ -1,12 +0,0 @@ -(define-package "dwim-shell-command" "20230709.2129" "Shell commands with DWIM behaviour" - '((emacs "28.1")) - :commit "2503c5a749eaa288d5e7250561893416fd40fbf9" :authors - '(("Alvaro Ramirez")) - :maintainers - '(("Alvaro Ramirez")) - :maintainer - '("Alvaro Ramirez") - :url "https://github.com/xenodium/dwim-shell-command") -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/dwim-shell-command-20241115.845/dwim-shell-command-autoloads.el b/elpa/dwim-shell-command-20241115.845/dwim-shell-command-autoloads.el new file mode 100644 index 00000000..534831c1 --- /dev/null +++ b/elpa/dwim-shell-command-20241115.845/dwim-shell-command-autoloads.el @@ -0,0 +1,335 @@ +;;; dwim-shell-command-autoloads.el --- automatically extracted autoloads (do not edit) -*- lexical-binding: t -*- +;; Generated by the `loaddefs-generate' function. + +;; This file is part of GNU Emacs. + +;;; Code: + +(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path))) + + + +;;; Generated autoloads from dwim-shell-command.el + +(autoload 'dwim-shell-command "dwim-shell-command" "\ +Execute DWIM shell command asynchronously using noweb templates. + +Which files + + `dwim-shell-command' attempts to guess which file(s) you may want + the command to operate on. + + 1. If visiting a `dired' buffer, draw the marked file(s). + 2. If visiting any other buffer with an associated file, use that. + +Templates + + Operate on drawn files using either the following: + + <> (file path) + <> (file path without extension) + <> (extension) + <> (generate a temporary directory) + <<*>> (all files joined) + <> (clipboard) + <>, <<1n>>, or <> (for current iteration) + + For example: + + With drawn files '(\"path/to/image1.png\" \"path/to/image2.png\") + + \"convert '<>' '<>.jpg'\" expands to + + \"convert 'path/to/image1.png' 'path/to/image1.jpg'\" + \"convert 'path/to/image2.png' 'path/to/image2.jpg'\" + + while \"ls -lh <<*>>\" expands to + + \"ls -lh path/to/image1.png path/to/image2.png\" + +Focus + + `dwim-shell-command' creates a process buffer to capture command + output, but doesn't display or focus on it by default. Instead, + it tries to guess what's more convenient to focus on. + + While the process is busy, show a spinner in the minibuffer. No + focus changes. + + After process is finished: + + 1. If there were any files created in the `default-directory', + jump to a `dired' buffer and move point to the new file (via + `dired-jump'). + + 2. If no new files were created, automatically switch focus to the + process buffer and display its output. + + Note: You can prevent this automatic focus by prepending your + command with whitespace. + + | + V + \" convert '<>' '<>.jpg'\" + + 3. If the shell command caused any errors, offer to focus the + process buffer and display its output. + +Quick exit + + Process buffers are read-only and can be quickly closed by + pressing `q'. + +Prefix + + With PREFIX, execute command that number of times. + +(fn PREFIX)" t) +(register-definition-prefixes "dwim-shell-command" '("dwim-shell-command-")) + + +;;; Generated autoloads from dwim-shell-commands.el + +(autoload 'dwim-shell-commands-audio-to-mp3 "dwim-shell-commands" "\ +Convert all marked audio to mp3(s)." t) +(autoload 'dwim-shell-extract-har-content "dwim-shell-commands" "\ +Extract all har content fields to files. + +(fn PREFIX)" t) +(autoload 'dwim-shell-extract-har-urls "dwim-shell-commands" "\ +Get all request URLs." t) +(autoload 'dwim-shell-view-open-ports-per-app "dwim-shell-commands" "\ +View open ports per app" t) +(autoload 'dwim-shell-commands-open-clipboard-url "dwim-shell-commands" "\ +Open clipboard URL. Offer to stream if possible." t) +(autoload 'dwim-shell-commands-stream-clipboard-url "dwim-shell-commands" "\ +Stream clipboard URL using mpv." t) +(autoload 'dwim-shell-commands-download-clipboard-stream-url "dwim-shell-commands" "\ +Download clipboard URL." t) +(autoload 'dwim-shell-commands-image-clear-exif-metadata "dwim-shell-commands" "\ +Clear EXIF metadata in image(s)." t) +(autoload 'dwim-shell-commands-image-scan-code "dwim-shell-commands" "\ +Scan any code (ie. qr, bar, etc) from image(s)." t) +(autoload 'dwim-shell-commands-image-exif-metadata "dwim-shell-commands" "\ +View EXIF metadata in image(s)." t) +(autoload 'dwim-shell-commands-tesseract-ocr-text-from-image "dwim-shell-commands" "\ +Extract text from image via tesseract." t) +(autoload 'dwim-shell-commands-image-view-location-in-openstreetmap "dwim-shell-commands" "\ +Open image(s) location in map/browser." t) +(autoload 'dwim-shell-commands-image-reverse-geocode-location "dwim-shell-commands" "\ +Reverse geocode image(s) location." t) +(autoload 'dwim-shell-commands-image-horizontal-flip "dwim-shell-commands" "\ +Horizontally flip image(s)." t) +(autoload 'dwim-shell-commands-image-vertical-flip "dwim-shell-commands" "\ +Horizontally flip image(s)." t) +(autoload 'dwim-shell-commands-image-to-jpg "dwim-shell-commands" "\ +Convert all marked images to jpg(s)." t) +(autoload 'dwim-shell-commands-image-to-png "dwim-shell-commands" "\ +Convert all marked images to png(s)." t) +(autoload 'dwim-shell-commands-svg-to-png "dwim-shell-commands" "\ +Convert all marked svg(s) to png(s)." t) +(autoload 'dwim-shell-commands-svg-to-favicons "dwim-shell-commands" "\ +Convert svg to common favicons." t) +(autoload 'dwim-shell-commands-make-transparent-png "dwim-shell-commands" "\ +Create a transparent png." t) +(autoload 'dwim-shell-commands-join-as-pdf "dwim-shell-commands" "\ +Join all marked images as a single pdf." t) +(autoload 'dwim-shell-commands-keep-pdf-page "dwim-shell-commands" "\ +Keep a page from pdf." t) +(autoload 'dwim-shell-commands-join-images-horizontally "dwim-shell-commands" "\ +Join all marked images horizontally as a single image." t) +(autoload 'dwim-shell-commands-join-images-vertically "dwim-shell-commands" "\ +Join all marked images vertically as a single image." t) +(autoload 'dwim-shell-commands-image-to-grayscale "dwim-shell-commands" "\ +Convert all marked images to grayscale." t) +(autoload 'dwim-shell-commands-reorient-image "dwim-shell-commands" "\ +Reorient images." t) +(autoload 'dwim-shell-commands-gif-to-video "dwim-shell-commands" "\ +Convert all marked gif(s) to video(s)." t) +(autoload 'dwim-shell-commands-macos-empty-trash "dwim-shell-commands" "\ +Empty macOS trash." t) +(autoload 'dwim-shell-commands-macos-ocr-text-from-desktop-region "dwim-shell-commands" "\ +Select a macOS desktop area to OCR and copy recognized text to kill ring." t) +(autoload 'dwim-shell-commands-macos-ocr-text-from-image "dwim-shell-commands" "\ +OCR file and copy recognized text to kill ring." t) +(autoload 'dwim-shell-commands-macos-convert-to-mp4 "dwim-shell-commands" "\ +Convert to mov to mp4" t) +(autoload 'dwim-shell-commands-video-to-gif "dwim-shell-commands" "\ +Convert all marked videos to gif(s)." t) +(autoload 'dwim-shell-commands-video-to-mov "dwim-shell-commands" "\ +Convert all marked videos to mov(s)." t) +(autoload 'dwim-shell-commands-video-to-webp "dwim-shell-commands" "\ +Convert all marked videos to webp(s)." t) +(autoload 'dwim-shell-commands-webp-to-video "dwim-shell-commands" "\ +Convert all marked webp(s) to video(s)." t) +(autoload 'dwim-shell-commands-webp-to-gif "dwim-shell-commands" "\ +Convert all marked webp(s) to gif(s)." t) +(autoload 'dwim-shell-commands-video-to-hevc-mkv "dwim-shell-commands" "\ +Convert all marked videos to hevc mkv." t) +(autoload 'dwim-shell-commands-video-to-optimized-gif "dwim-shell-commands" "\ +Convert all marked videos to optimized gif(s)." t) +(autoload 'dwim-shell-commands-unzip "dwim-shell-commands" "\ +Unzip all marked archives (of any kind) using `atool'." t) +(autoload 'dwim-shell-commands-zip "dwim-shell-commands" "\ +Zip all marked files into archive.zip." t) +(autoload 'dwim-shell-commands-zip-password-protect "dwim-shell-commands" "\ +Protect/encrypt zip file(s) with password." t) +(autoload 'dwim-shell-commands-optimize-gif "dwim-shell-commands" "\ +Convert all marked videos to optimized gif(s)." t) +(autoload 'dwim-shell-commands-speed-up-gif "dwim-shell-commands" "\ +Speeds up gif(s)." t) +(autoload 'dwim-shell-commands-image-apply-ios-round-corners "dwim-shell-commands" "\ +Apply iOS round corners to image(s)." t) +(autoload 'dwim-shell-commands-clip-round-rect-gif "dwim-shell-commands" "\ +Clip gif(s) with round rectangle." t) +(autoload 'dwim-shell-commands-resize-gif "dwim-shell-commands" "\ +Resize marked gif(s)." t) +(autoload 'dwim-shell-commands-epub-to-org "dwim-shell-commands" "\ +Convert epub(s) to org." t) +(autoload 'dwim-shell-commands-docx-to-pdf "dwim-shell-commands" "\ +Convert docx(s) to pdf (via latex)." t) +(autoload 'dwim-shell-commands-kill-process "dwim-shell-commands" "\ +Select and kill process." t) +(autoload 'dwim-shell-commands-macos-add-to-photos "dwim-shell-commands" "\ +Add to Photos.app." t) +(autoload 'dwim-shell-commands-macos-toggle-bluetooth-device-connection "dwim-shell-commands" "\ +Toggle Bluetooth device connection." t) +(autoload 'dwim-shell-commands-macos-bin-plist-to-xml "dwim-shell-commands" "\ +Convert binary plist to xml." t) +(autoload 'dwim-shell-commands-macos-toggle-dark-mode "dwim-shell-commands" "\ +Toggle macOS dark mode." t) +(autoload 'dwim-shell-commands-pdf-to-txt "dwim-shell-commands" "\ +Convert pdf to txt." t) +(autoload 'dwim-shell-commands-resize-image-by-factor "dwim-shell-commands" "\ +Resize marked image(s) by factor." t) +(autoload 'dwim-shell-commands-resize-image-in-pixels "dwim-shell-commands" "\ +Resize marked image(s) in pixels." t) +(autoload 'dwim-shell-commands-pdf-password-protect "dwim-shell-commands" "\ +Add a password to pdf(s)." t) +(autoload 'dwim-shell-commands-pdf-password-unprotect "dwim-shell-commands" "\ +Remove a password from pdf(s)." t) +(autoload 'dwim-shell-commands-video-to-mp3 "dwim-shell-commands" "\ +Convert video(s) to mp3." t) +(autoload 'dwim-shell-commands-video-to-mp3-with-artwork "dwim-shell-commands" "\ +Convert video(s) to mp3 (keep frame as artwork)." t) +(autoload 'dwim-shell-commands-ndjson-to-org "dwim-shell-commands" "\ +Convert ndjson file to org." t) +(autoload 'dwim-shell-commands-set-media-artwork-image-metadata "dwim-shell-commands" "\ +Set image artwork metadata for media file(s)." t) +(autoload 'dwim-shell-commands-video-trim-beginning "dwim-shell-commands" "\ +Drop audio from all marked videos." t) +(autoload 'dwim-shell-commands-video-trim-end "dwim-shell-commands" "\ +Drop audio from all marked videos." t) +(autoload 'dwim-shell-commands-video-to-thumbnail "dwim-shell-commands" "\ +Generate a thumbnail for marked video(s)." t) +(autoload 'dwim-shell-commands-drop-video-audio "dwim-shell-commands" "\ +Drop audio from all marked videos." t) +(autoload 'dwim-shell-commands-ping-google "dwim-shell-commands" "\ +Ping google.com." t) +(autoload 'dwim-shell-commands-speed-up-video "dwim-shell-commands" "\ +Speed up video(s)." t) +(autoload 'dwim-shell-commands-speed-up-video-fragment "dwim-shell-commands" "\ +Speed up fragment in video(s)." t) +(autoload 'dwim-shell-commands-resize-video "dwim-shell-commands" "\ +Resize marked images." t) +(autoload 'dwim-shell-commands-clipboard-to-qr "dwim-shell-commands" "\ +Generate a QR code from clipboard." t) +(autoload 'dwim-shell-commands-sha-256-hash-file-at-clipboard-url "dwim-shell-commands" "\ +Download file at clipboard URL and generate SHA-256 hash." t) +(autoload 'dwim-shell-commands-view-sqlite-schema-diagram "dwim-shell-commands" "\ +View sqlite schema diagram." t) +(autoload 'dwim-shell-commands-open-externally "dwim-shell-commands" "\ +Open file(s) externally." t) +(autoload 'dwim-shell-commands-macos-caffeinate "dwim-shell-commands" "\ +Invoke caffeinate to prevent mac from sleeping." t) +(autoload 'dwim-shell-commands-macos-make-finder-alias "dwim-shell-commands" "\ +Make macOS Finder alias." t) +(autoload 'dwim-shell-commands-macos-version-and-hardware-overview-info "dwim-shell-commands" "\ +View macOS version and hardware overview info." t) +(autoload 'dwim-shell-commands-macos-reveal-in-finder "dwim-shell-commands" "\ +Reveal selected files in macOS Finder." t) +(autoload 'dwim-shell-commands-macos-share "dwim-shell-commands" "\ +Share selected files from macOS." t) +(autoload 'dwim-shell-commands-macos-toggle-display-rotation "dwim-shell-commands" "\ +Rotate display." t) +(autoload 'dwim-shell-commands-make-swift-package-library "dwim-shell-commands" "\ +Create a swift package library" t) +(autoload 'dwim-shell-commands-make-swift-package-executable "dwim-shell-commands" "\ +Create a swift package executable" t) +(autoload 'dwim-shell-commands-macos-set-default-app "dwim-shell-commands" "\ +Set default app for file(s)." t) +(autoload 'dwim-shell-commands-macos-open-with "dwim-shell-commands" "\ +Open file(s) with specific external app." t) +(autoload 'dwim-shell-commands-macos-open-with-firefox "dwim-shell-commands" "\ +Open file(s) in Firefox." t) +(autoload 'dwim-shell-commands-macos-open-with-safari "dwim-shell-commands" "\ +Open file(s) in Safari." t) +(autoload 'dwim-shell-commands-macos-start-recording-window "dwim-shell-commands" "\ +Select and start recording a macOS window." t) +(autoload 'dwim-shell-commands-macos-end-recording-window "dwim-shell-commands" "\ +Stop recording a macOS window." t) +(autoload 'dwim-shell-commands-macos-abort-recording-window "dwim-shell-commands" "\ +Stop recording a macOS window." t) +(autoload 'dwim-shell-commands-macos-screenshot-window "dwim-shell-commands" "\ +Select and screenshot macOS window." t) +(autoload 'dwim-shell-commands-files-combined-size "dwim-shell-commands" "\ +Get files combined file size." t) +(autoload 'dwim-shell-commands-image-to-icns "dwim-shell-commands" "\ +Convert png to icns icon." t) +(autoload 'dwim-shell-commands-image-add-drop-shadow "dwim-shell-commands" "\ +Add a drop shadow." t) +(autoload 'dwim-shell-commands-image-trim-borders "dwim-shell-commands" "\ +Trim image(s) border (useful for video screenshots)." t) +(autoload 'dwim-shell-commands-git-clone-clipboard-url-to-downloads "dwim-shell-commands" "\ +Clone git URL in clipboard to \"~/Downloads/\"." t) +(autoload 'dwim-shell-commands-http-serve-dir "dwim-shell-commands" "\ +HTTP serve current directory." t) +(autoload 'dwim-shell-commands-git-clone-clipboard-url "dwim-shell-commands" "\ +Clone git URL in clipboard to `default-directory'." t) +(autoload 'dwim-shell-commands-pass-git-pull "dwim-shell-commands" "\ +Pass git pull." t) +(autoload 'dwim-shell-commands-git-list-untracked-files "dwim-shell-commands" "\ +List untracked git files in `default-directory'." t) +(autoload 'dwim-shell-commands-git-delete-untracked-files "dwim-shell-commands" "\ +Delete untracked git files in `default-directory'." t) +(autoload 'dwim-shell-commands-external-ip "dwim-shell-commands" "\ +Copy external IP to kill ring." t) +(autoload 'dwim-shell-commands-macos-install-iphone-device-ipa "dwim-shell-commands" "\ +Install iPhone device .ipa. +Needs ideviceinstaller and libmobiledevice installed." t) +(autoload 'dwim-shell-commands-copy-to-downloads "dwim-shell-commands" "\ +Copy file to ~/Downloads." t) +(autoload 'dwim-shell-commands-duplicate "dwim-shell-commands" "\ +Duplicate file." t) +(autoload 'dwim-shell-commands-rename-all "dwim-shell-commands" "\ +Rename all marked file(s)." t) +(autoload 'dwim-shell-commands-move-to-downloads "dwim-shell-commands" "\ +Move file to ~/Downloads." t) +(autoload 'dwim-shell-commands-copy-to-desktop "dwim-shell-commands" "\ +Copy file to ~/Desktop." t) +(autoload 'dwim-shell-commands-move-to-desktop "dwim-shell-commands" "\ +Move file to ~/Desktop." t) +(autoload 'dwim-shell-commands-kill-gpg-agent "dwim-shell-commands" "\ +Kill (thus restart) gpg agent. + +Useful for when you get this error: + +gpg: public key decryption failed: No pinentry +gpg: decryption failed: No pinentry" t) +(autoload 'dwim-shell-commands-upload-to-0x0 "dwim-shell-commands" "\ +Upload the marked files to 0x0.st" t) +(register-definition-prefixes "dwim-shell-commands" '("dwim-shell-commands-")) + +;;; End of scraped data + +(provide 'dwim-shell-command-autoloads) + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; no-native-compile: t +;; coding: utf-8-emacs-unix +;; End: + +;;; dwim-shell-command-autoloads.el ends here diff --git a/elpa/dwim-shell-command-20241115.845/dwim-shell-command-pkg.el b/elpa/dwim-shell-command-20241115.845/dwim-shell-command-pkg.el new file mode 100644 index 00000000..8c053012 --- /dev/null +++ b/elpa/dwim-shell-command-20241115.845/dwim-shell-command-pkg.el @@ -0,0 +1,7 @@ +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "dwim-shell-command" "20241115.845" + "Shell commands with DWIM behaviour." + '((emacs "28.1")) + :url "https://github.com/xenodium/dwim-shell-command" + :commit "1fa8b9d361f01618bf65111ac0b253adb0599a09" + :revdesc "1fa8b9d361f0") diff --git a/elpa/dwim-shell-command-20230709.2129/dwim-shell-command.el b/elpa/dwim-shell-command-20241115.845/dwim-shell-command.el similarity index 91% rename from elpa/dwim-shell-command-20230709.2129/dwim-shell-command.el rename to elpa/dwim-shell-command-20241115.845/dwim-shell-command.el index c9864044..0e3f8e14 100644 --- a/elpa/dwim-shell-command-20230709.2129/dwim-shell-command.el +++ b/elpa/dwim-shell-command-20241115.845/dwim-shell-command.el @@ -5,7 +5,8 @@ ;; Author: Alvaro Ramirez ;; Package-Requires: ((emacs "28.1")) ;; URL: https://github.com/xenodium/dwim-shell-command -;; Version: 0.48 +;; Package-Version: 20241115.845 +;; Package-Revision: 1fa8b9d361f0 ;; This package is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -38,7 +39,6 @@ (require 'dired-aux) (require 'map) (require 'seq) -(require 'shell) (require 'simple) (require 'subr-x) (require 'view) @@ -67,6 +67,11 @@ Otherwise, automatically focus buffer on process error." :type 'boolean :group 'dwim-shell-command) +(defcustom dwim-shell-command-use-absolute-paths nil + "If t, generate absolute paths in templates. Relative otherwise." + :type 'boolean + :group 'dwim-shell-command) + (defcustom dwim-shell-command-shell-util nil "Shell util, for example: \"zsh\" or \"bash\". Set to nil to use `shell-file-name'." @@ -116,6 +121,7 @@ Use `identify' to remove formatting." error-autofocus monitor-directory) +;;;###autoload (defun dwim-shell-command (prefix) "Execute DWIM shell command asynchronously using noweb templates. @@ -207,7 +213,7 @@ Prefix #'minibuffer-default-add-shell-commands)) (read-from-minibuffer dwim-shell-command-prompt dwim-shell-command-default-command nil nil 'shell-command-history))) -(cl-defun dwim-shell-command-on-marked-files (buffer-name script &key utils extensions shell-util shell-args shell-trace shell-pipe post-process-template on-completion repeat silent-success no-progress error-autofocus monitor-directory focus-now join-separator) +(cl-defun dwim-shell-command-on-marked-files (buffer-name script &key utils extensions shell-util shell-args shell-trace shell-pipe post-process-template on-completion repeat silent-success no-progress error-autofocus monitor-directory focus-now join-separator temp-dir) "Create DWIM utilities executing templated SCRIPT on given files. Here's a simple utility invoking SCRIPT to convert image files to jpg. @@ -308,9 +314,10 @@ Quick exit :error-autofocus error-autofocus :monitor-directory monitor-directory :focus-now focus-now - :join-separator join-separator)) + :join-separator join-separator + :temp-dir temp-dir)) -(cl-defun dwim-shell-command-execute-script (buffer-name script &key files extensions shell-util shell-args shell-trace shell-pipe utils post-process-template on-completion silent-success gen-temp-dir repeat no-progress error-autofocus monitor-directory focus-now join-separator) +(cl-defun dwim-shell-command-execute-script (buffer-name script &key files extensions shell-util shell-args shell-trace shell-pipe utils post-process-template on-completion silent-success temp-dir repeat no-progress error-autofocus monitor-directory focus-now join-separator) "Execute a script asynchronously, DWIM style with SCRIPT and BUFFER-NAME. :FILES are used to instantiate SCRIPT as a noweb template. @@ -373,7 +380,7 @@ internal behavior). :SILENT-SUCCESS to avoid jumping to process buffer if neither error nor file generated. -:GEN-TEMP-DIR to generate a temporary directory for this command. +:TEMP-DIR to generate a temporary directory for this command. This is implied when <> appears in the script. :REPEAT Use to repeat script N number of times. @@ -410,8 +417,8 @@ This is implied when <> appears in the script. (setq shell-args (seq-concatenate 'list '("-x") shell-args))) (when (stringp utils) (setq utils (list utils))) - (when (or gen-temp-dir (string-match-p "\<\\>" script 0)) - (setq gen-temp-dir (make-temp-file "dwim-shell-command-" t))) + (when (and (string-match-p "\<\\>" script 0) (not temp-dir)) + (setq temp-dir (make-temp-file "dwim-shell-command-" t))) (when (and repeat (> repeat 1)) (cl-assert (<= (length files) 1) nil "Must not repeat when multiple files are selected.") @@ -440,20 +447,20 @@ This is implied when <> appears in the script. (padding (dwim-shell-command--digits (length files))) (n (or (dwim-shell-command--n-start-value template padding) "1"))) (if (seq-empty-p files) - (setq script (dwim-shell-command--expand-file-template template nil post-process-template gen-temp-dir n replacements)) + (setq script (dwim-shell-command--expand-file-template template nil post-process-template temp-dir n replacements)) (if (dwim-shell-command--contains-multi-file-ref template) - (setq script (dwim-shell-command--expand-files-template template files post-process-template gen-temp-dir replacements join-separator)) + (setq script (dwim-shell-command--expand-files-template template files post-process-template temp-dir replacements join-separator)) (seq-do (lambda (file) (setq script (concat script "\n" - (dwim-shell-command--expand-file-template template file post-process-template gen-temp-dir n replacements))) + (dwim-shell-command--expand-file-template template file post-process-template temp-dir n replacements))) (setq n (dwim-shell-command--increment-string n padding))) files))) (setq script (string-trim script)) (with-current-buffer proc-buffer (let ((inhibit-message t)) ;; Silence noise of entering shell-mode. - (shell-mode)) + (comint-mode)) (setq default-directory default-directory) (shell-command-save-pos-or-erase) (view-mode +1) @@ -613,7 +620,9 @@ JOIN-SEPARATOR is used to join files from <<*>>." (dwim-shell-command--contains-multi-file-ref template) (dwim-shell-command--contains-single-file-ref template)) (setq files (seq-map (lambda (file) - (expand-file-name file)) + (if dwim-shell-command-use-absolute-paths + (expand-file-name file) + (file-relative-name (expand-file-name file) default-directory))) files)) (mapc (lambda (replacement) @@ -691,6 +700,9 @@ For example: (setq escaped-quote "\\\\\"")) ((string-equal unescaped-quote "'") (setq escaped-quote "'\"'\"'")) + ;; Ignore slashes as user may be joining paths. + ((string-equal unescaped-quote "/") + (setq escaped-quote "/")) (t (error "Couldn't figure out how to quote for \"%s\" using %s and %s" haystack @@ -732,7 +744,9 @@ REPLACEMENTS is a cons list of literals to replace with values." replacements) (when file - (setq file (expand-file-name file)) + (setq file (if dwim-shell-command-use-absolute-paths + (expand-file-name file) + (file-relative-name (expand-file-name file) default-directory))) ;; "<>" with "/path/tmp.txt" -> "/path/tmp" (if-let* ((quoting (dwim-shell-command--escaped-quote-around "\<\\>" template t)) (unescaped-quote (nth 0 quoting)) @@ -742,14 +756,25 @@ REPLACEMENTS is a cons list of literals to replace with values." template nil nil 2)) (setq template (replace-regexp-in-string "\\(\<\\>\\)" (file-name-sans-extension file) template nil nil 1))) - ;; "<>" with "/path/tmp.txt" -> "tmp.txt" - (if-let* ((quoting (dwim-shell-command--escaped-quote-around "\<\\>" template t)) + ;; "<>" with "/path/tmp.txt" -> "tmp.txt" + (if-let* ((quoting (dwim-shell-command--escaped-quote-around "\<\\>" template t)) (unescaped-quote (nth 0 quoting)) (escaped-quote (nth 1 quoting))) - (setq template (replace-regexp-in-string "\\(\<\\>\\)\\([^ ]\\)" + (setq template (replace-regexp-in-string "\\(\<\\>\\)\\([^ ]\\)" (string-replace unescaped-quote escaped-quote (file-name-nondirectory file)) template nil nil 1)) - (setq template (replace-regexp-in-string "\\(\<\\>\\)" (file-name-nondirectory file) template nil nil 1))) + (setq template (replace-regexp-in-string "\\(\<\\>\\)" (file-name-nondirectory file) template nil nil 1))) + + ;; "<>" with "/path/tmp.txt" -> "tmp" + (if-let* ((quoting (dwim-shell-command--escaped-quote-around "\<\\>" template t)) + (unescaped-quote (nth 0 quoting)) + (escaped-quote (nth 1 quoting))) + (setq template (replace-regexp-in-string "\\(\<\\>\\)\\([^ ]\\)" + (string-replace unescaped-quote escaped-quote + (file-name-sans-extension (file-name-nondirectory file))) + template nil nil 1)) + (setq template (replace-regexp-in-string "\\(\<\\>\\)" (file-name-sans-extension + (file-name-nondirectory file)) template nil nil 1))) ;; "<>" with "/path/tmp.txt" -> "txt" (if (file-name-extension file) @@ -813,8 +838,10 @@ REPLACEMENTS is a cons list of literals to replace with values." "<>") ((string-match "\<\\>" template) "<>") - ((string-match "\<\\>" template) - "<>") + ((string-match "\<\\>" template) + "<>") + ((string-match "\<\\>" template) + "<>") ((string-match "\<\\>" template) "<>"))) @@ -862,10 +889,13 @@ all needed to finalize processing." ;; Region is not accurate if new files added. Wipe it. (when (use-region-p) (deactivate-mark))) - (if (or buffer-auto-save-file-name - buffer-file-name) - (revert-buffer :ignore-auto :noconfirm))) - (setq files-after (dwim-shell-command--default-directory-files monitor-directory)) + (when (and (or buffer-auto-save-file-name + buffer-file-name) + (not (verify-visited-file-modtime))) + ;; Already visiting a file. Revert if modified by command. + (revert-buffer :ignore-auto :noconfirm))) + (with-current-buffer (process-buffer process) + (setq files-after (dwim-shell-command--default-directory-files monitor-directory))) (setq oldest-new-file (dwim-shell-command--last-modified-between files-before @@ -908,21 +938,26 @@ all needed to finalize processing." (setq dwim-shell-command--commands (map-delete dwim-shell-command--commands (process-name process))))) -(cl-defun dwim-shell-command--unique-new-file-path (file-path &key expand) - "Return a unique FILE-PATH using :EXPAND to expand FILE-PATH. +(defun dwim-shell-command--unique-new-file-path (file-path) + "Return a unique FILE-PATH. + +If FILE-PATH already contains a number in the format (n), set counter to n. + \"/tmp/blah.txt\" -> \"/tmp/blah(1).txt\" -\"/tmp/blah\" -> \"/tmp/blah(1)\"" - (let ((counter 1) - (name (file-name-sans-extension file-path)) - (extension (file-name-extension file-path))) +\"/tmp/blah(2).txt\" -> \"/tmp/blah(3).txt\"" + (let* ((name (file-name-sans-extension file-path)) + (extension (file-name-extension file-path)) + (counter (if (string-match "(\\([0-9]+\\))$" name) + (string-to-number (match-string 1 name)) + 0))) + (when (string-match "(\\([0-9]+\\))$" name) + (setq name(replace-match "" t t name))) (while (file-exists-p file-path) - (if extension - (setq file-path (format "%s(%d).%s" name counter extension)) - (setq file-path (format "%s(%d)" name counter))) - (setq counter (1+ counter))) - (if expand - (expand-file-name file-path) - file-path))) + (setq counter (1+ counter)) + (setq file-path (if extension + (format "%s(%d).%s" name counter extension) + (format "%s(%d)" name counter)))) + file-path)) (defun dwim-shell-command--sentinel (process _) "Handles PROCESS sentinel and STATE." diff --git a/elpa/dwim-shell-command-20230709.2129/dwim-shell-commands.el b/elpa/dwim-shell-command-20241115.845/dwim-shell-commands.el similarity index 66% rename from elpa/dwim-shell-command-20230709.2129/dwim-shell-commands.el rename to elpa/dwim-shell-command-20241115.845/dwim-shell-commands.el index 4fbaeca2..7e981ff0 100644 --- a/elpa/dwim-shell-command-20230709.2129/dwim-shell-commands.el +++ b/elpa/dwim-shell-command-20241115.845/dwim-shell-commands.el @@ -33,6 +33,7 @@ (require 'seq) (require 'subr-x) +;;;###autoload (defun dwim-shell-commands-audio-to-mp3 () "Convert all marked audio to mp3(s)." (interactive) @@ -41,6 +42,75 @@ "ffmpeg -stats -n -i '<>' -acodec libmp3lame '<>.mp3'" :utils "ffmpeg")) +;;;###autoload +(defun dwim-shell-extract-har-content (prefix) + "Extract all har content fields to files." + (interactive "P") + (when prefix + (setq prefix (string-trim (read-string "Transcription locale: " "ja-JP"))) + (when (string-empty-p prefix) + (errro "No locale given"))) + (dwim-shell-command-on-marked-files + "Extract har response content" + (format "declare -A mime_map=( \ + [\"audio/mpeg\"]=\"mp3\" \ + [\"image/jpeg\"]=\"jpg\" \ + [\"text/plain\"]=\"txt\" \ + [\"application/json\"]=\"json\" \ + # TODO: Add more mappings if needed. +) +outdir='<>' +mkdir -p \"${outdir}\" + : > \"${outdir}/<>.org\" +jq -r '.log.entries[] | @base64' '<>' | while read -r entry; do + url=$(echo \"$entry\" | base64 --decode | jq -r '.request.url') + basename=$(echo \"$entry\" | base64 --decode | jq -r '.request.url | capture(\"(?<=//)[^/]+/(?.*)\") | .path | gsub(\"[^a-zA-Z0-9]\"; \"_\")') + mime=$(echo \"$entry\" | base64 --decode | jq -r '.response.content.mimeType') + extension=${mime_map[$mime]:-\"bin\"} + name=\"${outdir}/${basename:0:255}.${extension}\" + echo \"${name}\" + content=$(echo \"$entry\" | base64 --decode | jq -r '.response.content.text') + echo \"$content\" | base64 --decode > \"${name}\" + if [ -f \"${name}\" ] && %s; then + transcription=$(macosrec --speech-to-text --locale %s --input \"${name}\") + if [ $? -eq 0 ]; then + transcribed_name=\"${outdir}/${transcription}.${extension}\" + mv \"${name}\" \"${transcribed_name}\" + basename=$(basename \"${transcribed_name}\") + echo \"[[file:${basename}][${transcription}]] [[${url}][remote]]\" >> \"${outdir}/<>.org\" + fi + fi +done" + (if prefix + "true" + "false") + prefix + (if prefix + "true" + "false")) + :utils "jq" + :extensions "har")) + +;;;###autoload +(defun dwim-shell-extract-har-urls () + "Get all request URLs." + (interactive) + (dwim-shell-command-on-marked-files + "Extract har request URLs" + "jq -r '.log.entries[].request.url' '<>'" + :utils "jq")) + +;;;###autoload +(defun dwim-shell-view-open-ports-per-app () + "View open ports per app" + (interactive) + (dwim-shell-command-on-marked-files + "Ports per app" + ;; https://x.com/nurmiwilliam/status/1823228630664634695 + "sudo lsof -iTCP -sTCP:LISTEN -n -P | awk 'NR>1 {print $9, $1, $2}' | sed 's/.*://' | sort -u | while read port process pid; do echo \"Port $port: $(ps -p $pid -o command= | sed 's/^-//') (PID: $pid)\"; done | sort -n" + :utils "jq")) + +;;;###autoload (defun dwim-shell-commands-open-clipboard-url () "Open clipboard URL. Offer to stream if possible." (interactive) @@ -68,6 +138,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :silent-success t) (funcall #'browse-url-default-browser url args))) +;;;###autoload (defun dwim-shell-commands-stream-clipboard-url () "Stream clipboard URL using mpv." (interactive) @@ -80,6 +151,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :error-autofocus t :silent-success t)) +;;;###autoload (defun dwim-shell-commands-download-clipboard-stream-url () "Download clipboard URL." (interactive) @@ -93,6 +165,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :monitor-directory "~/Downloads" :silent-success t)) +;;;###autoload (defun dwim-shell-commands-image-clear-exif-metadata () "Clear EXIF metadata in image(s)." (interactive) @@ -102,6 +175,16 @@ Optional argument ARGS as per `browse-url-default-browser'" exiftool -all:all= -overwrite_original '<>_cleared.<>'" :utils "exiftool")) +;;;###autoload +(defun dwim-shell-commands-image-scan-code () + "Scan any code (ie. qr, bar, etc) from image(s)." + (interactive) + (dwim-shell-command-on-marked-files + "Scan code" + "zbarimg --quiet '<>'" + :utils "zbarimg")) + +;;;###autoload (defun dwim-shell-commands-image-exif-metadata () "View EXIF metadata in image(s)." (interactive) @@ -110,7 +193,8 @@ Optional argument ARGS as per `browse-url-default-browser'" "exiftool '<>'" :utils "exiftool")) -(defun dwim-shell-commands-ocr-text-from-image () +;;;###autoload +(defun dwim-shell-commands-tesseract-ocr-text-from-image () "Extract text from image via tesseract." (interactive) (dwim-shell-command-on-marked-files @@ -118,8 +202,9 @@ Optional argument ARGS as per `browse-url-default-browser'" "tesseract '<>' -" :utils "tesseract")) -(defun dwim-shell-commands-image-browse-location () - "Open image(s) location in browser." +;;;###autoload +(defun dwim-shell-commands-image-view-location-in-openstreetmap () + "Open image(s) location in map/browser." (interactive) (dwim-shell-command-on-marked-files "Browse location" @@ -142,6 +227,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :error-autofocus t :silent-success t)) +;;;###autoload (defun dwim-shell-commands-image-reverse-geocode-location () "Reverse geocode image(s) location." (interactive) @@ -174,6 +260,7 @@ Optional argument ARGS as per `browse-url-default-browser'" "\n"))) (kill-buffer buffer))))) +;;;###autoload (defun dwim-shell-commands-image-horizontal-flip () "Horizontally flip image(s)." (interactive) @@ -182,6 +269,7 @@ Optional argument ARGS as per `browse-url-default-browser'" "convert -verbose -flop '<>' '<>_h_flipped.<>'" :utils "convert")) +;;;###autoload (defun dwim-shell-commands-image-vertical-flip () "Horizontally flip image(s)." (interactive) @@ -190,6 +278,7 @@ Optional argument ARGS as per `browse-url-default-browser'" "convert -verbose -flip '<>' '<>_v_flipped.<>'" :utils "convert")) +;;;###autoload (defun dwim-shell-commands-image-to-jpg () "Convert all marked images to jpg(s)." (interactive) @@ -198,6 +287,7 @@ Optional argument ARGS as per `browse-url-default-browser'" "convert -verbose '<>' '<>.jpg'" :utils "convert")) +;;;###autoload (defun dwim-shell-commands-image-to-png () "Convert all marked images to png(s)." (interactive) @@ -206,6 +296,7 @@ Optional argument ARGS as per `browse-url-default-browser'" "convert -verbose '<>' '<>.png'" :utils "convert")) +;;;###autoload (defun dwim-shell-commands-svg-to-png () "Convert all marked svg(s) to png(s)." (interactive) @@ -214,6 +305,31 @@ Optional argument ARGS as per `browse-url-default-browser'" "rsvg-convert -b white '<>' -f png -o '<>.png'" :utils "rsvg-convert")) +;;;###autoload +(defun dwim-shell-commands-svg-to-favicons () + "Convert svg to common favicons." + (interactive) + (dwim-shell-command-on-marked-files + "Create favicons" + "echo '>\">' + rsvg-convert -o '<>-16.png' -w 16 -h 16 '<>' + echo '>-16.png\" sizes=\"16x16\">' + rsvg-convert -o '<>-32.png' -w 32 -h 32 '<>' + echo '>-32.png\" sizes=\"32x32\">' + rsvg-convert -o '<>-48.png' -w 48 -h 48 '<>' + echo '>-48.png\" sizes=\"48x48\">' + convert '<>-16.png' '<>-32.png' '<>-48.png' '<>.ico' + echo '>.ico'\">' + rsvg-convert -o '<>-64.png' -w 64 -h 64 '<>' + echo '>-64.png\" sizes=\"64x64\">' + rsvg-convert -o '<>-180.png' -w 180 -h 180 '<>' + echo '>-180.png\" sizes=\"180x180\">' + read -n 1 -s -r" + :extensions "svg" + :utils '("convert" "rsvg-convert") + :focus-now t)) + +;;;###autoload (defun dwim-shell-commands-make-transparent-png () "Create a transparent png." (interactive) @@ -222,6 +338,7 @@ Optional argument ARGS as per `browse-url-default-browser'" "convert -verbose -size <>x<> xc:none '<>x<>.png(u)>>'" :utils "convert")) +;;;###autoload (defun dwim-shell-commands-join-as-pdf () "Join all marked images as a single pdf." (interactive) @@ -234,6 +351,17 @@ Optional argument ARGS as per `browse-url-default-browser'" :default "joined.pdf")) :utils "convert")) +;;;###autoload +(defun dwim-shell-commands-keep-pdf-page () + "Keep a page from pdf." + (interactive) + (let ((page-num (read-number "Keep page number: " 1))) + (dwim-shell-command-on-marked-files + "Keep pdf page" + (format "qpdf '<>' --pages . %d -- '<>_%d.<>'" page-num page-num) + :utils "qpdf"))) + +;;;###autoload (defun dwim-shell-commands-join-images-horizontally () "Join all marked images horizontally as a single image." (interactive) @@ -247,6 +375,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :default filename)) :utils "convert"))) +;;;###autoload (defun dwim-shell-commands-join-images-vertically () "Join all marked images vertically as a single image." (interactive) @@ -254,12 +383,13 @@ Optional argument ARGS as per `browse-url-default-browser'" (or (seq-first (dwim-shell-command--file-extensions)) "png")))) (dwim-shell-command-on-marked-files "Join images vertically" - (format "convert -verbose '<<*>>' -append '<<%s(u)>>'" + (format "convert -verbose '<<*>>' -gravity center -append '<<%s(u)>>'" (dwim-shell-command-read-file-name (format "Join as image named (default \"%s\"): " filename) :default filename)) :utils "convert"))) +;;;###autoload (defun dwim-shell-commands-image-to-grayscale () "Convert all marked images to grayscale." (interactive) @@ -268,6 +398,7 @@ Optional argument ARGS as per `browse-url-default-browser'" "convert -verbose -type Grayscale '<>' '<>_grayscale.<>'" :utils "convert")) +;;;###autoload (defun dwim-shell-commands-reorient-image () "Reorient images." (interactive) @@ -276,6 +407,80 @@ Optional argument ARGS as per `browse-url-default-browser'" "convert -verbose -auto-orient '<>' '<>_reoriented.<>'" :utils "convert")) +;;;###autoload +(defun dwim-shell-commands-gif-to-video () + "Convert all marked gif(s) to video(s)." + (interactive) + (dwim-shell-command-on-marked-files + "Convert to gif" + "ffmpeg -i '<>' -movflags faststart -pix_fmt yuv420p -vf 'scale=trunc(iw/2)*2:trunc(ih/2)*2' '<>.mp4'" + :utils "ffmpeg")) + +;;;###autoload +(defun dwim-shell-commands-macos-empty-trash () + "Empty macOS trash." + (interactive) + (when (y-or-n-p "Empty macOS trash? ") + (dwim-shell-command-on-marked-files + "Empty macOS trash" + "trash -e -y" + :silent-success t + :utils "trash"))) + +;;;###autoload +(defun dwim-shell-commands-macos-ocr-text-from-desktop-region () + "Select a macOS desktop area to OCR and copy recognized text to kill ring." + (interactive) + (dwim-shell-command-on-marked-files + "OCR area" + "macosrec --ocr" + ;; brew install xenodium/macosrec/macosrec + :utils "macosrec" + :on-completion + (lambda (buffer process) + (when-let ((success (= (process-exit-status process) 0)) + (text (with-current-buffer buffer + (string-trim (buffer-string))))) + (progn + (kill-new text) + (switch-to-buffer buffer) + (goto-char (point-min)) + (message "OCR copied to clipboard")))))) + +;;;###autoload +(defun dwim-shell-commands-macos-ocr-text-from-image () + "OCR file and copy recognized text to kill ring." + (interactive) + (dwim-shell-command-on-marked-files + "OCR area" + "macosrec --ocr --clipboard --input '<>'" + ;; brew install xenodium/macosrec/macosrec + :utils "macosrec" + :on-completion + (lambda (buffer process) + (when-let ((success (= (process-exit-status process) 0)) + (text (with-current-buffer buffer + (string-trim (buffer-string))))) + (progn + (kill-new text) + (switch-to-buffer buffer) + (goto-char (point-min)) + (message "OCR copied to clipboard")))))) + +;;;###autoload +(defun dwim-shell-commands-macos-convert-to-mp4 () + "Convert to mov to mp4" + (interactive) + (dwim-shell-command-on-marked-files + "Convert to mov to mp4" + ;; "ffmpeg -loglevel quiet -stats -y -i <>.mov -vcodec h264 -acodec copy <>.mp4" + ;; Found the encoder via ffmpeg -encoders | grep videotoolbox, + ;; source https://www.reddit.com/r/ffmpeg/comments/14pqeex/getting_0_gpu_utilization_with_apple_silicons/ + "ffmpeg -i '<>' -map_metadata 0 \ + -c:v hevc_videotoolbox -q:v 35 -preset fast -c:a aac -b:a 128k -tag:v hvc1 '<>'.mp4" + :utils "ffmpeg")) + +;;;###autoload (defun dwim-shell-commands-video-to-gif () "Convert all marked videos to gif(s)." (interactive) @@ -284,6 +489,16 @@ Optional argument ARGS as per `browse-url-default-browser'" "ffmpeg -loglevel quiet -stats -y -i '<>' -pix_fmt rgb24 -r 15 '<>.gif'" :utils "ffmpeg")) +;;;###autoload +(defun dwim-shell-commands-video-to-mov () + "Convert all marked videos to mov(s)." + (interactive) + (dwim-shell-command-on-marked-files + "Convert to mov" + "ffmpeg -i '<>' -c:v libx264 -c:a aac '<>.mov'" + :utils "ffmpeg")) + +;;;###autoload (defun dwim-shell-commands-video-to-webp () "Convert all marked videos to webp(s)." (interactive) @@ -292,6 +507,28 @@ Optional argument ARGS as per `browse-url-default-browser'" "ffmpeg -i '<>' -vcodec libwebp -filter:v fps=fps=10 -compression_level 3 -lossless 1 -loop 0 -preset default -an -vsync 0 '<>'.webp" :utils "ffmpeg")) +;;;###autoload +(defun dwim-shell-commands-webp-to-video () + "Convert all marked webp(s) to video(s)." + (interactive) + (dwim-shell-command-on-marked-files + "Convert webp to video" + "convert '<>' '<>/<>.gif' + ffmpeg -i '<>/<>.gif' -movflags faststart -pix_fmt yuv420p -vf 'scale=trunc(iw/2)*2:trunc(ih/2)*2' '<>.mp4'" + :utils '("ffmpeg" "convert") + :extensions "webp")) + +;;;###autoload +(defun dwim-shell-commands-webp-to-gif () + "Convert all marked webp(s) to gif(s)." + (interactive) + (dwim-shell-command-on-marked-files + "Convert webp to video" + "convert '<>' '<>.gif'" + :utils '("convert") + :extensions "webp")) + +;;;###autoload (defun dwim-shell-commands-video-to-hevc-mkv () "Convert all marked videos to hevc mkv." (interactive) @@ -308,6 +545,7 @@ Optional argument ARGS as per `browse-url-default-browser'" ruby $REPO_DIR/bin/other-transcode --hevc '<>'" :utils '("git" "ffmpeg" "mkvtoolnix" "mpv"))) +;;;###autoload (defun dwim-shell-commands-video-to-optimized-gif () "Convert all marked videos to optimized gif(s)." (interactive) @@ -317,6 +555,7 @@ Optional argument ARGS as per `browse-url-default-browser'" gifsicle -O3 '<>.gif' --lossy=80 -o '<>.gif'" :utils '("ffmpeg" "gifsicle"))) +;;;###autoload (defun dwim-shell-commands-unzip () "Unzip all marked archives (of any kind) using `atool'." (interactive) @@ -324,6 +563,26 @@ Optional argument ARGS as per `browse-url-default-browser'" "Unzip" "atool --extract --explain '<>'" :utils "atool")) +;;;###autoload +(defun dwim-shell-commands-zip () + "Zip all marked files into archive.zip." + (interactive) + (dwim-shell-command-on-marked-files + "Zip" (if (eq 1 (seq-length (dwim-shell-command--files))) + "zip -r '<>.<>' '<>'" + "zip -r '<>' '<<*>>'") + :utils "zip")) + +;;;###autoload +(defun dwim-shell-commands-zip-password-protect () + "Protect/encrypt zip file(s) with password." + (interactive) + (dwim-shell-command-on-marked-files + "Add zip password" "zipcloak --output-file '<>_protected.<>' '<>'" + :extensions "zip" + :utils "zipcloak")) + +;;;###autoload (defun dwim-shell-commands-optimize-gif () "Convert all marked videos to optimized gif(s)." (interactive) @@ -332,6 +591,7 @@ Optional argument ARGS as per `browse-url-default-browser'" "gifsicle -O3 '<>' --lossy=90 -o '<>_optimized.gif'" :utils '("ffmpeg" "gifsicle"))) +;;;###autoload (defun dwim-shell-commands-speed-up-gif () "Speeds up gif(s)." (interactive) @@ -344,6 +604,21 @@ Optional argument ARGS as per `browse-url-default-browser'" :post-process-template (lambda (script file) (string-replace "<>" (dwim-shell-commands--gifsicle-frames-every factor file) script))))) +;;;###autoload +(defun dwim-shell-commands-image-apply-ios-round-corners () + "Apply iOS round corners to image(s)." + (interactive) + (dwim-shell-command-on-marked-files + "Speed up gif" + "set -o xtrace + width=$(ffprobe -v error -select_streams v:0 -show_entries stream=width -of default=noprint_wrappers=1:nokey=1 '<>') + height=$(ffprobe -v error -select_streams v:0 -show_entries stream=height -of default=noprint_wrappers=1:nokey=1 '<>') + corner=$((${width}/4)) + echo ${corner} + convert -size ${width}x${height} xc:none -fill white -draw \"roundRectangle 0,0 ${width},${height} ${corner},${corner}\" '<>' -compose SrcIn -composite '<>_ios_round.<>'" + :utils '("ffprobe" "convert"))) + +;;;###autoload (defun dwim-shell-commands-clip-round-rect-gif () "Clip gif(s) with round rectangle." (interactive) @@ -362,6 +637,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :extensions "gif" :utils '("ffprobe" "convert"))) +;;;###autoload (defun dwim-shell-commands-resize-gif () "Resize marked gif(s)." (interactive) @@ -371,6 +647,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :extensions "gif" :utils "gifsicle")) +;;;###autoload (defun dwim-shell-commands-epub-to-org () "Convert epub(s) to org." (interactive) @@ -380,6 +657,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :extensions "epub" :utils "pandoc")) +;;;###autoload (defun dwim-shell-commands-docx-to-pdf () "Convert docx(s) to pdf (via latex)." (interactive) @@ -389,6 +667,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :extensions "docx" ;; brew install mactex :utils "pdflatex")) +;;;###autoload (defun dwim-shell-commands-kill-process () "Select and kill process." (interactive) @@ -432,6 +711,27 @@ Optional argument ARGS as per `browse-url-default-browser'" :error-autofocus t :silent-success t)))) +;;;###autoload +(defun dwim-shell-commands-macos-add-to-photos () + "Add to Photos.app." + (interactive) + (dwim-shell-command-on-marked-files + "Add to Photos.app" + "osascript <>\" + end tell +EOF" + :silent-success t + :utils "osascript" + :on-completion (lambda (buffer process) + (if-let ((success (= (process-exit-status process) 0))) + (progn + (kill-buffer buffer) + (start-process "Open Photos" nil "open" "-a" "Photos")) + (switch-to-buffer buffer))))) + +;;;###autoload (defun dwim-shell-commands-macos-toggle-bluetooth-device-connection () "Toggle Bluetooth device connection." (interactive) @@ -465,6 +765,7 @@ Optional argument ARGS as per `browse-url-default-browser'" ;; :silent-success t ))) +;;;###autoload (defun dwim-shell-commands-macos-bin-plist-to-xml () "Convert binary plist to xml." (interactive) @@ -473,6 +774,7 @@ Optional argument ARGS as per `browse-url-default-browser'" "plutil -convert xml1 -o '<>.xml' '<>'" :utils "plutil")) +;;;###autoload (defun dwim-shell-commands-macos-toggle-dark-mode () "Toggle macOS dark mode." (interactive) @@ -482,6 +784,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :utils "dark-mode" ;; brew install dark-mode :silent-success t)) +;;;###autoload (defun dwim-shell-commands-pdf-to-txt () "Convert pdf to txt." (interactive) @@ -490,8 +793,9 @@ Optional argument ARGS as per `browse-url-default-browser'" "pdftotext -layout '<>' '<>.txt'" :utils "pdftotext")) -(defun dwim-shell-commands-resize-image () - "Resize marked image(s)." +;;;###autoload +(defun dwim-shell-commands-resize-image-by-factor () + "Resize marked image(s) by factor." (interactive) (dwim-shell-command-on-marked-files "Resize image" @@ -500,17 +804,39 @@ Optional argument ARGS as per `browse-url-default-browser'" (* 100 factor) factor)) :utils "convert")) +;;;###autoload +(defun dwim-shell-commands-resize-image-in-pixels () + "Resize marked image(s) in pixels." + (interactive) + (dwim-shell-command-on-marked-files + "Resize image" + (let ((width (read-number "Resize width (pixels): " 500))) + (format "convert -resize %dx '<>' '<>_x%d.<>'" width width)) + :utils "convert")) + +;;;###autoload (defun dwim-shell-commands-pdf-password-protect () - "Speeds up gif(s)." + "Add a password to pdf(s)." (interactive) (dwim-shell-command-on-marked-files "Password protect pdf" - (format "qpdf --verbose --encrypt '%s' '%s' 256 -- '<>' '<>_enc.<>'" + (format "qpdf --verbose --encrypt '%s' '%s' 256 -- '<>' '<>_protected.<>'" (read-passwd "user-password: ") (read-passwd "owner-password: ")) :utils "qpdf" :extensions "pdf")) +;;;###autoload +(defun dwim-shell-commands-pdf-password-unprotect () + "Remove a password from pdf(s)." + (interactive) + (dwim-shell-command-on-marked-files + "Remove protection from pdf" + (format "qpdf --verbose --decrypt --password='%s' -- '<>' '<>_unprotected.<>'" + (read-passwd "password: ")) + :utils "qpdf" + :extensions "pdf")) + (defun dwim-shell-commands--gifsicle-frames-every (skipping-every file) "Generate frames SKIPPING-EVERY count for video FILE." (string-join @@ -520,14 +846,95 @@ Optional argument ARGS as per `browse-url-default-browser'" (seq-first (process-lines "identify" "-format" "%n\n" file))) skipping-every)) " ")) +;;;###autoload (defun dwim-shell-commands-video-to-mp3 () - "Drop audio from all marked videos." + "Convert video(s) to mp3." (interactive) (dwim-shell-command-on-marked-files "Convert to mp3" "ffmpeg -i '<>' -vn -ab 128k -ar 44100 -y '<>.mp3'" :utils "ffmpeg")) +;;;###autoload +(defun dwim-shell-commands-video-to-mp3-with-artwork () + "Convert video(s) to mp3 (keep frame as artwork)." + (interactive) + (dwim-shell-command-on-marked-files + "Convert to mp3" + "ffmpeg -i '<>' -vf 'select=eq(n\\,0)' -q:v 3 cover.jpg -i '<>' -vn -ab 128k -ar 44100 -y -map_metadata 0 -id3v2_version 3 -write_id3v1 1 -metadata:s:v title='Album cover' -metadata:s:v comment='Cover (front)' '<>.mp3'" + :utils "ffmpeg")) + +;;;###autoload +(defun dwim-shell-commands-ndjson-to-org () + "Convert ndjson file to org." + (interactive) + (unless (eq (length (dwim-shell-command--files)) 1) + (error "Only 1 file supported")) + (let* ((emacs-bin (file-truename (expand-file-name invocation-name + invocation-directory))) + (source (nth 0 (dwim-shell-command--files))) + (destination (concat (file-name-sans-extension + source) ".org")) + (fields (with-temp-buffer + (insert-file-contents source) + (buffer-substring-no-properties (point-min) (line-end-position)) + (read-string "Fields: " (mapconcat 'identity (mapcar (lambda (item) + (symbol-name (car item))) + (json-read-from-string + (buffer-substring-no-properties + (point-min) (line-end-position)))) + " "))))) + (dwim-shell-command-on-marked-files + "Convert ndjson to org" + (format "%s --quick --batch --eval \"%s\"" emacs-bin + (replace-regexp-in-string + "\"" "\\\\\"" + (prin1-to-string + `(progn + (require 'org) + (require 'json) + (defun convert-to-org-table (ndjson) + (let ((rows (mapcar #'json-read-from-string + (split-string ndjson "\n" t)))) + (orgtbl-to-orgtbl + (append + (list (split-string ,fields)) + '(hline) + (mapcar (lambda (obj) + (mapcar (lambda (key) + (or (alist-get (intern key) obj) "")) + (split-string ,fields))) + rows)) nil))) + (with-temp-buffer + (insert-file-contents ,source) + (let ((org (convert-to-org-table (buffer-string)))) + (with-temp-file ,destination + (insert org)))))))) + :extensions "ndjson"))) + +;;;###autoload +(defun dwim-shell-commands-set-media-artwork-image-metadata () + "Set image artwork metadata for media file(s)." + (interactive) + (let ((artwork-file (file-name-unquote + (read-file-name "Select artwork image: " + nil nil t))) + (should-backup (y-or-n-p "Create backup files? "))) + (unless (file-regular-p artwork-file) + (user-error "Not a file")) + (unless should-backup + (unless (y-or-n-p "Override file(s)? ") + (user-error "Aborted"))) + (dwim-shell-command-on-marked-files + "Set album artwork" + (format (if should-backup + "ffmpeg -i '<>' -i '%s' -map_metadata 0 -map 0:a -map 1 -c copy -disposition:v:0 attached_pic '<>.tmp.<>' && mv -f '<>' '<>.bak' && mv '<>.tmp.<>' '<>'" + "ffmpeg -i '<>' -i '%s' -map_metadata 0 -map 0:a -map 1 -c copy -disposition:v:0 attached_pic '<>.tmp.<>' && mv -f '<>.tmp.<>' '<>'") + artwork-file) + :utils "AtomicParsley" + :silent-success t))) + +;;;###autoload (defun dwim-shell-commands-video-trim-beginning () "Drop audio from all marked videos." (interactive) @@ -537,6 +944,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :silent-success t :utils "ffmpeg")) +;;;###autoload (defun dwim-shell-commands-video-trim-end () "Drop audio from all marked videos." (interactive) @@ -546,6 +954,17 @@ Optional argument ARGS as per `browse-url-default-browser'" :silent-success t :utils "ffmpeg")) +;;;###autoload +(defun dwim-shell-commands-video-to-thumbnail () + "Generate a thumbnail for marked video(s)." + (interactive) + (let ((temp-dir (make-temp-file "thumbnails-" t))) + (dwim-shell-command-on-marked-files + "Thumbnail with ffmpeg" + "ffmpeg -i '<>' -ss 00:00:01.000 -vframes 1 '<>.jpg'" + :utils "ffmpeg"))) + +;;;###autoload (defun dwim-shell-commands-drop-video-audio () "Drop audio from all marked videos." (interactive) @@ -554,8 +973,9 @@ Optional argument ARGS as per `browse-url-default-browser'" "ffmpeg -i '<>' -c copy -an '<>_no_audio.<>'" :utils "ffmpeg")) +;;;###autoload (defun dwim-shell-commands-ping-google () - "Ping duckduckgo.com." + "Ping google.com." (interactive) (dwim-shell-command-on-marked-files "Ping google.com" @@ -563,6 +983,7 @@ Optional argument ARGS as per `browse-url-default-browser'" :utils "ping" :focus-now t)) +;;;###autoload (defun dwim-shell-commands-speed-up-video () "Speed up video(s)." (interactive) @@ -573,6 +994,19 @@ Optional argument ARGS as per `browse-url-default-browser'" (/ 1 (float factor)) factor)) :utils "ffmpeg")) +;;;###autoload +(defun dwim-shell-commands-speed-up-video-fragment () + "Speed up fragment in video(s)." + (interactive) + (let ((start (read-number "Start (seconds): ")) + (end (read-number "End (seconds): ")) + (factor (read-number "Speed up factor: " 2))) + (dwim-shell-command-on-marked-files + "Speed up fragment in video" + (format "ffmpeg -i '<>' -filter_complex '[0:v]trim=start=0:end=%d,setpts=PTS-STARTPTS[v0];[0:v]trim=start=%d:end=%d,setpts=(PTS-1)/%d[v1];[0:v]trim=start=%d,setpts=PTS-STARTPTS[v2];[v0][v1][v2]concat=n=3:v=1:a=0' -preset fast '<>_%d:%dx%d.<>'" start start end factor end start end factor) + :utils "ffmpeg"))) + +;;;###autoload (defun dwim-shell-commands-resize-video () "Resize marked images." (interactive) @@ -590,6 +1024,7 @@ fi ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<>'" :utils "ffmpeg")) +;;;###autoload (defun dwim-shell-commands-clipboard-to-qr () "Generate a QR code from clipboard." (interactive) @@ -602,19 +1037,81 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (kill-buffer buffer) (switch-to-buffer (find-file-noselect temp-file t)))))) +;;;###autoload +(defun dwim-shell-commands-sha-256-hash-file-at-clipboard-url () + "Download file at clipboard URL and generate SHA-256 hash." + (interactive) + (unless (string-match-p "^http[s]?://" (current-kill 0)) + (user-error "No URL in clipboard")) + (dwim-shell-command-on-marked-files + "Generate SHA-256 hash from clipboard URL." + "curl -s '<>' | sha256sum - | cut -d ' ' -f1" + :utils '("curl" "sha256sum") + :on-completion + (lambda (buffer process) + (if-let ((success (= (process-exit-status process) 0)) + (hash (with-current-buffer buffer + (string-trim (buffer-string))))) + (progn + (kill-buffer buffer) + (kill-new hash) + (message "Copied %s to clipboard" + (propertize hash 'face 'font-lock-string-face))) + (switch-to-buffer buffer))))) + +;;;###autoload +(defun dwim-shell-commands-view-sqlite-schema-diagram () + "View sqlite schema diagram." + (interactive) + (dwim-shell-command-on-marked-files + "View sqlite schema" + "set -e +temp_dir=\"${TMPDIR:-/tmp/}\" +file_name=\"sqlite-schema-diagram.sql\" +file_path=\"${temp_dir}/${file_name}\" +url=\"https://gitlab.com/Screwtapello/sqlite-schema-diagram/-/raw/main/sqlite-schema-diagram.sql\" + +if [[ ! -f \"$file_path\" ]]; then + curl -o \"$file_path\" \"$url\" +fi + +sqlite3 -list \"<>\" < $file_path > \"<>.dot\" +dot -Tsvg \"<>.dot\" > \"<>.svg\" +echo \"<>.svg\" +" + :utils '("dot" "sqlite3") + :on-completion + (lambda (buffer process) + (if (= (process-exit-status process) 0) + (with-current-buffer buffer + (let ((svg-file (string-trim (buffer-string)))) + (if (string-suffix-p "svg" svg-file) + (progn + (find-file svg-file) + (kill-buffer buffer)) + (switch-to-buffer buffer)))) + (switch-to-buffer buffer))))) + +;;;###autoload (defun dwim-shell-commands-open-externally () "Open file(s) externally." (interactive) (dwim-shell-command-on-marked-files "Open externally" (if (eq system-type 'darwin) - "open '<>'" + (if (derived-mode-p 'prog-mode) + (format "xed --line %d '<>'" + (line-number-at-pos (point))) + "open '<>'") "xdg-open '<>'") + :shell-util "zsh" + :shell-args '("-x" "-c") :silent-success t :utils (if (eq system-type 'darwin) "open" "xdg-open"))) +;;;###autoload (defun dwim-shell-commands-macos-caffeinate () "Invoke caffeinate to prevent mac from sleeping." (interactive) @@ -625,6 +1122,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :no-progress t :focus-now t)) +;;;###autoload (defun dwim-shell-commands-macos-make-finder-alias () "Make macOS Finder alias." (interactive) @@ -641,6 +1139,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (kill-buffer buffer) (dired-jump nil (file-name-concat target-dir (file-name-nondirectory (nth 0 files)))))))) +;;;###autoload (defun dwim-shell-commands-macos-version-and-hardware-overview-info () "View macOS version and hardware overview info." (interactive) @@ -649,6 +1148,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< "sw_vers; system_profiler SPHardwareDataType" :utils '("sw_vers" "system_profiler"))) +;;;###autoload (defun dwim-shell-commands-macos-reveal-in-finder () "Reveal selected files in macOS Finder." (interactive) @@ -673,12 +1173,18 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (format "URL(fileURLWithPath: \"%s\")" file)) (dwim-shell-command--files)) ", "))) - (services (split-string (string-trim (shell-command-to-string (format "echo '%s' | swift -" source))) - "\n"))) + (services (split-string + (string-trim + ;; Remove anything that doesn't start with alpha characters + ;; There may be compilation warnings. + (replace-regexp-in-string "^[^[:alpha:]].*\n" "" + (shell-command-to-string (format "echo '%s' | swift -" source)))) + "\n"))) (when (seq-empty-p services) (error "No sharing services available")) services)) +;;;###autoload (defun dwim-shell-commands-macos-share () "Share selected files from macOS." (interactive) @@ -731,6 +1237,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :no-progress t :utils "swift"))) +;;;###autoload (defun dwim-shell-commands-macos-toggle-display-rotation () "Rotate display." (interactive) @@ -743,6 +1250,24 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (format "fb-rotate -d 1 -r %s" (if (equal current-rotation "270") "0" "270")) :utils "fb-rotate"))) +;;;###autoload +(defun dwim-shell-commands-make-swift-package-library () + "Create a swift package library" + (interactive) + (dwim-shell-command-on-marked-files + "Create a swift package library" + "swift package init --type library" + :utils "swift")) + +;;;###autoload +(defun dwim-shell-commands-make-swift-package-executable () + "Create a swift package executable" + (interactive) + (dwim-shell-command-on-marked-files + "Create a swift package executable" + "swift package init --type executable" + :utils "swift")) + (defun dwim-shell-commands--macos-apps () "Return alist of macOS apps (\"Emacs\" . \"/Applications/Emacs.app\")." (mapcar (lambda (path) @@ -755,6 +1280,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (not (string-suffix-p ".app" path))))) '("/Applications" "~/Applications" "/System/Applications"))))) +;;;###autoload (defun dwim-shell-commands-macos-set-default-app () "Set default app for file(s)." (interactive) @@ -772,6 +1298,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :no-progress t :utils "duti"))) +;;;###autoload (defun dwim-shell-commands-macos-open-with () "Open file(s) with specific external app." (interactive) @@ -786,26 +1313,29 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :no-progress t :utils "open"))) +;;;###autoload (defun dwim-shell-commands-macos-open-with-firefox () - "Open file(s) with specific external app." + "Open file(s) in Firefox." (interactive) (dwim-shell-command-on-marked-files - "Open with Firefox" + "Open in Firefox" "open -a Firefox '<<*>>'" :silent-success t :no-progress t :utils "open")) +;;;###autoload (defun dwim-shell-commands-macos-open-with-safari () - "Open file(s) with specific external app." + "Open file(s) in Safari." (interactive) (dwim-shell-command-on-marked-files - "Open with Firefox" + "Open in Safari" "open -a Safari '<<*>>'" :silent-success t :no-progress t :utils "open")) +;;;###autoload (defun dwim-shell-commands-macos-start-recording-window () "Select and start recording a macOS window." (interactive) @@ -858,6 +1388,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (cons window-app window-number) (user-error "No window found"))) +;;;###autoload (defun dwim-shell-commands-macos-end-recording-window () "Stop recording a macOS window." (interactive) @@ -872,6 +1403,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :error-autofocus t :utils "macosrec")))) +;;;###autoload (defun dwim-shell-commands-macos-abort-recording-window () "Stop recording a macOS window." (interactive) @@ -885,6 +1417,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :no-progress t :utils "macosrec")))) +;;;###autoload (defun dwim-shell-commands-macos-screenshot-window () "Select and screenshot macOS window." (interactive) @@ -899,6 +1432,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :no-progress t :utils "macosrec"))) +;;;###autoload (defun dwim-shell-commands-files-combined-size () "Get files combined file size." (interactive) @@ -914,6 +1448,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (match-string 1)))) (kill-buffer buffer)))) +;;;###autoload (defun dwim-shell-commands-image-to-icns () "Convert png to icns icon." (interactive) @@ -937,10 +1472,30 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :utils '("sips" "iconutil") :extensions "png")) +;;;###autoload +(defun dwim-shell-commands-image-add-drop-shadow () + "Add a drop shadow." + (interactive) + (dwim-shell-command-on-marked-files + "Add a drop shadow." + "convert <> -bordercolor white -border 13 \\( +clone -background black -shadow 80x3+2+2 \\) +swap -background white -layers merge +repage <>-shadow.<>" + :utils "convert")) + +;;;###autoload +(defun dwim-shell-commands-image-trim-borders () + "Trim image(s) border (useful for video screenshots)." + (interactive) + (dwim-shell-command-on-marked-files + "Trim image border" + "magick convert -fuzz 3% -define trim:percent-background=0% -trim +repage '<>' '<>_trimmed.<>'" + :utils "magick")) + +;;;###autoload (defun dwim-shell-commands-git-clone-clipboard-url-to-downloads () "Clone git URL in clipboard to \"~/Downloads/\"." (interactive) - (cl-assert (string-match-p "^\\(http\\|https\\|ssh\\)://" (current-kill 0)) nil "No URL in clipboard") + (cl-assert (or (string-match-p "^\\(http\\|https\\|ssh\\)://" (current-kill 0)) + (string-match-p "^git@" (current-kill 0))) nil "No URL in clipboard") (let* ((url (current-kill 0)) (download-dir (expand-file-name "~/Downloads/")) (project-dir (concat download-dir (file-name-base url))) @@ -957,6 +1512,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (kill-buffer buffer) (dired project-dir)))))) +;;;###autoload (defun dwim-shell-commands-http-serve-dir () "HTTP serve current directory." (interactive) @@ -984,6 +1540,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (t (error "No python found")))) +;;;###autoload (defun dwim-shell-commands-git-clone-clipboard-url () "Clone git URL in clipboard to `default-directory'." (interactive) @@ -992,6 +1549,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< "git clone <>" :utils "git")) +;;;###autoload (defun dwim-shell-commands-pass-git-pull () "Pass git pull." (interactive) @@ -1001,6 +1559,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :utils '("pass" "git") :silent-success t)) +;;;###autoload (defun dwim-shell-commands-git-list-untracked-files () "List untracked git files in `default-directory'." (interactive) @@ -1010,6 +1569,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :utils "git" :focus-now t)) +;;;###autoload (defun dwim-shell-commands-git-delete-untracked-files () "Delete untracked git files in `default-directory'." (interactive) @@ -1024,6 +1584,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< :utils "git" :silent-success t))) +;;;###autoload (defun dwim-shell-commands-external-ip () "Copy external IP to kill ring." (interactive) @@ -1031,6 +1592,7 @@ ffmpeg -n -i '<>' -vf \"scale=$width:-2\" '<>_x<>.<< (kill-new ip) (message "Copied %s" ip))) +;;;###autoload (defun dwim-shell-commands-macos-install-iphone-device-ipa () "Install iPhone device .ipa. Needs ideviceinstaller and libmobiledevice installed." @@ -1040,6 +1602,7 @@ Needs ideviceinstaller and libmobiledevice installed." "ideviceinstaller -i '<>'" :utils "ideviceinstaller")) +;;;###autoload (defun dwim-shell-commands-copy-to-downloads () "Copy file to ~/Downloads." (interactive) @@ -1049,6 +1612,7 @@ Needs ideviceinstaller and libmobiledevice installed." (file-name-concat "~/Downloads" (file-name-nondirectory file))) :monitor-directory "~/Downloads")) +;;;###autoload (defun dwim-shell-commands-duplicate () "Duplicate file." (interactive) @@ -1057,6 +1621,7 @@ Needs ideviceinstaller and libmobiledevice installed." "cp -R '<>' '<>'" :utils "cp")) +;;;###autoload (defun dwim-shell-commands-rename-all () "Rename all marked file(s)." (interactive) @@ -1065,6 +1630,7 @@ Needs ideviceinstaller and libmobiledevice installed." "mv '<>' '<>(<>).<>'" :utils "mv")) +;;;###autoload (defun dwim-shell-commands-move-to-downloads () "Move file to ~/Downloads." (interactive) @@ -1079,6 +1645,7 @@ Needs ideviceinstaller and libmobiledevice installed." (file-name-concat "~/Downloads" (file-name-nondirectory file))) :monitor-directory "~/Downloads")) +;;;###autoload (defun dwim-shell-commands-copy-to-desktop () "Copy file to ~/Desktop." (interactive) @@ -1088,6 +1655,7 @@ Needs ideviceinstaller and libmobiledevice installed." (file-name-concat "~/Desktop" (file-name-nondirectory file))) :monitor-directory "~/Desktop")) +;;;###autoload (defun dwim-shell-commands-move-to-desktop () "Move file to ~/Desktop." (interactive) @@ -1102,6 +1670,7 @@ Needs ideviceinstaller and libmobiledevice installed." (file-name-concat "~/Desktop" (file-name-nondirectory file))) :monitor-directory "~/Desktop")) +;;;###autoload (defun dwim-shell-commands-kill-gpg-agent () "Kill (thus restart) gpg agent. @@ -1118,6 +1687,7 @@ gpg: decryption failed: No pinentry" ;; Based on ;; https://apps.bram85.nl/git/bram/gists/src/commit/31ac3363da925daafa2420b7f96c67612ca28241/gists/dwim-0x0-upload.el +;;;###autoload (defun dwim-shell-commands-upload-to-0x0 () "Upload the marked files to 0x0.st" (interactive) -- 2.47.3