2014-07-14 22:51:33 +02:00
# http://daringfireball.net/projects/markdown
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
# Detection
# ‾‾‾‾‾‾‾‾‾
2015-08-13 21:06:55 +02:00
hook global BufCreate .*[.](markdown|md|mkd) %{
2017-11-03 08:34:41 +01:00
set-option buffer filetype markdown
2014-07-14 22:51:33 +02:00
}
2019-04-12 00:54:58 +02:00
# Initialization
# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾
hook global WinSetOption filetype=markdown %{
2019-03-13 06:24:33 +01:00
require-module markdown
2019-04-12 00:54:58 +02:00
2022-05-08 15:01:25 +02:00
hook window ModeChange pop:insert:.* -group markdown-trim-indent markdown-trim-indent
2021-04-02 02:18:11 +02:00
hook window InsertChar \n -group markdown-insert markdown-insert-on-new-line
2019-04-12 00:54:58 +02:00
hook window InsertChar \n -group markdown-indent markdown-indent-on-new-line
hook -once -always window WinSetOption filetype=.* %{ remove-hooks window markdown-.+ }
2019-03-13 06:24:33 +01:00
}
2019-07-23 04:01:40 +02:00
hook -group markdown-load-languages global WinSetOption filetype=markdown %{
2022-08-16 19:47:23 +02:00
markdown-load-languages '%'
}
hook -group markdown-load-languages global WinSetOption filetype=markdown %{
hook -group markdown-load-languages window NormalIdle .* %{markdown-load-languages gtGbGl}
hook -group markdown-load-languages window InsertIdle .* %{markdown-load-languages gtGbGl}
2019-03-13 06:24:33 +01:00
}
2019-07-23 04:01:40 +02:00
2019-04-12 00:54:58 +02:00
hook -group markdown-highlight global WinSetOption filetype=markdown %{
add-highlighter window/markdown ref markdown
hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/markdown }
}
2019-03-13 06:24:33 +01:00
provide-module markdown %{
2014-07-14 22:51:33 +02:00
# Highlighters
# ‾‾‾‾‾‾‾‾‾‾‾‾
2018-06-28 14:10:22 +02:00
add-highlighter shared/markdown regions
2018-11-08 18:44:03 +01:00
add-highlighter shared/markdown/inline default-region regions
add-highlighter shared/markdown/inline/text default-region group
2018-06-28 14:10:22 +02:00
2022-08-16 19:44:08 +02:00
add-highlighter shared/markdown/listblock region ^\h*[-*]\s ^(?=\S) regions
add-highlighter shared/markdown/listblock/g default-region group
add-highlighter shared/markdown/listblock/g/ ref markdown/inline
add-highlighter shared/markdown/listblock/g/marker regex ^\h*([-*])\s 1:bullet
2021-09-23 16:42:53 +02:00
add-highlighter shared/markdown/codeblock region -match-capture \
^(\h*)```\h* \
^(\h*)```\h*$ \
2022-08-16 19:47:23 +02:00
regions
add-highlighter shared/markdown/codeblock/ default-region fill meta
2021-09-23 16:42:53 +02:00
add-highlighter shared/markdown/listblock/codeblock region -match-capture \
^(\h*)```\h* \
^(\h*)```\h*$ \
2022-08-16 19:47:23 +02:00
regions
add-highlighter shared/markdown/listblock/codeblock/ default-region fill meta
2021-09-23 16:42:53 +02:00
add-highlighter shared/markdown/codeline region "^( {4}|\t)" "$" fill meta
2021-01-05 18:51:37 +01:00
# https://spec.commonmark.org/0.29/#link-destination
add-highlighter shared/markdown/angle_bracket_url region (?<=<)([a-z]+://|(mailto|magnet|xmpp):) (?!\\).(?=>)|\n fill link
2022-08-15 22:22:23 +02:00
add-highlighter shared/markdown/inline/url region -recurse \( (\b[a-z]+://|(mailto|magnet|xmpp):) (?!\\).(?=\))|\s fill link
add-highlighter shared/markdown/listblock/angle_bracket_url region (?<=<)(\b[a-z]+://|(mailto|magnet|xmpp):) (?!\\).(?=>)|\n fill link
2018-11-08 18:44:03 +01:00
2021-01-05 19:09:33 +01:00
try %{
require-module html
2021-03-21 09:52:00 +01:00
add-highlighter shared/markdown/inline/tag region (?i)</?[a-z][a-z0-9-]*\s*([a-z_:]|(?=>)) > ref html/tag
2021-01-05 19:09:33 +01:00
}
2018-11-08 18:44:03 +01:00
add-highlighter shared/markdown/inline/code region -match-capture (`+) (`+) fill mono
markdown.kak: Clean up code-block and code-span formatting.
Previously, a code block was anything between triple-backtics, including inline
blocks:
some text ```
not a codeblock, but highlighted as one
``` other text
and even if the closing backticks had the wrong indent:
```
this is a code block containing a triple backtick
```
this is still a code block, but Kakoune thinks otherwise
```
Now we use the -match-capture flag to ensure the start and end fences have
exactly the same indent.
Previously, the generic code-block region was defined first, which meant that
it took priority over all the language-specific highlighters. Now we define
the generic code-block highlighting *after* the others, which fixes #2304.
Previously, code-spans were defined as ordinary inline markup, but in Markdown
ordinary formatting doesn't work inside code-spans. Therefore, they are now
regions unto themselves, defined according to section 6.3 of the CommonMark
spec <https://spec.commonmark.org/0.28/#code-spans>, which addresses a comment
on #2111.
2018-09-18 10:55:24 +02:00
2014-07-14 22:51:33 +02:00
# Setext-style header
2020-05-28 08:33:00 +02:00
add-highlighter shared/markdown/inline/text/ regex (\A|^\n)[^\n]+\n={2,}\h*\n\h*$ 0:title
add-highlighter shared/markdown/inline/text/ regex (\A|^\n)[^\n]+\n-{2,}\h*\n\h*$ 0:header
2014-07-14 22:51:33 +02:00
# Atx-style header
2018-11-27 08:22:21 +01:00
add-highlighter shared/markdown/inline/text/ regex ^#[^\n]* 0:header
2018-11-08 18:44:03 +01:00
2020-05-15 10:56:38 +02:00
add-highlighter shared/markdown/inline/text/ regex (?<!\*)(\*([^\s*]|([^\s*](\n?[^\n*])*[^\s*]))\*)(?!\*) 1:+i
add-highlighter shared/markdown/inline/text/ regex (?<!_)(_([^\s_]|([^\s_](\n?[^\n_])*[^\s_]))_)(?!_) 1:+i
add-highlighter shared/markdown/inline/text/ regex (?<!\*)(\*\*([^\s*]|([^\s*](\n?[^\n*])*[^\s*]))\*\*)(?!\*) 1:+b
add-highlighter shared/markdown/inline/text/ regex (?<!_)(__([^\s_]|([^\s_](\n?[^\n_])*[^\s_]))__)(?!_) 1:+b
2018-11-08 18:44:03 +01:00
add-highlighter shared/markdown/inline/text/ regex ^\h*(>\h*)+ 0:comment
2020-09-01 12:11:36 +02:00
add-highlighter shared/markdown/inline/text/ regex "\H( {2,})$" 1:+r@meta
2014-07-14 22:51:33 +02:00
# Commands
# ‾‾‾‾‾‾‾‾
2022-08-16 19:47:23 +02:00
define-command markdown-load-languages -params 1 %{
evaluate-commands -draft %{ try %{
Avoid semantically significant comments in kak files
Kakoune's balanced strings require that delimiter characters nested inside
them are also paired, so for example in %{ }, each nested { must occur
before a corresponding } to balance it out.
In general this will automatically be the case for code in common scripting
languages, but sometimes regular expressions used for syntax highlighting
do end up containing an unbalanced bracket of one type or another.
This problem is easily solved because there is a free choice of balanced
delimiter characters. However, it can also be worked around by adding
a comment which itself contains an unbalanced delimiter character, to
'balance out' the unpaired one in the regular expression.
These unbalanced comments are not ideal as the semantic role they perform
is easy for a casual reader to overlook. A good example is
catch %{
# indent after lines with an unclosed { or (
try %< execute-keys -draft [c[({],[)}] <ret> <a-k> \A[({][^\n]*\n[^\n]*\n?\z <ret> j<a- gt> >
# indent after a switch's case/default statements
try %[ execute-keys -draft kx <a-k> ^\h*(case|default).*:$ <ret> j<a-gt> ]
# deindent closing brace(s) when after cursor
try %[ execute-keys -draft x <a-k> ^\h*[})] <ret> gh / [})] <ret> m <a-S> 1<a-&> ]
}
in rc/filetype/go/kak. Here, it is not instantly obvious that the comment
containing an unmatched { is required for correctness. If you change the
comment, delete it or rearrange the contents of the catch block, go.kak
will fail to load, and if you cut-and-paste this code as the basis for
a new filetype, it is a loaded gun pointing at your feet.
Luckily, a careful audit of the standard kakoune library turned up only
three such instances, in go.kak, hare.kak and markdown.kak.
The examples in go.kak and hare.kak are easily made robust by replacing
a %{ } with %< > or %[ ] respectively. The example in markdown.kak is
least-intrusively fixed by rewriting the affected regular expression
slightly so it has balanced { and } anyway.
2023-12-13 17:40:48 +01:00
execute-keys "%arg{1}1s```\h*\{?[.=]?(\w+)\}?<ret>"
2022-08-16 19:47:23 +02:00
evaluate-commands -itersel %{ try %{
require-module %val{selection}
add-highlighter "shared/markdown/codeblock/%val{selection}" region -match-capture "^(\h*)```\h*(%val{selection}\b|\{[.=]?%val{selection}\})" ^(\h*)``` regions
add-highlighter "shared/markdown/codeblock/%val{selection}/" default-region fill meta
add-highlighter "shared/markdown/codeblock/%val{selection}/inner" region \A\h*```[^\n]*\K (?=```) ref %val{selection}
add-highlighter "shared/markdown/listblock/codeblock/%val{selection}" region -match-capture "^(\h*)```\h*(%val{selection}\b|\{[.=]?%val{selection}\})" ^(\h*)``` regions
add-highlighter "shared/markdown/listblock/codeblock/%val{selection}/" default-region fill meta
add-highlighter "shared/markdown/listblock/codeblock/%val{selection}/inner" region \A\h*```[^\n]*\K (?=```) ref %val{selection}
}}
}}
}
2022-05-08 15:01:25 +02:00
define-command -hidden markdown-trim-indent %{
evaluate-commands -no-hooks -draft -itersel %{
2022-03-16 23:20:07 +01:00
execute-keys x
2022-05-08 15:01:25 +02:00
# remove trailing white spaces
try %{ execute-keys -draft s \h + $ <ret> d }
}
}
2021-04-02 02:18:11 +02:00
define-command -hidden markdown-insert-on-new-line %{
2022-03-16 23:20:07 +01:00
try %{ execute-keys -draft -itersel k x s ^\h*\K((>\h*)+([*+-]\h)?|(>\h*)*[*+-]\h)\h* <ret> y gh j P }
2021-04-02 02:18:11 +02:00
}
2017-11-03 08:34:41 +01:00
define-command -hidden markdown-indent-on-new-line %{
2017-11-03 09:09:45 +01:00
evaluate-commands -draft -itersel %{
2014-07-14 22:51:33 +02:00
# preserve previous line indent
2019-10-22 11:02:06 +02:00
try %{ execute-keys -draft <semicolon> K <a-&> }
2015-11-04 10:48:47 +01:00
# remove trailing white spaces
2022-03-16 23:20:07 +01:00
try %{ execute-keys -draft k x s \h+$ <ret> d }
2014-07-14 22:51:33 +02:00
}
}
2019-03-13 06:24:33 +01:00
}