dotfiles

A steaming hot pile of sh...ell scripts and configuration files.
git clone https://kaka.farm/~git/dotfiles
Log | Files | Refs

kakafarm.el (16062B)


      1 ;;; kakafarm.el --- Various functions for my GNU Emacs configuration.  -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (C) 2024  Yuval Langer
      4 
      5 ;; Author: Yuval Langer <yuval.langer@gmail.com>
      6 ;; Version: 0.0.0
      7 ;; Keywords: Personal, Auxiliary
      8 ;; URL: https://codeberg.org/kakafarm/dotfiles/
      9 
     10 ;; This program is free software; you can redistribute it and/or modify
     11 ;; it under the terms of the GNU General Public License as published by
     12 ;; the Free Software Foundation, either version 3 of the License, or
     13 ;; (at your option) any later version.
     14 
     15 ;; This program is distributed in the hope that it will be useful,
     16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18 ;; GNU General Public License for more details.
     19 
     20 ;; You should have received a copy of the GNU General Public License
     21 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
     22 
     23 ;;; Commentary:
     24 
     25 ;; Do not expect any of these functions to remain stable.
     26 ;;
     27 ;; The functions are ordered in an alphabetic order.  I do not know
     28 ;; if it makes much sense, but so be it.
     29 
     30 ;;; Code:
     31 
     32 (require 'cl-lib)
     33 
     34 ;;;###autoload
     35 (defun kakafarm/advice-remove-all (function)
     36   "Remove every advice function from FUNCTION."
     37   (advice-mapc
     38    (lambda (advice-function properties-alist)
     39      (advice-remove function
     40                     advice-function))
     41    function))
     42 
     43 ;;;###autoload
     44 (defun kakafarm/call-process-with-string-as-input (program &optional input-string &rest args)
     45   (with-temp-buffer
     46     (let ((our-output-buffer (current-buffer)))
     47       (if input-string
     48           (with-temp-buffer
     49             (let ((our-input-buffer (current-buffer)))
     50               (progn
     51                 (erase-buffer)
     52                 (insert input-string)
     53                 (apply 'call-process-region
     54                        (buffer-end -1)
     55                        (buffer-end 1)
     56                        program
     57                        nil
     58                        our-output-buffer
     59                        nil
     60                        args))))
     61         (apply 'call-process
     62                program
     63                nil
     64                our-output-buffer
     65                nil
     66                args)))
     67     (buffer-string)))
     68 
     69 ;; (list (kakafarm/call-process-with-string-as-input "cat"
     70 ;;                                                   "cat says moo")
     71 ;;       (kakafarm/call-process-with-string-as-input "echo"
     72 ;;                                                   nil
     73 ;;                                                   "-n"
     74 ;;                                                   "echo echo echo"))
     75 
     76 ;;;###autoload
     77 (defun kakafarm/colorize-compilation ()
     78   "Colorize from `compilation-filter-start' to `point'.
     79 
     80 Used to convert raw ANSI color codes into visually (sometimes dis-)pleasing colors.
     81 
     82 From:
     83 
     84 https://endlessparentheses.com/ansi-colors-in-the-compilation-buffer-output.html"
     85   (let ((inhibit-read-only t))
     86     (ansi-color-apply-on-region compilation-filter-start
     87                                 (point))))
     88 
     89 ;;;###autoload
     90 (defun kakafarm/copy-elfeed-links ()
     91   (interactive)
     92 
     93   (cl-letf* ((elfeed-entry-to-url-nl (lambda (entry)
     94                                        (concat (elfeed-entry-link entry) "\n")))
     95              (all-urls-string (apply 'concat
     96                                      (mapcar elfeed-entry-to-url-nl
     97                                              (elfeed-search-selected)))))
     98     (with-temp-buffer
     99       (insert all-urls-string)
    100       (kill-region (point-min)
    101                    (point-max)))))
    102 
    103 ;;;###autoload
    104 (defun kakafarm/drop-while (lst predp)
    105   (named-let loop ((lst lst))
    106     (cond
    107      (()
    108       lst)
    109      ((predp (car lst))
    110       (cdr lst))
    111      (t
    112       (loop (cdr lst))))))
    113 
    114 ;;;###autoload
    115 (defun kakafarm/easy-underscore (arg)
    116   "Convert all inputs of semicolon to an underscore
    117 If given ARG, then it will insert an actual semicolon.
    118 
    119 from https://www.youtube.com/watch?v=6R-73hsL5wk"
    120   (interactive "P")
    121   (message (format "%s" arg))
    122   (if arg
    123       (insert ";")
    124     (insert "_")))
    125 
    126 ;;;###autoload
    127 (defun kakafarm/elfeed-sort-feed-tags (a-feed)
    128   (cond
    129    ((stringp a-feed)
    130     a-feed)
    131    (t
    132     (let* ((feed-url (car a-feed))
    133            (tags (cdr a-feed))
    134            (tags-as-strings (mapcar #'symbol-name
    135                                     tags))
    136            (sorted-tags (sort tags-as-strings
    137                               #'string-lessp))
    138            (tags-as-symbols (mapcar #'intern sorted-tags)))
    139       (cons feed-url tags-as-symbols)))))
    140 
    141 ;;;###autoload
    142 (defun kakafarm/elfeed-compare-feeds-urls (feed-a feed-b)
    143   (string-lessp (car feed-a)
    144                 (car feed-b)))
    145 
    146 ;;;###autoload
    147 (defun kakafarm/elfeed-sort-feeds (feeds)
    148   "Sort A-FEED, an `elfeed-feeds' list."
    149   (sort (mapcar #'kakafarm/elfeed-sort-feed-tags
    150                 feeds)
    151         #'kakafarm/elfeed-compare-feeds-urls))
    152 
    153 ;;;###autoload
    154 (defun kakafarm/ffap-browse-urls ()
    155   "Open all visible URLs."
    156   (interactive)
    157 
    158   (let* ((urls (mapcar 'car (ffap-menu-rescan)))
    159          (urls-newlined (mapcar (lambda (url) (concat url "\n"))
    160                                 urls))
    161          (prompt (format "Open URLs? [y/n]
    162 
    163 %s"
    164                          (apply 'concat
    165                                 urls-newlined))))
    166     (when (y-or-n-p prompt)
    167       (dolist (url urls)
    168         (browse-url url)))))
    169 
    170 ;;;###autoload
    171 (defun kakafarm/kill-ring-save-unlines ()
    172   "Like `kill-ring-save', but also unlines and trims the newly killed stuff."
    173   (interactive)
    174 
    175   (kill-ring-save (point) (mark))
    176 
    177   (with-temp-buffer
    178     (yank-pop)
    179     (goto-char 1)
    180     (replace-regexp "\n+" " ")
    181     (let ((trimmed (string-trim (buffer-string))))
    182       (with-temp-buffer
    183         (insert trimmed)
    184         (kill-region (point-min) (point-max))))))
    185 
    186 ;;;###autoload
    187 (defun kakafarm/list-all-http-or-https ()
    188   (interactive)
    189   (dolist (url (let* ((list-of-lines
    190                        (split-string (substring-no-properties (buffer-string))
    191                                      "[ \n]")))
    192                  (cl-reduce (lambda (accumulator line)
    193                               (if (string-match-p "https?://.+"
    194                                                   line)
    195                                   (cons line accumulator)
    196                                 accumulator))
    197                             list-of-lines
    198                             :initial-value '())))
    199     (message "%s" url)))
    200 
    201 ;;;###autoload
    202 (defun kakafarm/org-roam-keyword-is-filetags-p (keyword-node)
    203   (equal (org-element-property :key
    204                                keyword-node)
    205          "FILETAGS"))
    206 
    207 ;;;###autoload
    208 (defun kakafarm/org-roam-filetags-keyword-is-publishable-p (filestags-keyword-node)
    209   (seq-contains-p (split-string (org-element-property :value
    210                                                       filestags-keyword-node)
    211                                 ":")
    212                   "publish"))
    213 
    214 ;;;###autoload
    215 (defun kakafarm/org-roam-publishable-node-p (org-filename)
    216   (with-temp-buffer
    217     (insert-file-contents org-filename)
    218     (org-element-map
    219      (org-element-parse-buffer)
    220      'keyword
    221      (lambda (keyword)
    222        (and (kakafarm/org-roam-keyword-is-filetags-p keyword)
    223             (kakafarm/org-roam-filetags-keyword-is-publishable-p keyword)))
    224      nil
    225      t)))
    226 
    227 ;;;###autoload
    228 (defun kakafarm/org-roam-sitemap (title list-of-org-links)
    229   (message (format "kakafarm/org-roam-sitemap title: %S; list-of-links: %S\n"
    230                    title
    231                    list-of-org-links))
    232   ;; (let ((a-publishable-org-roam-node
    233   ;;        (seq-filter (lambda (org-link-list)
    234   ;;                      (pcase org-link-list
    235   ;;                        (`(,org-link)
    236   ;;                         (with-temp-buffer
    237   ;;                           (insert org-link)
    238   ;;                           (org-element-map (org-element-parse-buffer) 'link
    239   ;;                             (lambda (link)
    240   ;;                               ;; Check if file linked is publishable.
    241   ;;                               (kakafarm/org-roam-publishable-node-p
    242   ;;                                (concat "~/mine/roam/"
    243   ;;                                        (org-element-property :path
    244   ;;                                                              link))))
    245   ;;                             nil
    246   ;;                             t)))))
    247   ;;                    list-of-org-links)))
    248   ;;   (message "poop %S" a-publishable-org-roam-node))
    249 
    250   (concat
    251    "# -*- encoding: utf-8 -*-\n"
    252    "#+OPTIONS: ^:nil author:nil html-postamble:nil\n"
    253    ;;"#SETUPFILE: ./simple_inline.theme\n" ; No theme yet.
    254    "#+FILETAGS: publish\n"
    255    "#+TITLE: " title "\n\n"
    256    (org-list-to-org list-of-org-links) "\n"
    257 
    258    ;; TODO: No sitemap SVG yet because it shows all the fucking
    259    ;; files in the org-roam database.
    260    ;;
    261    ;;"file:sitemap.svg\n"
    262    ))
    263 
    264 ;;;###autoload
    265 (defun kakafarm/org-roam-publication-wrapper (plist filename pubdir)
    266   ;; (when (kakafarm/org-roam-publishable-node-p filename)
    267   ;;   nil)
    268   ;;(org-roam-graph) ; How the fuck do I make this one not show every fucking node in the org-roam database?!
    269   (org-html-publish-to-html plist
    270                             filename
    271                             pubdir)
    272   (setq kakafarm/org-roam-project-publish-time
    273         (cadr (current-time))))
    274 
    275 ;;;###autoload
    276 (defun kakafarm/org-roam-custom-link-builder (node)
    277   (let ((node-file (org-roam-node-file node)))
    278     ;; (when (kakafarm/org-roam-publishable-node-p node-file)
    279     ;;   nil)
    280     (message (format "kakafarm/org-roam-custom-link-builder: %S" node))
    281     (concat (file-name-base node-file)
    282             ".html")))
    283 
    284 ;;;###autoload
    285 (defun kakafarm/percent-read ()
    286   "Display percent read by current cursor location vs. total characters in file."
    287 
    288   (interactive)
    289 
    290   (message "%.2f%%"
    291            (* 100
    292               (/ (float (- (point) 1))
    293                  (+ 1 (buffer-size))))))
    294 
    295 ;;;###autoload
    296 (defun kakafarm/percent-read-point-min-max ()
    297   "Display percent read by current cursor location vs. place within (point-min) and (point-max)."
    298 
    299   (interactive)
    300 
    301   (let* ((our-location (point))
    302          (our-location-0-indexed (- our-location 1)))
    303     (message "%.2f%%"
    304              (* 100
    305                 (/ (float (- our-location-0-indexed
    306                              (point-min)))
    307                    (- (point-max)
    308                       (point-min)))))))
    309 
    310 ;;;###autoload
    311 (defun kakafarm/recenter-top-bottom (original-function &rest arguments)
    312   "Move view such that point is 4 lines from the top of the frame when function is `recenter-top-bottom'."
    313 
    314   (cond
    315    ((null (car arguments))
    316     (apply original-function '(4)))
    317    (t
    318     (apply original-function arguments))))
    319 
    320 ;;;###autoload
    321 (defun kakafarm/pulse-current-region (&rest _)
    322   "Pulse the selected bit, either the marked region or if there's no
    323 mark, the bit between mark and point... or something like
    324 that... I don't even work here.
    325 
    326 From Goparism (https://www.youtube.com/@goparism)
    327 https://www.youtube.com/watch?v=oQ9JE9kRwG8 which is from the
    328 user 0xMii on R***** which copied it from
    329 who-knows-where-and-who."
    330   (if mark-active
    331       (pulse-momentary-highlight-region (region-beginning)
    332                                         (region-end))
    333     (pulse-momentary-highlight-region (mark)
    334                                       (point))))
    335 
    336 ;;;###autoload
    337 (defun kakafarm/multi-vterm-weechat ()
    338   "Either start a weechat vterm buffer, or switch to it if it already exists."
    339 
    340   (interactive)
    341 
    342   (let* ((weechat-buffer-name "weechat")
    343          (maybe-weechat-buffer (get-buffer weechat-buffer-name)))
    344     (cond
    345      ((multi-vterm-buffer-exist-p maybe-weechat-buffer)
    346       (switch-to-buffer maybe-weechat-buffer))
    347      (t
    348       (let ((vterm-shell (expand-file-name "~/bin/w")))
    349         (multi-vterm)
    350         (rename-buffer weechat-buffer-name))))))
    351 
    352 ;;;###autoload
    353 (defun kakafarm/sentence-end-double-nilify-for-read-only-buffers ()
    354   "Set `sentence-end-double-space' in read-only buffer to `nil'."
    355   (when buffer-read-only
    356     (setq-local sentence-end-double-space
    357                 nil)))
    358 
    359 ;; Uploading README.html from README.org stuff.
    360 ;;;###autoload
    361 (defun kakafarm/srht-repo-id (repository-name)
    362   "Returns the unique numerical I Dentification associated with
    363 every sourcehut repository.
    364 
    365 https://www.tomsdiner.org/blog/post_0003_sourcehut_readme_org_export.html"
    366 
    367   (interactive "sRepo name: ")
    368   (let* ((srht (netrc-machine (netrc-parse "~/.netrc.gpg")
    369                               "repo.git.sr.ht"))
    370          (srht-token (netrc-get srht
    371                                 "password"))
    372          (our-response (with-temp-buffer
    373                          (call-process "curl"
    374                                        nil
    375                                        (list (current-buffer) nil)
    376                                        nil
    377                                        "--oauth2-bearer" srht-token
    378                                        "-G"
    379                                        "--data-urlencode"
    380                                        (concat "query=query { me { repository(name: \""
    381                                                repository-name
    382                                                "\") { id } } }")
    383                                        "https://git.sr.ht/query")
    384                          (buffer-string)))
    385          (repository-id (string-trim (kakafarm/call-process-with-string-as-input "jq"
    386                                                                                  our-response
    387                                                                                  ".data.me.repository.id"))))
    388     (if (called-interactively-p)
    389         (message "Repository ID: %S" repository-id)
    390       repository-id)))
    391 
    392 ;;;###autoload
    393 (defun kakafarm/srht-set-readme (repository-id)
    394   "Export the current file to HTML and set the result as README for
    395 the sourcehut repo identified by ID.
    396 
    397 https://www.tomsdiner.org/blog/post_0003_sourcehut_readme_org_export.html"
    398 
    399   (interactive "sRepository ID: ")
    400   (let* ((srht (netrc-machine (netrc-parse "~/.netrc.gpg")
    401                               "repo.git.sr.ht"))
    402          (srht-token (netrc-get srht
    403                                 "password"))
    404          (readme.html (org-export-as (org-export-get-backend 'html)
    405                                      nil
    406                                      nil
    407                                      t))
    408          (our-json-query (kakafarm/call-process-with-string-as-input
    409                           "jq"
    410                           readme.html
    411                           "-sR"
    412                           (concat "
    413 { \"query\": \"mutation UpdateRepo($id: Int!, $readme: String!) { updateRepository(id: $id, input: { readme: $readme }) { id } }\",
    414     \"variables\": {
    415         \"id\": " repository-id ",
    416         \"readme\": .
    417     }
    418 }"))))
    419     (kakafarm/call-process-with-string-as-input "curl"
    420                                                 our-json-query
    421                                                 "--oauth2-bearer" srht-token
    422                                                 "-H" "Content-Type: application/json"
    423                                                 "-d@-"
    424                                                 "https://git.sr.ht/query")))
    425 
    426 ;;;###autoload
    427 (defun kakafarm/take-while (lst predp)
    428   (named-let loop ((lst lst)
    429                    (accumulator '()))
    430     (cond
    431      ((null lst)
    432       (reverse accumulator))
    433      ((predp (car lst))
    434       (reverse accumulator))
    435      (t
    436       (loop (cdr lst)
    437             accumulator)))))
    438 
    439 ;;;###autoload
    440 (defun kakafarm/url-response-to-body (response)
    441   (cdr (kakafarm/drop-while
    442         (string-split response
    443                       "\n")
    444         (lambda (line)
    445           (not (string-blank-p line))))))
    446 
    447 ;;;###autoload
    448 (defun kakafarm/yank-unlines ()
    449   "`yank' with each consecutive newlines converted to a single space, and trim both ends."
    450   (interactive)
    451 
    452   (insert
    453    (string-trim
    454     (with-temp-buffer
    455       (yank)
    456       (goto-char 1)
    457       (replace-regexp "\n+" " ")
    458       (buffer-string)))))
    459 
    460 (provide 'kakafarm)
    461 
    462 ;;; Local Variables:
    463 ;;; read-symbol-shorthands: (("kf/" . "kakafarm/"))
    464 ;;; End:
    465 ;;; kakafarm.el ends here.