Commit 16be6c4b authored by Sergey Litvinov's avatar Sergey Litvinov
Browse files

Merge branch 'master' of

parents a8a4f10d 43e0bd73
(add-to-list 'auto-mode-alist '("\\.adoc\\'" . adoc-mode))
;;; adoc-mode.el --- a major-mode for editing AsciiDoc files in Emacs
;; Copyright 2010-2013 Florian Kaufmann <>
;; Author: Florian Kaufmann <>
;; URL:
;; Created: 2009
;; Version: 0.6.6
;; Package-Requires: ((markup-faces "1.0.0"))
;; Keywords: wp AsciiDoc
;; 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)
;; any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; 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]( 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.
;; # Download
;; The raw file (adoc-mode.el) can be found
;; [here](
;; Optionally you can get the sources from the [git
;; repository](
;; You will also need to download the library
;; [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]( and or Emacs 24, where the
;; packages library is already included. adoc-mode is on the
;; [Marmalade]( 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](
;;; 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:
(defvar adoc-mode-hook nil
"Hook run when entering adoc mode.")
(require 'markup-faces) ;
(require 'cl) ; I know, I should remove it, I will, eventually
;; tempo or tempo-snippet is required later below
(define-derived-mode adoc-mode text-mode "AsciiDoc"
"Major mode for editing AsciiDoc files.")
(defconst adoc-mode-version "0.6.6"
"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))
(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
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.
You need to call `adoc-calc' after a change."
:type '(list (float :tag "Subscript")
(float :tag "Superscript"))
: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.
(defcustom adoc-insert-replacement nil
"When non-nil the character/string a replacment/entity stands for is displayed.
E.g. after '&amp;' an '&' is displayed, after '(C)' the copy right
sign is displayed. It's 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.
'&amp;', in contrast to '&#20;' 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
:type 'boolean
:group 'adoc)
(defcustom adoc-unichar-name-resolver nil
"Function taking a unicode char name and returing it's codepoint.
E.g. when given \"amp\" (as in the character entity reference
\"&amp;\"), 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
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.
You can set it to `adoc-unichar-by-name'; however it requires
unichars.el ( When
you set adoc-unichar-name-resolver to adoc-unichar-by-name, you
need to call `adoc-calc' for the change to take effect."
:type '(choice (const nil)
(const adoc-unichar-by-name)
:group 'adoc)
(defcustom adoc-two-line-title-del '("==" "--" "~~" "^^" "++")
"Delimiter used for the underline of two line titles.
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") )
: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
"Regexp used for delimited blocks.
WARNING: They should not contain a $. It is implied that they
match up to end of the line;
They correspond to delimiter variable blockdef-xxx sections in
the AsciiDoc configuration file.
However contrary to the AsciiDoc configuration file a separate
regexp can be given for the start line and for the end line. You
may want to do that because adoc-mode often can't properly
distinguish between a) a two line tile b) start of a delimited
block and c) end of a delimited block. If you start a listing
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
(defcustom adoc-default-title-type 1
"Default title type, see `adoc-title-descriptor'."
:group 'adoc)
;; 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 )
(defcustom adoc-enable-two-line-title t
"Wether 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
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
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)
:group 'adoc)
(defcustom adoc-title-style 'adoc-title-style-one-line
"Title style used for title tempo templates.
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 "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))
:group 'adoc)
;;;; faces / font lock
(define-obsolete-face-alias 'adoc-orig-default 'adoc-align "23.3")
(defface adoc-align
'((t (:inherit (markup-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
- 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")
;; 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)
;;;; misc
(defconst adoc-title-max-level 4
"Max title level, counting starts at 0.")
(defconst adoc-uolist-max-level 5
"Max unordered (bulleted) list item nesting level, counting starts at 0.")
;; I think it's actually not worth the fuzz to try to sumarize regexps until
;; 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.")
(defconst adoc-summarize-re-olisti t
"As `adoc-summarize-re-uolisti', but for ordered list items.")
(defconst adoc-summarize-re-llisti t
"As `adoc-summarize-re-uolisti', but for labeled list items.")
(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
;; 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))
"An alist, key=attribute id, value=face.")
(defvar adoc-mode-abbrev-table nil
"Abbrev table in use in adoc-mode buffers.")
(defvar adoc-font-lock-keywords nil
"Font lock keywords in adoc-mode buffers.")
(defvar adoc-replacement-failed nil )
(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)
"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
adjoining punctuation characters. These are the most commonly
used type of quote.")
(defconst adoc-help-emphasis
"Usually rendered italic")
(defconst adoc-help-strong
"Usually rendered bold")
(defconst adoc-help-monospace
"Aka typewritter. This does _not_ mean verbatim / literal")
(defconst adoc-help-single-quote
"Single quotation marks around enclosed text.")
(defconst adoc-help-double-quote
"Quotation marks around enclosed text.")
(defconst adoc-help-attributed
"A mechanism to allow inline attributes to be applied to
otherwise unformatted text.")
(defconst adoc-help-unconstrained-quotes
"Unconstrained quotes have no boundary constraints and can be
placed anywhere within inline text.")
(defconst adoc-help-line-break
"A plus character preceded by at least one space character at
the end of a non-blank line forces a line break. It generates a
line break (`br`) tag for HTML outputs and a custom XML
`asciidoc-br` processing instruction for DocBook outputs")
(defconst adoc-help-page-break
"A line of three or more less-than (`<<<`) characters will
generate a hard page break in DocBook and printed HTML
(defconst adoc-help-ruler-line
"A line of three or more apostrophe characters will generate a
ruler line. It generates a ruler (`hr`) tag for HTML outputs
and a custom XML `asciidoc-hr` processing instruction for
DocBook outputs.")
(defconst adoc-help-entity-reference
"You can also include arbitrary character entity references in
the AsciiDoc source. Example both `&amp;` and `&#38;` are
replace by an & (ampersand).")
(defconst adoc-help-literal-paragraph
"Verbatim in a monospaced font. Applyied to paragraphs where
the first line is indented by one or more space or tab
(defconst adoc-help-delimited-block
"Delimited blocks are blocks of text enveloped by leading and
trailing delimiter lines (normally a series of four or more
repeated characters).")
(defconst adoc-help-delimited-block-comment
"The contents of 'CommentBlocks' are not processed; they are
useful for annotations and for excluding new or outdated
content that you don't want displayed. CommentBlocks are never
written to output files.")
(defconst adoc-help-delimited-block-passthrouh
"By default the block contents is subject only to 'attributes'
and 'macros' substitutions (use an explicit 'subs' attribute to
apply different substitutions). PassthroughBlock content will
often be backend specific. The following styles can be applied
to passthrough blocks: pass:: No substitutions are performed.
This is equivalent to `subs=\"none\"`. asciimath, latexmath::
By default no substitutions are performed, the contents are
rendered as mathematical formulas.")
(defconst adoc-help-delimited-block-listing
"'ListingBlocks' are rendered verbatim in a monospaced font,
they retain line and whitespace formatting and are often
distinguished by a background or border. There is no text
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-delimited-block-literal
"'LiteralBlocks' are rendered just like literal paragraphs.")
(defconst adoc-help-delimited-block-quote
"'QuoteBlocks' are used for quoted passages of text. There are
two styles: 'quote' and 'verse'. The style behavior is
identical to quote and verse paragraphs except that blocks can
contain multiple paragraphs and, in the case of the 'quote'
style, other section elements. The first positional attribute
sets the style, if no attributes are specified the 'quote'
style is used. The optional 'attribution' and 'citetitle'
attributes (positional attributes 2 and3) specify the quote's
author and source.")
(defconst adoc-help-delimited-block-example
"'ExampleBlocks' encapsulate the DocBook Example element and
are used for, well, examples. Example blocks can be titled by
preceding them with a 'BlockTitle'. DocBook toolchains will
normally automatically number examples and generate a 'List of
Examples' backmatter section.
Example blocks are delimited by lines of equals characters and
can contain any block elements apart from Titles, BlockTitles
and Sidebars) inside an example block.")
(defconst adoc-help-delimited-block-sidebar
"A sidebar is a short piece of text presented outside the
narrative flow of the main text. The sidebar is normally
presented inside a bordered box to set it apart from the main
text.The sidebar body is treated like a normal section body.")
(defconst adoc-help-delimited-block-open-block
"An 'OpenBlock' groups a set of block elements.")
(defconst adoc-help-list
"Indentation is optional and does _not_ determine nesting.")
(defconst adoc-help-bulleted-list
"Aka itimized or unordered.")
(defconst adoc-help-list-item-continuation
"Another list or a literal paragraph immediately following a
list item is implicitly appended to the list item; to append
other block elements to a list item you need to explicitly join
them to the list item with a 'list continuation' (a separator
line containing a single plus character). Multiple block
elements can be appended to a list item using list
continuations (provided they are legal list item children in
the backend markup).")
(defconst adoc-help-table
"The AsciiDoc table syntax looks and behaves like other
delimited block types and supports standard block configuration
(defconst adoc-help-macros
"Inline Macros occur in an inline element context. A Block
macro reference must be contained in a single line separated
either side by a blank line or a block delimiter. Block macros
behave just like Inline macros, with the following differences:
1) They occur in a block context. 2) The default syntax is
<name>::<target>[<attrlist>] (two colons, not one). 3) Markup
template section names end in -blockmacro instead of
(defconst adoc-help-url
"If you don’t need a custom link caption you can enter the
http, https, ftp, file URLs and email addresses without any
special macro syntax.")
(defconst adoc-help-anchor
"Used to specify hypertext link targets. The `<id>` is a unique
string that conforms to the output markup's anchor syntax. The
optional `<xreflabel>` is the text to be displayed by
captionless 'xref' macros that refer to this anchor.")
(defconst adoc-help-xref
"Creates a hypertext link to a document anchor. The `<id>`