diff options
author | Yuchen Pei <id@ypei.org> | 2025-01-04 11:51:05 +1100 |
---|---|---|
committer | Yuchen Pei <id@ypei.org> | 2025-01-04 11:51:05 +1100 |
commit | 4bfc032aa411552271100301b341b764b5967ce1 (patch) | |
tree | 6fef124b8109540d0be45f1ae8026ff8a61435f1 | |
parent | 70609bd73a36d6c590a08fa8d09b2d38959d3feb (diff) |
Add navigation to sections and dir-local variables support
sections: foo#bar will navigate to section bar of entry foo
dir-local variable support: currently applicable to outline headings
only.
-rw-r--r-- | wiki-engine.el | 32 | ||||
-rw-r--r-- | wiki-markup.el | 35 |
2 files changed, 44 insertions, 23 deletions
diff --git a/wiki-engine.el b/wiki-engine.el index 5cd666b..c10de6e 100644 --- a/wiki-engine.el +++ b/wiki-engine.el @@ -155,23 +155,26 @@ If the site has a `local' engine, \"fetch\" locally. Otherwise, if `wiki-fetch-prefer-local' is non-nil, try fetching locally, and if the title cannot be found locally, fetch remotely." (when (string-empty-p title) (setq title "Main Page")) - (let* ((engine (wiki-engine-compute-engine (alist-get site-id wiki-sites))) - (found-local - (when (or wiki-fetch-prefer-local (eq engine 'local)) - (wiki-find-file title (wiki-locate-dir site-id) - (eq engine 'local)))) - (post-proc (plist-get (alist-get site-id wiki-sites) :fetch-post-proc))) + (pcase-let* + ((engine (wiki-engine-compute-engine (alist-get site-id wiki-sites))) + (found-local + (when (or wiki-fetch-prefer-local (eq engine 'local)) + (wiki-find-file title (wiki-locate-dir site-id) + (eq engine 'local)))) + (post-proc (plist-get (alist-get site-id wiki-sites) :fetch-post-proc)) + (`(,entry ,section) (split-string title "#"))) (if found-local (switch-to-buffer found-local) (wiki-fetch-url - (wiki-engine-wiki-url site-id title) - title + (wiki-engine-wiki-url site-id entry) + entry (wiki-locate-dir site-id) (lambda () (wiki-mode) (setq-local wiki-site site-id wiki-title title) - (when post-proc (funcall post-proc))))))) + (when post-proc (funcall post-proc)) + (when section (wiki-goto-heading section))))))) (defun wiki-engine-mediawiki-api-wiki (api-base-url title) "Fetch the wikitext of TITLE using json api. @@ -224,18 +227,21 @@ API-BASE-URL is the base url for the api request." "Find local TITLE in DIR. Do not switch to buffer. Return the buffer if success, and nil otherwise. If -CREATE-IF-NOT-EXISTS is non-nil, creates the file is not found. +CREATE-IF-NOT-EXISTS is non-nil, creates the file if not found. DIR defaults to `default-directory'." (interactive (list (read-file-name "Find wiki file: "))) (unless dir (setq dir default-directory)) - (let ((file-name (expand-file-name - (concat title wiki-extension) - dir))) + (pcase-let* + ((`(,entry ,section) (split-string title "#")) + (file-name (expand-file-name + (concat entry wiki-extension) + dir))) (when (or (file-exists-p file-name) create-if-not-exists) (setq dir (file-name-directory file-name)) (unless (file-exists-p dir) (make-directory dir t)) (with-current-buffer (find-file-noselect file-name) (wiki-mode) + (when section (wiki-goto-heading section)) (buffer-name))))) (defmacro wiki-define-site-commands () diff --git a/wiki-markup.el b/wiki-markup.el index 61cdca8..4b6bc3e 100644 --- a/wiki-markup.el +++ b/wiki-markup.el @@ -71,7 +71,10 @@ (wiki-activate-raw-links) )) -(defvar wiki-outline-re "=+.*=+\ *$") +(defvar-local wiki-outline-re "=+.+=+\\ *$" + "Regexp to match outline headings.") +(defvar-local wiki-outline-format-re "=+\\ *%s\\ *=+\\ *$" + "Regexp format string to match a specific outline heading.") (defvar-local wiki-site nil "The identifier of the site of the current wiki buffer.") @@ -81,7 +84,19 @@ "Button action to follow a wikilink. The button data is passed as DATA." - (funcall (wiki-site-fetcher wiki-site) (alist-get 'target data))) + (let ((target (alist-get 'target data))) + (if (string-prefix-p "#" target) + (wiki-goto-heading (string-remove-prefix "#" target)) + (funcall (wiki-site-fetcher wiki-site) (alist-get 'target data))))) + +(defun wiki-goto-heading (heading) + (let ((point (point))) + (goto-char (point-min)) + (if (re-search-forward + (format wiki-outline-format-re (regexp-quote heading)) nil t) + (beginning-of-line 1) + (goto-char point) + (error "Cannot find heading: %s" heading)))) (defun wiki-guess-site () "Guess `wiki-site' from the default directory. @@ -288,21 +303,21 @@ LIMIT is the limit of the search, used for `font-lock-keywords'." (font-lock-extra-managed-props invisible font-lock-face button-data action category button htmlize-link help-echo display))) + (wiki-update-local-settings) + ) + +(defun wiki-update-local-settings () (setq-local outline-regexp wiki-outline-re) (setq-local outline-level 'wiki-outline-level) ;; We have to do this again because `outline-mode' used the default ;; `outline-regexp'. (setq-local imenu-generic-expression (list (list nil (concat "^\\(?:" outline-regexp "\\).*$") 0)) - imenu-space-replacement nil) - ) + imenu-space-replacement nil)) -(defun set-wiki-site (site) - "Set `wiki-site' to SITE." - (interactive (list - (completing-read "Set wiki site: " - (mapcar 'car wiki-sites)))) - (setq-local wiki-site (intern site))) +(add-hook 'hack-local-variables-hook + (lambda () (when (derived-mode-p 'wiki-mode) + (wiki-update-local-settings)))) (add-hook 'wiki-mode-hook 'wiki-guess-site) (add-hook 'wiki-mode-hook 'wiki-guess-title) |