commit d99515695c4f46436d2118d50373b649c1a55b80
parent c9fd15953cccb15a22c4c1f2b3250dda4c09a5ee
Author: Yuval Langer <yuval.langer@gmail.com>
Date: Tue, 30 Jul 2024 00:21:11 +0300
Move kakafarm-utils.el to kakafarm.el in its own location.
Diffstat:
3 files changed, 412 insertions(+), 376 deletions(-)
diff --git a/config/emacs/init.el b/config/emacs/init.el
@@ -11,7 +11,9 @@
(require 'benchmark-init)
-(load (locate-user-emacs-file "kakafarm-utils.el"))
+(add-to-list 'load-path (concat user-emacs-directory
+ "local-packages/emacs-kakafarm/"))
+
(load (locate-user-emacs-file "local-stuff.el"))
(setq package-archives '())
diff --git a/config/emacs/kakafarm-utils.el b/config/emacs/kakafarm-utils.el
@@ -1,375 +0,0 @@
-;;; -*- lexical-binding:t -*-
-
-(require 'cl-lib)
-
-(defun kakafarm/advice-remove-all (function)
- "Remove every advice function from FUNCTION."
- (advice-mapc
- (lambda (advice-function properties-alist)
- (advice-remove function
- advice-function))
- function))
-
-(defun kakafarm/call-process-with-string-as-input (program &optional input-string &rest args)
- (with-temp-buffer
- (let ((our-output-buffer (current-buffer)))
- (if input-string
- (with-temp-buffer
- (let ((our-input-buffer (current-buffer)))
- (progn
- (erase-buffer)
- (insert input-string)
- (apply 'call-process-region
- (buffer-end -1)
- (buffer-end 1)
- program
- nil
- our-output-buffer
- nil
- args))))
- (apply 'call-process
- program
- nil
- our-output-buffer
- nil
- args)))
- (buffer-string)))
-
-(list (kakafarm/call-process-with-string-as-input "cat"
- "cat says moo")
- (kakafarm/call-process-with-string-as-input "echo"
- nil
- "-n"
- "echo echo echo"))
-
-(defun kakafarm/drop-while (lst predp)
- (named-let loop ((lst lst))
- (cond
- (()
- lst)
- ((predp (car lst))
- (cdr lst))
- (t
- (loop (cdr lst))))))
-
-(defun kakafarm/easy-underscore (arg)
- "Convert all inputs of semicolon to an underscore
-If given ARG, then it will insert an actual semicolon.
-
-from https://www.youtube.com/watch?v=6R-73hsL5wk"
- (interactive "P")
- (message (format "%s" arg))
- (if arg
- (insert ";")
- (insert "_")))
-
-(defun kakafarm/elfeed-sort-feed-tags (a-feed)
- (cond
- ((stringp a-feed)
- a-feed)
- (t
- (let* ((feed-url (car a-feed))
- (tags (cdr a-feed))
- (tags-as-strings (mapcar #'symbol-name
- tags))
- (sorted-tags (sort tags-as-strings
- #'string-lessp))
- (tags-as-symbols (mapcar #'intern sorted-tags)))
- (cons feed-url tags-as-symbols)))))
-
-(defun kakafarm/elfeed-compare-feeds-urls (feed-a feed-b)
- (string-lessp (car feed-a)
- (car feed-b)))
-
-(defun kakafarm/elfeed-sort-feeds (feeds)
- "Sort A-FEED, an `elfeed-feeds' list."
- (sort (mapcar #'kakafarm/elfeed-sort-feed-tags
- feeds)
- #'kakafarm/elfeed-compare-feeds-urls))
-
-(defun kakafarm/ffap-browse-urls ()
- "Open all visible URLs."
- (interactive)
-
- (let* ((urls (mapcar 'car (ffap-menu-rescan)))
- (urls-newlined (mapcar (lambda (url) (concat url "\n"))
- urls))
- (prompt (format "Open URLs? [y/n]
-
-%s"
- (apply 'concat
- urls-newlined))))
- (when (y-or-n-p prompt)
- (dolist (url urls)
- (browse-url url)))))
-
-(defun kakafarm/kill-ring-save-unlines ()
- "Like `kill-ring-save', but also unlines and trims the newly killed stuff."
- (interactive)
-
- (kill-ring-save (point) (mark))
-
- (with-temp-buffer
- (yank-pop)
- (goto-char 1)
- (replace-regexp "\n+" " ")
- (let ((trimmed (string-trim (buffer-string))))
- (with-temp-buffer
- (insert trimmed)
- (kill-region (point-min) (point-max))))))
-
-(defun kakafarm/list-all-http-or-https ()
- (interactive)
- (dolist (url (let* ((list-of-lines
- (split-string (substring-no-properties (buffer-string))
- "[ \n]")))
- (cl-reduce (lambda (accumulator line)
- (if (string-match-p "https?://.+"
- line)
- (cons line accumulator)
- accumulator))
- list-of-lines
- :initial-value '())))
- (message "%s" url)))
-
-(defun kakafarm/org-roam-keyword-is-filetags-p (keyword-node)
- (equal (org-element-property :key
- keyword-node)
- "FILETAGS"))
-
-(defun kakafarm/org-roam-filetags-keyword-is-publishable-p (filestags-keyword-node)
- (seq-contains-p (split-string (org-element-property :value
- filestags-keyword-node)
- ":")
- "publish"))
-
-(defun kakafarm/org-roam-publishable-node-p (org-filename)
- (with-temp-buffer
- (insert-file-contents org-filename)
- (org-element-map (org-element-parse-buffer) 'keyword
- (lambda (keyword)
- (and (kakafarm/org-roam-keyword-is-filetags-p keyword)
- (kakafarm/org-roam-filetags-keyword-is-publishable-p keyword)))
- nil
- t)))
-
-(defun kakafarm/org-roam-sitemap (title list-of-org-links)
- (message (format "kakafarm/org-roam-sitemap title: %S; list-of-links: %S\n"
- title
- list-of-org-links))
- ;; (let ((a-publishable-org-roam-node
- ;; (seq-filter (lambda (org-link-list)
- ;; (pcase org-link-list
- ;; (`(,org-link)
- ;; (with-temp-buffer
- ;; (insert org-link)
- ;; (org-element-map (org-element-parse-buffer) 'link
- ;; (lambda (link)
- ;; ;; Check if file linked is publishable.
- ;; (kakafarm/org-roam-publishable-node-p
- ;; (concat "~/mine/roam/"
- ;; (org-element-property :path
- ;; link))))
- ;; nil
- ;; t)))))
- ;; list-of-org-links)))
- ;; (message "poop %S" a-publishable-org-roam-node))
-
- (concat
- "# -*- encoding: utf-8 -*-\n"
- "#+OPTIONS: ^:nil author:nil html-postamble:nil\n"
- ;;"#SETUPFILE: ./simple_inline.theme\n" ; No theme yet.
- "#+FILETAGS: publish\n"
- "#+TITLE: " title "\n\n"
- (org-list-to-org list-of-org-links) "\n"
-
- ;; TODO: No sitemap SVG yet because it shows all the fucking
- ;; files in the org-roam database.
- ;;
- ;;"file:sitemap.svg\n"
- ))
-
-(defun kakafarm/org-roam-publication-wrapper (plist filename pubdir)
- ;; (when (kakafarm/org-roam-publishable-node-p filename)
- ;; nil)
- ;;(org-roam-graph) ; How the fuck do I make this one not show every fucking node in the org-roam database?!
- (org-html-publish-to-html plist
- filename
- pubdir)
- (setq kakafarm/org-roam-project-publish-time
- (cadr (current-time))))
-
-(defun kakafarm/org-roam-custom-link-builder (node)
- (let ((node-file (org-roam-node-file node)))
- ;; (when (kakafarm/org-roam-publishable-node-p node-file)
- ;; nil)
- (message (format "kakafarm/org-roam-custom-link-builder: %S" node))
- (concat (file-name-base node-file)
- ".html")))
-
-(defun kakafarm/percent-read ()
- "Display percent read by current cursor location vs. total characters in file."
-
- (interactive)
-
- (message "%.2f%%"
- (* 100
- (/ (float (- (point) 1))
- (+ 1 (buffer-size))))))
-
-(defun kakafarm/percent-read-point-min-max ()
- "Display percent read by current cursor location vs. place within (point-min) and (point-max)."
-
- (interactive)
-
- (let* ((our-location (point))
- (our-location-0-indexed (- our-location 1)))
- (message "%.2f%%"
- (* 100
- (/ (float (- our-location-0-indexed
- (point-min)))
- (- (point-max)
- (point-min)))))))
-
-(defun kakafarm/recenter-top-bottom (original-function &rest arguments)
- "Move view such that point is 4 lines from the top of the frame when function is `recenter-top-bottom'."
-
- (cond
- ((null (car arguments))
- (apply original-function '(4)))
- (t
- (apply original-function arguments))))
-
-(defun kakafarm/pulse-current-region (&rest _)
- "Pulse the selected bit, either the marked region or if there's no
-mark, the bit between mark and point... or something like
-that... I don't even work here.
-
-From Goparism (https://www.youtube.com/@goparism)
-https://www.youtube.com/watch?v=oQ9JE9kRwG8 which is from the
-user 0xMii on R***** which copied it from
-who-knows-where-and-who."
- (if mark-active
- (pulse-momentary-highlight-region (region-beginning)
- (region-end))
- (pulse-momentary-highlight-region (mark)
- (point))))
-
-(defun kakafarm/multi-vterm-weechat ()
- "Either start a weechat vterm buffer, or switch to it if it already exists."
-
- (interactive)
-
- (require 'multi-vterm)
-
- (let* ((vterm-shell (expand-file-name "~/bin/w"))
- (weechat-buffer-name "weechat")
- (maybe-weechat-buffer (get-buffer "weechat")))
- (cond
- ((multi-vterm-buffer-exist-p maybe-weechat-buffer)
- (switch-to-buffer maybe-weechat-buffer))
- (t
- (multi-vterm)
- (rename-buffer weechat-buffer-name)))))
-
-(defun kakafarm/sentence-end-double-nilify-for-read-only-buffers ()
- "Set `sentence-end-double-space' in read-only buffer to `nil'."
- (when buffer-read-only
- (setq-local sentence-end-double-space
- nil)))
-
-;; Uploading README.html from README.org stuff.
-(defun kakafarm/srht-repo-id (repository-name)
- "Returns the unique numerical I Dentification associated with
-every sourcehut repository.
-
-https://www.tomsdiner.org/blog/post_0003_sourcehut_readme_org_export.html"
-
- (interactive "sRepo name: ")
- (let* ((srht (netrc-machine (netrc-parse "~/.netrc.gpg")
- "repo.git.sr.ht"))
- (srht-token (netrc-get srht
- "password"))
- (our-response (with-temp-buffer
- (call-process "curl"
- nil
- (list (current-buffer) nil)
- nil
- "--oauth2-bearer" srht-token
- "-G"
- "--data-urlencode"
- (concat "query=query { me { repository(name: \""
- repository-name
- "\") { id } } }")
- "https://git.sr.ht/query")
- (buffer-string)))
- (repository-id (string-trim (kakafarm/call-process-with-string-as-input "jq"
- our-response
- ".data.me.repository.id"))))
- (if (called-interactively-p)
- (message "Repository ID: %S" repository-id)
- repository-id)))
-
-(defun kakafarm/srht-set-readme (repository-id)
- "Export the current file to HTML and set the result as README for
-the sourcehut repo identified by ID.
-
-https://www.tomsdiner.org/blog/post_0003_sourcehut_readme_org_export.html"
-
- (interactive "sRepository ID: ")
- (let* ((srht (netrc-machine (netrc-parse "~/.netrc.gpg")
- "repo.git.sr.ht"))
- (srht-token (netrc-get srht
- "password"))
- (readme.html (org-export-as (org-export-get-backend 'html)
- nil
- nil
- t))
- (our-json-query (kakafarm/call-process-with-string-as-input
- "jq"
- readme.html
- "-sR"
- (concat "
-{ \"query\": \"mutation UpdateRepo($id: Int!, $readme: String!) { updateRepository(id: $id, input: { readme: $readme }) { id } }\",
- \"variables\": {
- \"id\": " repository-id ",
- \"readme\": .
- }
-}"))))
- (kakafarm/call-process-with-string-as-input "curl"
- our-json-query
- "--oauth2-bearer" srht-token
- "-H" "Content-Type: application/json"
- "-d@-"
- "https://git.sr.ht/query")))
-
-(defun kakafarm/take-while (lst predp)
- (named-let loop ((lst lst)
- (accumulator '()))
- (cond
- ((null lst)
- (reverse accumulator))
- ((predp (car lst))
- (reverse accumulator))
- (t
- (loop (cdr lst)
- accumulator)))))
-
-(defun kakafarm/url-response-to-body (response)
- (cdr (kakafarm/drop-while
- (string-split response
- "\n")
- (lambda (line)
- (not (string-blank-p line))))))
-
-(defun kakafarm/yank-unlines ()
- "`yank' with each consecutive newlines converted to a single space, and trim both ends."
- (interactive)
-
- (insert
- (string-trim
- (with-temp-buffer
- (yank)
- (goto-char 1)
- (replace-regexp "\n+" " ")
- (buffer-string)))))
diff --git a/config/emacs/local-packages/emacs-kakafarm/kakafarm.el b/config/emacs/local-packages/emacs-kakafarm/kakafarm.el
@@ -0,0 +1,409 @@
+;;; kakafarm.el --- Various functions for my GNU Emacs configuration. -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2024 Yuval Langer
+
+;; Author: Yuval Langer <yuval.langer@gmail.com>
+;; Version: 0.0.0
+;; Keywords: Personal, Auxiliary
+;; URL: https://codeberg.org/kakafarm/dotfiles/
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Do not expect any of these functions to remain stable.
+;;
+;; The functions are ordered in an alphabetic order. I do not know
+;; if it makes much sense, but so be it.
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defun kakafarm/advice-remove-all (function)
+ "Remove every advice function from FUNCTION."
+ (advice-mapc
+ (lambda (advice-function properties-alist)
+ (advice-remove function
+ advice-function))
+ function))
+
+(defun kakafarm/call-process-with-string-as-input (program &optional input-string &rest args)
+ (with-temp-buffer
+ (let ((our-output-buffer (current-buffer)))
+ (if input-string
+ (with-temp-buffer
+ (let ((our-input-buffer (current-buffer)))
+ (progn
+ (erase-buffer)
+ (insert input-string)
+ (apply 'call-process-region
+ (buffer-end -1)
+ (buffer-end 1)
+ program
+ nil
+ our-output-buffer
+ nil
+ args))))
+ (apply 'call-process
+ program
+ nil
+ our-output-buffer
+ nil
+ args)))
+ (buffer-string)))
+
+(list (kakafarm/call-process-with-string-as-input "cat"
+ "cat says moo")
+ (kakafarm/call-process-with-string-as-input "echo"
+ nil
+ "-n"
+ "echo echo echo"))
+
+(defun kakafarm/drop-while (lst predp)
+ (named-let loop ((lst lst))
+ (cond
+ (()
+ lst)
+ ((predp (car lst))
+ (cdr lst))
+ (t
+ (loop (cdr lst))))))
+
+(defun kakafarm/easy-underscore (arg)
+ "Convert all inputs of semicolon to an underscore
+If given ARG, then it will insert an actual semicolon.
+
+from https://www.youtube.com/watch?v=6R-73hsL5wk"
+ (interactive "P")
+ (message (format "%s" arg))
+ (if arg
+ (insert ";")
+ (insert "_")))
+
+(defun kakafarm/elfeed-sort-feed-tags (a-feed)
+ (cond
+ ((stringp a-feed)
+ a-feed)
+ (t
+ (let* ((feed-url (car a-feed))
+ (tags (cdr a-feed))
+ (tags-as-strings (mapcar #'symbol-name
+ tags))
+ (sorted-tags (sort tags-as-strings
+ #'string-lessp))
+ (tags-as-symbols (mapcar #'intern sorted-tags)))
+ (cons feed-url tags-as-symbols)))))
+
+(defun kakafarm/elfeed-compare-feeds-urls (feed-a feed-b)
+ (string-lessp (car feed-a)
+ (car feed-b)))
+
+(defun kakafarm/elfeed-sort-feeds (feeds)
+ "Sort A-FEED, an `elfeed-feeds' list."
+ (sort (mapcar #'kakafarm/elfeed-sort-feed-tags
+ feeds)
+ #'kakafarm/elfeed-compare-feeds-urls))
+
+(defun kakafarm/ffap-browse-urls ()
+ "Open all visible URLs."
+ (interactive)
+
+ (let* ((urls (mapcar 'car (ffap-menu-rescan)))
+ (urls-newlined (mapcar (lambda (url) (concat url "\n"))
+ urls))
+ (prompt (format "Open URLs? [y/n]
+
+%s"
+ (apply 'concat
+ urls-newlined))))
+ (when (y-or-n-p prompt)
+ (dolist (url urls)
+ (browse-url url)))))
+
+(defun kakafarm/kill-ring-save-unlines ()
+ "Like `kill-ring-save', but also unlines and trims the newly killed stuff."
+ (interactive)
+
+ (kill-ring-save (point) (mark))
+
+ (with-temp-buffer
+ (yank-pop)
+ (goto-char 1)
+ (replace-regexp "\n+" " ")
+ (let ((trimmed (string-trim (buffer-string))))
+ (with-temp-buffer
+ (insert trimmed)
+ (kill-region (point-min) (point-max))))))
+
+(defun kakafarm/list-all-http-or-https ()
+ (interactive)
+ (dolist (url (let* ((list-of-lines
+ (split-string (substring-no-properties (buffer-string))
+ "[ \n]")))
+ (cl-reduce (lambda (accumulator line)
+ (if (string-match-p "https?://.+"
+ line)
+ (cons line accumulator)
+ accumulator))
+ list-of-lines
+ :initial-value '())))
+ (message "%s" url)))
+
+(defun kakafarm/org-roam-keyword-is-filetags-p (keyword-node)
+ (equal (org-element-property :key
+ keyword-node)
+ "FILETAGS"))
+
+(defun kakafarm/org-roam-filetags-keyword-is-publishable-p (filestags-keyword-node)
+ (seq-contains-p (split-string (org-element-property :value
+ filestags-keyword-node)
+ ":")
+ "publish"))
+
+(defun kakafarm/org-roam-publishable-node-p (org-filename)
+ (with-temp-buffer
+ (insert-file-contents org-filename)
+ (org-element-map (org-element-parse-buffer) 'keyword
+ (lambda (keyword)
+ (and (kakafarm/org-roam-keyword-is-filetags-p keyword)
+ (kakafarm/org-roam-filetags-keyword-is-publishable-p keyword)))
+ nil
+ t)))
+
+(defun kakafarm/org-roam-sitemap (title list-of-org-links)
+ (message (format "kakafarm/org-roam-sitemap title: %S; list-of-links: %S\n"
+ title
+ list-of-org-links))
+ ;; (let ((a-publishable-org-roam-node
+ ;; (seq-filter (lambda (org-link-list)
+ ;; (pcase org-link-list
+ ;; (`(,org-link)
+ ;; (with-temp-buffer
+ ;; (insert org-link)
+ ;; (org-element-map (org-element-parse-buffer) 'link
+ ;; (lambda (link)
+ ;; ;; Check if file linked is publishable.
+ ;; (kakafarm/org-roam-publishable-node-p
+ ;; (concat "~/mine/roam/"
+ ;; (org-element-property :path
+ ;; link))))
+ ;; nil
+ ;; t)))))
+ ;; list-of-org-links)))
+ ;; (message "poop %S" a-publishable-org-roam-node))
+
+ (concat
+ "# -*- encoding: utf-8 -*-\n"
+ "#+OPTIONS: ^:nil author:nil html-postamble:nil\n"
+ ;;"#SETUPFILE: ./simple_inline.theme\n" ; No theme yet.
+ "#+FILETAGS: publish\n"
+ "#+TITLE: " title "\n\n"
+ (org-list-to-org list-of-org-links) "\n"
+
+ ;; TODO: No sitemap SVG yet because it shows all the fucking
+ ;; files in the org-roam database.
+ ;;
+ ;;"file:sitemap.svg\n"
+ ))
+
+(defun kakafarm/org-roam-publication-wrapper (plist filename pubdir)
+ ;; (when (kakafarm/org-roam-publishable-node-p filename)
+ ;; nil)
+ ;;(org-roam-graph) ; How the fuck do I make this one not show every fucking node in the org-roam database?!
+ (org-html-publish-to-html plist
+ filename
+ pubdir)
+ (setq kakafarm/org-roam-project-publish-time
+ (cadr (current-time))))
+
+(defun kakafarm/org-roam-custom-link-builder (node)
+ (let ((node-file (org-roam-node-file node)))
+ ;; (when (kakafarm/org-roam-publishable-node-p node-file)
+ ;; nil)
+ (message (format "kakafarm/org-roam-custom-link-builder: %S" node))
+ (concat (file-name-base node-file)
+ ".html")))
+
+(defun kakafarm/percent-read ()
+ "Display percent read by current cursor location vs. total characters in file."
+
+ (interactive)
+
+ (message "%.2f%%"
+ (* 100
+ (/ (float (- (point) 1))
+ (+ 1 (buffer-size))))))
+
+(defun kakafarm/percent-read-point-min-max ()
+ "Display percent read by current cursor location vs. place within (point-min) and (point-max)."
+
+ (interactive)
+
+ (let* ((our-location (point))
+ (our-location-0-indexed (- our-location 1)))
+ (message "%.2f%%"
+ (* 100
+ (/ (float (- our-location-0-indexed
+ (point-min)))
+ (- (point-max)
+ (point-min)))))))
+
+(defun kakafarm/recenter-top-bottom (original-function &rest arguments)
+ "Move view such that point is 4 lines from the top of the frame when function is `recenter-top-bottom'."
+
+ (cond
+ ((null (car arguments))
+ (apply original-function '(4)))
+ (t
+ (apply original-function arguments))))
+
+(defun kakafarm/pulse-current-region (&rest _)
+ "Pulse the selected bit, either the marked region or if there's no
+mark, the bit between mark and point... or something like
+that... I don't even work here.
+
+From Goparism (https://www.youtube.com/@goparism)
+https://www.youtube.com/watch?v=oQ9JE9kRwG8 which is from the
+user 0xMii on R***** which copied it from
+who-knows-where-and-who."
+ (if mark-active
+ (pulse-momentary-highlight-region (region-beginning)
+ (region-end))
+ (pulse-momentary-highlight-region (mark)
+ (point))))
+
+(defun kakafarm/multi-vterm-weechat ()
+ "Either start a weechat vterm buffer, or switch to it if it already exists."
+
+ (interactive)
+
+ (let* ((vterm-shell (expand-file-name "~/bin/w"))
+ (weechat-buffer-name "weechat")
+ (maybe-weechat-buffer (get-buffer weechat-buffer-name)))
+ (cond
+ ((multi-vterm-buffer-exist-p maybe-weechat-buffer)
+ (switch-to-buffer maybe-weechat-buffer))
+ (t
+ (multi-vterm)
+ (rename-buffer weechat-buffer-name)))))
+
+(defun kakafarm/sentence-end-double-nilify-for-read-only-buffers ()
+ "Set `sentence-end-double-space' in read-only buffer to `nil'."
+ (when buffer-read-only
+ (setq-local sentence-end-double-space
+ nil)))
+
+;; Uploading README.html from README.org stuff.
+(defun kakafarm/srht-repo-id (repository-name)
+ "Returns the unique numerical I Dentification associated with
+every sourcehut repository.
+
+https://www.tomsdiner.org/blog/post_0003_sourcehut_readme_org_export.html"
+
+ (interactive "sRepo name: ")
+ (let* ((srht (netrc-machine (netrc-parse "~/.netrc.gpg")
+ "repo.git.sr.ht"))
+ (srht-token (netrc-get srht
+ "password"))
+ (our-response (with-temp-buffer
+ (call-process "curl"
+ nil
+ (list (current-buffer) nil)
+ nil
+ "--oauth2-bearer" srht-token
+ "-G"
+ "--data-urlencode"
+ (concat "query=query { me { repository(name: \""
+ repository-name
+ "\") { id } } }")
+ "https://git.sr.ht/query")
+ (buffer-string)))
+ (repository-id (string-trim (kakafarm/call-process-with-string-as-input "jq"
+ our-response
+ ".data.me.repository.id"))))
+ (if (called-interactively-p)
+ (message "Repository ID: %S" repository-id)
+ repository-id)))
+
+(defun kakafarm/srht-set-readme (repository-id)
+ "Export the current file to HTML and set the result as README for
+the sourcehut repo identified by ID.
+
+https://www.tomsdiner.org/blog/post_0003_sourcehut_readme_org_export.html"
+
+ (interactive "sRepository ID: ")
+ (let* ((srht (netrc-machine (netrc-parse "~/.netrc.gpg")
+ "repo.git.sr.ht"))
+ (srht-token (netrc-get srht
+ "password"))
+ (readme.html (org-export-as (org-export-get-backend 'html)
+ nil
+ nil
+ t))
+ (our-json-query (kakafarm/call-process-with-string-as-input
+ "jq"
+ readme.html
+ "-sR"
+ (concat "
+{ \"query\": \"mutation UpdateRepo($id: Int!, $readme: String!) { updateRepository(id: $id, input: { readme: $readme }) { id } }\",
+ \"variables\": {
+ \"id\": " repository-id ",
+ \"readme\": .
+ }
+}"))))
+ (kakafarm/call-process-with-string-as-input "curl"
+ our-json-query
+ "--oauth2-bearer" srht-token
+ "-H" "Content-Type: application/json"
+ "-d@-"
+ "https://git.sr.ht/query")))
+
+(defun kakafarm/take-while (lst predp)
+ (named-let loop ((lst lst)
+ (accumulator '()))
+ (cond
+ ((null lst)
+ (reverse accumulator))
+ ((predp (car lst))
+ (reverse accumulator))
+ (t
+ (loop (cdr lst)
+ accumulator)))))
+
+(defun kakafarm/url-response-to-body (response)
+ (cdr (kakafarm/drop-while
+ (string-split response
+ "\n")
+ (lambda (line)
+ (not (string-blank-p line))))))
+
+(defun kakafarm/yank-unlines ()
+ "`yank' with each consecutive newlines converted to a single space, and trim both ends."
+ (interactive)
+
+ (insert
+ (string-trim
+ (with-temp-buffer
+ (yank)
+ (goto-char 1)
+ (replace-regexp "\n+" " ")
+ (buffer-string)))))
+
+(provide 'kakafarm)
+
+;;; Local Variables:
+;; read-symbol-shorthands: (("kf/" . "kakafarm/"))
+;; End:
+;;; kakafarm.el ends here.