diff --git a/.elpaignore b/.elpaignore new file mode 100644 index 0000000..9ccab9a --- /dev/null +++ b/.elpaignore @@ -0,0 +1,7 @@ +/images/ +/test/ +/adoc-mode-autoloads.el +/adoc-mode-pkg.el +Eldev +*.md +/.github/ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..6ee83e2 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,34 @@ +name: CI + +on: + push: + paths-ignore: ['**.md', '**.adoc'] + pull_request: + paths-ignore: ['**.md', '**.adoc'] + +jobs: + test: + runs-on: ubuntu-latest + continue-on-error: ${{matrix.emacs_version == 'snapshot'}} + + strategy: + matrix: + # Earliest supported + latest in each stable branch + snapshot. + emacs_version: ['26.3', '27.1', '28.1', 'snapshot'] + + steps: + - name: Set up Emacs + uses: purcell/setup-emacs@master + with: + version: ${{matrix.emacs_version}} + + - name: Install Eldev + run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh + + - name: Check out the source code + uses: actions/checkout@v2 + + - name: Test the project + run: | + eldev -p -dtT -C test + eldev -dtT -C compile --warnings-as-errors diff --git a/.gitignore b/.gitignore index d27fb03..3e4ada4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.elc #*# TAGS +.eldev diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8f94c9c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,26 @@ +# Changelog + +## master (unreleased) + +### New features + +- [#21](https://github.com/bbatsov/adoc-mode/pull/21): Add support for native font-locking in code blocks. + +## 0.7.0 (2023-03-09) + +### New features + +- Added `imenu` support. +- Associate with `.adoc` and `.asciidoc` files automatically. + +### Changes + +- Require Emacs 26. +- Respect `mode-require-final-newline`. +- [#25](https://github.com/bbatsov/adoc-mode/issues/25): Remove `markup-faces` dependency. + +### Bugs fixed + +- Handle `unichars.el` properly. +- Add missing quote before `adoc-reserved` in `adoc-kw-verbatim-paragraph-sequence`. +- [#17](https://github.com/bbatsov/adoc-mode/issues/17): Show only titles in `imenu`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..af09839 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,34 @@ +# Contributing + +If you discover issues, have ideas for improvements or new features, please +report them to the [issue tracker][1] of the repository or submit a pull +request. Please, try to follow these guidelines when you do so. + +## Issue reporting + +* Check that the issue has not already been reported. +* Check that the issue has not already been fixed in the latest code + (a.k.a. `master`). +* Be clear, concise and precise in your description of the problem. +* Open an issue with a descriptive title and a summary in grammatically correct, + complete sentences. +* Include any relevant code to the issue summary. +* If you're reporting performance issues it'd be nice if you added some profiling data (Emacs has a built-in profiler). + +## Pull requests + +* Read [how to properly contribute to open source projects on Github][2]. +* Use a topic branch to easily amend a pull request later, if necessary. +* Write [good commit messages][3]. +* Mention related tickets in the commit messages (e.g. `[Fix #N] Add missing autoload cookies`) +* Update the [changelog][5]. +* Use the same coding conventions as the rest of the project. +* Verify your Emacs Lisp code with `checkdoc` (C-c ? d). +* Open a [pull request][4] that relates to *only* one subject with a clear title + and description in grammatically correct, complete sentences. + +[1]: https://github.com/bbatsov/adoc-mode/issues +[2]: http://gun.io/blog/how-to-github-fork-branch-and-pull-request +[3]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html +[4]: https://help.github.com/articles/using-pull-requests +[5]: https://github.com/bbatsov/adoc-mode/blob/master/CHANGELOG.md diff --git a/Eldev b/Eldev new file mode 100644 index 0000000..c51ddaa --- /dev/null +++ b/Eldev @@ -0,0 +1 @@ +(eldev-use-package-archive 'melpa) diff --git a/FUNDING.yml b/FUNDING.yml new file mode 100644 index 0000000..a318a15 --- /dev/null +++ b/FUNDING.yml @@ -0,0 +1,7 @@ +# These are supported funding model platforms + +github: bbatsov +patreon: bbatsov +ko_fi: bbatsov +liberapay: bbatsov +custom: https://www.paypal.me/bbatsov diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..414804d --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,33 @@ +*Use the template below when reporting bugs. Please, make sure that +you're running the latest stable adoc-mode and that the problem you're reporting +hasn't been reported (and potentially fixed) already.* + +**Remove all of the placeholder text in your final report!** + +## Expected behavior + +## Actual behavior + +## Steps to reproduce the problem + +*This is extremely important! Providing us with a reliable way to reproduce +a problem will expedite its solution.* + +## Environment & Version information + +### Adoc-Mode version information + +*Include here the version string displayed by `M-x +adoc-show-version`. Here's an example:* + +``` +Adoc-Mode version: 0.7 +``` + +### Emacs version + +*E.g. 27.1* (use C-h C-a to see it) + +### Operating system + +*E.g. Windows 10* diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..99e8555 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +**Replace this placeholder text with a summary of the changes in your PR. +The more detailed you are, the better.** + +----------------- + +Before submitting a PR make sure the following things have been done (and denote this +by checking the relevant checkboxes): + +- [ ] The commits are consistent with our [contribution guidelines](../blob/master/CONTRIBUTING.md) +- [ ] You've added tests (if possible) to cover your change(s) +- [ ] All tests are passing ([`eldev test`](https://github.com/doublep/eldev)) +- [ ] The new code is not generating bytecode or `M-x checkdoc` warnings +- [ ] You've updated the [changelog](../blob/master/CHANGELOG.md) (if adding/changing user-visible functionality) +- [ ] You've updated the readme (if adding/changing user-visible functionality) + +Thanks! diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..5dc1aca --- /dev/null +++ b/README.adoc @@ -0,0 +1,263 @@ +:experimental: +:highlighter: coderay +:melpa-badge: http://melpa.org/packages/adoc-mode-badge.svg +:melpa-stable-badge: http://stable.melpa.org/packages/adoc-mode-badge.svg +:melpa-package: http://melpa.org/#/adoc-mode +:melpa-stable-package: http://stable.melpa.org/#/adoc-mode +:melpa: http://melpa.org +:melpa-stable: http://stable.melpa.org +:license-badge: https://img.shields.io/badge/license-GPL_3-green.svg +:copying: http://www.gnu.org/copyleft/gpl.html + + +image:https://github.com/bbatsov/adoc-mode/workflows/CI/badge.svg[link="https://github.com/bbatsov/adoc-mode/actions?query=workflow%3ACI"] +image:{melpa-badge}[link="{melpa-package}"] +image:{melpa-stable-badge}[link="{melpa-stable-package}"] +image:{license-badge}[link="{copying}"] + += adoc-mode + +== Introduction + +https://asciidoc.org/[AsciiDoc] is a text document format for +writing short documents, articles, books and UNIX man pages. AsciiDoc files +can be translated to HTML and DocBook markups. + +`adoc-mode` is an Emacs major mode for editing AsciiDoc files. It emphasizes on +the idea that the document is highlighted so it pretty much looks like the +final output. What must be bold is bold, what must be italic is italic etc. +Meta characters are naturally still visible, but in a faint way, so they can +be easily ignored. + +== Features + +Here are some of the main features of `adoc-mode`: + +- sophisticated highlighting +- native fontification of code blocks +- promote / demote title +- toggle title type between one line title and two line title +- adjust underline length of a two line title to match title text's length +- goto anchor defining a given id, default reading from xref at point +- support for outline (however only with the one-line title style) + +=== Demo + +The highlighting emphasizes on how the output will look like. _All_ +characters are visible, however meta characters are displayed in a faint way. + +image:images/adoc-mode.png[alt=screenshot] + +== Installation + +`adoc-mode` is available on the community-maintained +link:{melpa-stable-package}[MELPA Stable] and link:{melpa-package}[MELPA] repos. + +Using MELPA Stable is recommended as it has the latest stable version. +MELPA has a development snapshot for users who don't mind breakage but +don't want to run `adoc-mode` from a git checkout. + +You can install `adoc-mode` using the following command: + +kbd:[M-x] `package-install` kbd:[RET] `adoc-mode` kbd:[RET] + +If the installation doesn't work try refreshing the package list: + +kbd:[M-x] `package-refresh-contents` + +Alternative, you can add something like this to your Emacs config: + +[source,emacs-lisp] +---- +(unless (package-installed-p 'adoc-mode) + (package-refresh-contents) + (package-install 'adoc-mode)) +---- + +or if you're into `use-package`: + +[source,emacs-lisp] +---- +(use-package adoc-mode + :ensure t) +---- + +== Configuration + +=== General + +According to an old AsciiDoc manual, `.txt` is the standard file extension of +AsciiDoc files. Add the following to your initialization file to open all `.txt` +files with adoc-mode as major mode automatically: + +[source,emacs-lisp] +---- +(add-to-list 'auto-mode-alist (cons "\\.txt\\'" 'adoc-mode)) +---- + +Modern conventions for AsciiDoc file extensions favor `.adoc` and +`.asciidoc` and they are associated with `adoc-mode` automatically. + +You can see a list of all configuration options offered by `adoc-mode` by running the following command - kbd:[M-x] `customize-group adoc`. + +=== Native Syntax Highlighting of Source Code Blocks + +Out-of-the-box `adoc-mode` will try to apply native font-locking to source code blocks (e.g. the same font-locking that `ruby-mode` would use for Ruby code blocks). +This can be tweaked by several configuration options: + +* Native fontification of source blocks can be switched off by setting `adoc-fontify-code-blocks-natively` to `nil`. +* Native fontification of lengthy code blocks can cause performance problems. If the value of `adoc-fontify-code-blocks-natively` is an integer only those code blocks are fontified natively whose length is less or equal to that value. +* To avoid performance problems with code block beginnings that do not have a matching end yet the scanning for the code block end is delimited by `adoc-font-lock-extend-after-change-max`. +* All programming languages `XYZ` that have an Emacs major mode `XYZ-mode` and use `font-lock` are automatically supported. Some other languages not fitting into that name scheme are supported through the alist `adoc-code-lang-modes`. You can add your own languages and modes there if they work based on `font-lock` and are not automatically supported. +* The fall-back language mode is `prog-mode` without any fontification. You can set your own default by `adoc-fontify-code-block-default-mode`. + +=== Syntax Highlighting Customization + +It is possible to customize the way `adoc-mode` renders different text +elements (faces) like section titles, text or punctuation styles. For +example, if you would like a level 1 section title to have a different +text color or height you can achieve this by using standard Emacs +functionality. + +First of all, list all available faces by running + +kbd:[M-x] `list-faces-display` + +and searching for lines with the `adoc-` prefix. + +Alternatively, you can get information about the face under point by calling + +kbd:[M-x] `describe-face` + +One possible solution to change the look of a face is to use the +built-in `use-package` feature `:custom-face`. + +Example: + +[source,emacs-lisp] +---- +(use-package adoc-mode + :ensure t + :custom-face + (adoc-title-0-face ((t (:height 1.0 :weight bold))))) +---- + +Of course, this is only one way to do it. Emacs has a few ways to +customize faces. Simply, pick the one you prefer. + +If your default face is a fixed pitch (monospace) face, but in AsciiDoc files +you liked to have normal text with a variable pitch face, `buffer-face-mode` +is one good options for you: + +[source,emacs-lisp] +---- +(defun my-buffer-face-mode-variable () + "Set font to a variable width (proportional) fonts in current buffer." + (interactive) + (setq buffer-face-mode-face '(:family "DejaVu Sans" :height 100 :width semi-condensed)) + (buffer-face-mode)) + +(add-hook 'adoc-mode-hook (lambda() (buffer-face-mode t))) +---- + +== Roadmap + +Here are some features that we're considering to add in the future: + +- Demote / promote for list items +- Outline support also for two line titles +- Correctly highlighting backslash escapes + +Check out the issue tracker for more details. + +== Hacking + +adoc-mode uses https://github.com/doublep/eldev[Eldev] for development, so +you should install the tool first. + +The easiest and "purest" way to run adoc-mode is to execute: + + $ eldev emacs + +This will start a separate Emacs process with adoc-mode and its +dependencies available, but _without_ your normal packages installed. +However, you can use `Eldev-local` to add some packages with +`(eldev-add-extra-dependencies 'emacs ...)` forms. See Eldev +documentation for details. + +Alternatively, if you want to load adoc-mode from source code in the Emacs +you use for editing: + +- Generate autoloads file (that's done automatically when installing +via `package.el` but you'll have to do it manually in this case): + +[source,shellsession] +---- +$ eldev build :autoloads +---- + +- Add to your `.emacs`: + +[source,emacs-lisp] +---- +;; load adoc-mode from its source code +(add-to-list 'load-path "~/projects/adoc-mode") +(load "adoc-mode-autoloads" t t) +---- + +=== Changing the code + +It's perfectly fine to load adoc-mode from `package.el` and then to start making +experiments by changing existing code and adding new code. + +A very good workflow is to just open the source code you've cloned and start +evaluating the code you've altered/added with commands like `C-M-x`, +`eval-buffer` and so on. + +Once you've evaluated the new code, you can invoke some interactive command that +uses it internally or open a Emacs Lisp REPL and experiment with it there. You +can open an Emacs Lisp REPL with `M-x ielm`. + +You can also quickly evaluate some Emacs Lisp code in the minibuffer with `M-:`. + +=== Running the tests + +Run all tests with: + +[source,shellsession] +---- +$ eldev test +---- + +NOTE: Tests may not run correctly inside Emacs' `shell-mode` buffers. Running +them in a terminal is recommended. + +You can also check for compliance with a variety of coding standards in batch mode (including docstrings): + +[source,shellsession] +---- +$ eldev lint +---- + +To check for byte-compilation warnings you can just compile the project with Eldev: + +[source,shellsession] +---- +$ eldev compile +---- + +== History + +`adoc-mode` was created by https://github.com/sensorflo/[Florian Kaufmann] in 2009. Eventually the development +was halted in 2016 and the mode was dormant for the next 6 years. In 2022 +https://github.com/TobiasZawada[Tobias Zawada] encouraged the Emacs community to revive the development and after a brief period under the https://github.com/emacsorphanage[Emacs Orphanage] org, https://github.com/bbatsov/[Bozhidar Batsov] assumed the project's maintenance. + +These days all upstream packages (e.g. on MELPA) are build from Bozhidar's fork. + +== License + +Copyright © 2009-2016 Florian Kaufmann + +Copyright © 2022-2023 Bozhidar Batsov and `adoc-mode` contributors + +Distributed under the link:{copying}[GNU General Public License]; type kbd:[C-h] kbd:[C-c] to view it. diff --git a/adoc-mode-test.el b/adoc-mode-test.el deleted file mode 100644 index 51d7590..0000000 --- a/adoc-mode-test.el +++ /dev/null @@ -1,1001 +0,0 @@ -;;; adoc-mode-test.el --- test suite for adoc-mode.el -;;; -;;; Commentary: -;; -;; Call adoc-test-run to run the test suite -;; -;;; Todo: -;; - test for font lock multiline property -;; - test for presence of adoc-reserved (we do white-box testing here) -;; - test also with multiple versions of (X)Emacs -;; - compare adoc-mode fontification with actuall output from AsciiDoc, being -;; almost the ultimative test for correctness -;; - -;;; Code: -(require 'ert) -(require 'adoc-mode) - -;; todo: -;; - auto-create different contexts like -;; - beginning/end of buffer -;; - beginning/end of paragraph -;; - side-to-side yes/no with next same construct -(defun adoctest-faces (name &rest args) - (let ((not-done t) - (font-lock-support-mode)) - (with-temp-buffer - ;; setup - (while args - (insert (propertize (car args) 'adoctest (cadr args))) - (setq args (cddr args))) - - ;; exercise - (adoc-mode) - (font-lock-fontify-buffer) - - ;; verify - (goto-char (point-min)) - (while not-done - (let* ((tmp (get-text-property (point) 'adoctest)) - (tmp2 (get-text-property (point) 'face))) - (cond - ((null tmp)) ; nop - ((eq tmp 'no-face) - (should (null tmp2))) - (t - (if (and (listp tmp2) (not (listp tmp))) - (should (and (= 1 (length tmp2)) (equal tmp (car tmp2)))) - (should (equal tmp tmp2))))) - (if (< (point) (point-max)) - (forward-char 1) - (setq not-done nil))))))) - -(defun adoctest-trans (original-text expected-text transform) - "Calling TRANSFORM on EXPECTED-TEXT, ORIGINAL-TEXT `should' result. -ORIGINAL-TEXT is put in an temporary buffer and TRANSFORM is -evaluated using `eval'. The resulting buffer content is compared -to EXPECTED-TEXT. - -ORIGINAL-TEXT optionaly may contain the following special -charachters. Escaping them is not (yet) supported. They are -removed before TRANSFORM is evaluated. - -! Position of point before TRANSFORM is evaluated - -<> Position of mark (<) and point (>) before TRANSFORM is - evaluatred" - (if (string-match "[!<>]" original-text) - ;; original-text has ! markers - (let ((pos 0) ; pos in original-text - (pos-old 0) ; pos of the last iteration - (pos-in-new-region-start 0) - (pos-new-list) ; list of positions in new-original-text - (new-original-text "")) ; as original-text, but with < > ! stripped - ;; original-text -> new-original-text by removing ! and remembering their positions - (while (and (< pos (length original-text)) - (setq pos (string-match "[!<>]" original-text pos))) - (setq new-original-text (concat new-original-text (substring original-text pos-old pos))) - (cond - ((eq (aref original-text pos) ?<) - (setq pos-in-new-region-start (length new-original-text))) - ((eq (aref original-text pos) ?>) - (setq pos-new-list (cons (cons pos-in-new-region-start (length new-original-text)) pos-new-list))) - (t - (setq pos-new-list (cons (length new-original-text) pos-new-list)))) - (setq pos (1+ pos)) - (setq pos-old pos)) - (setq new-original-text (concat new-original-text (substring original-text pos-old pos))) - ;; run adoctest-trans-inner for each remembered pos - (while pos-new-list - (adoctest-trans-inner new-original-text expected-text transform (car pos-new-list)) - (setq pos-new-list (cdr pos-new-list)))) - ;; original-text has no ! markers - (adoctest-trans-inner original-text expected-text transform))) - -(defun adoctest-trans-inner (original-text expected-text transform &optional pos) - (let ((not-done t) - (font-lock-support-mode)) - (with-temp-buffer - ;; setup - (adoc-mode) - (insert original-text) - (cond ; 1+: buffer pos starts at 1, but string pos at 0 - ((consp pos) - (goto-char (1+ (car pos))) - (set-mark (1+ (cdr pos)))) - (pos - (goto-char (1+ pos)))) - ;; exercise - (eval transform) - ;; verify - (should (string-equal (buffer-substring (point-min) (point-max)) expected-text))))) - -(ert-deftest adoctest-test-titles-simple-one-line-before () - (adoctest-faces "titles-simple-one-line-before" - "= " markup-meta-hide-face "document title" markup-title-0-face "\n" nil - "\n" nil - "== " markup-meta-hide-face "chapter 1" markup-title-1-face "\n" nil - "\n" nil - "=== " markup-meta-hide-face "chapter 2" markup-title-2-face "\n" nil - "\n" nil - "==== " markup-meta-hide-face "chapter 3" markup-title-3-face "\n" nil - "\n" nil - "===== " markup-meta-hide-face "chapter 4" markup-title-4-face)) - -(ert-deftest adoctest-test-titles-simple-one-line-enclosed () - (adoctest-faces "titles-simple-one-line-enclosed" - "= " markup-meta-hide-face "document title" markup-title-0-face " =" markup-meta-hide-face "\n" nil - "\n" nil - "== " markup-meta-hide-face "chapter 1" markup-title-1-face " ==" markup-meta-hide-face "\n" nil - "\n" nil - "=== " markup-meta-hide-face "chapter 2" markup-title-2-face " ===" markup-meta-hide-face "\n" nil - "\n" nil - "==== " markup-meta-hide-face "chapter 3" markup-title-3-face " ====" markup-meta-hide-face "\n" nil - "\n" nil - "===== " markup-meta-hide-face "chapter 4" markup-title-4-face " =====" markup-meta-hide-face)) - -(ert-deftest adoctest-test-titles-simple-two-line () - (adoctest-faces "titles-simple-two-line" - ;; todo - ;; ensure somehow adoc-enable-two-line-title is t - "document title" markup-title-0-face "\n" nil - "==============" markup-meta-hide-face "\n" nil - "\n" nil - "chapter 1" markup-title-1-face "\n" nil - "---------" markup-meta-hide-face "\n" nil - "\n" nil - "chapter 2" markup-title-2-face "\n" nil - "~~~~~~~~~" markup-meta-hide-face "\n" nil - "\n" nil - "chapter 3" markup-title-3-face "\n" nil - "^^^^^^^^^" markup-meta-hide-face "\n" nil - "\n" nil - "chapter 4" markup-title-4-face "\n" nil - "+++++++++" markup-meta-hide-face)) - -(ert-deftest adoctest-test-titles-simple-block-title () - (adoctest-faces "titles-simple-block-title" - "." markup-meta-face "Block title" markup-gen-face)) - -(ert-deftest adoctest-test-delimited-blocks-simple () - (adoctest-faces "delimited-blocks-simple" - - ;; note that the leading spaces are NOT allowed to have adoc-align face - "////////" markup-meta-hide-face "\n" nil - " comment line 1\n comment line 2" markup-comment-face "\n" nil - "////////" markup-meta-hide-face "\n" nil - "\n" nil - "++++++++" markup-meta-hide-face "\n" nil - " passthrouh line 1\n passthrouh line 2" markup-passthrough-face "\n" nil - "++++++++" markup-meta-hide-face "\n" nil - "\n" nil - "--------" markup-meta-hide-face "\n" nil - " listing line 1\n listing line 2" markup-code-face "\n" nil - "--------" markup-meta-hide-face "\n" nil - "\n" nil - "........" markup-meta-hide-face "\n" nil - " literal line 1\n literal line 2" markup-verbatim-face "\n" nil - "........" markup-meta-hide-face "\n" nil - "\n" nil - - "________" markup-meta-hide-face "\n" nil - "quote line 1\nquote line 2" nil "\n" nil - "________" markup-meta-hide-face "\n" nil - "\n" nil - "========" markup-meta-hide-face "\n" nil - "example line 1\nexample line 2" nil "\n" nil - "========" markup-meta-hide-face "\n" nil - "\n" nil - "********" markup-meta-hide-face "\n" nil - "sidebar line 1\nsidebar line 2" markup-secondary-text-face "\n" nil - "********" markup-meta-hide-face "\n")) - -;; Don't mistake text between two same delimited blocks as a delimited block, -;; i.e. wrongly treating the end of block 1 as a beginning and wrongly -;; treating the beginning of block 2 as ending. -(ert-deftest adoctest-test-delimited-blocks-simple () - (adoctest-faces "delimited-blocks-special-case" - - "--------" markup-meta-hide-face "\n" nil - "11\n12\n13\n14" markup-code-face "\n" nil - "--------" markup-meta-hide-face "\n" nil - "\n" nil - "lorem" 'no-face "\n" nil - "\n" nil - "--------" markup-meta-hide-face "\n" nil - "21\n22\n23\n24" markup-code-face "\n" nil - "--------" markup-meta-hide-face "\n" nil - "\n" nil - "ipsum" 'no-face "\n" nil)) - -(ert-deftest adoctest-test-delimited-blocks-simple () - (adoctest-faces "delimited-blocks-empty" - "////////" markup-meta-hide-face "\n" nil - "////////" markup-meta-hide-face "\n" nil - "\n" nil - "++++++++" markup-meta-hide-face "\n" nil - "++++++++" markup-meta-hide-face "\n" nil - "\n" nil - "--------" markup-meta-hide-face "\n" nil - "--------" markup-meta-hide-face "\n" nil - "\n" nil - "........" markup-meta-hide-face "\n" nil - "........" markup-meta-hide-face "\n" nil - "\n" nil - "________" markup-meta-hide-face "\n" nil - "________" markup-meta-hide-face "\n" nil - "\n" nil - "========" markup-meta-hide-face "\n" nil - "========" markup-meta-hide-face "\n" nil - "\n" nil - "********" markup-meta-hide-face "\n" nil - "********" markup-meta-hide-face "\n")) - -(ert-deftest adoctest-test-open-block () - (adoctest-faces "open-block" - "--" markup-meta-hide-face "\n" nil - "open block line 1\nopen block line 2" nil "\n" nil - "--" markup-meta-hide-face)) - -(ert-deftest adoctest-test-comments () - (adoctest-faces "comments" - ;; as block macro - "// lorem ipsum\n" markup-comment-face - "\n" nil - ;; as inline macro - "lorem ipsum\n" 'no-face - "// dolor sit\n" markup-comment-face - "amen\n" 'no-face - "\n" nil - ;; block macro and end of buffer - "// lorem ipsum" markup-comment-face - ;; as delimited block it's tested in delimited-blocks-simple - )) - -(ert-deftest adoctest-test-anchors () - (adoctest-faces "anchors" - ;; block id - "[[" markup-meta-face "foo" markup-anchor-face "]]" markup-meta-face "\n" nil - "[[" markup-meta-face "foo" markup-anchor-face "," markup-meta-face - "bar" markup-secondary-text-face "]]" markup-meta-face "\n" nil - - ;; special inline syntax: [[id]] [[id,xreftext]] - "lorem " 'no-face "[[" markup-meta-face "foo" markup-anchor-face "]]" - markup-meta-face "ipsum" 'no-face "\n" nil - "lorem " 'no-face "[[" markup-meta-face "foo" markup-anchor-face "," markup-meta-face - "bla bli bla blu" markup-secondary-text-face "]]" markup-meta-face "ipsum" 'no-face "\n" nil - - ;; general inline macro syntax - "lorem " 'no-face "anchor" markup-command-face ":" markup-meta-face - "foo" markup-anchor-face - "[]" markup-meta-face "ipsum" 'no-face "\n" nil - "lorem " 'no-face "anchor" markup-command-face ":" markup-meta-face - "foo" markup-anchor-face - "[" markup-meta-face "bla bli bla blu" markup-secondary-text-face "]" markup-meta-face - "ipsum" 'no-face "\n" nil - - ;; biblio - "lorem " 'no-face "[[" markup-meta-face "[foo]" markup-gen-face "]]" markup-meta-face - " ipsum" 'no-face - )) - -(ert-deftest adoctest-test-references () - (adoctest-faces "references" - "lorem " 'no-face "xref" markup-command-face ":" markup-meta-face - "foo" markup-reference-face "[]" markup-meta-face "\n" nil - "lorem " 'no-face "xref" markup-command-face ":" markup-meta-face - "foo" markup-internal-reference-face "[" markup-meta-face - "bla bli bla blu" markup-reference-face "]" markup-meta-face "\n" nil - - ;; caption spawns multiple lines - "xref" markup-command-face ":" markup-meta-face - "foo" markup-internal-reference-face "[" markup-meta-face - "bla\nbli\nbla\nblu" markup-reference-face "]" markup-meta-face "\n" nil - )) - -(ert-deftest adoctest-test-footnotes () - (adoctest-faces "footnotes" - ;; simple example - "footnote" markup-command-face ":" markup-meta-face - "[" markup-meta-face "lorem ipsum" markup-secondary-text-face - "]" markup-meta-face "\n" nil - - ;; footnote can be hard up against the preceding word - "lorem" 'no-face "footnote" markup-command-face ":" markup-meta-face - "[" markup-meta-face "ipsum" markup-secondary-text-face - "]" markup-meta-face "\n" nil - - ;; attribute-list is not really an attribute list but normal text, - ;; i.e. comma, equal, double quotes are not fontified as meta characters - "footnote" markup-command-face ":" markup-meta-face - "[" markup-meta-face - "lorem, ipsum=dolor, sit=\"amen\"" markup-secondary-text-face - "]" markup-meta-face "\n" nil - - ;; multiline attribute list - "footnote" markup-command-face ":" markup-meta-face - "[" markup-meta-face - "lorem\nipsum\ndolor\nsit\namen" markup-secondary-text-face - "]" markup-meta-face "\n" nil - )) - -(ert-deftest adoctest-test-footnoterefs () - (adoctest-faces "footnoterefs" - ;; simple example - "footnoteref" markup-command-face ":" markup-meta-face - "[" markup-meta-face - "myid" markup-internal-reference-face - "]" markup-meta-face "\n" nil - - "footnoteref" markup-command-face ":" markup-meta-face - "[" markup-meta-face - "myid" markup-anchor-face - "," markup-meta-face - "lorem ipsum" markup-secondary-text-face - "]" markup-meta-face "\n" nil - - ;; footnoteref can be hard up against the preceding word - "lorem" 'no-face - "footnoteref" markup-command-face ":" markup-meta-face - "[" markup-meta-face - "myid" markup-internal-reference-face - "]" markup-meta-face "\n" nil - - "lorem" 'no-face - "footnoteref" markup-command-face ":" markup-meta-face - "[" markup-meta-face - "myid" markup-anchor-face - "," markup-meta-face - "lorem ipsum" markup-secondary-text-face - "]" markup-meta-face "\n" nil - - ;; multiline text - "lorem" 'no-face - "footnoteref" markup-command-face ":" markup-meta-face - "[" markup-meta-face - "myid" markup-anchor-face - "," markup-meta-face - "lorem\nipsum\ndolor\nsit" markup-secondary-text-face - "]" markup-meta-face "\n" nil - )) - -(ert-deftest adoctest-test-images () - (adoctest-faces "images" - ;; block macros - ;; empty arglist - "image" markup-complex-replacement-face "::" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[]" markup-meta-face "\n" nil - ;; pos attribute 0 = alternate text - "image" markup-complex-replacement-face "::" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[" markup-meta-face "lorem ipsum" markup-secondary-text-face "]" markup-meta-face "\n" nil - ;; keyword title - "image" markup-complex-replacement-face "::" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[" markup-meta-face "alt" markup-attribute-face "=" markup-meta-face "lorem ipsum" markup-secondary-text-face "]" markup-meta-face "\n" nil - ;; keyword alt and title - "image" markup-complex-replacement-face "::" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[" markup-meta-face "alt" markup-attribute-face "=" markup-meta-face "lorem ipsum" markup-secondary-text-face "," markup-meta-face - "title" markup-attribute-face "=" markup-meta-face "lorem ipsum" markup-secondary-text-face "]" markup-meta-face "\n" nil - ;; multiline alt and title - "image" markup-complex-replacement-face "::" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[" markup-meta-face "alt" markup-attribute-face "=" markup-meta-face - "lorem\nipsum\nsit" markup-secondary-text-face "," markup-meta-face - "title" markup-attribute-face "=" markup-meta-face - "lorem\nipsum\nsit" markup-secondary-text-face "]" markup-meta-face "\n" nil - - ;; no everything again with inline macros - "foo " 'no-face "image" markup-complex-replacement-face ":" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[]" markup-meta-face "bar" 'no-face "\n" nil - - "foo " 'no-face "image" markup-complex-replacement-face ":" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[" markup-meta-face "lorem ipsum" markup-secondary-text-face "]" markup-meta-face "bar" 'no-face "\n" nil - - "foo " 'no-face "image" markup-complex-replacement-face ":" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[" markup-meta-face "alt" markup-attribute-face "=" markup-meta-face "lorem ipsum" markup-secondary-text-face "]" markup-meta-face "bar" 'no-face "\n" nil - - "foo " 'no-face "image" markup-complex-replacement-face ":" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[" markup-meta-face "alt" markup-attribute-face "=" markup-meta-face "lorem ipsum" markup-secondary-text-face "," markup-meta-face - "title" markup-attribute-face "=" markup-meta-face "lorem ipsum" markup-secondary-text-face "]" markup-meta-face "bar" 'no-face "\n" nil - - "image" markup-complex-replacement-face ":" markup-meta-face - "./foo/bar.png" markup-internal-reference-face - "[" markup-meta-face "alt" markup-attribute-face "=" markup-meta-face - "lorem\nipsum\nsit" markup-secondary-text-face "," markup-meta-face - "title" markup-attribute-face "=" markup-meta-face - "lorem\nipsum\nsit" markup-secondary-text-face "]" markup-meta-face "\n" nil)) - -(ert-deftest adoctest-test-attribute-list () - (adoctest-faces "attribute-list" - ;; positional attribute - "[" markup-meta-face "hello" markup-value-face "]" markup-meta-face "\n" nil - ;; positional attribute containing spaces - "[" markup-meta-face "hello world" markup-value-face "]" markup-meta-face "\n" nil - ;; positional attribute as string - "[\"" markup-meta-face "hello world" markup-value-face "\"]" markup-meta-face "\n" nil - - ;; multiple positional attributes - "[" markup-meta-face "hello" markup-value-face "," markup-meta-face "world" markup-value-face "]" markup-meta-face "\n" nil - - ;; multiple positional attributes, however one or both are empty (really empty or only one space) - "[" markup-meta-face "hello" markup-value-face ",]" markup-meta-face "\n" nil - "[" markup-meta-face "hello" markup-value-face "," markup-meta-face " " markup-value-face "]" markup-meta-face "\n" nil - "[," markup-meta-face "hello" markup-value-face "]" markup-meta-face "\n" nil - "[" markup-meta-face " " markup-value-face "," markup-meta-face "hello" markup-value-face "]" markup-meta-face "\n" nil - "[,]" markup-meta-face "\n" nil - "[," markup-meta-face " " markup-value-face "]" markup-meta-face "\n" nil - "[" markup-meta-face " " markup-value-face ",]" markup-meta-face "\n" nil - "[" markup-meta-face " " markup-value-face "," markup-meta-face " " markup-value-face "]" markup-meta-face "\n" nil - - ;; zero positional attributes - "[]" markup-meta-face "\n" nil - "[" markup-meta-face " " markup-value-face "]" markup-meta-face "\n" nil - - ;; keyword attribute - "[" markup-meta-face "salute" markup-attribute-face "=" markup-meta-face "hello" markup-value-face "]" markup-meta-face "\n" nil - ;; keyword attribute where value is a string - "[" markup-meta-face "salute" markup-attribute-face "=\"" markup-meta-face "hello world" markup-value-face "\"]" markup-meta-face "\n" nil - - ;; multiple positional attributes, multiple keyword attributes - "[" markup-meta-face "lorem" markup-value-face "," markup-meta-face "ipsum" markup-value-face "," markup-meta-face - "dolor" markup-attribute-face "=" markup-meta-face "sit" markup-value-face "," markup-meta-face - "dolor" markup-attribute-face "=" markup-meta-face "sit" markup-value-face "]" markup-meta-face "\n" nil - - ;; is , within strings really part of the string and not mistaken as element separator - "[\"" markup-meta-face "lorem,ipsum=dolor" markup-value-face "\"]" markup-meta-face "\n" nil - ;; does escaping " in strings work - "[\"" markup-meta-face "lorem \\\"ipsum\\\" dolor" markup-value-face "\"]" markup-meta-face - )) - -(ert-deftest adoctest-test-block-macro () - (adoctest-faces "block-macro" - "lorem" markup-command-face "::" markup-meta-face "ipsum[]" markup-meta-face)) - -(ert-deftest adoctest-test-quotes-simple () - (adoctest-faces "test-quotes-simple" - ;; note that in unconstraned quotes cases " ipsum " has spaces around, in - ;; constrained quotes case it doesn't - "Lorem " nil "`" markup-meta-hide-face "ipsum" '(markup-typewriter-face markup-verbatim-face) "`" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "+++" markup-meta-hide-face " ipsum " '(markup-typewriter-face markup-verbatim-face) "+++" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "$$" markup-meta-hide-face " ipsum " '(markup-typewriter-face markup-verbatim-face) "$$" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "**" markup-meta-hide-face " ipsum " markup-strong-face "**" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "*" markup-meta-hide-face "ipsum" markup-strong-face "*" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "``" markup-replacement-face "ipsum" nil "''" markup-replacement-face " dolor\n" nil - "Lorem " nil "'" markup-meta-hide-face "ipsum" markup-emphasis-face "'" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "`" markup-replacement-face "ipsum" nil "'" markup-replacement-face " dolor\n" nil - "Lorem " nil "++" markup-meta-hide-face " ipsum " markup-typewriter-face "++" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "+" markup-meta-hide-face "ipsum" markup-typewriter-face "+" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "__" markup-meta-hide-face " ipsum " markup-emphasis-face "__" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "_" markup-meta-hide-face "ipsum" markup-emphasis-face "_" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "##" markup-meta-hide-face " ipsum " markup-gen-face "##" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "#" markup-meta-hide-face "ipsum" markup-gen-face "#" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "~" markup-meta-hide-face " ipsum " markup-subscript-face "~" markup-meta-hide-face " dolor\n" nil - "Lorem " nil "^" markup-meta-hide-face " ipsum " markup-superscript-face "^" markup-meta-hide-face " dolor")) - -(ert-deftest adoctest-test-quotes-medium () - (adoctest-faces "test-quotes-medium" - ;; test wheter constrained/unconstrained quotes can spawn multiple lines - "Lorem " 'no-face "*" markup-meta-hide-face "ipsum" markup-strong-face - "\n" nil "dolor" markup-strong-face "\n" nil "dolor" markup-strong-face - "\n" nil "dolor" markup-strong-face "\n" nil "dolor" markup-strong-face - "*" markup-meta-hide-face - " sit" 'no-face "\n" nil - - "Lorem " 'no-face "__" markup-meta-hide-face "ipsum" markup-emphasis-face - "\n" nil "dolor" markup-emphasis-face "\n" nil "dolor" markup-emphasis-face - "\n" nil "dolor" markup-emphasis-face "\n" nil "dolor" markup-emphasis-face - "__" markup-meta-hide-face - " sit" 'no-face "\n" nil - - ;; tests border case that delimiter is at the beginnin/end of an paragraph/line - ;; constrained at beginning - "*" markup-meta-hide-face "lorem" 'markup-strong-face "*" markup-meta-hide-face " ipsum\n" 'no-face - "\n" nil - ;; constrained at end - "lorem " 'no-face "*" markup-meta-hide-face "ipsum" markup-strong-face "*" markup-meta-hide-face "\n" nil - "\n" nil - ;; constrained from beginning to end - "*" markup-meta-hide-face "lorem" markup-strong-face "*" markup-meta-hide-face "\n" nil - "\n" nil - ;; unconstrained at beginning. Note that "** " at the beginning of a line would be a list item. - "__" markup-meta-hide-face " lorem " 'markup-emphasis-face "__" markup-meta-hide-face " ipsum\n" 'no-face - "\n" nil - ;; unconstrained at end - "lorem " 'no-face "__" markup-meta-hide-face " ipsum " markup-emphasis-face "__" markup-meta-hide-face "\n" nil - "\n" nil - ;; unconstrained from beginning to end - "__" markup-meta-hide-face " lorem " markup-emphasis-face "__" markup-meta-hide-face "\n" nil - "\n" nil - - ;; test wheter quotes can nest - ;; done by meta-face-cleanup - - ;; tests that quotes work within titles / labeled lists - "== " markup-meta-hide-face "chapter " markup-title-1-face "*" markup-meta-hide-face "1" '(markup-title-1-face markup-strong-face) "*" markup-meta-hide-face " ==" markup-meta-hide-face "\n" nil - "\n" nil - "chapter " markup-title-2-face "_" markup-meta-hide-face "2" '(markup-title-2-face markup-emphasis-face) "_" markup-meta-hide-face "\n" nil - "~~~~~~~~~~~" markup-meta-hide-face "\n" nil - "." markup-meta-face "lorem " 'markup-gen-face "_" markup-meta-hide-face "ipsum" '(markup-gen-face markup-emphasis-face) "_" markup-meta-hide-face "\n" nil - "\n" nil - "lorem " markup-gen-face "+" markup-meta-hide-face "ipsum" '(markup-gen-face markup-typewriter-face) "+" markup-meta-hide-face " sit" markup-gen-face "::" markup-list-face " " adoc-align - )) - -;; test border cases where the quote delimiter is at the beginning and/or the -;; end of the buffer -(ert-deftest adoctest-test-quotes-medium-2 () - (adoctest-faces "test-quotes-medium-2" - "*" markup-meta-hide-face "lorem" markup-strong-face "*" markup-meta-hide-face " ipsum" 'no-face)) -(ert-deftest adoctest-test-quotes-medium-3 () - (adoctest-faces "test-quotes-medium-3" - "lorem " 'no-face "*" markup-meta-hide-face "ipsum" markup-strong-face "*" markup-meta-hide-face)) -(ert-deftest adoctest-test-quotes-medium-4 () - (adoctest-faces "test-quotes-medium-4" - "*" markup-meta-hide-face "lorem" markup-strong-face "*" markup-meta-hide-face)) - -(ert-deftest adoctest-test-lists-simple () - (adoctest-faces "test-lists-simple" - " " adoc-align "-" markup-list-face " " adoc-align "uo list item\n" nil - " " adoc-align "*" markup-list-face " " adoc-align "uo list item\n" nil - " " adoc-align "**" markup-list-face " " adoc-align "uo list item\n" nil - " " adoc-align "***" markup-list-face " " adoc-align "uo list item\n" nil - " " adoc-align "****" markup-list-face " " adoc-align "uo list item\n" nil - " " adoc-align "*****" markup-list-face " " adoc-align "uo list item\n" nil - "+" markup-list-face " " adoc-align "uo list item\n" nil - - " " adoc-align "1." markup-list-face " " adoc-align "o list item\n" nil - " " adoc-align "a." markup-list-face " " adoc-align "o list item\n" nil - " " adoc-align "B." markup-list-face " " adoc-align "o list item\n" nil - " " adoc-align "ii)" markup-list-face " " adoc-align "o list item\n" nil - " " adoc-align "II)" markup-list-face " " adoc-align "o list item\n" nil - - " " adoc-align "." markup-list-face " " adoc-align "implicitly numbered list item\n" nil - " " adoc-align ".." markup-list-face " " adoc-align "implicitly numbered list item\n" nil - " " adoc-align "..." markup-list-face " " adoc-align "implicitly numbered list item\n" nil - " " adoc-align "...." markup-list-face " " adoc-align "implicitly numbered list item\n" nil - " " adoc-align "....." markup-list-face " " adoc-align "implicitly numbered list item\n" nil - "<1>" markup-list-face " " adoc-align "callout\n" nil - "1>" markup-list-face " " adoc-align "callout\n" nil - - " " adoc-align "term" markup-gen-face "::" markup-list-face " " adoc-align "lorem ipsum\n" nil - " " adoc-align "term" markup-gen-face ";;" markup-list-face " " adoc-align "lorem ipsum\n" nil - " " adoc-align "term" markup-gen-face ":::" markup-list-face " " adoc-align "lorem ipsum\n" nil - " " adoc-align "term" markup-gen-face "::::" markup-list-face " " adoc-align "lorem ipsum\n" nil - " " adoc-align "question" markup-gen-face "??" markup-list-face "\n" nil - "glossary" markup-gen-face ":-" markup-list-face "\n" nil - - "-" markup-list-face " " adoc-align "uo list item\n" nil - "+" markup-meta-face "\n" nil - "2nd list paragraph\n" nil )) - -(ert-deftest adoctest-test-lists-medium () - (adoctest-faces "test-lists-medium" - ;; white box test: labeled list item font lock keyword is implemented - ;; specially in that it puts adoc-reserved text-property on the preceding - ;; newline. However it shall deal with the situation that there is no - ;; preceding newline, because we're at the beginning of the buffer - "lorem" markup-gen-face "::" markup-list-face " " nil "ipsum" 'no-face)) - -(ert-deftest adoctest-test-inline-macros () - (adoctest-faces "inline-macros" - "commandname" markup-command-face ":target[" markup-meta-face "attribute list" markup-value-face "]" markup-meta-face)) - -(ert-deftest adoctest-test-meta-face-cleanup () - ;; begin with a few simple explicit cases which are easier to debug in case of troubles - - ;; 1) test that meta characters always only have a single meta and don't get - ;; markup-bold/-emphasis/... face just because they are within a - ;; strongh/emphasis/... construct. - ;; 2) test that nested quotes really apply the faces of both quotes to the inner text - (adoctest-faces "meta-face-cleanup-1" - "*" markup-meta-hide-face "lorem " markup-strong-face - "_" markup-meta-hide-face "ipsum" '(markup-strong-face markup-emphasis-face) "_" markup-meta-hide-face - " dolor" markup-strong-face "*" markup-meta-hide-face "\n" nil) - (adoctest-faces "meta-face-cleanup-2" - "_" markup-meta-hide-face "lorem " markup-emphasis-face - "*" markup-meta-hide-face "ipsum" '(markup-strong-face markup-emphasis-face) "*" markup-meta-hide-face - " dolor" markup-emphasis-face "_" markup-meta-hide-face) - - ;; now test all possible cases - ;; mmm, that is all possible cases inbetween constrained/unconstrained quotes - - ;; .... todo - ) - -(ert-deftest adoctest-test-url () - (adoctest-faces "url" - ;; url inline macro with attriblist - "foo " nil - "http://www.lorem.com/ipsum.html" markup-internal-reference-face - "[" markup-meta-face "sit amet" markup-reference-face "]" markup-meta-face - " bar \n" nil - ;; link text contains newlines and commas - "http://www.lorem.com/ipsum.html" markup-internal-reference-face - "[" markup-meta-face - "sit,\namet,\nconsectetur" markup-reference-face - "]" markup-meta-face - " bar \n" nil - ;; url inline macro withOUT attriblist - "http://www.lorem.com/ipsum.html" markup-reference-face - "[]" markup-meta-face - " bar \n" nil - ;; plain url - "http://www.lorem.com/ipsum.html" markup-reference-face - " foo " nil "joe.bloggs@foobar.com" markup-reference-face )) - -(ert-deftest adoctest-test-url-enclosing-quote () - (adoctest-faces "url-enclosing-quote" - ;; spaces between __ and url seem really to be needed also in asciidoc - "foo " nil "__" markup-meta-hide-face " " nil - "http://www.lorem.com/ipsum.html" '(markup-emphasis-face markup-reference-face) - " " nil "__" markup-meta-hide-face - - "\nfoo " nil - "**" markup-meta-hide-face " " nil - "joe.bloggs@foobar.com" '(markup-strong-face markup-reference-face) - " " nil "**" markup-meta-hide-face )) - -;; inline substitutions only within the block they belong to. I.e. don't cross -;; block boundaries. -(ert-deftest adoctest-test-inline-subst-boundaries () - (adoctest-faces "inline-subst-boundaries" - - ;; 1) don't cross title boundaries. - ;; 2) don't cross paragraph boundaries. - ;; 3) verify that the (un)constrained quotes would work however - "== " markup-meta-hide-face "chapter ** 1" markup-title-1-face "\n" nil - "lorem ** ipsum\n" 'no-face - "\n" nil - "lorem " 'no-face "**" markup-meta-hide-face " ipsum " markup-strong-face "**" markup-meta-hide-face "\n" nil - "\n" nil - - "== " markup-meta-hide-face "chapter __ 1" markup-title-1-face " ==" markup-meta-hide-face "\n" nil - "lorem __ ipsum\n" 'no-face - "\n" nil - "lorem " 'no-face "__" markup-meta-hide-face " ipsum " markup-emphasis-face "__" markup-meta-hide-face "\n" nil - "\n" nil - - "chapter ++ 1" markup-title-1-face "\n" nil - "------------" markup-meta-hide-face "\n" nil - "lorem ++ ipsum\n" 'no-face - "\n" nil - "lorem " 'no-face "++" markup-meta-hide-face " ipsum " markup-typewriter-face "++" markup-meta-hide-face "\n" nil - "\n" nil - - "." markup-meta-face "block ^title" markup-gen-face "\n" nil - "lorem^ ipsum\n" 'no-face - "\n" nil - "lorem " 'no-face "^" markup-meta-hide-face " ipsum " markup-superscript-face "^" markup-meta-hide-face "\n" nil - "\n" nil - - ;; Being able to use a ** that potentially could be mistaken as an end - ;; delimiter as start delimiter - "== " markup-meta-hide-face "chapter ** 1" markup-title-1-face "\n" nil - "lorem " 'no-face "**" markup-meta-hide-face " ipsum " markup-strong-face "**" markup-meta-hide-face "\n" nil - "\n" nil - - ;; don't cross list item boundaries - "-" markup-list-face " " nil "lorem ** ipsum\n" 'no-face - "-" markup-list-face " " nil "dolor ** sit\n" 'no-face - ;; test that a quote within the list element works - "-" markup-list-face " " nil "dolor " 'no-face "**" markup-meta-hide-face " sit " markup-strong-face "**" markup-meta-hide-face "\n" nil - ;; dont mistake '**' list elements for quote starters/enders - "**" markup-list-face " " nil "lorem ** ipsum\n" 'no-face - "**" markup-list-face " " nil "dolor ** sit\n" 'no-face - "**" markup-list-face " " nil "dolor ** sit\n" 'no-face - ;; don't cross list item boundaries in the case of labeled lists - "lorem ** ipsum " markup-gen-face "::" markup-list-face " " nil "sit ** dolor\n" 'no-face - "lorem ** ipsum " markup-gen-face "::" markup-list-face " " nil "sit ** dolor" 'no-face)) - -(ert-deftest adoctest-test-promote-title () - (adoctest-trans "= foo" "== foo" '(adoc-promote-title 1)) - (adoctest-trans "===== foo" "= foo" '(adoc-promote-title 1)) - (adoctest-trans "== foo" "==== foo" '(adoc-promote-title 2)) - - (adoctest-trans "= foo =" "== foo ==" '(adoc-promote-title 1)) - (adoctest-trans "===== foo =====" "= foo =" '(adoc-promote-title 1)) - (adoctest-trans "== foo ==" "==== foo ====" '(adoc-promote-title 2)) - - (adoctest-trans "foo!\n===!" "foo\n---" '(adoc-promote-title 1)) - (adoctest-trans "foo!\n+++!" "foo\n===" '(adoc-promote-title 1)) - (adoctest-trans "foo!\n---!" "foo\n^^^" '(adoc-promote-title 2))) - -;; since it's a whitebox test we know demote and promote only differ by inverse -;; arg. So demote doesn't need to be throuhly tested again -(ert-deftest adoctest-test-demote-title () - (adoctest-trans "= foo" "===== foo" '(adoc-demote-title 1)) - (adoctest-trans "= foo =" "===== foo =====" '(adoc-demote-title 1)) - (adoctest-trans "foo!\n===!" "foo\n+++" '(adoc-demote-title 1))) - -;; todo: test after transition point is still on title lines -(ert-deftest adoctest-test-toggle-title-type () - (adoctest-trans "= one" "one\n===" '(adoc-toggle-title-type)) - (adoctest-trans "two!\n===!" "= two" '(adoc-toggle-title-type)) - (adoctest-trans "= three!\nbar" "three\n=====\nbar" '(adoc-toggle-title-type)) - (adoctest-trans "four!\n====!\nbar" "= four\nbar" '(adoc-toggle-title-type)) - (adoctest-trans "= five" "= five =" '(adoc-toggle-title-type t)) - (adoctest-trans "= six =" "= six" '(adoc-toggle-title-type t))) - -(ert-deftest adoctest-test-adjust-title-del () - (adoctest-trans "lorem!\n===!" "lorem\n=====" '(adoc-adjust-title-del)) - (adoctest-trans "lorem!\n========!" "lorem\n=====" '(adoc-adjust-title-del)) - (adoctest-trans "lorem!\n=====!" "lorem\n=====" '(adoc-adjust-title-del))) - -(ert-deftest adoctest-test-xref-at-point-1 () - (unwind-protect - (progn - (set-buffer (get-buffer-create "adoc-test")) - (insert "lorem xref:bogous1[] ipsum xref:foo[bla\nbli] dolor xref:bogous2[]") - (re-search-backward "bli") ; move point within ref - (should (equal (adoc-xref-id-at-point) "foo"))) - (kill-buffer "adoc-test"))) - -(ert-deftest adoctest-test-xref-at-point-2 () - (unwind-protect - (progn - (set-buffer (get-buffer-create "adoc-test")) - (insert "lorem <> ipsum <> dolor <>") - (re-search-backward "bli") ; move point within ref - (should (equal (adoc-xref-id-at-point) "foo"))) - (kill-buffer "adoc-test"))) - -(ert-deftest adoctest-test-goto-ref-label () - (unwind-protect - (progn - (set-buffer (get-buffer-create "adoc-test")) - (insert "[[foo]]\n" ;1 - "lorem ipsum\n" ;2 - "[[bar]]\n" ;3 - "dolor [[geil]]sit amen\n" ;4 - "anchor:cool[]\n") ;5 - (adoc-goto-ref-label "cool") - (should (equal (line-number-at-pos) 5)) - (adoc-goto-ref-label "geil") - (should (equal (line-number-at-pos) 4)) - (adoc-goto-ref-label "bar") - (should (equal (line-number-at-pos) 3))) - (kill-buffer "adoc-test"))) - -(defun adoctest-template (template expected) - (let ((buf-name (concat "adoctest-" (symbol-name template)))) - (unwind-protect - (progn - ;; setup - (set-buffer (get-buffer-create buf-name)) - (delete-region (point-min) (point-max)) - (funcall template) - (should (equal (buffer-substring-no-properties (point-min) (point-max)) expected))) - ;; tear-down - (kill-buffer buf-name)))) - -(defun adoctest-quotes (start-del end-del transform) - (adoctest-trans "lorem ! ipsum" - (concat "lorem " start-del end-del " ipsum") transform) - (adoctest-trans "lorem dolor" - (concat "lorem " start-del "ipsum" end-del " dolor") transform)) - -;; todo: test templates also with tempo-snippets -(ert-deftest adoctest-test-tempo-quotes () - (adoctest-quotes "_" "_" '(tempo-template-adoc-emphasis)) - (adoctest-quotes "*" "*" '(tempo-template-adoc-strong)) - (adoctest-quotes "+" "+" '(tempo-template-adoc-monospace)) - (adoctest-quotes "`" "`" '(tempo-template-adoc-monospace-literal)) - (adoctest-quotes "`" "'" '(tempo-template-adoc-single-quote)) - (adoctest-quotes "``" "''" '(tempo-template-adoc-double-quote)) - (adoctest-quotes "[]#" "#" '(tempo-template-adoc-attributed)) - (adoctest-quotes "__" "__" '(tempo-template-adoc-emphasis-uc)) - (adoctest-quotes "**" "**" '(tempo-template-adoc-strong-uc)) - (adoctest-quotes "++" "++" '(tempo-template-adoc-monospace-uc)) - (adoctest-quotes "^" "^" '(tempo-template-adoc-superscript)) - (adoctest-quotes "~" "~" '(tempo-template-adoc-subscript))) - -(ert-deftest adoctest-test-tempo-formatting-misc () - - (adoctest-trans "" " +" '(tempo-template-adoc-line-break)) - (adoctest-trans "lor!em" "lor +\nem" '(tempo-template-adoc-line-break)) - ;; dont change only white sequence between point and end of line - (adoctest-trans "lorem! \nipsum" "lorem + \nipsum" '(tempo-template-adoc-line-break)) - ;; if befor point already a space is, dont insert a new one - (adoctest-trans "lorem !\nipsum" "lorem +\nipsum" '(tempo-template-adoc-line-break)) - - (adoctest-trans "" "<<<" '(tempo-template-adoc-page-break)) - (adoctest-trans "lorem\n!\nipsum" "lorem\n<<<\nipsum" '(tempo-template-adoc-page-break)) - (adoctest-trans "lor!em\nipsum" "lor\n<<<\nem\nipsum" '(tempo-template-adoc-page-break)) - - (adoctest-trans "" "---" '(tempo-template-adoc-ruler-line)) - (adoctest-trans "lorem\n!\nipsum" "lorem\n---\nipsum" '(tempo-template-adoc-ruler-line)) - (adoctest-trans "lor!em\nipsum" "lor\n---\nem\nipsum" '(tempo-template-adoc-ruler-line))) - -;; todo: check buffer position after insertion (aka transionsion). Probably -;; factor out from adoctest-trans a defun which translates a string containing -;; !s into one with the ! stripped and a buffer-position-list -(ert-deftest adoctest-test-tempo-title () - (let ((adoc-title-style 'adoc-title-style-one-line)) - ;; BUG!! somehow I need to load adoc-mode twice until it works!!! - (adoctest-trans "" "= " '(tempo-template-adoc-title-1)) - (adoctest-trans "" "=== " '(tempo-template-adoc-title-3)) - (adoctest-trans "lorem\n!\nipsum" "lorem\n= \nipsum" '(tempo-template-adoc-title-1))) - - (let ((adoc-title-style 'adoc-title-style-one-line-enclosed)) - (adoctest-trans "" "= =" '(tempo-template-adoc-title-1)) - (adoctest-trans "" "=== ===" '(tempo-template-adoc-title-3)) - (adoctest-trans "lorem\n!\nipsum" "lorem\n= =\nipsum" '(tempo-template-adoc-title-1))) - - (let ((adoc-title-style 'adoc-title-style-two-line)) - (adoctest-trans "" "\n====" '(tempo-template-adoc-title-1)) - (adoctest-trans "" "\n~~~~" '(tempo-template-adoc-title-3)) - (adoctest-trans "lorem\n!\nipsum" "lorem\n\n====\nipsum" '(tempo-template-adoc-title-1)))) - -(ert-deftest adoctest-test-tempo-paragraphs () - (adoctest-trans "" " " '(tempo-template-adoc-literal-paragraph)) - (adoctest-trans "lorem" "lorem\n ipsum" '(tempo-template-adoc-literal-paragraph)) - (adoctest-trans "" "TIP: " '(tempo-template-adoc-paragraph-tip)) - (adoctest-trans "lorem" "lorem\nTIP: ipsum" '(tempo-template-adoc-paragraph-tip))) - -(defun adoctest-delimited-block (del transform) - (let ((del-line (if (integerp del) (make-string 50 del) del))) - (adoctest-trans - "" (concat del-line "\n\n" del-line) transform) - (adoctest-trans - "lorem\n!\nipsum" (concat "lorem\n" del-line "\n\n" del-line "\nipsum") transform) - (adoctest-trans - "lorem\n\ndolor" (concat "lorem\n" del-line "\nipsum\n" del-line "\ndolor") transform) - (adoctest-trans - "lorem !dolor" (concat "lorem \n" del-line "\n\n" del-line "\ndolor") transform) - (adoctest-trans - "lorem dolor" (concat "lorem \n" del-line "\nipsum \n" del-line "\ndolor") transform))) - -(ert-deftest adoctest-test-tempo-delimited-blocks () - (adoctest-delimited-block ?/ '(tempo-template-adoc-delimited-block-comment)) - (adoctest-delimited-block ?+ '(tempo-template-adoc-delimited-block-passthrough)) - (adoctest-delimited-block ?- '(tempo-template-adoc-delimited-block-listing)) - (adoctest-delimited-block ?. '(tempo-template-adoc-delimited-block-literal)) - (adoctest-delimited-block ?_ '(tempo-template-adoc-delimited-block-quote)) - (adoctest-delimited-block ?= '(tempo-template-adoc-delimited-block-example)) - (adoctest-delimited-block ?* '(tempo-template-adoc-delimited-block-sidebar)) - (adoctest-delimited-block "--" '(tempo-template-adoc-delimited-block-open-block))) - -(ert-deftest adoctest-test-tempo-lists () - (let ((tab-width 2) - (indent-tabs-mode nil)) - (adoctest-trans "" "- " '(tempo-template-adoc-bulleted-list-item-1)) - (adoctest-trans "" " ** " '(tempo-template-adoc-bulleted-list-item-2)) - (adoctest-trans "" "- foo" '(tempo-template-adoc-bulleted-list-item-1)) - (adoctest-trans "" ":: " '(tempo-template-adoc-labeled-list-item)) - (adoctest-trans "" ":: foo" '(tempo-template-adoc-labeled-list-item)))) - -(ert-deftest adoctest-test-tempo-macros () - (adoctest-trans "" "http://foo.com[]" '(tempo-template-adoc-url-caption)) - (adoctest-trans "see for" "see http://foo.com[here] for" '(tempo-template-adoc-url-caption)) - (adoctest-trans "" "mailto:[]" '(tempo-template-adoc-email-caption)) - (adoctest-trans "ask for" "ask mailto:[bob] for" '(tempo-template-adoc-email-caption)) - (adoctest-trans "" "[[]]" '(tempo-template-adoc-anchor)) - (adoctest-trans "lorem dolor" "lorem [[ipsum]] dolor" '(tempo-template-adoc-anchor)) - (adoctest-trans "" "anchor:[]" '(tempo-template-adoc-anchor-default-syntax)) - (adoctest-trans "lorem dolor" "lorem anchor:ipsum[] dolor" '(tempo-template-adoc-anchor-default-syntax)) - (adoctest-trans "" "<<,>>" '(tempo-template-adoc-xref)) - (adoctest-trans "see for" "see <<,here>> for" '(tempo-template-adoc-xref)) - (adoctest-trans "" "xref:[]" '(tempo-template-adoc-xref-default-syntax)) - (adoctest-trans "see for" "see xref:[here] for" '(tempo-template-adoc-xref-default-syntax)) - (adoctest-trans "" "image:[]" '(tempo-template-adoc-image))) - -(ert-deftest adoctest-test-tempo-passthroug-macros () - ;; backticks are tested in adoctest-test-tempo-quotes - (adoctest-trans "" "pass:[]" '(tempo-template-adoc-pass)) - (adoctest-trans "lorem dolor" "lorem pass:[ipsum] dolor" '(tempo-template-adoc-pass)) - (adoctest-trans "" "asciimath:[]" '(tempo-template-adoc-asciimath)) - (adoctest-trans "lorem dolor" "lorem asciimath:[ipsum] dolor" '(tempo-template-adoc-asciimath)) - (adoctest-trans "" "latexmath:[]" '(tempo-template-adoc-latexmath)) - (adoctest-trans "lorem dolor" "lorem latexmath:[ipsum] dolor" '(tempo-template-adoc-latexmath)) - (adoctest-trans "" "++++++" '(tempo-template-adoc-pass-+++)) - (adoctest-trans "lorem dolor" "lorem +++ipsum+++ dolor" '(tempo-template-adoc-pass-+++)) - (adoctest-trans "" "$$$$" '(tempo-template-adoc-pass-$$)) - (adoctest-trans "lorem dolor" "lorem $$ipsum$$ dolor" '(tempo-template-adoc-pass-$$))) - -(ert-deftest adoctest-test-make-two-line-title-underline () - (should (equal (adoc-make-two-line-title-underline 0 6) - "======")) - (should (equal (adoc-make-two-line-title-underline 2) - "~~~~"))) - -(ert-deftest adoctest-test-repeat-string () - (should (equal (adoc-repeat-string "lorem" 0) "")) - (should (equal (adoc-repeat-string "lorem" 1) "lorem")) - (should (equal (adoc-repeat-string "lorem" 2) "loremlorem"))) - -(ert-deftest adoctest-test-indent-by-example () - (let ((tab-width 2) - (indent-tabs-mode nil)) - (adoctest-trans "" " x" '(adoc-insert-indented "x" 1)) - (adoctest-trans "" " x" '(adoc-insert-indented "x" 2))) - - (let ((tab-width 3) - (indent-tabs-mode t)) - (adoctest-trans "" " x" '(adoc-insert-indented "x" 1)) - (adoctest-trans "" "\t x" '(adoc-insert-indented "x" 2)))) - -(ert-deftest adoctest-test-imenu-create-index () - (unwind-protect - (progn - (set-buffer (get-buffer-create "adoc-test")) - (insert "= document title\n" - "== chapter 1\n" - "=== sub chapter 1.1\n" - "chapter 2\n" - "----------\n" - "sub chapter 2.1\n" - "~~~~~~~~~~~~~~\n") - (should - (equal - (adoc-imenu-create-index) - (list - (cons "document title" 1) - (cons "chapter 1" 18) - (cons "sub chapter 1.1" 31) - (cons "chapter 2" 51) - (cons "sub chapter 2.1" 72))))) - (kill-buffer "adoc-test"))) - -;; purpose -;; - ensure that the latest version, i.e. the one currently in buffer(s), of -;; adoc-mode and adoc-mode-test is used for the test -;; - test that adoc-mode and adoc-mode-test are compileble & loadable -;; - ensure no *.elc are lying around because they are 'dangerous' when the -;; corresponding .el is edited regulary; dangerous because it's not unlikely -;; that the .el is newer than the .elc, but load-library takes the outdated -;; .elc. -;; -;; todo: also test for warnings -(defun adoctest-save-compile-load () - (unwind-protect - (progn - (let ((buf-adoc-mode (find-buffer-visiting "adoc-mode.el")) - (buf-adoc-mode-test (find-buffer-visiting "adoc-mode-test.el"))) - - ;; adoc-mode - (cond - ((null buf-adoc-mode)) ;nop - ((bufferp buf-adoc-mode) (save-buffer buf-adoc-mode)) - (t (error "Multiple buffer are visiting adoc-mode.el. Save them first"))) - (or (byte-compile-file (locate-library "adoc-mode.el" t)) (error "compile error")) - (or (load "adoc-mode.el" nil nil t) (error "load error")) - - ;; adoc-mode-test - (cond - ((null buf-adoc-mode-test)) ;nop - ((bufferp buf-adoc-mode-test) (save-buffer buf-adoc-mode-test)) - (t (error "Multiple buffer are visiting adoc-mode-test.el. Save them first"))) - (or (byte-compile-file (locate-library "adoc-mode-test.el" t)) (error "compile error")) - (or (load "adoc-mode-test.el" nil nil t) (error "load error")))) - - (when (file-exists-p "adoc-mode.elc") - (delete-file "adoc-mode.elc")) - (when (file-exists-p "adoc-mode-test.elc") - (delete-file "adoc-mode-test.elc")))) - -(defun adoc-test-run() - (interactive) - - ;; ensure that a failed test can be re-run - (when (get-buffer "*ert*") - (kill-buffer "*ert*")) - - ;; ensure no no-longer test defuns exist, which would otherwise be executed - (mapatoms - (lambda (x) (if (string-match "^adoctest-test-" (symbol-name x)) - (unintern x nil)))) - - (adoctest-save-compile-load) - - ;; todo: execute tests in an smart order: the basic/simple tests first, so - ;; when a complicated test fails one knows that the simple things do work - (ert-run-tests-interactively "^adoctest-test-")) - -;;; adoc-mode-test.el ends here diff --git a/adoc-mode.el b/adoc-mode.el index 87e9650..312dff7 100644 --- a/adoc-mode.el +++ b/adoc-mode.el @@ -1,16 +1,18 @@ -;;; adoc-mode.el --- a major-mode for editing AsciiDoc files in Emacs +;;; adoc-mode.el --- a major-mode for editing AsciiDoc files -*- lexical-binding: t; -*- ;; -;; Copyright 2010-2013 Florian Kaufmann +;; Copyright 2009-2016 Florian Kaufmann +;; Copyright 2022-2023 Bozhidar Batsov and adoc-mode contributors ;; ;; Author: Florian Kaufmann -;; URL: https://github.com/sensorflo/adoc-mode/wiki +;; URL: https://github.com/bbatsov/adoc-mode +;; Maintainer: Bozhidar Batsov ;; Created: 2009 -;; Version: 0.6.6 -;; Package-Requires: ((markup-faces "1.0.0")) -;; Keywords: wp AsciiDoc -;; +;; Version: 0.8.0-snapshot +;; Package-Requires: ((emacs "26")) +;; Keywords: docs, wp +;; ;; This file is not part of GNU Emacs. -;; +;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) @@ -25,185 +27,45 @@ ;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth ;; Floor, Boston, MA 02110-1301, USA. -;; -;; -;; The syntax of the following commentary section is Markdown, so the same text -;; can be used for the wiki page on GitHub. Also, each paragraph, including list -;; items, are separated by blank lines, so it also looks good on Marmalade. + ;;; Commentary: -;; -;; # Introduction -;; -;; [AsciiDoc](http://www.methods.co.nz/asciidoc/) is a text document format for -;; writing short documents, articles, books and UNIX man pages. AsciiDoc files + +;; AsciiDoc is a text document format for +;; writing short documents, articles, books and UNIX man pages. AsciiDoc files ;; can be translated to HTML and DocBook markups. -;; -;; adoc-mode is an Emacs major mode for editing AsciiDoc files. It emphasizes on +;; +;; adoc-mode is an Emacs major mode for editing AsciiDoc files. It emphasizes on ;; the idea that the document is highlighted so it pretty much looks like the -;; final output. What must be bold is bold, what must be italic is italic etc. +;; final output. What must be bold is bold, what must be italic is italic etc. ;; Meta characters are naturally still visible, but in a faint way, so they can ;; be easily ignored. -;; -;; -;; # Download -;; -;; The raw file (adoc-mode.el) can be found -;; [here](https://raw.github.com/sensorflo/adoc-mode/master/adoc-mode.el). -;; Optionally you can get the sources from the [git -;; repository](https://github.com/sensorflo/adoc-mode). -;; -;; You will also need to download the library -;; [markup-faces](https://github.com/sensorflo/markup-faces). If you install -;; adoc-mode via Emacs Lisp Packages, see below, markup-faces is installed -;; automatically if you don't have it yet. -;; -;; -;; # Installation -;; -;; Installation is as usual, so if you are proficient with Emacs you don't need -;; to read this. -;; -;; ## Install the traditional way -;; -;; 1. Copy the file adoc-mode.el to a directory in your load-path, e.g. -;; \~/.emacs.d. To add a specific directory to the load path, add this to our -;; initialization file (probably ~/.emacs): `(add-to-list 'load-path -;; "mypath")` -;; -;; 2. Add either of the two following lines to your initialization file. The -;; first only loads adoc mode when necessary, the 2nd always during startup -;; of Emacs. -;; -;; * `(autoload 'adoc-mode "adoc-mode" nil t)` -;; -;; * `(require 'adoc-mode)` -;; -;; 3. Optionally byte compile adoc-mode.el for faster startup: `M-x -;; byte-compile` -;; -;; 4. To use adoc mode, call adoc-mode after you opened an AsciiDoc file: `M-x -;; adoc-mode` -;; -;; -;; ## Install via Emacs Lisp Packages (on Marmalade) -;; -;; For this way you either need packages.el from -;; [here](https://github.com/technomancy/package.el) and or Emacs 24, where the -;; packages library is already included. adoc-mode is on the -;; [Marmalade](http://marmalade-repo.org/) package archive. -;; -;; * Type `M-x package-install RET adoc-mode RET`. -;; -;; -;; ## Possible steps after installation -;; -;; Each of the following is optional -;; -;; * According to AsciiDoc manual, .txt is the standard file extension of -;; AsciiDoc files. Add the following to your initialization file to open all -;; .txt files with adoc-mode as major mode automatically: `(add-to-list -;; 'auto-mode-alist (cons "\\.txt\\'" 'adoc-mode))` -;; -;; * If your default face is a fixed pitch (monospace) face, but in AsciiDoc -;; files you liked to have normal text with a variable pitch face, -;; buffer-face-mode is for you: `(add-hook 'adoc-mode-hook (lambda() -;; (buffer-face-mode t)))` -;; -;; -;; # Features -;; -;; - sophisticated highlighting -;; -;; - promote / demote title -;; -;; - toggle title type between one line title and two line title -;; -;; - adjust underline length of a two line title to match title text's length -;; -;; - goto anchor defining a given id, default reading from xref at point -;; -;; - support for outline (however only with the one-line title style) -;; -;; -;; ## Coming features -;; -;; The next features I plan to implement -;; -;; - Demote / promote for list items -;; - Outline support also for two line titles -;; - Correctly highlighting backslash escapes -;; -;; -;; # Screenshot -;; -;; The highlighting emphasizes on how the output will look like. _All_ -;; characters are visible, however meta characters are displayed in a faint way. -;; -;; ![screenshot](http://dl.dropbox.com/u/75789984/adoc-mode.png) -;; -;; -;;; Todo: -;; - Fontlock -;; - make font-lock regexps based upon AsciiDoc configuration file, or make -;; them configurable in a way similar to that configuration file -;; - respect font-lock-maximum-decoration -;; - delimited blocks are supported, but not well at all -;; - Most regexps for highlighting can spawn at most over two lines. -;; - font-lock's multi line capabilities are not used well enough. At least 2 -;; line spawns should be covered - replace all .*? by .*?\\(?:\n.*?\\)?? -;; - backslash escapes are seldom highlighted correctly -;; - Other common Emacs functionality/features -;; - demote/promote/create/delete titles/list-items. Also put emphasis on a -;; convenient simple user interface. -;; - hideshow -;; - outline mode shall support two line titles -;; - tags tables for anchors, indixes, bibliography items, titles, ... -;; - spell check shall ignore meta characters -;; - supply a regexp for magic-mode-alist -;; - Is there something that would remove hard newlines within a paragraph, -;; but just for display, so the paragraph uses the whole buffer length. -;; - are there generic base packages to handle lists / tables? -;; - a read only view mode where commands for navigation are on short key -;; bindings like alphanum letters -;; - study what other markup modes like rst offer -;; - AsciiDoc related features -;; - Two (or gradually fading) display modes: one emphasises to see the -;; AsciiDoc source text, the other emphasises to see how the output will -;; look like. Or even hide meta characters all together - -;;; Variables: -(require 'markup-faces) ; https://github.com/sensorflo/markup-faces -(require 'cl) ; I know, I should remove it, I will, eventually -;; tempo or tempo-snippet is required later below +;;; Code: +(require 'cl-lib) +(require 'tempo) -(defconst adoc-mode-version "0.6.6" +(defconst adoc-mode-version "0.8.0-snapshot" "adoc mode version number. Based upon AsciiDoc version 8.5.2. I.e. regexeps and rules are taken from that version's asciidoc.conf / manual.") - -;;;; customization -(defgroup adoc nil - "Major-mode for editing AsciiDoc files in Emacs. - -Most faces adoc-mode uses belong to the markup-faces -customization group, see link below, and have to be customized -there. adoc-mode has only a few faces of its own, which can be -customized on this page." - :group 'wp - :link '(custom-group-link markup-faces)) +;;;; customization +(defgroup adoc nil "Support for editing AsciiDoc files in GNU Emacs." + :group 'text + :prefix "adoc-" + :version "0.8.0" + :link '(url-link "https://github.com/bbatsov/adoc-mode")) (defcustom adoc-script-raise '(-0.3 0.3) "How much to lower and raise subscript and superscript content. -This is a list of two floats. The first is negative and specifies +This is a list of two floats. The first is negative and specifies how much subscript is lowered, the second is positive and -specifies how much superscript is raised. Heights are measured -relative to that of the normal text. The faces used are -markup-superscript-face and markup-subscript-face respectively. +specifies how much superscript is raised. Heights are measured +relative to that of the normal text. The faces used are +`adoc-superscript-face' and `adoc-subscript-face' respectively. You need to call `adoc-calc' after a change." :type '(list (float :tag "Subscript") @@ -211,18 +73,18 @@ You need to call `adoc-calc' after a change." :group 'adoc) ;; Interacts very badly with minor-modes using overlays because -;; adoc-unfontify-region-function removes ALL overlays, not only those which -;; where insered by adoc-mode. +;; `adoc-unfontify-region-function' removes ALL overlays, not only those which +;; where insered by `adoc-mode'. (defcustom adoc-insert-replacement nil - "When non-nil the character/string a replacment/entity stands for is displayed. + "When non-nil the character/string a replacement/entity stands for is displayed. -E.g. after '&' an '&' is displayed, after '(C)' the copy right -sign is displayed. It's only about display, neither the file nor +E.g. after \\='&\\=' an \\='&\\=' is displayed, after \\='(C)\\=' the copy right +sign is displayed. It is only about display, neither the file nor the buffer content is affected. You need to call `adoc-calc' after you change -`adoc-insert-replacement'. For named character entities (e.g. -'&', in contrast to '' or '(C)' ) to be displayed you +`adoc-insert-replacement'. For named character entities (e.g. +\\='&\\=', in contrast to \\='\\=' or \\='(C)\\=' ) to be displayed you need to set `adoc-unichar-name-resolver'. Setting it to non-nil interacts very badly with minor-modes using @@ -231,12 +93,12 @@ overlays." :group 'adoc) (defcustom adoc-unichar-name-resolver nil - "Function taking a unicode char name and returing it's codepoint. + "Function taking a unicode char name and returning it's codepoint. E.g. when given \"amp\" (as in the character entity reference \"&\"), it shall return 38 (#x26). Is used to insert the -character a character entity reference is refering to after the -entity. When adoc-unichar-name-resolver is nil, or when its +character a character entity reference is referring to after the +entity. When adoc-unichar-name-resolver is nil, or when its function returns nil, nothing is done with named character entities. Note that if `adoc-insert-replacement' is nil, adoc-unichar-name-resolver is not used. @@ -256,22 +118,23 @@ Each string must be exactly 2 characters long. Corresponds to the underlines element in the titles section of the asciidoc configuration file." :type '(list - (string :tag "level 0") - (string :tag "level 1") - (string :tag "level 2") - (string :tag "level 3") - (string :tag "level 4") ) + (string :tag "level 0") + (string :tag "level 1") + (string :tag "level 2") + (string :tag "level 3") + (string :tag "level 4") + (string :tag "level 5")) :group 'adoc) (defcustom adoc-delimited-block-del - '("^/\\{4,\\}" ; 0 comment - "^\\+\\{4,\\}" ; 1 pass - "^-\\{4,\\}" ; 2 listing - "^\\.\\{4,\\}" ; 3 literal - "^_\\{4,\\}" ; 4 quote - "^=\\{4,\\}" ; 5 example - "^\\*\\{4,\\}" ; 6 sidebar - "^--") ; 7 open block + '("^/\\{4,\\}" ; 0 comment + "^\\+\\{4,\\}" ; 1 pass + "^-\\{4,\\}" ; 2 listing + "^\\.\\{4,\\}" ; 3 literal + "^_\\{4,\\}" ; 4 quote + "^=\\{4,\\}" ; 5 example + "^\\*\\{4,\\}" ; 6 sidebar + "^--") ; 7 open block "Regexp used for delimited blocks. WARNING: They should not contain a $. It is implied that they @@ -289,73 +152,75 @@ delimited block with '>----' and end it with '<----', then all three cases can easily be distinguished. The regexp in your AsciiDoc config file would the probably be '^[<>]-{4,}$'" :type '(list - (choice :tag "comment" - (regexp :tag "start/end regexp") - (list :tag "separate regexp" - (regexp :tag "start regexp") - (regexp :tag "end regexp"))) - (choice :tag "pass" - (regexp :tag "start/end regexp") - (list :tag "separate regexp" - (regexp :tag "start regexp") - (regexp :tag "end regexp"))) - (choice :tag "listing" - (regexp :tag "start/end regexp") - (list :tag "separate regexp" - (regexp :tag "start regexp") - (regexp :tag "end regexp"))) - (choice :tag "literal" - (regexp :tag "start/end regexp") - (list :tag "separate regexp" - (regexp :tag "start regexp") - (regexp :tag "end regexp"))) - (choice :tag "quote" - (regexp :tag "start/end regexp") - (list :tag "separate regexp" - (regexp :tag "start regexp") - (regexp :tag "end regexp"))) - (choice :tag "example" - (regexp :tag "start/end regexp") - (list :tag "separate regexp" - (regexp :tag "start regexp") - (regexp :tag "end regexp"))) - (choice :tag "sidebar" - (regexp :tag "start/end regexp") - (list :tag "separate regexp" - (regexp :tag "start regexp") - (regexp :tag "end regexp"))) - (choice :tag "open" - (regexp :tag "start/end regexp") - (list :tag "separate regexp" - (regexp :tag "start regexp") - (regexp :tag "end regexp"))))) - -;; todo: limit value range to 1 or 2 + (choice :tag "comment" + (regexp :tag "start/end regexp") + (list :tag "separate regexp" + (regexp :tag "start regexp") + (regexp :tag "end regexp"))) + (choice :tag "pass" + (regexp :tag "start/end regexp") + (list :tag "separate regexp" + (regexp :tag "start regexp") + (regexp :tag "end regexp"))) + (choice :tag "listing" + (regexp :tag "start/end regexp") + (list :tag "separate regexp" + (regexp :tag "start regexp") + (regexp :tag "end regexp"))) + (choice :tag "literal" + (regexp :tag "start/end regexp") + (list :tag "separate regexp" + (regexp :tag "start regexp") + (regexp :tag "end regexp"))) + (choice :tag "quote" + (regexp :tag "start/end regexp") + (list :tag "separate regexp" + (regexp :tag "start regexp") + (regexp :tag "end regexp"))) + (choice :tag "example" + (regexp :tag "start/end regexp") + (list :tag "separate regexp" + (regexp :tag "start regexp") + (regexp :tag "end regexp"))) + (choice :tag "sidebar" + (regexp :tag "start/end regexp") + (list :tag "separate regexp" + (regexp :tag "start regexp") + (regexp :tag "end regexp"))) + (choice :tag "open" + (regexp :tag "start/end regexp") + (list :tag "separate regexp" + (regexp :tag "start regexp") + (regexp :tag "end regexp"))))) + +;; TODO: limit value range to 1 or 2 (defcustom adoc-default-title-type 1 "Default title type, see `adoc-title-descriptor'." + :type 'integer :group 'adoc) -;; todo: limit value range to 1 or 2 +;; TODO: limit value range to 1 or 2 (defcustom adoc-default-title-sub-type 1 "Default title sub type, see `adoc-title-descriptor'." - :group 'adoc ) + :type 'integer + :group 'adoc) (defcustom adoc-enable-two-line-title t - "Wether or not two line titles shall be fontified. + "Whether or not two line titles shall be fontified. nil means never fontify. t means always fontify. A number means -only fontify if the line below has NOT the lenght of the given +only fontify if the line below has NOT the length of the given number. You could use a number for example when all your delimited block lines have a certain length. -This is usefull because adoc-mode has troubles to properly +This is useful because adoc-mode has troubles to properly distinguish between two line titles and a line of text before a delimited block. Note however that adoc-mode knows the AsciiDoc rule that the length of a two line title underline can differ at most 3 chars from the length of the title text." :type '(choice (const nil) - (const t) - number) + (const t) + number) :group 'adoc) (defcustom adoc-title-style 'adoc-title-style-one-line @@ -363,74 +228,107 @@ most 3 chars from the length of the title text." See for example `tempo-template-adoc-title-1'." :type '(choice (const :tag "== one line" adoc-title-style-one-line) - (const :tag "== one line enclosed ==" adoc-title-style-one-line-enclosed) + (const :tag "== one line enclosed ==" adoc-title-style-one-line-enclosed) (const :tag "two line\\n--------" adoc-title-style-two-line)) :group 'adoc) (defcustom adoc-tempo-frwk 'tempo-vanilla "Tempo framework to be used by adoc's templates. " :type '(choice (const :tag "tempo" tempo-vanilla) - (const :tag "tempo-snippets" tempo-snippets)) + (const :tag "tempo-snippets" tempo-snippets)) :group 'adoc) +(defcustom adoc-fontify-code-blocks-natively 5000 + "When non-nil, fontify code in code blocks using the native major mode. +This only works for code blocks where the language is +specified where we can automatically determine the appropriate +mode to use. The language to mode mapping may be customized by +setting the variable `adoc-code-lang-modes'. + +The value can be a number that determines the size +up to which code blocks are fontified natively. +If the value is another non-nil value then code blocks +are fontified natively regardless of their size." + :group 'adoc + :type '(choice :tag "Fontify code blocks " :format "\n%{%t%}: %[Size%] %v" + (integer :tag "limited to") + (boolean :tag "unlimited")) + :safe #'(lambda (x) (or (booleanp x) (numberp x))) + :package-version '(adoc-mode . "0.8.0")) + +;; This is based on `org-src-lang-modes' from org-src.el +(defcustom adoc-code-lang-modes + '( + ("asymptote" . asy-mode) + ("bash" . sh-mode) + ("C" . c-mode) + ("cpp" . c++-mode) + ("C++" . c++-mode) + ("calc" . fundamental-mode) + ("ditaa" . artist-mode) + ("dot" . fundamental-mode) + ("elisp" . emacs-lisp-mode) + ("ocaml" . tuareg-mode) + ("screen" . shell-script-mode) + ("shell" . sh-mode) + ("sqlite" . sql-mode) + ) + "Alist mapping languages to their major mode. +The key is the language name, the value is the major mode. For +many languages this is simple, but for language where this is not +the case, this variable provides a way to simplify things on the +user side. For example, there is no ocaml-mode in Emacs, but the +mode to use is `tuareg-mode'." + :group 'adoc + :type '(repeat + (cons + (string "Language name") + (symbol "Major mode"))) + :package-version '(adoc-mode . "0.8.0")) + +(defcustom adoc-fontify-code-block-default-mode 'prog-mode + "Default mode to use to fontify code blocks. +This mode is used when automatic detection fails, such as for +code blocks with no language specified." + :group 'adoc + :type '(choice function (const :tag "None" nil)) + :package-version '(adoc-mode . "0.8.0")) + +(defcustom adoc-font-lock-extend-after-change-max 5000 + "Number of chars scanned backwards for re-fontification of code block headers. +Also used to delimit the scan for the end delimiter." + :type 'integer + :group 'adoc + :package-version '(adoc-mode . "0.8.0")) + -;;;; faces / font lock -(define-obsolete-face-alias 'adoc-orig-default 'adoc-align "23.3") -(defface adoc-align - '((t (:inherit (markup-meta-face)))) +;;;; faces / font lock +(define-obsolete-face-alias 'adoc-orig-default 'adoc-align-face "23.3") +(defface adoc-align-face + '((t (:inherit (adoc-meta-face)))) "Face used so the text looks left aligned. Is applied to whitespaces at the beginning of a line. You want to set it to a fixed width face. This is useful if your default face is a variable with face. Because for e.g. in a variable with face, '- ' and ' ' (two spaces) don't have equal with, with -`adoc-align' in the following example the item's text looks +`adoc-align-face' in the following example the item's text looks aligned. - lorem ipsum dolor ..." - :group 'adoc) - -(define-obsolete-face-alias 'adoc-generic 'markup-gen-face "23.3") -(define-obsolete-face-alias 'adoc-monospace 'markup-typewriter-face "23.3") -(define-obsolete-face-alias 'adoc-strong 'markup-strong-face "23.3") -(define-obsolete-face-alias 'adoc-emphasis 'markup-emphasis-face "23.3") -(define-obsolete-face-alias 'adoc-superscript 'markup-superscript-face "23.3") -(define-obsolete-face-alias 'adoc-subscript 'markup-subscript-face "23.3") -(define-obsolete-face-alias 'adoc-secondary-text 'markup-secondary-text-face "23.3") -(define-obsolete-face-alias 'adoc-replacement 'markup-replacement-face "23.3") -(define-obsolete-face-alias 'adoc-complex-replacement 'markup-complex-replacement-face "23.3") -(define-obsolete-face-alias 'adoc-list-item 'markup-list-face "23.3") -(define-obsolete-face-alias 'adoc-table-del 'markup-table-face "23.3") -(define-obsolete-face-alias 'adoc-reference 'markup-reference-face "23.3") -(define-obsolete-face-alias 'adoc-delimiter 'markup-meta-face "23.3") -(define-obsolete-face-alias 'adoc-hide-delimiter 'markup-hide-delimiter-face "23.3") -(define-obsolete-face-alias 'adoc-anchor 'markup-anchor-face "23.3") -(define-obsolete-face-alias 'adoc-comment 'markup-comment-face "23.3") -(define-obsolete-face-alias 'adoc-warning 'markup-error-face "23.3") -(define-obsolete-face-alias 'adoc-preprocessor 'markup-preprocessor-face "23.3") + :group 'adoc-faces) +(defvar adoc-align-face 'adoc-align-face) ;; Despite the comment in font-lock.el near 'defvar font-lock-comment-face', it ;; seems I still need variables to refer to faces in adoc-font-lock-keywords. ;; Not having variables and only referring to face names in ;; adoc-font-lock-keywords does not work. -(defvar adoc-align 'adoc-align) -(defvar adoc-generic 'markup-gen-face) -(defvar adoc-monospace 'markup-typewriter-face) -(defvar adoc-replacement 'markup-replacement-face) -(defvar adoc-complex-replacement 'markup-complex-replacement-face) -(defvar adoc-table-del 'markup-table-face) -(defvar adoc-reference 'markup-reference-face) -(defvar adoc-secondary-text 'markup-secondary-text-face) -(defvar adoc-delimiter 'markup-meta-face) -(defvar adoc-hide-delimiter 'markup-meta-hide-face) -(defvar adoc-anchor 'markup-anchor-face) -(defvar adoc-comment 'markup-comment-face) -(defvar adoc-warning 'markup-error-face) -(defvar adoc-preprocessor 'markup-preprocessor-face) +(defvar adoc-delimiter 'adoc-meta-face) +(defvar adoc-hide-delimiter 'adoc-meta-hide-face) - -;;;; misc + +;;;; misc (defconst adoc-title-max-level 4 "Max title level, counting starts at 0.") @@ -441,7 +339,8 @@ aligned. ;; profiling profes otherwise. Nevertheless I can't stop doing it. (defconst adoc-summarize-re-uolisti t "When non-nil, sumarize regexps for unordered list items into one regexp. -To become a customizable variable when regexps for list items become customizable.") +To become a customizable variable when regexps for list items become +customizable.") (defconst adoc-summarize-re-olisti t "As `adoc-summarize-re-uolisti', but for ordered list items.") @@ -452,19 +351,19 @@ To become a customizable variable when regexps for list items become customizabl (defvar adoc-unichar-alist nil "An alist, key=unicode character name as string, value=codepoint.") -;; altough currently always the same face is used, I prefer an alist over a -;; list. It is faster to find out wheter any attribute id is in the alist or -;; not. And maybe markup-faces splits up markup-secondary-text-face into more +;; although currently always the same face is used, I prefer an alist over a +;; list. It is faster to find out whether any attribute id is in the alist or +;; not. And maybe adoc-faces splits up adoc-secondary-text-face into more ;; specific faces. (defvar adoc-attribute-face-alist - '(("id" . markup-anchor-face) - ("caption" . markup-secondary-text-face) - ("xreflabel" . markup-secondary-text-face) - ("alt" . markup-secondary-text-face) - ("title" . markup-secondary-text-face) - ("attribution" . markup-secondary-text-face) - ("citetitle" . markup-secondary-text-face) - ("text" . markup-secondary-text-face)) + '(("id" . adoc-anchor-face) + ("caption" . adoc-secondary-text-face) + ("xreflabel" . adoc-secondary-text-face) + ("alt" . adoc-secondary-text-face) + ("title" . adoc-secondary-text-face) + ("attribution" . adoc-secondary-text-face) + ("citetitle" . adoc-secondary-text-face) + ("text" . adoc-secondary-text-face)) "An alist, key=attribute id, value=face.") (defvar adoc-mode-abbrev-table nil @@ -477,16 +376,7 @@ To become a customizable variable when regexps for list items become customizabl (define-abbrev-table 'adoc-mode-abbrev-table ()) -(defvar adoc-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-c\C-d" 'adoc-demote) - (define-key map "\C-c\C-p" 'adoc-promote) - (define-key map "\C-c\C-t" 'adoc-toggle-title-type) - (define-key map "\C-c\C-g" 'adoc-goto-ref-label) - map) - "Keymap used in adoc mode.") - ;;;; help text copied from asciidoc manual (defconst adoc-help-constrained-quotes "Constrained quotes must be bounded by white space or commonly @@ -494,7 +384,7 @@ To become a customizable variable when regexps for list items become customizabl used type of quote.") (defconst adoc-help-emphasis "Usually rendered italic") -(defconst adoc-help-strong +(defconst adoc-help-bold "Usually rendered bold") (defconst adoc-help-monospace "Aka typewritter. This does _not_ mean verbatim / literal") @@ -502,6 +392,18 @@ To become a customizable variable when regexps for list items become customizabl "Single quotation marks around enclosed text.") (defconst adoc-help-double-quote "Quotation marks around enclosed text.") +(defconst adoc-help-underline + "Applies an underline decoration to the span of text.") +(defconst adoc-help-overline + "Applies an overline decoration to the span of text.") +(defconst adoc-help-line-through + "Applies a line-through (aka strikethrough) decoration to the span of text.") +(defconst adoc-help-nobreak + "Disables words within the span of text from being broken.") +(defconst adoc-help-nowrap + "Prevents the span of text from wrapping at all.") +(defconst adoc-help-pre-wrap + "Prevents sequences of space and space-like characters from being collapsed (i.e., all spaces are preserved).") (defconst adoc-help-attributed "A mechanism to allow inline attributes to be applied to otherwise unformatted text.") @@ -527,7 +429,7 @@ To become a customizable variable when regexps for list items become customizabl the AsciiDoc source. Example both `&` and `&` are replace by an & (ampersand).") (defconst adoc-help-literal-paragraph - "Verbatim in a monospaced font. Applyied to paragraphs where + "Verbatim in a monospaced font. Applied to paragraphs where the first line is indented by one or more space or tab characters") (defconst adoc-help-delimited-block @@ -555,6 +457,7 @@ To become a customizable variable when regexps for list items become customizabl formatting or substitutions within Listing blocks apart from Special Characters and Callouts. Listing blocks are often used for computer output and file listings.") +(defconst adoc-help-bold "Bold.") (defconst adoc-help-delimited-block-literal "'LiteralBlocks' are rendered just like literal paragraphs.") (defconst adoc-help-delimited-block-quote @@ -674,8 +577,349 @@ To become a customizable variable when regexps for list items become customizabl text containing inline substitutions use a plus character instead of a backtick.") - -;;; Code: +;;; adoc Hiding =============================================================== +(defconst adoc-markup-properties + '(face adoc-markup-face invisible adoc-markup) + "List of properties and values to apply to markup.") + +(defconst adoc-language-keyword-properties + '(face adoc-language-keyword-face invisible adoc-markup) + "List of properties and values to apply to code block language names.") + +(defconst adoc-language-info-properties + '(face adoc-language-info-face invisible adoc-markup) + "List of properties and values to apply to code block language info strings.") + +(defconst adoc-include-title-properties + '(face adoc-link-title-face invisible adoc-markup) + "List of properties and values to apply to included code titles.") + +;;; Font Lock ================================================================= + +(require 'font-lock) + +(defgroup adoc-faces nil + "Faces used in Adoc Mode." + :group 'adoc + :group 'faces) + +(defface adoc-gen-face + '((((background light)) + (:foreground "medium blue")) + (((background dark)) + (:foreground "skyblue"))) + "Generic/base face for text with special formatting. + +Typically `adoc-title-0-face', `adoc-bold-face' etc. +inherit from it. Also used for generic text thas hasn't got its +own dedicated face, e.g. if a markup command imposes arbitrary +colors/sizes/fonts upon it." + :group 'adoc-faces) +(defvar adoc-gen-face 'adoc-gen-face) + +(defface adoc-meta-face + '((default ( + :family "Monospace" ; emacs's faces.el also directly uses "Monospace", so I assume it is safe to do so + :stipple nil + :inverse-video nil + :box nil + :strike-through nil + :overline nil + :underline nil + :slant normal + :weight normal + :width normal + :foundry "unknown")) + (((background light)) (:foreground "gray65")) + (((background dark)) (:foreground "gray30"))) + "Face for general meta characters and base for special meta characters. +The default sets all face properties to a value because then it's +easier for major mode to write font lock regular expressions." + ;; For example in '......', if is fontified before , + ;; might then make bold, which is not the intend. + :group 'adoc-faces) +(defvar adoc-meta-face 'adoc-meta-face) + +(defface adoc-value-face + '((t :inherit adoc-meta-face)) + "For attribute values." + :group 'adoc-faces) +(defvar adoc-value-face 'adoc-value-face) + +(defface adoc-bold-face + '((t (:inherit (adoc-gen-face bold)))) + "Face for bold text." + :group 'adoc-faces) +(defvar adoc-bold-face 'adoc-bold-face) + +(defface adoc-emphasis-face + '((t :inherit (adoc-gen-face italic))) + "For emphasized text." + :group 'adoc-faces) +(defvar adoc-emphasis-face 'adoc-emphasis-face) + +(defface adoc-markup-face + '((t (:inherit shadow :slant normal :weight normal))) + "Face for markup elements." + :group 'adoc-faces) +(defvar adoc-markup-face 'adoc-markup-face) + +(defface adoc-meta-hide-face + '((default (:inherit adoc-meta-face)) + (((background light)) :foreground "gray75") + (((background dark)) :foreground "gray25")) + "For meta characters which can be \\='hidden\\='. +Hidden in the sense of *almost* not visible. They does not need to +be properly seen because one knows what these characters must be; +deduced from the highlighting of the near context. E.g in +AsciiDocs \\='_important_\\=', the underlines would be highlighted with +adoc-hide-delimiter-face, and the text \\='important\\=' would be +highlighted with adoc-emphasis-face. Because \\='important\\=' is +highlighted, one knows that it must be surrounded with the meta +characters \\='_\\=', and thus the meta characters do not need to be +properly seen. +For example: +AsciiDoc: *bold emphasis text* or _emphasis text_ + ^ ^ ^ ^" + :group 'adoc-faces) +(defvar adoc-meta-hide-face 'adoc-meta-hide-face) + +(defface adoc-attribute-face + '((t :inherit adoc-meta-face :slant italic)) + "For attribute names." + :group 'adoc-faces) +(defvar adoc-attribute-face 'adoc-attribute-face) + +(defface adoc-anchor-face + '((t :inherit adoc-meta-face :overline t)) + "For the name/id of an anchor." + :group 'adoc-faces) +(defvar adoc-anchor-face 'adoc-anchor-face) + +(defface adoc-list-face + '((t (:inherit adoc-markup-face))) + "Face for list item markers." + :group 'adoc-faces) +(defvar adoc-list-face 'adoc-list-face) + +(defface adoc-code-face + '((t (:inherit fixed-pitch))) + "Face for inline code and fenced code blocks. + This may be used, for example, to add a contrasting background to + inline code fragments and code blocks." + :group 'adoc-faces) +(defvar adoc-code-face 'adoc-code-face) + +(defface adoc-command-face + '((default (:inherit (adoc-meta-face bold) + :box( + :line-width 2 + :style released-button))) + (((background light))(:background "#f5f5f5" :foreground "black" :box (:color "#dcdcdc"))) + (((background dark))(:background "#272822" :foreground "#e6db74" :box (:color "#e6db74")))) + "Face for command names." + :group 'adoc-faces) +(defvar adoc-command-face 'adoc-command-face) + +(defface adoc-complex-replacement-face + '((default (:inherit adoc-meta-face + :box (:line-width 2 :style released-button))) + (((background light)) (:background "plum1" :foreground "purple3" :box (:color "plum1"))) + (((background dark)) (:background "purple3" :foreground "plum1" :box (:color "purple3")))) + "Markup that is replaced by something complex. + For example an image, or a table of contents. + AsciiDoc: image:...[...]" + :group 'adoc-faces) +(defvar adoc-complex-replacement-face 'adoc-complex-replacement-face) + +(defface adoc-passthrough-face + '((t :inherit (fixed-pitch adoc-gen-face))) + "For text that is passed through yet another marser/renderer. + + Since this text is passed to an arbitrary renderer, it is unknown + wich of its chars are meta characters and which are literal characters." + :group 'adoc-faces) +(defvar adoc-passthrough-face 'adoc-passthrough-face) + +(defface adoc-preprocessor-face + '((t :inherit (font-lock-preprocessor-face adoc-meta-face))) + "For preprocessor constructs" + :group 'adoc-faces) +(defvar adoc-preprocessor-face 'adoc-preprocessor-face) + +(defface adoc-verbatim-face + '((((background light)) + (:background "cornsilk")) + (((background dark)) + (:background "saddlebrown"))) + "For verbatim text. + +Verbatim in a sense that all its characters are to be taken +literally. Note that does not necessarily mean that that it is in +a typewritter font. +For example \\='foo\\=' in the following examples. In parantheses is a +summary what the command is for according to the given markup +language. +\\=`foo\\=` (verbatim and typewriter font) ++++foo+++ (only verbatim)" + :group 'adoc-faces) +(defvar adoc-verbatim-face 'adoc-verbatim-face) + +(defface adoc-warning-face + '((t :inherit (font-lock-warning-face))) + "For things that should stand out" + :group 'adoc-faces) +(defvar adoc-warning-face 'adoc-warning-face) + +(defface adoc-table-face + '((t (:inherit (adoc-code-face)))) + "Face for tables." + :group 'adoc-faces) +(defvar adoc-table-face 'adoc-table-face) + +(defface adoc-language-keyword-face + '((t (:inherit font-lock-type-face))) + "Face for programming language identifiers." + :group 'adoc-faces) +(defvar adoc-language-keyword-face 'adoc-language-keyword-face) + +(defface adoc-replacement-face + '((default (:family "Monospace")) + (((background light)) (:foreground "purple3")) + (((background dark)) (:foreground "plum1"))) + "Meta characters that are replaced by text in the output. +See also `adoc-complex-replacement-face'. +For example +AsciiDoc: \\='->\\=' is replaced by an Unicode arrow +It is difficult to say whether adoc-replacement-face is part of +the group adoc-faces-meta or part of the group +adoc-faces-text. Technically they are clearly meta characters. +However they are just another representation of normal text and I +want to fontify them as such. E.g. in HTML \\='foo & bar\\=', +the output \\='foo & bar\\=' is fontified bold, thus I also want \\='foo +& bar\\=' in the Emacs buffer be fontified with +adoc-bold-face. Thus adoc-replacement-face needs to be +something that is orthogonal to the adoc-bold-face etc faces." + :group 'adoc-faces) +(defvar adoc-replacement-face 'adoc-replacement-face) + +(defface adoc-language-info-face + '((t (:inherit font-lock-string-face))) + "Face for programming language info strings." + :group 'adoc-faces) +(defvar adoc-language-info-face 'adoc-language-info-face) + +(defface adoc-reference-face + '((t (:inherit adoc-markup-face))) + "Face for link references." + :group 'adoc-faces) +(defvar adoc-reference-face 'adoc-reference-face) + +(defface adoc-link-title-face + '((t (:inherit font-lock-comment-face))) + "Face for reference link titles." + :group 'adoc-faces) +(defvar adoc-link-title-face 'adoc-link-title-face) + +(defface adoc-comment-face + '((t (:inherit font-lock-comment-face))) + "Face for HTML comments." + :group 'adoc-faces) +(defvar adoc-comment-face 'adoc-comment-face) + +(defface adoc-superscript-face + '((t :inherit adoc-gen-face :height 0.8)) + "For superscript text. +For example \\='foo\\=' in the ^foo^ +Note that typically the major mode doing the font lock +additionaly raises the text; face customization does not provide +this feature." + :group 'adoc-faces) +(defvar adoc-superscript-face 'adoc-superscript-face) + +(defface adoc-subscript-face + '((t :inherit adoc-gen-face :height 0.8)) + "For subscript text. +For example \\='foo\\=' in the ~foo~ +Note that typically the major mode doing the font lock +additionally lowers the text; face customization does not provide +this feature." + :group 'adoc-faces) +(defvar adoc-subscript-face 'adoc-subscript-face) + +(defface adoc-title-face + '((t (:inherit adoc-gen-face :weight bold))) + "Base face for titles." + :group 'adoc-faces) +(defvar adoc-title-face 'adoc-title-face) + +(defface adoc-title-0-face + '((t (:inherit adoc-title-face :height 2.0))) + "Face for document's title." + :group 'adoc-faces) +(defvar adoc-title-0-face 'adoc-title-0-face) + +(defface adoc-title-1-face + '((t (:inherit adoc-title-face :height 1.8))) + "Face for level 1 titles." + :group 'adoc-faces) +(defvar adoc-title-1-face 'adoc-title-1-face) + +(defface adoc-title-2-face + '((t (:inherit adoc-title-face :height 1.6))) + "Face for level 2 titles." + :group 'adoc-faces) +(defvar adoc-title-2-face 'adoc-title-2-face) + +(defface adoc-title-3-face + '((t (:inherit adoc-title-face :height 1.4))) + "Face for level 3 titles." + :group 'adoc-faces) +(defvar adoc-title-3-face 'adoc-title-3-face) + +(defface adoc-title-4-face + '((t (:inherit adoc-title-face :height 1.2))) + "Face for level 4 titles." + :group 'adoc-faces) +(defvar adoc-title-4-face 'adoc-title-4-face) + +(defface adoc-title-5-face + '((t (:inherit adoc-title-face :height 1.0))) + "Face for level 5 titles." + :group 'adoc-faces) +(defvar adoc-title-5-face 'adoc-title-5-face) + +(defface adoc-typewriter-face + '((t :inherit (fixed-pitch adoc-gen-face))) + "For text in typewriter/monospaced font. + + For example \\='foo\\=' in the following examples: + +foo+ (only typewriter font) + \\=`foo\\=` (verbatim and typewriter font)" + :group 'adoc-faces) +(defvar adoc-typewriter-face 'adoc-typewriter-face) + +(defface adoc-internal-reference-face + '((t :inherit adoc-meta-face :underline t)) + "For an internal reference." + :group 'adoc-faces) +(defvar adoc-internal-reference-face 'adoc-internal-reference-face) + +(defface adoc-secondary-text-face + '((t :inherit adoc-gen-face :foreground "firebrick" :height 0.9)) + "For text that is not part of the running text. +For example for captions of tables or images, +or for footnotes, or for floating text." + :group 'adoc-faces) +(defvar adoc-secondary-text-face 'adoc-secondary-text-face) + +(defface adoc-native-code-face + '((t (:inherit fixed-pitch))) + "For code blocks that are highlighted natively. + +Use it to change the background of the code blocks." + :group 'adoc-faces) +(defvar adoc-native-code-face 'adoc-native-code-face) ;;;; regexps ;; from AsciiDoc manual: The attribute name/value syntax is a single line ... @@ -696,7 +940,7 @@ When LEVEL is nil, a one line title of any level is matched. match-data has these sub groups: 1 leading delimiter inclusive whites between delimiter and title text 2 title's text exclusive leading/trailing whites -3 trailing delimiter with all whites +3 trailing delimiter with all whites 4 trailing delimiter only inclusive whites between title text and delimiter 0 only chars that belong to the title block element @@ -704,12 +948,12 @@ match-data has these sub groups: ---12------23------ 4--4" (let* ((del (if level - (make-string (+ level 1) ?=) - (concat "=\\{1," (+ adoc-title-max-level 1) "\\}")))) + (make-string (+ level 1) ?=) + (concat "=\\{1," (+ adoc-title-max-level 1) "\\}")))) (concat - "^\\(" del "[ \t]+\\)" ; 1 + "^\\(" del "[ \t]+\\)" ; 1 "\\([^ \t\n].*?\\)" ; 2 - ;; using \n instad $ is important so group 3 is guaranteed to be at least 1 + ;; using \n instead $ is important so group 3 is guaranteed to be at least 1 ;; char long (except when at the end of the buffer()). That is important to ;; to have a place to put the text property adoc-reserved on. "\\(\\([ \t]+" del "\\)?[ \t]*\\(?:\n\\|\\'\\)\\)" ))) ; 3 & 4 @@ -717,7 +961,7 @@ match-data has these sub groups: (defun adoc-make-one-line-title (sub-type level text) "Returns a one line title of LEVEL and SUB-TYPE containing the given text." (let ((del (make-string (+ level 1) ?=))) - (concat del " " text (when (eq sub-type 2) (concat " " del))))) + (concat del " " text (when (eq sub-type 2) (concat " " del))))) ;; AsciiDoc handles that by source code, there is no regexp in AsciiDoc. See ;; also adoc-re-one-line-title. @@ -735,11 +979,11 @@ a two line title underline, see also `adoc-re-two-line-title'." (lambda(x) (concat "\\(?:" - "\\(?:" (regexp-quote x) "\\)+" + "\\(?:" (regexp-quote x) "\\)+" (regexp-quote (substring x 0 1)) "?" "\\)")) - (if del (list del) adoc-two-line-title-del) "\\|") - ;; adoc-re-two-line-title shall have same behaviour als one line, thus + (if del (list del) adoc-two-line-title-del) "\\|") + ;; adoc-re-two-line-title shall have same behaviour also one line, thus ;; also here use \n instead $ "\\)[ \t]*\\(?:\n\\|\\'\\)")) @@ -749,7 +993,7 @@ a two line title underline, see also `adoc-re-two-line-title'." "Returns a regexps that matches a two line title. Note that even if this regexp matches it still doesn't mean it is -a two line title. You additionaly have to test if the underline +a two line title. You additionally have to test if the underline has the correct length. DEL is described in `adoc-re-two-line-title-undlerline'. @@ -774,7 +1018,7 @@ match-data has these sub groups: "Returns a two line title of given LEVEL containing given TEXT. LEVEL starts at 1." (concat text "\n" (adoc-make-two-line-title-underline level (length text)))) - + (defun adoc-make-two-line-title-underline (level &optional length) "Returns a two line title underline. LEVEL is the level of the title, starting at 1. LENGTH is the @@ -782,8 +1026,8 @@ line of the title's text. When nil it defaults to 4." (unless length (setq length 4)) (let* ((repetition-cnt (if (>= length 2) (/ length 2) 1)) - (del (nth level adoc-two-line-title-del)) - (result "")) + (del (nth level adoc-two-line-title-del)) + (result "")) (while (> repetition-cnt 0) (setq result (concat result del)) (setq repetition-cnt (- repetition-cnt 1))) @@ -802,22 +1046,21 @@ match-data his this sub groups: WARNING: See warning about list item nesting level in `adoc-list-descriptor'." (cond - - ;; ^\s*- +(?P.+)$ normal 0 + ;; ^\s*- +(?P.+)$ normal 0 ;; ^\s*\* +(?P.+)$ normal 1 ;; ... ... ;; ^\s*\*{5} +(?P.+)$ normal 5 - ;; ^\+ +(?P.+)$ bibliograpy(DEPRECATED) + ;; ^\+ +(?P.+)$ bibliograpy(DEPRECATED) ((eq type 'adoc-unordered) (cond ((or (eq sub-type 'adoc-normal) (null sub-type)) (let ((r (cond ((numberp level) (if (eq level 0) "-" (make-string level ?\*))) ((or (null level) (eq level 'adoc-all-levels)) "-\\|\\*\\{1,5\\}") - (t (error "adoc-unordered/adoc-normal: invalid level"))))) + (t (error "Adoc-unordered/adoc-normal: invalid level"))))) (concat "^\\([ \t]*\\)\\(" r "\\)\\([ \t]+\\)"))) ((and (eq sub-type 'adoc-bibliography) (null level)) "^\\(\\)\\(\\+\\)\\([ \t]+\\)") - (t (error "adoc-unordered: invalid sub-type/level combination")))) + (t (error "Adoc-unordered: invalid sub-type/level combination")))) ;; ^\s*(?P\d+\.) +(?P.+)$ decimal = 0 ;; ^\s*(?P[a-z]\.) +(?P.+)$ lower alpha = 1 @@ -825,30 +1068,30 @@ WARNING: See warning about list item nesting level in `adoc-list-descriptor'." ;; ^\s*(?P[ivx]+\)) +(?P.+)$ lower roman = 3 ;; ^\s*(?P[IVX]+\)) +(?P.+)$ upper roman = 4 ((eq type 'adoc-explicitly-numbered) - (when level (error "adoc-explicitly-numbered: invalid level")) + (when level (error "Adoc-explicitly-numbered: invalid level")) (let* ((l '("[0-9]+\\." "[a-z]\\." "[A-Z]\\." "[ivx]+)" "[IVX]+)")) (r (cond ((numberp sub-type) (nth sub-type l)) ((or (null sub-type) (eq sub-type 'adoc-all-subtypes)) (mapconcat 'identity l "\\|")) - (t (error "adoc-explicitly-numbered: invalid subtype"))))) + (t (error "Adoc-explicitly-numbered: invalid subtype"))))) (concat "^\\([ \t]*\\)\\(" r "\\)\\([ \t]+\\)"))) ;; ^\s*\. +(?P.+)$ normal 0 ;; ^\s*\.{2} +(?P.+)$ normal 1 ;; ... etc until 5 ... - ((eq type 'adoc-implicitly-numbered) + ((eq type 'adoc-implicitly-numbered) (let ((r (cond ((numberp level) (number-to-string (+ level 1))) ((or (null level) (eq level 'adoc-all-levels)) "1,5") - (t (error "adoc-implicitly-numbered: invalid level"))))) + (t (error "Adoc-implicitly-numbered: invalid level"))))) (concat "^\\([ \t]*\\)\\(\\.\\{" r "\\}\\)\\([ \t]+\\)"))) ;; ^\d*>) +(?P.+)$ callout ((eq type 'adoc-callout) - (when (or level sub-type) (error "adoc-callout invalid level/sub-type")) + (when (or level sub-type) (error "Adoc-callout invalid level/sub-type")) "^\\(\\)\\(\\)\\([ \t]+\\)") ;; invalid (t (error "invalid (un)ordered list type")))) - + (defun adoc-make-uolisti (level is-1st-line) "Returns a regexp matching a unordered list item." (let* ((del (if (eq level 0) "-" (make-string level ?\*))) @@ -881,25 +1124,25 @@ Subgroups: (del (regexp-quote deluq)) (del1st (substring deluq 0 1))) (concat - "^\\([ \t]*\\)" ; 1 - "\\(.*[^" del1st "\n]\\)" ; 2 + "^\\([ \t]*\\)" ; 1 + "\\(.*[^" del1st "\n]\\)" ; 2 "\\(\\(" del "\\)\\(?:[ \t]+\\|$\\)\\)"))) ; 3 & 4 ;; glossary (DEPRECATED) - ;; ^(?P