;;; wiki-markup.el -- A wikitext mode -*- lexical-binding: t -*- ;; Copyright (C) 2023 Free Software Foundation. ;; Author: Yuchen Pei ;; Package-Requires: ((emacs "28.2")) ;; This file is part of wiki-markup.el. ;; wiki-markup.el 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. ;; wiki-markup.el 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 wiki-markup.el. If not, see . ;;; Commentary: ;; A wikitext mode for wiki-markup ;;; Code: (require 'wiki-faces) (defvar wiki-url-regexp "https?://[^ ]+") (defvar wiki-external-link-re (rx (seq "[[" (group (seq "http" (opt "s") "://" (+ (not " ")))) (opt (seq " " (group (+? anything)))) "]]"))) (defvar wiki-internal-link-re (rx (seq "[[" ;; Target (group (one-or-more (not (any "[|]")))) ;; Label (optional) (opt (seq "|" (group (+? anything)))) "]]")) ) (defvar wiki-font-lock-keywords (list (cons "^======.*======\\ *$" 'wiki-level-6) (cons "^=====.*=====\\ *$" 'wiki-level-5) (cons "^====.*====\\ *$" 'wiki-level-4) (cons "^===.*===\\ *$" 'wiki-level-3) (cons "^==.*==\\ *$" 'wiki-level-2) (cons "^=.*=\\ *$" 'wiki-level-1) (cons "^----+\\ *$" 'wiki-hr-face) (cons "'''''[^ \t\n].*?[^ \t\n]'''''" 'wiki-bold-italic) (cons "'''[^ \t\n'].*?[^ \t\n']'''" 'wiki-bold) (cons "''[^ \t\n'].*?[^ \t\n']''" 'wiki-italic) (cons "^ .*$" 'wiki-pre-face) '(wiki-activate-external-links) '(wiki-activate-internal-links) )) (defvar wiki-outline-regexp "=+.*=+\ *$") (defun wiki-outline-level () (when (looking-at "\\(=+\\).*\\(=+\\)\ *$") (min (length (match-string 1)) (length (match-string 2)) 6))) ;; Like `org-activate-links' (defun wiki-activate-links (link-re limit) (save-excursion (goto-char (point-min)) (while (re-search-forward link-re limit t) (let ((start (match-beginning 0)) (end (match-end 0)) (visible-start (or (match-beginning 2) (match-beginning 1))) (visible-end (or (match-end 2) (match-end 1))) ) (put-text-property start visible-start 'invisible t) (put-text-property start end 'font-lock-face 'wiki-link) (put-text-property visible-end end 'invisible t) (add-text-properties (1- visible-start) visible-start '(rear-nonsticky (invisible))) (add-text-properties (1- visible-end) visible-end '(rear-nonsticky (invisible))) )))) (defun wiki-activate-internal-links (limit) (wiki-activate-links wiki-internal-link-re limit)) (defun wiki-activate-external-links (limit) (wiki-activate-links wiki-external-link-re limit)) (define-derived-mode wiki-mode outline-mode "Wiki" "A wikitext mode." (setq-local comment-start "") ;; FIXME: this should not be necessary in outline mode (setq-local font-lock-defaults '(wiki-font-lock-keywords t nil nil (font-lock-extra-managed-props invisible font-lock-face))) (setq-local outline-regexp wiki-outline-regexp) (setq-local outline-level 'wiki-outline-level) ) (provide 'wiki-markup) ;;; wiki-markup.el ends here