aboutsummaryrefslogtreecommitdiff
path: root/emacs/.emacs.d
diff options
context:
space:
mode:
Diffstat (limited to 'emacs/.emacs.d')
-rw-r--r--emacs/.emacs.d/init/ycp-emms.el2
-rw-r--r--emacs/.emacs.d/init/ycp-markup.el11
-rw-r--r--emacs/.emacs.d/init/ycp-org.el22
-rw-r--r--emacs/.emacs.d/init/ycp-web.el7
-rw-r--r--emacs/.emacs.d/lisp/my/infobox.el65
-rw-r--r--emacs/.emacs.d/lisp/my/my-buffer.el55
-rw-r--r--emacs/.emacs.d/lisp/my/my-emms.el48
-rw-r--r--emacs/.emacs.d/lisp/my/my-gitlab.el80
-rw-r--r--emacs/.emacs.d/lisp/my/my-ledger.el43
-rw-r--r--emacs/.emacs.d/lisp/my/my-mariadb.el15
-rw-r--r--emacs/.emacs.d/lisp/my/my-net.el10
-rw-r--r--emacs/.emacs.d/lisp/my/my-nov.el3
-rw-r--r--emacs/.emacs.d/lisp/my/my-org-jira.el10
-rw-r--r--emacs/.emacs.d/lisp/my/my-org-remark.el36
-rw-r--r--emacs/.emacs.d/lisp/my/my-org.el5
-rw-r--r--emacs/.emacs.d/lisp/my/my-prog.el2
-rw-r--r--emacs/.emacs.d/lisp/my/my-web.el13
-rw-r--r--emacs/.emacs.d/lisp/my/my-ytdl.el12
m---------emacs/.emacs.d/lisp/nov.el0
m---------emacs/.emacs.d/lisp/wiki.el0
20 files changed, 399 insertions, 40 deletions
diff --git a/emacs/.emacs.d/init/ycp-emms.el b/emacs/.emacs.d/init/ycp-emms.el
index a3a4604..458a6b0 100644
--- a/emacs/.emacs.d/init/ycp-emms.el
+++ b/emacs/.emacs.d/init/ycp-emms.el
@@ -90,6 +90,8 @@
(my-override emms-mode-line-toggle)
(add-hook 'emms-playlist-selection-changed-hook
'my-emms-output-current-track-to-i3bar-file)
+ (add-hook 'emms-player-finished-hook 'my-emms-score-up-playing)
+ (add-hook 'emms-player-started-hook 'my-emms-score-up-chosen-bonus)
(setq emms-player-next-function 'my-emms-next-track-or-random-album)
(setq emms-players-preference-f 'my-emms-players-preference)
(my-keybind dired-mode-map "e" #'my-dired-add-to-emms)
diff --git a/emacs/.emacs.d/init/ycp-markup.el b/emacs/.emacs.d/init/ycp-markup.el
index d55586d..fcb98ff 100644
--- a/emacs/.emacs.d/init/ycp-markup.el
+++ b/emacs/.emacs.d/init/ycp-markup.el
@@ -83,14 +83,21 @@
(setq-local completion-cycle-threshold t)
(setq-local ledger-complete-in-steps t)
(setq-local company-mode nil)))
- (setq ledger-binary-path "hledger"))
+ (setq ledger-binary-path "hledger")
+ (require 'my-ledger)
+ (my-keybind ledger-mode-map
+ "M-<down>" #'my-ledger-move-xact-down
+ "M-<up>" #'my-ledger-move-xact-up))
;;; todo: open epub in emacs client with nov
(my-package nov
(:delay 15)
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
- (setq nov-text-width fill-column)
+ (setq nov-text-width 76)
(add-hook 'nov-mode-hook 'follow-mode)
+ (add-hook 'nov-mode-hook (lambda ()
+ (setq next-screen-context-lines 4)))
+ (add-hook 'nov-post-html-render-hook 'my-nov-set-left-margin)
(require 'my-nov)
(my-override nov-render-title)
(my-override nov-scroll-up)
diff --git a/emacs/.emacs.d/init/ycp-org.el b/emacs/.emacs.d/init/ycp-org.el
index bb1b828..ea95d2a 100644
--- a/emacs/.emacs.d/init/ycp-org.el
+++ b/emacs/.emacs.d/init/ycp-org.el
@@ -441,7 +441,11 @@
(add-to-list 'org-protocol-protocol-alist
'("grok"
:protocol "grok"
- :function my-org-protocol-grok)))
+ :function my-org-protocol-grok))
+ (add-to-list 'org-protocol-protocol-alist
+ '("browse-url"
+ :protocol "browse-url"
+ :function my-org-protocol-browse-url)))
;; org man links
(my-package ol-man
@@ -518,5 +522,21 @@
(:delay 60)
(require 'my-ox-jira))
+(my-package org-remark
+ (:install t)
+ (:delay 60)
+ (require 'my-org-remark)
+ (setq org-remark-notes-display-buffer-action
+ '(display-buffer-reuse-mode-window))
+ (require 'nov)
+ (my-keybind nov-mode-map
+ "M-n" #'org-remark-next
+ "M-p" #'org-remark-prev
+ "<return>" #'my-org-remark-open-or-create
+ "o" #'org-remark-view
+ "d" #'org-remark-delete)
+ (with-eval-after-load 'nov
+ (org-remark-nov-mode +1)))
+
(provide 'ycp-org)
;;; ycp-org.el ends here
diff --git a/emacs/.emacs.d/init/ycp-web.el b/emacs/.emacs.d/init/ycp-web.el
index ffdb83d..a4fa8f5 100644
--- a/emacs/.emacs.d/init/ycp-web.el
+++ b/emacs/.emacs.d/init/ycp-web.el
@@ -203,6 +203,7 @@
org-jira-jira-status-to-org-keyword-alist
org-jira-project-filename-alist
org-jira-custom-jqls)
+ (org-link-set-parameters "jira" '((:follow . org-jira-open)))
(require 'my-org-jira)
(my-override org-jira--render-issue)
(my-override org-jira-update-worklogs-from-org-clocks)
@@ -254,12 +255,14 @@
. ,(lambda (url &rest _) (exitter-open-post url)))
(my-hacker-news-url-p
. ,(lambda (url &rest _) (hnreader-comment url)))
- (my-mariadb-kb-url-p
- . ,(lambda (url &rest _) (my-mariadb-fetch-kb-source url)))
+ (my-gitlab-project-url-p
+ . ,(lambda (url &rest _) (my-gitlab-project-infobox url)))
(my-mastodon-url-p
. ,(lambda (url &rest _) (mastorg-open url)))
(my-newscorp-au-url-p
. ,(lambda (url &rest _) (my-open-newscorp-au url)))
+ (my-org-jira-url-p
+ . ,(lambda (url &rest _) (my-org-jira-open-url url)))
(reddio-reddit-url-p
. ,(lambda (url &rest _) (reddio-open-url url)))
("^https?://www.spectator.com.au\\>" .
diff --git a/emacs/.emacs.d/lisp/my/infobox.el b/emacs/.emacs.d/lisp/my/infobox.el
new file mode 100644
index 0000000..81a66ce
--- /dev/null
+++ b/emacs/.emacs.d/lisp/my/infobox.el
@@ -0,0 +1,65 @@
+;;; infobox.el -- Infobox in a help buffer -*- lexical-binding: t -*-
+
+;; Copyright (C) 2025 Free Software Foundation, Inc.
+
+;; Author: Yuchen Pei <id@ypei.org>
+;; Package-Requires: ((emacs "29.4"))
+
+;; This file is part of dotted.
+
+;; dotted is free software: you can redistribute it and/or modify it under
+;; the terms of the GNU Affero General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; dotted 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 Affero General
+;; Public License for more details.
+
+;; You should have received a copy of the GNU Affero General Public
+;; License along with dotted. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Infobox in a help buffer.
+
+;;; Code:
+
+
+(defun infobox-translate (info specs)
+ "Translate INFO according to SPECS.
+
+TODO: allow multiple levels in specs keys using let-alist, i.e.
+something like
+
+(.channel.name . \"Channel name\")"
+ (seq-map
+ (lambda (pair)
+ (when-let ((val (alist-get (car pair) info)))
+ (if (or (stringp (cdr pair)) (symbolp (cdr pair)))
+ (cons (cdr pair) val)
+ (cons (cadr pair) (funcall (cddr pair) val)))))
+ specs))
+
+(defun infobox-render (info item &optional interactive-p)
+ "Render and display a help buffer of INFO."
+ (help-setup-xref item interactive-p)
+ (with-help-window (help-buffer)
+ (with-current-buffer standard-output
+ (let ((n-rows 0))
+ (seq-do
+ (lambda (pair)
+ (when pair
+ (when (stringp (car pair))
+ (insert (car pair) ": ")
+ (setq n-rows (1+ n-rows)))
+ (insert (cdr pair) "\n")))
+ info)
+ (align-regexp
+ (point-min)
+ (progn (goto-line (1+ n-rows)) (point))
+ "\\(\\s-*\\):"))
+ (visual-line-mode))))
+
+(provide 'infobox)
diff --git a/emacs/.emacs.d/lisp/my/my-buffer.el b/emacs/.emacs.d/lisp/my/my-buffer.el
index f06956f..f2da7f5 100644
--- a/emacs/.emacs.d/lisp/my/my-buffer.el
+++ b/emacs/.emacs.d/lisp/my/my-buffer.el
@@ -239,24 +239,54 @@ that point."
(setq buffer temp-buffer))
(set-window-buffer first-window buffer)))
+(defun my-set-left-buffer ()
+ "Generate and switch to an empty buffer."
+ (interactive)
+ (set-window-buffer
+ (window-left (get-buffer-window))
+ (with-current-buffer (get-buffer-create "*my-left*")
+ (read-only-mode t)
+ (current-buffer))))
+
+(defun my-set-right-buffer ()
+ "Generate and switch to an empty buffer."
+ (interactive)
+ (set-window-buffer
+ (window-right (get-buffer-window))
+ (with-current-buffer (get-buffer-create "*my-right*")
+ (read-only-mode t)
+ (current-buffer))))
+
(defun my-toggle-focus-write ()
"Toggle focus write mode.
Focus write: make the current window the only one centered with
-width 80. If in org-mode, also narrow to current subtree."
+width 80. If in org-mode, also narrow to current subtree. Make
+buffers on both sides empty read-only buffers."
(interactive)
;; Only one window in the current frame indicates we are in focus
;; write mode.
- (if (length= (window-list) 1)
+ (if (and (equal
+ (buffer-name
+ (window-buffer (window-left (get-buffer-window))))
+ "*my-left*")
+ (equal
+ (buffer-name
+ (window-buffer (window-right (get-buffer-window))))
+ "*my-right*"))
(progn
(winner-undo)
(when (derived-mode-p 'org-mode)
(widen)))
(when (derived-mode-p 'org-mode)
(org-narrow-to-subtree))
- (delete-other-windows)
- (let ((margin (/ (- (window-width) 80) 2)))
- (set-window-margins nil margin margin))))
+ (my-set-left-buffer)
+ (my-set-right-buffer)
+ (let ((margin (/ (- 80 (window-width)) 2)))
+ (enlarge-window margin t)
+ (windmove-left)
+ (enlarge-window (- margin) t)
+ (windmove-right))))
(defun my-select-new-window-matching-mode (mode)
"Select a new window."
@@ -415,6 +445,11 @@ for the given MAJOR-MODE, any text is appended to it."
(4 (my-buffer-scratch-setup region default-mode))
(_ (my-buffer-scratch-setup region)))))
+(defun my-new-empty-buffer ()
+ "Generate and switch to an empty buffer."
+ (interactive)
+ (switch-to-buffer (generate-new-buffer "empty")))
+
(defcustom my-scratch-buffer-default-mode 'org-mode
"Default major mode for `my-buffer-create-scratch'."
:type 'symbol
@@ -483,5 +518,15 @@ With double prefix arguments, create a new indirect buffer."
(revert-buffer t t))
(switch-to-buffer buffer)))
+(defun my-fontify-with-mode (text mode)
+ "Fontify TEXT with MODE."
+ (with-temp-buffer
+ (funcall mode)
+ (insert text)
+ (if (fboundp 'font-lock-ensure)
+ (font-lock-ensure)
+ (with-no-warnings (font-lock-fontify-buffer)))
+ (buffer-string)))
+
(provide 'my-buffer)
;;; my-buffer.el ends here
diff --git a/emacs/.emacs.d/lisp/my/my-emms.el b/emacs/.emacs.d/lisp/my/my-emms.el
index 803ac0a..03392be 100644
--- a/emacs/.emacs.d/lisp/my/my-emms.el
+++ b/emacs/.emacs.d/lisp/my/my-emms.el
@@ -300,10 +300,23 @@ filter extensions from filter-exts."
(defvar my-emms-i3bar-file (locate-user-emacs-file "emms-i3bar")
"File to write current playing to which i3bar reads")
(defun my-emms-get-display-name (track)
+ "Return the display name of a track.
+
+The display name is either the info-title, or the display name of
+the filename."
(or (alist-get 'info-title track)
(when-let ((name
(alist-get 'name track)))
- (replace-regexp-in-string "^\\(.*/\\)\\(.*/.*/.*\\)" "\\2" name))))
+ (my-emms-get-display-name-1 name))))
+
+(defun my-emms-get-display-name-1 (name)
+ "Return the display name of a filename NAME.
+
+The display name is the last three components of the filename,
+assuming the filesystem hierarchy is arranged in
+artist/album/track."
+ (replace-regexp-in-string "^\\(.*/\\)\\(.*/.*/.*\\)" "\\2" name))
+
(defun my-emms-output-current-track-to-i3bar-file ()
(let ((current-track
(my-emms-get-display-name (emms-playlist-current-selected-track))))
@@ -473,13 +486,40 @@ Hex-encoded characters in URLs are replaced by the decoded
character."
(let ((type (emms-track-type track)))
(cond ((emms-track-get track 'description)
- (emms-track-get track 'description))
- ((eq 'file type)
- (emms-track-name track))
+ (emms-track-get track 'description))
+ ((eq 'file type)
+ (emms-track-name track))
((eq 'url type)
(emms-format-url-track-name (emms-track-name track)))
(t (concat (symbol-name type)
": " (emms-track-name track))))))
+(defvar my-emms-score-delta 1)
+
+(defun my-emms-score-up-playing ()
+ "Increase score by `my-emms-score-delta', then reset it to 1."
+ (emms-score-change-score
+ my-emms-score-delta
+ (my-emms-get-display-name-1 (emms-score-current-selected-track-filename)))
+ (setq my-emms-score-delta 1))
+
+(defun my-emms-score-up-chosen-bonus ()
+ "Bonus score up if the track is started intentionally.
+
+If the last command is `emms-playlist-mode-play-smart', then set
+`my-emms-score-delta' to 2."
+ (when (eq last-command 'emms-playlist-mode-play-smart)
+ (setq my-emms-score-delta 2)))
+
+(defun my-emms-wrapped ()
+ "Print top 5 scored tracks."
+ (interactive)
+ (let (keys)
+ (maphash (lambda (k _) (push k keys)) emms-score-hash)
+ (sort keys (lambda (k1 k2)
+ (< (second (gethash k1 emms-score-hash))
+ (second (gethash k2 emms-score-hash)))))
+ (message "Top 5: %s" (string-join (take 5 keys) "\n"))))
+
(provide 'my-emms)
;;; my-emms.el ends here
diff --git a/emacs/.emacs.d/lisp/my/my-gitlab.el b/emacs/.emacs.d/lisp/my/my-gitlab.el
index 6dd484c..ad7f0ed 100644
--- a/emacs/.emacs.d/lisp/my/my-gitlab.el
+++ b/emacs/.emacs.d/lisp/my/my-gitlab.el
@@ -26,8 +26,9 @@
;;; Code:
+(require 'infobox)
-(defun my-get-gitlab-project-id (url)
+(defun my-gitlab-get-project-id (url)
(with-current-buffer (url-retrieve-synchronously
(replace-regexp-in-string "\\.git$" "" url))
(let ((dom (libxml-parse-html-region (point-min) (point-max))))
@@ -35,16 +36,75 @@
(dom-search dom (lambda (n) (dom-attr n 'data-project-id))))
'data-project-id))))
-(defun my-grok-gitlab (url)
+(defun my-gitlab-api-projects (url)
(when-let* ((urlobj (url-generic-parse-url url))
- (project-id (my-get-gitlab-project-id url)))
- (with-current-buffer
- (url-retrieve-synchronously
- (concat (url-type urlobj) "://" (url-host urlobj)
- "/api/v4/projects/" project-id))
- (set-buffer-multibyte t)
- (my-delete-http-header)
- (my-grok-gitlab-make-info (json-read)))))
+ (project-id (my-gitlab-get-project-id url)))
+ (my-url-fetch-json
+ (format "%s://%s/api/v4/projects/%s"
+ (url-type urlobj)
+ (url-host urlobj)
+ project-id))))
+
+(defvar my-gitlab-readme-get-raw nil "Whether to get raw or html readme")
+
+(defun my-gitlab-project-info (url)
+ "Given a url, returns project info."
+ (let ((info (my-gitlab-api-projects url)))
+ (let-alist info
+ (when .readme_url
+ (setf (alist-get 'readme info)
+ (if my-gitlab-readme-get-raw
+ (format
+ "\n%s"
+ (my-url-fetch-raw
+ (replace-regexp-in-string "/-/blob/" "/-/raw/" .readme_url)))
+ (alist-get
+ 'html
+ (my-url-fetch-json
+ (format "%s?format=json&viewer=rich" .readme_url)))))))
+ info))
+
+(defun my-gitlab-format-time-string (t)
+ (format-time-string "%Y-%m-%d %M:%M:%S" (encode-time (parse-time-string t))))
+
+(defun my-gitlab-project-url-p (url)
+ (let ((urlobj (url-generic-parse-url url)))
+ (and (equal (url-host urlobj) "gitlab.com")
+ (string-match-p "^/[^/]+/[^/]+$" (url-filename urlobj)))))
+
+(require 'my-buffer)
+
+(defvar my-gitlab-project-info-specs
+ `((http_url_to_repo . "Clone")
+ (name_with_namespace . "Name")
+ (description . "Description")
+ (created_at . ("Created at" . my-gitlab-format-time-string))
+ (last_activity_at . ("Updated at" . my-gitlab-format-time-string))
+ (topics . ("Topics" . ,(lambda (xs)
+ (mapconcat #'identity xs "; "))))
+ (star_count . ("Stars" . number-to-string))
+ (forks_count . ("Forks" . number-to-string))
+ (readme . (body . ,(lambda (text)
+ (with-temp-buffer
+ (insert text)
+ (shr-render-region (point-min) (point-max))
+ (buffer-string)))))))
+
+(defun my-gitlab-project-infobox (url)
+ "Display a gitlab project info at URL in a help buffer.
+
+A good example would be
+<https://gitlab.com/woob/woob>
+"
+ (interactive "sGitlab project URL: ")
+ (infobox-render
+ (infobox-translate
+ (my-gitlab-project-info url) my-gitlab-project-info-specs)
+ `(my-gitlab-project-infobox ,url)
+ (called-interactively-p 'interactive)))
+
+(defun my-grok-gitlab (url)
+ (my-grok-gitlab-make-info (my-gitlab-api-projects url)))
(defun my-grok-gitlab-make-info (raw)
(list (cons "Title" (alist-get 'name raw))
diff --git a/emacs/.emacs.d/lisp/my/my-ledger.el b/emacs/.emacs.d/lisp/my/my-ledger.el
new file mode 100644
index 0000000..8c955c6
--- /dev/null
+++ b/emacs/.emacs.d/lisp/my/my-ledger.el
@@ -0,0 +1,43 @@
+;;; my-ledger.el -- customizations to ledger mode -*- lexical-binding: t -*-
+
+;; Copyright (C) 2025 Free Software Foundation, Inc.
+
+;; Author: Yuchen Pei <id@ypei.org>
+;; Package-Requires: ((emacs "29.4"))
+
+;; This file is part of dotted.
+
+;; dotted is free software: you can redistribute it and/or modify it under
+;; the terms of the GNU Affero General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; dotted 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 Affero General
+;; Public License for more details.
+
+;; You should have received a copy of the GNU Affero General Public
+;; License along with dotted. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; customizations to ledger mode.
+
+;;; Code:
+
+
+(defun my-ledger-move-xact-down ()
+ (interactive)
+ (call-interactively 'transpose-paragraphs)
+ (call-interactively 'ledger-navigate-prev-xact-or-directive))
+
+(defun my-ledger-move-xact-up ()
+ (interactive)
+ (call-interactively 'ledger-navigate-prev-xact-or-directive)
+ (call-interactively 'transpose-paragraphs)
+ (call-interactively 'ledger-navigate-prev-xact-or-directive)
+ (call-interactively 'ledger-navigate-prev-xact-or-directive))
+
+(provide 'my-ledger)
+;;; my-ledger.el ends here
diff --git a/emacs/.emacs.d/lisp/my/my-mariadb.el b/emacs/.emacs.d/lisp/my/my-mariadb.el
index 01bc063..bdb1c60 100644
--- a/emacs/.emacs.d/lisp/my/my-mariadb.el
+++ b/emacs/.emacs.d/lisp/my/my-mariadb.el
@@ -254,6 +254,21 @@ enum spider_malloc_id {
(defun my-mariadb-kb-url-p (url)
(string-match-p "https://mariadb.com/kb/en/\\([^/]+\\)/" url))
+(defun my-wiki-mariadb-extract-kb-source ()
+ "Extract the kb source from the current buffer.
+
+Used for wiki mode as a post-processor."
+ (let ((source
+ (dom-text
+ (dom-by-id
+ (libxml-parse-html-region (point-min) (point-max))
+ "answer_source"))))
+ (erase-buffer)
+ (insert source))
+ (goto-char (point-min))
+ (save-buffer)
+ )
+
(defun my-mariadb-fetch-kb-source (url)
"Fetches the source to an maridb kb entry at URL.
diff --git a/emacs/.emacs.d/lisp/my/my-net.el b/emacs/.emacs.d/lisp/my/my-net.el
index 1f1cbc6..2574789 100644
--- a/emacs/.emacs.d/lisp/my/my-net.el
+++ b/emacs/.emacs.d/lisp/my/my-net.el
@@ -119,6 +119,14 @@ It checks the STATUS, and if it is ok, saves the payload to FILE-NAME."
decompression
with-header))
+
+(defun my-url-fetch-raw (url &optional decompression with-header)
+ (my-url-fetch-internal
+ url
+ (lambda () (decode-coding-string (buffer-string) 'utf-8))
+ decompression
+ with-header))
+
(defun my-url-fetch-internal (url buffer-processor decompression with-header)
(with-current-buffer (get-buffer-create my-client-buffer-name)
(goto-char (point-max))
@@ -141,7 +149,7 @@ It checks the STATUS, and if it is ok, saves the payload to FILE-NAME."
(list
(cons 'header fields)
(cons 'json (funcall buffer-processor)))
- (funcall buffer-processor)))
+ (when buffer-processor (funcall buffer-processor))))
(error "HTTP error: %s" (buffer-substring (point) (point-max)))))))
(provide 'my-net)
diff --git a/emacs/.emacs.d/lisp/my/my-nov.el b/emacs/.emacs.d/lisp/my/my-nov.el
index 4e2f60a..d893017 100644
--- a/emacs/.emacs.d/lisp/my/my-nov.el
+++ b/emacs/.emacs.d/lisp/my/my-nov.el
@@ -64,5 +64,8 @@ chapter title."
(my-copy-file-with-staging
nov-file-name dest staging)))
+(defun my-nov-set-left-margin ()
+ (set-left-margin (point-min) (point-max) 2))
+
(provide 'my-nov)
;;; my-nov.el ends here
diff --git a/emacs/.emacs.d/lisp/my/my-org-jira.el b/emacs/.emacs.d/lisp/my/my-org-jira.el
index 2502f02..9e2f821 100644
--- a/emacs/.emacs.d/lisp/my/my-org-jira.el
+++ b/emacs/.emacs.d/lisp/my/my-org-jira.el
@@ -82,7 +82,7 @@
:proj-key (path '(fields project key))
:related-issues (mapconcat
(lambda (c)
- (print c)
+ ;; (print c)
(if (org-jira-sdk-path c '(inwardIssue))
(if (equal
(org-jira-sdk-path
@@ -269,5 +269,13 @@
(interactive)
(kill-new (my-org-jira-comment-url-at-point)))
+(defun my-org-jira-url-p (url)
+ (string-match-p (format "^%s/browse/[^/]" jiralib-url) url))
+
+(defun my-org-jira-open-url (url)
+ (interactive "sJIRA issue url: ")
+ (when (string-match (format "^%s/browse/\\([^/]+\\)" jiralib-url) url)
+ (org-jira-get-issue (match-string 1 url))))
+
(provide 'my-org-jira)
;;; my-org-jira.el ends here
diff --git a/emacs/.emacs.d/lisp/my/my-org-remark.el b/emacs/.emacs.d/lisp/my/my-org-remark.el
new file mode 100644
index 0000000..3e0ef0a
--- /dev/null
+++ b/emacs/.emacs.d/lisp/my/my-org-remark.el
@@ -0,0 +1,36 @@
+;;; my-org-remark.el -- customization to org-remark -*- lexical-binding: t -*-
+
+;; Copyright (C) 2025 Free Software Foundation, Inc.
+
+;; Author: Yuchen Pei <id@ypei.org>
+;; Package-Requires: ((emacs "29.4"))
+
+;; This file is part of dotted.
+
+;; dotted is free software: you can redistribute it and/or modify it under
+;; the terms of the GNU Affero General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; dotted 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 Affero General
+;; Public License for more details.
+
+;; You should have received a copy of the GNU Affero General Public
+;; License along with dotted. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; customization to org-remark.
+
+;;; Code:
+
+(defun my-org-remark-open-or-create ()
+ (interactive)
+ (if mark-active
+ (call-interactively 'org-remark-mark)
+ (call-interactively 'org-remark-open)))
+
+(provide 'my-org-remark)
+;;; my-org-remark.el ends here
diff --git a/emacs/.emacs.d/lisp/my/my-org.el b/emacs/.emacs.d/lisp/my/my-org.el
index e99352d..5d7203f 100644
--- a/emacs/.emacs.d/lisp/my/my-org.el
+++ b/emacs/.emacs.d/lisp/my/my-org.el
@@ -1062,6 +1062,11 @@ On success, also move everything from staging to to-dir."
(org-protocol-grok
(list :url (plist-get eww-data :url))))
+(defun my-org-protocol-browse-url (data)
+ (when-let ((url (plist-get data :url)))
+ (browse-url url))
+ nil)
+
;; org capture rss
(defun my-org-rss-xml-create-audio-node (url)
(interactive (list (read-string "Feed URL: "
diff --git a/emacs/.emacs.d/lisp/my/my-prog.el b/emacs/.emacs.d/lisp/my/my-prog.el
index 396d919..a81d36d 100644
--- a/emacs/.emacs.d/lisp/my/my-prog.el
+++ b/emacs/.emacs.d/lisp/my/my-prog.el
@@ -419,7 +419,7 @@ overlay arrow in source buffer."
;; (gdb-input (concat "complete " context command)
;; (lambda () (setq gud-gdb-fetch-lines-in-progress nil)))
;; (while gud-gdb-fetch-lines-in-progress
-;; (accept-process-output (get-buffer-process gud-comint-buffer) 1)))
+;; (accept-process-output (get-buffer-process gud-comint-buffer) .1)))
;; (gud-gdb-completions-1 gud-gdb-fetched-lines)))
;;; which-func
diff --git a/emacs/.emacs.d/lisp/my/my-web.el b/emacs/.emacs.d/lisp/my/my-web.el
index f33f30c..f2e48ba 100644
--- a/emacs/.emacs.d/lisp/my/my-web.el
+++ b/emacs/.emacs.d/lisp/my/my-web.el
@@ -86,19 +86,6 @@
(start-process (concat "mullvad-browser " url) nil "mullvad-browser"
url))
-;; TODO: change to using hmm matching url with default app
-;; override browse-url
-(defun my-browse-url (url &optional arg)
- (interactive "P")
- (cond ((equal arg '(4))
- (funcall browse-url-secondary-browser-function url))
- ((equal arg '(16))
- (my-browse-url-tor-browser url))
- (t (luwak-open url))))
-
-;; this fixes clicking url buttons like those in gnus messages
-(defalias 'browse-url-button-open-url 'my-browse-url)
-
(defun my-browse-url-at-point (arg)
(interactive "P")
(my-browse-url (browse-url-url-at-point) arg))
diff --git a/emacs/.emacs.d/lisp/my/my-ytdl.el b/emacs/.emacs.d/lisp/my/my-ytdl.el
index 9118493..d3998ee 100644
--- a/emacs/.emacs.d/lisp/my/my-ytdl.el
+++ b/emacs/.emacs.d/lisp/my/my-ytdl.el
@@ -76,6 +76,18 @@
(if (eq type 'video) my-ytdl-video-args my-ytdl-audio-args)
(split-string urls)))))
+(defun my-ytdl-video-info (url)
+ "Given a video URL, return an alist of its properties."
+ (with-temp-buffer
+ (call-process my-ytdl-program nil t nil "-j" url)
+ (let ((start (point)))
+ (call-process-region
+ nil nil "jq" nil t nil
+ "pick(.webpage_url, .fulltitle, .description, .channel_url, .channel, .channel_follower_count, .thumbnail, .duration_string, .view_count, .upload_date, .like_count, .is_live, .was_live, .categories, .tags, .chapters, .availability)")
+ (goto-char start)
+ (json-read)))
+ )
+
;;; fixme: autoload
(defun my-ytdl-video (urls)
"Download videos with ytdl."
diff --git a/emacs/.emacs.d/lisp/nov.el b/emacs/.emacs.d/lisp/nov.el
-Subproject bbb5c60bfd6b09cffe0406a56930105335f0788
+Subproject c0d30da504fb0b68d8c28ff61a5e0095acda7f5
diff --git a/emacs/.emacs.d/lisp/wiki.el b/emacs/.emacs.d/lisp/wiki.el
-Subproject 7c90e1c35abb0a8eb25bcb5f3b5d8676dc13fc5
+Subproject 3bb836e703480e23b3eee8fdb369dacb294dc46