├── targets
├── deps
├── melpa-init.el
├── checkdoc.el
├── test.el
├── lint.el
├── local.el
├── utils.el
└── melpa.el
├── .gitignore
├── Eask
├── README.md
├── tests
├── input
│ ├── markdown-with-yaml.md
│ └── markdown.md
└── poly-markdown-tests.el
├── .github
└── workflows
│ └── test.yml
├── Makefile
└── poly-markdown.el
/targets/deps:
--------------------------------------------------------------------------------
1 | (yaml-mode)
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | *#
3 | #*
4 | auto/
5 | *\[weaved\]*
6 | tmp/
7 | *woven*
8 | *exported*
9 | .tmd
10 | tmp*
11 | .ELPA
12 | .MELPA
13 | site/
14 | *autoloads.el
15 | *.elc
16 | *.html
17 | *.pdf
18 |
19 | # Packaging
20 | .eask/
21 | dist/
22 |
--------------------------------------------------------------------------------
/targets/melpa-init.el:
--------------------------------------------------------------------------------
1 |
2 | (require 'package)
3 |
4 | (setq package-user-dir (expand-file-name (format ".ELPA/%s" emacs-version))
5 | package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
6 | ("melpa" . "https://melpa.org/packages/")))
7 |
8 | (package-initialize)
9 |
--------------------------------------------------------------------------------
/targets/checkdoc.el:
--------------------------------------------------------------------------------
1 |
2 | (let ((sentence-end-double-space)
3 | (checkdoc-arguments-in-order-flag)
4 | (checkdoc-verb-check-experimental-flag)
5 | (checkdoc-force-docstrings-flag))
6 | (let ((files (directory-files default-directory nil "^[^.].*el$")))
7 | (dolist (f files)
8 | (unless (member f '("poly-markdown-autoloads.el"))
9 | (checkdoc-file f)))))
10 |
--------------------------------------------------------------------------------
/targets/test.el:
--------------------------------------------------------------------------------
1 | (setq polymode-test-dir (expand-file-name "tests/"))
2 | (add-to-list 'load-path polymode-test-dir)
3 | (dolist (f (directory-files polymode-test-dir t ".*el$"))
4 | (load f))
5 |
6 | (setq pm-verbose (getenv "PM_VERBOSE")
7 | ert-batch-backtrace-right-margin 200
8 | ert-batch-print-level nil
9 | ert-batch-print-length nil)
10 |
11 | ;; (toggle-debug-on-error)
12 | (ert-run-tests-batch-and-exit t)
13 |
--------------------------------------------------------------------------------
/targets/lint.el:
--------------------------------------------------------------------------------
1 |
2 | (require 'checkdoc)
3 | (require 'elisp-lint)
4 |
5 | (let ((sentence-end-double-space)
6 | (checkdoc-arguments-in-order-flag)
7 | (checkdoc-verb-check-experimental-flag)
8 | (checkdoc-force-docstrings-flag)
9 | (elisp-lint-indent-specs
10 | '((pm-test-run-on-file . 2)
11 | (pm-test-run-on-string . 1)
12 | (pm-test-poly-lock . 2)))
13 | (elisp-lint-ignored-validators '("package-format" "indent-character" "fill-column")))
14 |
15 | (elisp-lint-files-batch))
16 |
--------------------------------------------------------------------------------
/Eask:
--------------------------------------------------------------------------------
1 | ;; -*- mode: eask; lexical-binding: t -*-
2 |
3 | (package "poly-markdown"
4 | "0.2.2"
5 | "Polymode for markdown-mode")
6 |
7 | (website-url "https://github.com/polymode/poly-markdown")
8 | (keywords "emacs")
9 |
10 | (package-file "poly-markdown.el")
11 |
12 | (script "test" "echo \"Error: no test specified\" && exit 1")
13 |
14 | (source 'gnu)
15 | (source 'melpa)
16 |
17 | (depends-on "emacs" "25")
18 | (depends-on "polymode")
19 | (depends-on "markdown-mode")
20 |
21 | (development
22 | (depends-on "yaml-mode"))
23 |
--------------------------------------------------------------------------------
/targets/local.el:
--------------------------------------------------------------------------------
1 | (load-file "targets/utils.el")
2 |
3 | ;; add .ELPA packages
4 | (let ((elpa-dirs (directory-files (expand-file-name (format ".ELPA/%s" emacs-version)) t)))
5 | (setq load-path (append elpa-dirs load-path)))
6 |
7 | ;; add all poly* and deps in the parent directory and overate any in the .ELPA
8 | (let* ((deps (cons 'poly (polymode-library-deps "poly-markdown.el")))
9 | (regx (format "^\\(%s\\)" (mapconcat #'symbol-name deps "\\|")))
10 | (local-dirs (directory-files (file-name-directory (directory-file-name default-directory))
11 | t regx)))
12 | (setq load-path (append local-dirs load-path)))
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Polymode for [markdown-mode](https://github.com/jrblevin/markdown-mode).
10 |
--------------------------------------------------------------------------------
/targets/utils.el:
--------------------------------------------------------------------------------
1 |
2 | (defun polymode-library-deps (lib-file)
3 | (let ((dev-deps '(elisp-lint))
4 | (deps (let ((file (expand-file-name "targets/deps")))
5 | (when (file-exists-p file)
6 | (with-temp-buffer
7 | (insert-file-contents file)
8 | (read (buffer-string))))))
9 | (deps-requires (with-temp-buffer
10 | (insert-file-contents lib-file)
11 | (goto-char (point-min))
12 | (when (re-search-forward "Package-Requires:" nil t)
13 | (car (read-from-string (buffer-substring (point) (point-at-eol))))))))
14 | (delq 'emacs (delete-dups (append deps (mapcar #'car deps-requires))))))
15 |
--------------------------------------------------------------------------------
/tests/input/markdown-with-yaml.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | date: 2015-08-13 11:35:25 EST
4 | ---
5 |
6 | Polymode Markdown Test Cases
7 | ============================
8 |
9 | ## Intro
10 |
11 | Fragments taken from `markdown-mode/tests/test-cases.text` and interspersed with
12 | various code blocks.
13 |
14 | 1. Lists
15 | --------
16 |
17 | Unordered lists:
18 |
19 | - This is a `el (defvar bullet-point "bullet-point")`.
20 | - This is a `ada "Sub bullet point"`.
21 | - This is `python ["*" + x + "*" for x in ["another", "bullet", "point"]]`
22 |
23 | ```fortran
24 | * euclid.f (FORTRAN 77)
25 | * Find greatest common divisor using the Euclidean algorithm
26 | PROGRAM EUCLID
27 | PRINT *, 'A?'
28 | READ *, NA
29 | IF (NA.LE.0) THEN
30 | PRINT *, 'A must be a positive integer.'
31 | STOP
32 | END IF
33 | PRINT *, 'B?'
34 | READ *, NB
35 | IF (NB.LE.0) THEN
36 | PRINT *, 'B must be a positive integer.'
37 | STOP
38 | END IF
39 | PRINT *, 'The GCD of', NA, ' and', NB, ' is', NGCD(NA, NB), '.'
40 | STOP
41 | END
42 | ```
43 |
--------------------------------------------------------------------------------
/targets/melpa.el:
--------------------------------------------------------------------------------
1 |
2 | (load-file "targets/utils.el")
3 | (require 'package)
4 |
5 | (setq package-deps (polymode-library-deps "poly-markdown.el")
6 | package-user-dir (expand-file-name (format ".ELPA/%s" emacs-version))
7 | package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
8 | ("melpa" . "https://melpa.org/packages/")))
9 |
10 | (defun package-desc-new (name)
11 | (cadr (assq name package-archive-contents)))
12 |
13 | (defun package-outdated-p (name)
14 | (let ((old-version (package-desc-version (cadr (assq name package-alist))))
15 | (new-version (package-desc-version (cadr (assq name package-archive-contents)))))
16 | (and (listp old-version) (listp new-version)
17 | (version-list-< old-version new-version))))
18 |
19 | (package-initialize)
20 | (package-refresh-contents)
21 |
22 | (dolist (package (append dev-deps package-deps))
23 | (if (package-installed-p package)
24 | (when (package-outdated-p package)
25 | (package-install-from-archive (cadr (assq package package-archive-contents))))
26 | (package-install package)))
27 |
28 | (message "INSTALLED DEPS: %s"
29 | (mapconcat
30 | (lambda (pkg)
31 | (format "%s:%S" pkg
32 | (package-desc-version (cadr (assq pkg package-archive-contents)))))
33 | package-deps
34 | " "))
35 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | workflow_dispatch:
9 |
10 | concurrency:
11 | group: ${{ github.workflow }}-${{ github.ref }}
12 | cancel-in-progress: true
13 |
14 | jobs:
15 | test:
16 | runs-on: ${{ matrix.os }}
17 | continue-on-error: ${{ matrix.experimental }}
18 | strategy:
19 | fail-fast: false
20 | matrix:
21 | os: [ubuntu-latest, macos-latest, windows-latest]
22 | emacs-version:
23 | #- 26.3
24 | #- 27.2
25 | #- 28.2
26 | #- 29.4
27 | - 30.1
28 | experimental: [false]
29 | include:
30 | - os: ubuntu-latest
31 | emacs-version: snapshot
32 | experimental: true
33 | - os: macos-latest
34 | emacs-version: snapshot
35 | experimental: true
36 | - os: windows-latest
37 | emacs-version: snapshot
38 | experimental: true
39 |
40 | steps:
41 | - uses: actions/checkout@v4
42 |
43 | - uses: jcs090218/setup-emacs@master
44 | with:
45 | version: ${{ matrix.emacs-version }}
46 |
47 | - uses: emacs-eask/setup-eask@master
48 | with:
49 | version: 'snapshot'
50 |
51 | - name: Build
52 | run: |
53 | eask package
54 | eask install
55 | eask compile
56 |
57 | - name: Run tests
58 | run: |
59 | eask install-deps --dev
60 | eask test ert ./tests/*.el
61 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | MODULE = poly-markdown
2 | export EMACS ?= emacs
3 | EMACS_VERSION = $(shell ${EMACS} -Q --batch --eval "(princ emacs-version)")
4 | ELPA_DIR := .ELPA/$(EMACS_VERSION)
5 | EMACSRUN = $(EMACS) -Q --debug-init -L . -L modes -L tests -L $(ELPA_DIR)
6 | EMACSBATCH = $(EMACSRUN) --batch
7 |
8 | ELS = $(wildcard *.el)
9 | OBJECTS = $(ELS:.el=.elc)
10 | LINTELS = $(filter-out poly-markdown-autoloads.el, $(ELS))
11 |
12 | # export PM_VERBOSE
13 |
14 | .PHONY: all build checkdoc lint clean cleanall melpa elpa start test version
15 |
16 | all: build checkdoc test
17 |
18 | build: version clean
19 | @echo "******************* BUILDING $(MODULE) *************************"
20 | $(EMACSBATCH) --load targets/melpa-init.el --funcall batch-byte-compile *.el
21 |
22 | checkdoc: version
23 | @echo "******************* CHECKDOC $(MODULE) *************************"
24 | $(EMACSBATCH) --load targets/checkdoc.el
25 |
26 | lint: version
27 | @$(EMACSBATCH) --load targets/melpa-init.el --load targets/lint.el $(LINTELS)
28 |
29 | clean:
30 | rm -f $(OBJECTS)
31 |
32 | cleanall: clean
33 | rm -rf $(ELPA_DIR) *autoloads.el
34 |
35 | melpa: version
36 | $(EMACSBATCH) --load targets/melpa.el
37 |
38 | elpa: melpa
39 |
40 | start: version melpa
41 | $(EMACSRUN) -L . --load targets/melpa-init.el --load tests/*.el
42 |
43 | startvs: version
44 | $(EMACSRUN) -L . --load targets/local.el \
45 | --load tests/*.el --load ~/.eBasic.el
46 |
47 | test: build version
48 | @echo "******************* Testing $(MODULE) ***************************"
49 | $(EMACSBATCH) --load targets/melpa-init.el --load targets/test.el
50 |
51 | test-local: version
52 | @echo "******************* Testing $(MODULE) ***************************"
53 | $(EMACSBATCH) --load targets/local.el --load targets/test.el
54 |
55 | version:
56 | @echo "EMACS VERSION: $(EMACS_VERSION)"
57 | @echo "GIT HEAD: $(shell git rev-parse --short HEAD)"
58 |
59 |
--------------------------------------------------------------------------------
/tests/input/markdown.md:
--------------------------------------------------------------------------------
1 |
2 | Polymode Markdown Test Cases
3 | ============================
4 |
5 | ## Intro
6 |
7 | Fragments taken from `markdown-mode/tests/test-cases.text` and interspersed with
8 | various code blocks.
9 |
10 | 1. Lists
11 | --------
12 |
13 | Unordered lists:
14 |
15 | - This is a `el (defvar bullet-point "bullet-point")`.
16 | - This is a `ada "Sub bullet point"`.
17 | - This is `python ["*" + x + "*" for x in ["another", "bullet", "point"]]`
18 |
19 | ```fortran
20 | * euclid.f (FORTRAN 77)
21 | * Find greatest common divisor using the Euclidean algorithm
22 | PROGRAM EUCLID
23 | PRINT *, 'A?'
24 | READ *, NA
25 | IF (NA.LE.0) THEN
26 | PRINT *, 'A must be a positive integer.'
27 | STOP
28 | END IF
29 | PRINT *, 'B?'
30 | READ *, NB
31 | IF (NB.LE.0) THEN
32 | PRINT *, 'B must be a positive integer.'
33 | STOP
34 | END IF
35 | PRINT *, 'The GCD of', NA, ' and', NB, ' is', NGCD(NA, NB), '.'
36 | STOP
37 | END
38 | ```
39 |
40 | Ordered lists
41 |
42 | 1. This is an ordered list
43 | 2. With a second element.
44 | 44. And a forty-fourth element.
45 | 3. Remember, Markdown doesn't care which number you use.
46 |
47 | ```perl
48 | # Scan a file and print all the URL's it links to.
49 | sub scan {
50 | my ($fn) = @_;
51 |
52 | open(IN, $fn) or return 0;
53 |
54 | # Go through each line in the file.
55 | while() {
56 | # Repeatedly match URLs in the line. Each one is removed by
57 | # replacing it with the empty string. The loop body will execute
58 | # once for each match/replace, and prints the URL part of the
59 | # matched text.
60 | while(s/<\s*A\s+[^>]*HREF\s*\=\s*"([^"]+)"//i) {
61 | print " $1\n";
62 | }
63 | }
64 |
65 | close IN;
66 | return 1;
67 | }
68 | ```
69 | List items with bold and italic
70 |
71 | > * This is a list item *in italics*, just a test.
72 | > * *List item in italics.*
73 | > * This is a list item **in bold**, just a test.
74 | > * **List item in bold.**
75 |
76 | Bold and italic phrases at the beginning of lines:
77 |
78 | ```el
79 | (defmacro thread-last (&rest forms)
80 | "Thread FORMS elements as the last argument of their successor.
81 | Example:
82 | (thread-last
83 | 5
84 | (+ 20)
85 | (/ 25)
86 | -
87 | (+ 40))
88 | Is equivalent to:
89 | (+ 40 (- (/ 25 (+ 20 5))))
90 | Note how the single `-' got converted into a list before
91 | threading."
92 | (declare (indent 1) (debug thread-first))
93 | `(internal--thread-argument nil ,@forms))
94 | ```
95 |
96 | *not a list*
97 | **also not a list**
98 |
99 |
100 | 2. Blockquotes
101 | --------------
102 |
103 | > this is a test
104 | > of the blockquote mechanism
105 |
106 | ```pascal
107 |
108 | type
109 | pNode = ^Node;
110 | Node = record
111 | a :integer;
112 | b : char;
113 | c : pNode {extra semicolon not strictly required}
114 | end;
115 | var
116 | NodePtr : pNode;
117 | IntPtr : ^integer;
118 |
119 | ```
120 |
121 |
122 | 3. Two Inline Links on One Line
123 | -------------------------------
124 |
125 | I did notice a minor bug. if there are two inline links in the same line, e.g.
126 | [foo](bar) baz [foo](bar), it colors the text between the links (baz) as well.
127 |
128 |
129 | 4. Empty Inline Links
130 | ---------------------
131 |
132 | []()
133 | [](asdf)
134 | [asdf]()
135 |
136 | ```python
137 | def insertion_sort_bin(seq):
138 | for i in range(1, len(seq)):
139 | key = seq[i]
140 | # invariant: ``seq[:i]`` is sorted
141 | # find the least `low' such that ``seq[low]`` is not less then `key'.
142 | # Binary search in sorted sequence ``seq[low:up]``:
143 | low, up = 0, i
144 | while up > low:
145 | middle = (low + up) // 2
146 | if seq[middle] < key:
147 | low = middle + 1
148 | else:
149 | up = middle
150 | # insert key at position ``low`` // no-indent-test
151 | seq[:] = seq[:low] + [key] + seq[low:i] + seq[i + 1:]
152 | ```
153 |
154 | ## 5. Bold and Italics on the Same Line
155 |
156 | **foo and doo** or *ziddle zop*
157 |
158 | ```el
159 |
160 | (defun delete-dups (list)
161 | "Destructively remove `equal' duplicates from LIST.
162 | Store the result in LIST and return it. LIST must be a proper list.
163 | Of several `equal' occurrences of an element in LIST, the first
164 | one is kept."
165 | (let ((l (length list)))
166 | (if (> l 100)
167 | (let ((hash (make-hash-table :test #'equal :size l))
168 | (tail list) retail)
169 | (puthash (car list) t hash)
170 | (while (setq retail (cdr tail))
171 | (let ((elt (car retail)))
172 | (if (gethash elt hash)
173 | (setcdr tail (cdr retail))
174 | (puthash elt t hash)
175 | (setq tail retail)))))
176 | (let ((tail list))
177 | (while tail
178 | (setcdr tail (delete (car tail) (cdr tail)))
179 | (setq tail (cdr tail))))))
180 | list)
181 |
182 | ```
183 |
184 | Indentation of modes with simple `indent-line-function` like `indent-relative`
185 |
186 | ```sql
187 | SELECT * FROM table;
188 | SELECT * FROM table;
189 | SELECT * FROM table;
190 | ```
191 |
192 | The end.
193 |
--------------------------------------------------------------------------------
/poly-markdown.el:
--------------------------------------------------------------------------------
1 | ;;; poly-markdown.el --- Polymode for markdown-mode -*- lexical-binding: t -*-
2 | ;;
3 | ;; Author: Vitalie Spinu
4 | ;; Maintainer: Vitalie Spinu
5 | ;; Copyright (C) 2018
6 | ;; Version: 0.2.2
7 | ;; Package-Requires: ((emacs "25") (polymode "0.2.2") (markdown-mode "2.3"))
8 | ;; URL: https://github.com/polymode/poly-markdown
9 | ;; Keywords: emacs
10 | ;;
11 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12 | ;;
13 | ;; This file is *NOT* part of GNU Emacs.
14 | ;;
15 | ;; This program is free software; you can redistribute it and/or
16 | ;; modify it under the terms of the GNU General Public License as
17 | ;; published by the Free Software Foundation; either version 3, or
18 | ;; (at your option) any later version.
19 | ;;
20 | ;; This program is distributed in the hope that it will be useful,
21 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 | ;; General Public License for more details.
24 | ;;
25 | ;; You should have received a copy of the GNU General Public License
26 | ;; along with this program; see the file COPYING. If not, write to
27 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
28 | ;; Floor, Boston, MA 02110-1301, USA.
29 | ;;
30 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31 | ;;
32 | ;;; Commentary:
33 | ;;
34 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35 | ;;
36 | ;;; Code:
37 |
38 | (require 'polymode)
39 | (require 'poly-lock)
40 | (require 'markdown-mode)
41 |
42 | ;; Declarations
43 | (defvar markdown-enable-math)
44 |
45 | (define-obsolete-variable-alias 'pm-host/markdown 'poly-markdown-hostmode "v0.2")
46 | (define-obsolete-variable-alias 'pm-inner/markdown-yaml-metadata 'poly-markdown-yaml-metadata-innermode "v0.2")
47 | (define-obsolete-variable-alias 'pm-inner/markdown-fenced-code 'poly-markdown-fenced-code-innermode "v0.2")
48 | (define-obsolete-variable-alias 'pm-inner/markdown-inline-code 'poly-markdown-inline-code-innermode "v0.2")
49 | (define-obsolete-variable-alias 'pm-inner/markdown-displayed-math 'poly-markdown-displayed-math-innermode "v0.2")
50 | (define-obsolete-variable-alias 'pm-inner/markdown-inline-math 'poly-markdown-inline-math-innermode "v0.2")
51 | (define-obsolete-variable-alias 'pm-poly/markdown 'poly-markdown-polymode "v0.2")
52 |
53 | (defgroup poly-markdown nil
54 | "Settings for ‘poly-markdown’."
55 | :group 'polymode)
56 |
57 | (defcustom poly-markdown-enable-latex-math t
58 | "When non-nil, enable LaTeX-related innermodes in poly-markdown:
59 | - inline/display math regions ($...$, $$...$$, \\(...\\), \\[...\\])
60 | - fenced code blocks with language \"latex\" or \"tex\"."
61 | :type 'boolean
62 | :group 'poly-markdown)
63 |
64 | (define-hostmode poly-markdown-hostmode
65 | :mode 'markdown-mode
66 | :init-functions '(poly-markdown-remove-markdown-hooks))
67 |
68 | (define-innermode poly-markdown-root-innermode
69 | :mode nil
70 | :fallback-mode 'host
71 | :head-mode 'host
72 | :tail-mode 'host)
73 |
74 | (define-innermode poly-markdown-yaml-metadata-innermode poly-markdown-root-innermode
75 | :mode 'yaml-mode
76 | :head-matcher (pm-make-text-property-matcher 'markdown-yaml-metadata-begin :inc-end)
77 | :tail-matcher (pm-make-text-property-matcher 'markdown-yaml-metadata-end))
78 |
79 | ;; allow extra . before language name https://github.com/polymode/polymode/issues/296
80 | ;; allow extra = before language name https://github.com/polymode/poly-markdown/issues/22
81 | (define-auto-innermode poly-markdown-fenced-code-innermode poly-markdown-root-innermode
82 | :head-matcher (cons "^[ \t]*\\(```[ \t]*{?[[:alpha:].=].*\n\\)" 1)
83 | :tail-matcher (cons "^[ \t]*\\(```\\)[ \t]*$" 1)
84 | :mode-matcher (cons "```[ \t]*{?[.=]?\\(?:lang *= *\\)?\\([^ \t\n;=,}]+\\)" 1))
85 |
86 | ;; Intended to be inherited from by more specialized innermodes.
87 | ;; FIXME: Some font-lock issues on deletion.
88 | ;; TOTHINK: Can be added to the default configuration for the sake of the
89 | ;; default fallback, but it's problematic given that inline code blocks often
90 | ;; have arbitrary non-code or language specific content.
91 | (define-innermode poly-markdown-inline-code-innermode poly-markdown-root-innermode
92 | :head-matcher (cons "[^`]\\(`\\)[[:alpha:]+-&({*[]" 1)
93 | :tail-matcher (cons "[^`]\\(`\\)[^`]" 1)
94 | ;; :mode-matcher (cons "`[ \t]*{?\\(?:lang *= *\\)?\\([[:alpha:]+-]+\\)" 1)
95 | :allow-nested nil)
96 |
97 | (defun poly-markdown-displayed-math-head-matcher (count)
98 | (when markdown-enable-math
99 | (when (re-search-forward "\\\\\\[\\|^[ \t]*\\(\\$\\$\\)." nil t count)
100 | (if (match-beginning 1)
101 | (cons (match-beginning 1) (match-end 1))
102 | (cons (match-beginning 0) (match-end 0))))))
103 |
104 | (defun poly-markdown-displayed-math-tail-matcher (_count)
105 | (when markdown-enable-math
106 | (if (match-beginning 1)
107 | ;; head matched an $$..$$ block
108 | (when (re-search-forward "[^$]\\(\\$\\$\\)[^$[:alnum:]]" nil t)
109 | (cons (match-beginning 1) (match-end 1)))
110 | ;; head matched an \[..\] block
111 | (when (re-search-forward "\\\\\\]" nil t)
112 | (cons (match-beginning 0) (match-end 0))))))
113 |
114 | (define-innermode poly-markdown-displayed-math-innermode poly-markdown-root-innermode
115 | "Displayed math $$..$$ innermode.
116 | Tail must be flowed by a new line but head need not (a space or
117 | comment character would do)."
118 | :mode 'LaTeX-mode ; AucTeX mode by default
119 | :fallback-mode 'latex-mode
120 | :head-matcher #'poly-markdown-displayed-math-head-matcher
121 | :tail-matcher #'poly-markdown-displayed-math-tail-matcher
122 | :allow-nested nil)
123 |
124 | (defun poly-markdown-inline-math-head-matcher (count)
125 | (when markdown-enable-math
126 | (when (re-search-forward "\\\\(\\|[ \t\n]\\(\\$\\)[^ $\t[:digit:]]" nil t count)
127 | (if (match-beginning 1)
128 | (cons (match-beginning 1) (match-end 1))
129 | (cons (match-beginning 0) (match-end 0))))))
130 |
131 | (defun poly-markdown-inline-math-tail-matcher (_count)
132 | (when markdown-enable-math
133 | (if (match-beginning 1)
134 | ;; head matched an $..$ block
135 | (when (re-search-forward "[^ $\\\t]\\(\\$\\)[^$[:alnum:]]" nil t)
136 | (cons (match-beginning 1) (match-end 1)))
137 | ;; head matched an \(..\) block
138 | (when (re-search-forward "\\\\)" nil t)
139 | (cons (match-beginning 0) (match-end 0))))))
140 |
141 | (define-innermode poly-markdown-inline-math-innermode poly-markdown-root-innermode
142 | "Inline math $..$ block.
143 | First $ must be preceded by a white-space character and followed
144 | by a non-whitespace/digit character. The closing $ must be
145 | preceded by a non-whitespace and not followed by an alphanumeric
146 | character."
147 | :mode 'LaTeX-mode
148 | :fallback-mode 'latex-mode
149 | :head-matcher #'poly-markdown-inline-math-head-matcher
150 | :tail-matcher #'poly-markdown-inline-math-tail-matcher
151 | :allow-nested nil)
152 |
153 | ;;;###autoload (autoload 'poly-markdown-mode "poly-markdown")
154 | (define-polymode poly-markdown-mode
155 | :hostmode 'poly-markdown-hostmode
156 | :innermodes (append
157 | '(poly-markdown-fenced-code-innermode
158 | poly-markdown-yaml-metadata-innermode)
159 | (when poly-markdown-enable-latex-math
160 | '(poly-markdown-inline-math-innermode
161 | poly-markdown-displayed-math-innermode))))
162 |
163 | ;;;###autoload
164 | (add-to-list 'auto-mode-alist '("\\.md\\'" . poly-markdown-mode))
165 |
166 | ;;; FIXES:
167 | (defun poly-markdown-remove-markdown-hooks (_)
168 | ;; get rid of aggressive hooks (VS[02-09-2018]: probably no longer necessary)
169 | (remove-hook 'window-configuration-change-hook 'markdown-fontify-buffer-wiki-links t)
170 | (remove-hook 'after-change-functions 'markdown-check-change-for-wiki-link t))
171 |
172 | ;;; Polymode for GitHub Flavored Markdown
173 | (define-hostmode poly-gfm-hostmode poly-markdown-hostmode
174 | :mode 'gfm-mode)
175 |
176 | ;;;###autoload (autoload 'poly-gfm-mode "poly-markdown")
177 | (define-polymode poly-gfm-mode poly-markdown-mode
178 | :hostmode 'poly-gfm-hostmode)
179 |
180 | (provide 'poly-markdown)
181 |
--------------------------------------------------------------------------------
/tests/poly-markdown-tests.el:
--------------------------------------------------------------------------------
1 | (require 'markdown-mode)
2 | (require 'poly-markdown)
3 | (require 'polymode-test-utils)
4 | (require 'yaml-mode)
5 | ;; ada mode auto loading breaks without this
6 | (require 'speedbar)
7 |
8 | ;; fixme: add tests when after change spans wrongly temporally cover other spans
9 |
10 | (setq python-indent-offset 4
11 | python-indent-guess-indent-offset nil)
12 |
13 | (defun poly-markdown-tests-set-protected (protect)
14 | (let ((mode (if protect 'poly-head-tail-mode 'host)))
15 | (oset pm-host/markdown :protect-syntax protect)
16 | (oset pm-host/markdown :protect-font-lock protect)
17 | (oset pm-inner/markdown-inline-code :head-mode mode)
18 | (oset pm-inner/markdown-inline-code :tail-mode mode)
19 | (oset pm-inner/markdown-fenced-code :head-mode mode)
20 | (oset pm-inner/markdown-fenced-code :tail-mode mode)))
21 |
22 | (ert-deftest poly-markdown/spans-at-borders ()
23 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
24 | (pm-map-over-spans
25 | (lambda (span)
26 | (let* ((sbeg (nth 1 span))
27 | (send (nth 2 span))
28 | (range1 (pm-innermost-range sbeg))
29 | (range2 (pm-innermost-range send)))
30 | (should (eq sbeg (car range1)))
31 | (should (eq send (cdr range1)))
32 | (unless (eq send (point-max))
33 | (should (eq send (car range2)))))))))
34 |
35 | (ert-deftest poly-markdown/spans-at-narrowed-borders ()
36 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
37 | (pm-map-over-spans
38 | (lambda (span)
39 | (pm-with-narrowed-to-span span
40 | (let* ((range1 (pm-innermost-range (point-min)))
41 | (range2 (pm-innermost-range (point-max))))
42 | (should (eq (car range1) (point-min)))
43 | (should (eq (cdr range1) (point-max)))
44 | (should (eq (car range2) (point-min)))
45 | (should (eq (cdr range2) (point-max)))))))))
46 |
47 | (ert-deftest poly-markdown/narrowed-spans ()
48 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
49 | (narrow-to-region 60 200)
50 | (let ((span (pm-innermost-span (point-min))))
51 | (should (eq (car span) nil))
52 | (should (= (nth 1 span) 60))
53 | (should (= (nth 2 span) 200)))
54 | (widen)
55 | (narrow-to-region 60 500)
56 | (let ((span (pm-innermost-span (point-min))))
57 | (should (= (nth 1 span) 60))
58 | ;; 223 should be when inline-innermode is in
59 | ;; (should (= (nth 2 span) 223))
60 | (should (= (nth 2 span) 380)))))
61 |
62 | (ert-deftest poly-markdown/spans-at-point-max ()
63 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
64 | (goto-char (point-max))
65 | (pm-switch-to-buffer)
66 |
67 | (let ((span (pm-innermost-span (point-max))))
68 | (should (eq (car span) nil))
69 | (should (eq (nth 2 span) (point-max)))
70 | (delete-region (nth 1 span) (nth 2 span)))
71 |
72 | (let ((span (pm-innermost-span (point-max))))
73 | (should (eq (car span) 'tail))
74 | (should (eq (nth 2 span) (point-max)))
75 | (delete-region (nth 1 span) (nth 2 span)))
76 |
77 | (let ((span (pm-innermost-span (point-max))))
78 | (should (eq (car span) 'body))
79 | (should (eq (nth 2 span) (point-max)))
80 | (delete-region (nth 1 span) (nth 2 span)))
81 |
82 | (let ((span (pm-innermost-span (point-max))))
83 | (should (eq (car span) 'head))
84 | (should (eq (nth 2 span) (point-max)))
85 | (delete-region (nth 1 span) (nth 2 span)))
86 |
87 | (let ((span (pm-innermost-span (point-max))))
88 | (should (eq (car span) nil))
89 | (should (eq (nth 2 span) (point-max)))
90 | (delete-region (nth 1 span) (nth 2 span)))))
91 |
92 | ;; on emacs25 in batch mode these tests fail
93 | (when (or pm--emacs>26 (not noninteractive))
94 | (ert-deftest poly-markdown/headings ()
95 | (poly-markdown-tests-set-protected nil)
96 | (pm-test-poly-lock poly-markdown-mode "markdown.md"
97 | ((insert-1 ("^## Intro" beg))
98 | (insert " ")
99 | (pm-test-faces)
100 | (delete-backward-char 1))
101 | ((delete-2 "^2. Blockquotes")
102 | (pm-test-faces)
103 | (backward-kill-word 1))
104 | ((insert-new-line-3 ("^3. Two Inline" end))
105 | (insert "\n")
106 | (pm-test-faces)
107 | (delete-backward-char 1))))
108 | (ert-deftest poly-markdown/headings-protected ()
109 | (poly-markdown-tests-set-protected t)
110 | (pm-test-poly-lock poly-markdown-mode "markdown.md"
111 | ((insert-1 ("^## Intro" beg))
112 | (insert " ")
113 | (pm-test-faces)
114 | (delete-backward-char 1))
115 | ((delete-2 "^2. Blockquotes")
116 | (backward-kill-word 1))
117 | ((insert-new-line-3 ("^3. Two Inline" end))
118 | (insert "\n")
119 | (pm-test-faces)
120 | (delete-backward-char 1)))))
121 |
122 | (ert-deftest poly-markdown/fenced-code ()
123 | (poly-markdown-tests-set-protected nil)
124 | (pm-test-poly-lock poly-markdown-mode "markdown.md"
125 | ((delete-fence (38))
126 | ;; (switch-to-buffer (current-buffer))
127 | (delete-forward-char 1)
128 | ;; (polymode-syntax-propertize (point-min) (point-max))
129 | (pm-test-faces)
130 | (insert "`"))
131 | ((delete-fortran-print (23))
132 | (forward-word)
133 | (delete-backward-char 1))
134 | ((insert-perl-hello (51))
135 | (insert "\"hello!\"\n")
136 | (indent-for-tab-command))
137 | ((insert-lisp-arg "&rest forms")
138 | (backward-sexp 2)
139 | (insert "first-arg "))
140 | ((python-kill-line (145))
141 | (kill-line 3))
142 | ((elisp-kill-sexp ("(while (setq retail" beg))
143 | (kill-sexp))
144 | ((elisp-kill-defun ("(defun delete-dups" beg))
145 | (kill-sexp))))
146 |
147 | (ert-deftest poly-markdown/fenced-code-protected ()
148 | (poly-markdown-tests-set-protected t)
149 | (pm-test-poly-lock poly-markdown-mode "markdown.md"
150 | ((delete-fortran-print (23))
151 | (forward-word)
152 | (delete-backward-char 1))
153 | ((insert-ada-hello (51))
154 | (insert "\"hello!\"\n")
155 | (indent-for-tab-command))
156 | ((insert-lisp-arg "&rest forms")
157 | (backward-sexp 2)
158 | (insert "first-arg "))
159 | ((python-kill-line (130))
160 | (kill-line 3))
161 | ((elisp-kill-sexp ("(while (setq retail" beg))
162 | (kill-sexp))
163 | ((elisp-kill-defun ("(defun delete-dups" beg))
164 | (kill-sexp))))
165 |
166 | (ert-deftest poly-markdown/inline-math ()
167 | (ert-skip "FIXME: failing test")
168 | (let ((markdown-enable-math t))
169 | (pm-test-run-on-string 'poly-markdown-mode
170 | "Some text with $\\text{inner math}$, formulas $E=mc^2$
171 | $E=mc^2$, and more formulas $E=mc^2$;
172 | ```pascal
173 | Some none-sense (formula $E=mc^2$)
174 | ```"
175 | (switch-to-buffer (current-buffer))
176 | (goto-char 17)
177 | (pm-switch-to-buffer)
178 | (should (eq major-mode 'latex-mode))
179 | (goto-char 35)
180 | (pm-switch-to-buffer)
181 | (should (eq major-mode 'markdown-mode))
182 | (goto-char 47)
183 | (pm-switch-to-buffer)
184 | (should (eq major-mode 'latex-mode))
185 | (goto-char 54)
186 | (pm-switch-to-buffer)
187 | (should (eq major-mode 'markdown-mode))
188 | (goto-char 56)
189 | (pm-switch-to-buffer)
190 | (should (eq major-mode 'latex-mode))
191 | (goto-char 84)
192 | (pm-switch-to-buffer)
193 | (should (eq major-mode 'latex-mode))
194 | (goto-char 91)
195 | (pm-switch-to-buffer)
196 | (should (eq major-mode 'markdown-mode))
197 | (goto-char 127)
198 | (pm-switch-to-buffer)
199 | (should (eq major-mode 'pascal-mode)))))
200 |
201 | (ert-deftest poly-markdown/inline-math-both ()
202 | (let ((markdown-enable-math t))
203 | (pm-test-run-on-string 'poly-markdown-mode
204 | "Some text with $\\text{inner math}$, formulas $E=mc^2$,
205 | \\(E=mc^2\\), $E=mc^2$, and more formulas \\(E=mc^2\\)
206 |
207 | ```pascal
208 | Some none-sense (formula $E=mc^2$ \\(dddd\\))
209 | ```"
210 | ;; (switch-to-buffer (current-buffer))
211 | (goto-char 17)
212 | (pm-switch-to-buffer)
213 | (should (eq major-mode 'latex-mode))
214 | (goto-char 35)
215 | (pm-switch-to-buffer)
216 | (should (eq major-mode 'markdown-mode))
217 | (goto-char 48)
218 | (pm-switch-to-buffer)
219 | (should (eq major-mode 'latex-mode))
220 | (goto-char 54)
221 | (pm-switch-to-buffer)
222 | (should (eq major-mode 'markdown-mode))
223 | (goto-char 57)
224 | (pm-switch-to-buffer)
225 | (should (eq major-mode 'markdown-mode))
226 | (goto-char 58)
227 | (pm-switch-to-buffer)
228 | (should (eq major-mode 'latex-mode))
229 | (goto-char 64)
230 | (pm-switch-to-buffer)
231 | (should (eq major-mode 'markdown-mode))
232 | (goto-char 69)
233 | (pm-switch-to-buffer)
234 | (should (eq major-mode 'latex-mode))
235 | (goto-char 97)
236 | (pm-switch-to-buffer)
237 | (should (eq major-mode 'markdown-mode))
238 | (goto-char 98)
239 | (pm-switch-to-buffer)
240 | (should (eq major-mode 'latex-mode))
241 | (goto-char 155)
242 | (pm-switch-to-buffer)
243 | (should (eq major-mode 'pascal-mode)))))
244 |
245 | (ert-deftest poly-markdown/displayed-math ()
246 | (let ((markdown-enable-math t))
247 | (pm-test-run-on-string 'poly-markdown-mode
248 | "Some text with
249 | $$\\text{displayed math}$$, formulas
250 | $$E=mc^2$$
251 | $$E=mc^2$$, and $343 more $$$ formulas $$$ and $3
252 | $$ E=mc^2 $$;
253 | ```pascal
254 | Some none-sense (formula
255 | $$E=mc^2$$ )
256 | ```"
257 | ;; (switch-to-buffer (current-buffer))
258 | (goto-char 18)
259 | (pm-switch-to-buffer)
260 | (should (eq major-mode 'latex-mode))
261 | (goto-char 42)
262 | (pm-switch-to-buffer)
263 | (should (eq major-mode 'markdown-mode))
264 | (goto-char 55)
265 | (pm-switch-to-buffer)
266 | (should (eq major-mode 'latex-mode))
267 | (goto-char 64)
268 | (pm-switch-to-buffer)
269 | (should-not (eq major-mode 'latex-mode))
270 | (goto-char 66)
271 | (pm-switch-to-buffer)
272 | (should (eq major-mode 'latex-mode))
273 | (goto-char 84)
274 | (pm-switch-to-buffer)
275 | (should (eq major-mode 'markdown-mode))
276 | (goto-char 102)
277 | (pm-switch-to-buffer)
278 | (should (eq major-mode 'markdown-mode))
279 | (goto-char 118)
280 | (pm-switch-to-buffer)
281 | (should (eq major-mode 'latex-mode))
282 | (goto-char 169)
283 | (pm-switch-to-buffer)
284 | (should (eq major-mode 'pascal-mode)))))
285 |
286 | (ert-deftest poly-markdown/inline-code-in-host-mode ()
287 | (pm-test-run-on-string 'poly-markdown-mode
288 | "aaa `non-mode bbb` cccc"
289 | ;; (switch-to-buffer (current-buffer))
290 | (goto-char 14)
291 | (pm-switch-to-buffer)
292 | (should (eq major-mode 'markdown-mode))
293 | (should (eq (car (get-text-property (point) 'face))
294 | 'markdown-inline-code-face))))
295 |
296 | (ert-deftest poly-markdown/displayed-math-both ()
297 | (let ((markdown-enable-math t))
298 | (pm-test-run-on-string 'poly-markdown-mode
299 | "Some text with
300 | $$\\text{displayed math}$$, formulas \\[E=mc^2\\]
301 | \\[E=mc^2\\]
302 | $$E=mc^2$$, and $343 more $$$ formulas $$$ and $3
303 | \\[ E=mc^2
304 | \\];
305 | ```pascal
306 | Some none-sense (formula
307 | \\[E=mc^2\\] )
308 | ```"
309 | ;; (switch-to-buffer (current-buffer))
310 | (goto-char 18)
311 | (pm-switch-to-buffer)
312 | (should (eq major-mode 'latex-mode))
313 | (goto-char 42)
314 | (pm-switch-to-buffer)
315 | (should (eq major-mode 'markdown-mode))
316 | (goto-char 55)
317 | (pm-switch-to-buffer)
318 | (should (eq major-mode 'latex-mode))
319 | (goto-char 64)
320 | (pm-switch-to-buffer)
321 | (should (eq major-mode 'markdown-mode))
322 | (goto-char 65)
323 | (pm-switch-to-buffer)
324 | (should (eq major-mode 'latex-mode))
325 | (goto-char 59)
326 | (pm-switch-to-buffer)
327 | (should (eq major-mode 'latex-mode))
328 | (goto-char 76)
329 | (pm-switch-to-buffer)
330 | (should (eq major-mode 'latex-mode))
331 | (goto-char 104)
332 | (pm-switch-to-buffer)
333 | (should (eq major-mode 'markdown-mode))
334 | (goto-char 122)
335 | (pm-switch-to-buffer)
336 | (should (eq major-mode 'markdown-mode))
337 | (goto-char 126)
338 | (pm-switch-to-buffer)
339 | (should (eq major-mode 'markdown-mode))
340 | (goto-char 127)
341 | (pm-switch-to-buffer)
342 | (should (eq major-mode 'latex-mode))
343 | (goto-char 135)
344 | (pm-switch-to-buffer)
345 | (should (eq major-mode 'latex-mode))
346 | (goto-char 136)
347 | (pm-switch-to-buffer)
348 | (should (eq major-mode 'markdown-mode))
349 | (goto-char 178)
350 | (pm-switch-to-buffer)
351 | (should (eq major-mode 'pascal-mode)))))
352 |
353 | (ert-deftest poly-markdown/nested-$-body ()
354 | "Test for #6"
355 | (ert-skip "FIXME: failing test")
356 | (oset poly-markdown-inline-math-innermode :allow-nested t)
357 | (pm-test-spans 'poly-markdown-mode
358 | "```python
359 | $
360 | python-mode-here
361 | ```
362 | ")
363 | (pm-test-run-on-string 'poly-markdown-mode
364 | "```python
365 | $
366 | python-mode-here
367 | ```
368 | "
369 | (switch-to-buffer (current-buffer))
370 | (goto-char 14)
371 | (pm-switch-to-buffer)
372 | (should (eq major-mode 'python-mode))
373 | (should (equal (pm-innermost-range 31 'no-cache)
374 | (cons 31 34))))
375 | (oset poly-markdown-inline-math-innermode :allow-nested nil))
376 |
377 | (ert-deftest poly-markdown/nested-$-head ()
378 | "Test for #6"
379 | (ert-skip "FIXME: failing test")
380 | (oset poly-markdown-inline-math-innermode :allow-nested t)
381 | (pm-test-spans 'poly-markdown-mode
382 | "```{python $ }
383 | python-mode-here
384 | ```
385 | ")
386 | (pm-test-run-on-string 'poly-markdown-mode
387 | "```{python $ }
388 | python-mode-here
389 | ```
390 | "
391 | (switch-to-buffer (current-buffer))
392 | (goto-char 16)
393 | (pm-switch-to-buffer)
394 | (should (eq major-mode 'python-mode))
395 | (should (equal (pm-innermost-range 16 'no-cache)
396 | (cons 16 33))))
397 | (oset poly-markdown-inline-math-innermode :allow-nested nil))
398 |
399 | (ert-deftest poly-markdown/nested-$-general ()
400 | "Test for #6"
401 | (ert-skip "FIXME: failing test")
402 | (pm-test-spans 'poly-markdown-mode
403 | "```{python}
404 | sf $sfsfdsfsfd
405 | ```
406 |
407 | ```{python test1}
408 | python-here
409 | a + 3 $
410 | python-here
411 | ```
412 | ")
413 | (pm-test-run-on-string 'poly-markdown-mode
414 | "```{python}
415 | sf $sfsfdsfsfd
416 | ```
417 |
418 | ```{python test1}
419 | python-here
420 | a + 3 $
421 | python-here
422 | ```
423 | "
424 | (switch-to-buffer (current-buffer))
425 | (pm-switch-to-buffer (goto-char 40))
426 | (should (or (eq major-mode 'markdown-mode)
427 | (eq major-mode 'poly-head-tail-mode)))
428 | (pm-switch-to-buffer (goto-char 71))
429 | (should (eq major-mode 'python-mode))))
430 |
431 | (ert-deftest poly-markdown/yaml-block ()
432 | (pm-test-run-on-file poly-markdown-mode "markdown-with-yaml.md"
433 | (goto-char (point-min))
434 | (pm-switch-to-buffer)
435 | (should (eq major-mode 'markdown-mode))
436 | (forward-line 1)
437 | (pm-switch-to-buffer)
438 | (should (eq major-mode 'yaml-mode))
439 | (forward-line 2)
440 | (pm-switch-to-buffer)
441 | (should (eq major-mode 'markdown-mode))))
442 |
443 | ;; useless :( #163 shows only when `kill-buffer` is called interactively
444 | (ert-deftest poly-markdown/kill-buffer ()
445 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
446 | (let ((base-buff (buffer-base-buffer)))
447 | (re-search-forward "defmacro")
448 | (pm-switch-to-buffer)
449 | (let (kill-buffer-query-functions)
450 | (kill-buffer))
451 | (should-not (buffer-live-p base-buff)))))
452 |
453 | (ert-deftest poly-markdown/indentation ()
454 | (pm-test-indentation poly-markdown-mode "markdown.md"))
455 |
456 | (ert-deftest infra/poly-markdown/clone-indirect-buffer ()
457 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
458 |
459 | ;; preserve ib in the host mode
460 | (let ((bname "cloned-buffer")
461 | (cbuff (current-buffer))
462 | (inhibit-message t))
463 | (goto-char 1)
464 | (clone-indirect-buffer bname t)
465 | (switch-to-buffer bname)
466 | (should (equal bname (buffer-name)))
467 | (should (eq 'markdown-mode major-mode))
468 | (goto-line 22) ;; fortran location
469 | (should (eq 'markdown-mode major-mode))
470 | (pm-switch-to-buffer)
471 | (should (eq 'markdown-mode major-mode))
472 | (should (equal bname (buffer-name)))
473 | (kill-buffer)
474 | (should (buffer-live-p cbuff))
475 | (switch-to-buffer cbuff))
476 |
477 | ;; also host from the innermode
478 | (let ((bname "cloned-buffer")
479 | (cbuff (current-buffer))
480 | (inhibit-message t))
481 | (goto-line 22)
482 | (pm-switch-to-buffer)
483 | (clone-indirect-buffer bname t)
484 | (switch-to-buffer bname)
485 | (should (equal bname (buffer-name)))
486 | (should (eq 'markdown-mode major-mode))
487 | (pm-switch-to-buffer)
488 | (should (eq 'markdown-mode major-mode))
489 | (should (equal bname (buffer-name)))
490 | (kill-buffer)
491 | (should (buffer-live-p cbuff)))))
492 |
493 | (ert-deftest infra/poly-markdown/pm-map-over-modes ()
494 | (pm-test-map-over-modes poly-markdown-mode "markdown.md"))
495 |
496 |
497 | (ert-deftest infra/poly-markdown/pm-map-over-modes-regions ()
498 | (let ((pm-use-cache t)
499 | (ref-regions '((markdown-mode nil nil 1 391)
500 | (fortran-mode body body 391 872)
501 | (markdown-mode tail nil 872 1043)
502 | (perl-mode body body 1043 1597)
503 | (markdown-mode tail nil 1597 1849)
504 | (emacs-lisp-mode body body 1849 2239)
505 | (markdown-mode tail nil 2239 2368)
506 | (pascal-mode body body 2368 2587)
507 | (markdown-mode tail nil 2587 2897)
508 | (python-mode body body 2897 3502)
509 | (markdown-mode tail nil 3502 3587)
510 | (emacs-lisp-mode body body 3587 4377)
511 | (markdown-mode tail nil 4377 4469)
512 | (sql-mode body body 4469 4532)
513 | (markdown-mode tail nil 4532 4546)))
514 | acc)
515 |
516 | (cl-labels ((sub-ref (beg &optional end)
517 | (setq end (or end (point-max)))
518 | (let ((acc ref-regions)
519 | out)
520 | (while (and acc (< (nth 3 (car acc)) beg))
521 | (pop acc))
522 | (while (and acc (< (nth 3 (car acc)) end))
523 | (push (pop acc) out))
524 | (reverse out)))
525 | (req (beg end)
526 | (let ((span (pm-innermost-span beg)))
527 | (push (list (pm-span-mode span) (car span) (pm-true-span-type span)
528 | beg end)
529 | acc)))
530 | (run (beg end)
531 | (setq acc nil)
532 | (pm-map-over-modes #'req beg end)
533 | (sort acc (lambda (x y) (< (nth 3 x) (nth 3 y))))))
534 |
535 | ;; ;; exact span
536 | ;; (pm-test-run-on-file poly-markdown-mode "markdown.md"
537 | ;; (let ((ref '((fortran-mode body body 391 872))))
538 | ;; (should (equal ref (run 391 872)))
539 | ;; (should (equal ref (run 391 872)))
540 | ;; (let ((pm-use-cache nil))
541 | ;; (should (equal ref (run 391 872))))))
542 |
543 | ;; (pm-test-run-on-file poly-markdown-mode "markdown.md"
544 | ;; (let ((ref '((markdown-mode head nil 380 391))))
545 | ;; (should (equal ref (run 380 391)))
546 | ;; (should (equal ref (run 380 391)))
547 | ;; (let ((pm-use-cache nil))
548 | ;; (should (equal ref (run 380 391))))))
549 |
550 | ;; (pm-test-run-on-file poly-markdown-mode "markdown.md"
551 | ;; (let ((ref '((markdown-mode tail nil 872 875))))
552 | ;; (let ((pm-use-cache nil))
553 | ;; (should (equal ref (run 872 875))))
554 | ;; (should (equal ref (run 872 875)))))
555 |
556 | ;; multi spans
557 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
558 | (let ((pm-use-cache nil))
559 | (should (equal ref-regions (run 1 (point-max)))))
560 | (should (equal ref-regions (run 1 (point-max)))))
561 |
562 |
563 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
564 | (should (equal ref-regions (run 200 (point-max))))
565 | (let ((pm-use-cache nil))
566 | (should (equal ref-regions (run 200 (point-max)))))
567 | (should (equal ref-regions (run 200 (point-max)))))
568 |
569 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
570 | (let ((ref (sub-ref 872)))
571 | (let ((pm-use-cache nil))
572 | (should (equal ref (run 872 (point-max)))))
573 | (should (equal ref (run 872 (point-max))))))
574 |
575 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
576 | (let ((ref (sub-ref 1843)))
577 | (should (equal ref (run 2221 (point-max))))
578 | (let ((pm-use-cache nil))
579 | (should (equal ref (run 2221 (point-max)))))
580 | (should (equal ref (run 2221 (point-max))))))
581 |
582 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
583 | (let ((ref (sub-ref 2239)))
584 | (let ((pm-use-cache nil))
585 | (should (equal ref (run 2239 (point-max)))))
586 | (should (equal ref (run 2239 (point-max))))))
587 |
588 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
589 | (let ((ref '((markdown-mode tail nil 2239 2358))))
590 | (should (equal ref (run 2239 2256)))
591 | (let ((pm-use-cache nil))
592 | (should (equal ref (run 2239 2256))))))
593 |
594 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
595 | (let ((ref '((markdown-mode tail nil 2239 2358))))
596 | (should (equal ref (run 2239 2347)))
597 | (let ((pm-use-cache nil))
598 | (should (equal ref (run 2239 2347))))))
599 |
600 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
601 | (let ((ref (sub-ref 4532)))
602 | (should (equal ref (run 4533 (point-max))))
603 | (let ((pm-use-cache nil))
604 | (should (equal ref (run 4533 (point-max)))))))
605 |
606 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
607 | (let ((ref '((markdown-mode tail nil 4532 4546))))
608 | (should (equal ref (run 4532 (point-max))))
609 | (let ((pm-use-cache nil))
610 | (should (equal ref (run 4532 (point-max)))))))
611 |
612 | (pm-test-run-on-file poly-markdown-mode "markdown.md"
613 | (let ((ref (cons '(emacs-lisp-mode body body 3587 4377)
614 | (sub-ref 4369))))
615 | (should (equal ref (run 4369 (point-max))))
616 | (let ((pm-use-cache nil))
617 | (should (equal ref (run 4369 (point-max)))))))
618 |
619 | ))
620 | )
621 |
622 |
623 |
--------------------------------------------------------------------------------