mirror of
https://github.com/mawww/kakoune.git
synced 2025-04-11 21:18:46 +02:00
Merge remote-tracking branch 'igor-ramazanov/contrib/gendocs.sh'
This commit is contained in:
commit
11f6319830
2 changed files with 336 additions and 21 deletions
315
contrib/gendocs.py
Executable file
315
contrib/gendocs.py
Executable file
|
@ -0,0 +1,315 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# This script generates a static documentation web site
|
||||
# by parsing the `**/*.asiidoc` files from the repository.
|
||||
#
|
||||
# Dependencies:
|
||||
# * Python 3
|
||||
# * `xdg-open` for opening the final result in a web browser.
|
||||
# * `antora` - a static documentation web site generator,
|
||||
# https://docs.antora.org/antora/latest
|
||||
#
|
||||
# Usage:
|
||||
# ```console
|
||||
# $ ./contrib/gendocs.py
|
||||
# ```
|
||||
#
|
||||
# After running it should open the generated web site in a browser.
|
||||
#
|
||||
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
import glob
|
||||
import itertools
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
# Get the script directory.
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
# Switch to the projects root dir.
|
||||
os.chdir(os.path.join(script_dir, ".."))
|
||||
|
||||
# Recreating the final output dir to start from scratch.
|
||||
shutil.rmtree("doc_gen", ignore_errors=True)
|
||||
os.makedirs("doc_gen", exist_ok=True)
|
||||
|
||||
# Antora fails if the repo contains broken symbolic links.
|
||||
# shutil.rmtree("libexec", ignore_errors=True)
|
||||
|
||||
# Canonical Antora paths.
|
||||
# See: https://docs.antora.org/antora/latest/standard-directories.
|
||||
# https://docs.antora.org/antora/latest/root-module-directory.
|
||||
os.makedirs("doc_gen/modules/ROOT/images", exist_ok=True)
|
||||
os.makedirs("doc_gen/modules/ROOT/pages", exist_ok=True)
|
||||
|
||||
|
||||
# Put necessary images to the Antora canonical directory.
|
||||
# See: https://docs.antora.org/antora/latest/images-directory.
|
||||
for gif_file in glob.glob("doc/*.gif"):
|
||||
shutil.copy(gif_file, "doc_gen/modules/ROOT/images/")
|
||||
|
||||
|
||||
# Fix links according to the Antora specification.
|
||||
# See: https://docs.antora.org/antora/latest/page/xref.
|
||||
def fix_links(path):
|
||||
@dataclass
|
||||
class Link:
|
||||
path: Optional[str]
|
||||
file: Optional[str]
|
||||
fragment: Optional[str]
|
||||
title: str
|
||||
|
||||
def __init__(self, path, file, fragment, title):
|
||||
self.path = path
|
||||
self.file = file
|
||||
self.fragment = fragment
|
||||
self.title = title
|
||||
|
||||
def dropwhile(predicate, string):
|
||||
return "".join(
|
||||
itertools.dropwhile(
|
||||
predicate,
|
||||
string,
|
||||
)
|
||||
)
|
||||
|
||||
def dropwhileright(predicate, string):
|
||||
return "".join(
|
||||
reversed(
|
||||
list(
|
||||
itertools.dropwhile(
|
||||
predicate,
|
||||
reversed(string),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def takewhile(predicate, string):
|
||||
return "".join(
|
||||
itertools.takewhile(
|
||||
predicate,
|
||||
string,
|
||||
)
|
||||
)
|
||||
|
||||
def untag(string):
|
||||
no_opening = dropwhile(lambda c: c == "<", string)
|
||||
no_closing = dropwhileright(lambda c: c == ">", no_opening)
|
||||
return no_closing
|
||||
|
||||
def parse(string):
|
||||
untagged = untag(string)
|
||||
prefix, title = untagged.split(",", 1)
|
||||
title = title.strip()
|
||||
fragment = dropwhile(lambda c: c != "#", prefix)
|
||||
fragment = fragment if fragment else None
|
||||
fragmentless = takewhile(lambda c: c != "#", prefix)
|
||||
segments = fragmentless.split("/")
|
||||
path, file = (
|
||||
("/".join(segments[:-1]), segments[-1])
|
||||
if "/" in fragmentless
|
||||
else (None, fragmentless)
|
||||
)
|
||||
return Link(path, file, fragment, title)
|
||||
|
||||
def render(link):
|
||||
if link.path and link.file and link.fragment == "#":
|
||||
return f"xref:{link.path}/{link.file}.adoc[{link.title}]"
|
||||
elif link.path and link.file and link.fragment:
|
||||
return f"xref:{link.path}/{link.file}.adoc{link.fragment}[{link.title}]"
|
||||
elif not link.path and link.file and link.fragment == "#":
|
||||
return f"xref:./{link.file}.adoc[{link.title}]"
|
||||
elif not link.path and link.file and link.fragment:
|
||||
return f"xref:./{link.file}.adoc{link.fragment}[{link.title}]"
|
||||
elif not link.path and link.file and not link.fragment:
|
||||
return f"<<{link.file},{link.title}>>"
|
||||
else:
|
||||
raise RuntimeError(f"Failed to render link: {link}")
|
||||
|
||||
def process(m):
|
||||
string = m.group(0)
|
||||
return render(parse(string)) if "," in string else string
|
||||
|
||||
content = None
|
||||
|
||||
with open(path, "r") as file:
|
||||
content = file.read()
|
||||
|
||||
# Fix image links according the Antora specification.
|
||||
# See: https://docs.antora.org/antora/latest/page/image-resource-id-examples.
|
||||
content = content.replace("image::doc/", "image::")
|
||||
|
||||
with open(path, "w") as file:
|
||||
file.write(re.sub(r"<<[^>]+>>", process, content))
|
||||
|
||||
|
||||
# A useful documentation page.
|
||||
# Add the `.adoc` extension to include it into the result.
|
||||
shutil.copy(
|
||||
"VIMTOKAK",
|
||||
"doc_gen/modules/ROOT/pages/VIMTOKAK.adoc",
|
||||
)
|
||||
fix_links("doc_gen/modules/ROOT/pages/VIMTOKAK.adoc")
|
||||
|
||||
for source in glob.glob("**/*.asciidoc", recursive=True):
|
||||
# Create directories structure matching the project's original structure.
|
||||
# See: https://docs.antora.org/antora/latest/pages-directory.
|
||||
page_dir = os.path.join(
|
||||
"doc_gen/modules/ROOT/pages",
|
||||
os.path.dirname(source),
|
||||
)
|
||||
os.makedirs(page_dir, exist_ok=True)
|
||||
|
||||
# Copy the `asciidoc` file into the Antora `pages` directory
|
||||
# with the mandatory `.adoc` filename extension.
|
||||
adoc = os.path.join(page_dir, pathlib.Path(source).stem + ".adoc")
|
||||
shutil.copy(source, adoc)
|
||||
|
||||
if source == "README.asciidoc":
|
||||
# Update the filename so it reflects the content.
|
||||
# The filename is used for navigation links.
|
||||
shutil.move(
|
||||
"doc_gen/modules/ROOT/pages/README.adoc",
|
||||
"doc_gen/modules/ROOT/pages/index.adoc",
|
||||
)
|
||||
adoc = "doc_gen/modules/ROOT/pages/index.adoc"
|
||||
elif source == "test/README.asciidoc":
|
||||
# The file name is used for navigation links.
|
||||
# Update so it reflects the content.
|
||||
shutil.move(
|
||||
"doc_gen/modules/ROOT/pages/test/README.adoc",
|
||||
"doc_gen/modules/ROOT/pages/test/tests.adoc",
|
||||
)
|
||||
adoc = "doc_gen/modules/ROOT/pages/test/tests.adoc"
|
||||
fix_links(adoc)
|
||||
|
||||
|
||||
# A navigation file for the sidebar.
|
||||
# See: https://docs.antora.org/antora/latest/navigation/single-list.
|
||||
#
|
||||
# TODO: Generate automatically.
|
||||
nav_content = """
|
||||
* xref:index.adoc[Getting Started]
|
||||
* xref:doc/pages/commands.adoc[Commands]
|
||||
* xref:doc/pages/expansions.adoc[Expansions]
|
||||
* xref:doc/pages/execeval.adoc[Exec Eval]
|
||||
* xref:doc/pages/scopes.adoc[Scopes]
|
||||
* xref:doc/pages/faces.adoc[Faces]
|
||||
* xref:doc/pages/buffers.adoc[Buffers]
|
||||
* xref:doc/pages/registers.adoc[Registers]
|
||||
* xref:doc/pages/mapping.adoc[Mapping]
|
||||
* xref:doc/pages/hooks.adoc[Hooks]
|
||||
* xref:doc/pages/command-parsing.adoc[Command Parsing]
|
||||
* xref:doc/pages/keys.adoc[Keys]
|
||||
* xref:doc/pages/regex.adoc[Regex]
|
||||
* xref:doc/pages/options.adoc[Options]
|
||||
* xref:doc/pages/highlighters.adoc[Highlighters]
|
||||
* xref:doc/pages/modes.adoc[Modes]
|
||||
* xref:doc/pages/keymap.adoc[KEYMAP]
|
||||
* xref:doc/pages/faq.adoc[FAQ]
|
||||
* xref:doc/pages/changelog.adoc[Changelog]
|
||||
* xref:doc/design.adoc[Design]
|
||||
* xref:doc/coding-style.adoc[Coding Style]
|
||||
* xref:doc/writing_scripts.adoc[Writing Scripts]
|
||||
* xref:doc/json_ui.adoc[JSON UI]
|
||||
* xref:doc/autoedit.adoc[Autoedit]
|
||||
* xref:doc/interfacing.adoc[Interfacing]
|
||||
* xref:rc/tools/lint.adoc[Linting]
|
||||
* xref:rc/tools/autorestore.adoc[Autorestore]
|
||||
* xref:rc/tools/doc.adoc[Doc]
|
||||
* xref:test/tests.adoc[Tests]
|
||||
* xref:VIMTOKAK.adoc[Vi(m) to Kakoune]
|
||||
"""
|
||||
|
||||
with open("doc_gen/modules/ROOT/nav.adoc", "w") as f:
|
||||
f.write(nav_content)
|
||||
|
||||
# Antora component description file.
|
||||
# See: https://docs.antora.org/antora/latest/component-version-descriptor.
|
||||
antora_yml_content = """
|
||||
name: Kakoune
|
||||
nav:
|
||||
- modules/ROOT/nav.adoc
|
||||
title: Kakoune
|
||||
version: latest
|
||||
"""
|
||||
|
||||
with open("doc_gen/antora.yml", "w") as f:
|
||||
f.write(antora_yml_content)
|
||||
|
||||
# Antora playbook file.
|
||||
# See: https://docs.antora.org/antora/latest/playbook.
|
||||
antora_playbook_content = """
|
||||
asciidoc:
|
||||
attributes:
|
||||
|
||||
# Do not complain on missing attributes,
|
||||
# TODO: fix and turn to a fatal warning
|
||||
attribute-missing: skip
|
||||
|
||||
# To fix links
|
||||
idprefix: ""
|
||||
|
||||
# To fix links
|
||||
idseparator: "-"
|
||||
|
||||
# Better to be reproducible, in general
|
||||
reproducible: true
|
||||
|
||||
# More convenient to turn sections to IDs
|
||||
sectids: true
|
||||
|
||||
# More convenient to have sections as links
|
||||
sectlinks: true
|
||||
|
||||
# Do not want to miss something
|
||||
sectnumlevels: 5
|
||||
|
||||
# More convenient to number the sections
|
||||
sectnums: true
|
||||
|
||||
# Do not want to miss something
|
||||
toclevels: 5
|
||||
|
||||
sourcemap: true
|
||||
|
||||
content:
|
||||
sources:
|
||||
- url: ./..
|
||||
start_path: doc_gen
|
||||
branches: ["HEAD"]
|
||||
|
||||
runtime:
|
||||
cache_dir: ./doc_gen/cache # More convenient for the development
|
||||
fetch: true # More convenient for the development
|
||||
|
||||
log:
|
||||
failure_level: fatal
|
||||
level: warn
|
||||
|
||||
output:
|
||||
clean: true # More convenient for the development
|
||||
dir: ./build # Simpler to have it explicit in code
|
||||
|
||||
site:
|
||||
title: Kakoune Docs
|
||||
|
||||
ui:
|
||||
bundle:
|
||||
url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable
|
||||
"""
|
||||
|
||||
with open("doc_gen/antora-playbook.yml", "w") as f:
|
||||
f.write(antora_playbook_content)
|
||||
|
||||
# Finally, generate the documentation,
|
||||
# results will be saved to the output directory
|
||||
# as specified in the `antora-playbook.yml`.
|
||||
subprocess.run(["antora", "generate", "doc_gen/antora-playbook.yml"])
|
||||
subprocess.run(["xdg-open", "./doc_gen/build/Kakoune/latest/index.html"])
|
|
@ -1,27 +1,27 @@
|
|||
= Keymap
|
||||
|
||||
---
|
||||
┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┲━━━━━━━━━━━━━━┓
|
||||
│ upper│ cmdout│convtab│ │selpipe│sel all│ │ align│pattern│ rotate│ rotate│ trim│ ┃ ⇤ ┃
|
||||
├┄┄CASE┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┨ ┃
|
||||
│ lower│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ │ ┃ ┃
|
||||
┢━━━━━━━┷━━━┱───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┺━━━┳━━━━━━━━━━┫
|
||||
┃ ↹ ┃ record│ ᵐʷ│ ᵐʷ│ paste│ ᵐʳ│ │ redo │ INSERT│ above│ before│ ᵐ│ ᵐ┃ ┃
|
||||
┃ ┠┄MACRO┄┤ next│ word├REPLACE┤to char├┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄OPEN┄┄┼┄PASTE┄┤ object│ object┃ ⏎ ┃
|
||||
┃ ┃ replay│ word│ end│ char│ │ yank │ undo │ insert│ below│ after│ begin│ end┃ ┃
|
||||
┣━━━━━━━━━━━┻━┱─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┺━┓ ┃
|
||||
┃ ⇬ ┃ APPEND│ split│ │ ᵐʳ│ ᵐᵍ│ ᵐˡ│ ᵐ│ ᵐ│ ᵐˡ│cmdline│use reg│ pipe┃ ┃
|
||||
┃ ┠┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┤ find│ goto │ │ │ │ ├┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┨ ┃
|
||||
┃ ┃ append│ select│ delete│ char│ │ ← │ ↓ │ ↑ │ → │ cursor│ │eschook┃ ┃
|
||||
┣━━━━━━━━━┳━━━┹───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┲━━━┷━━━━━━━┻━━━━━━━━┫
|
||||
┃ ┃ indent│ save│ ᵐ│copysel│ ᵛ│ ᵐʷ│ ᵐʳ│ ᵐʳ│ dedent│ indent│ ᵐʳ┃ ┃
|
||||
┃ ┠┄┄┄┄┄┄┄┼┄MARKS┄┤ select├┄┄┄┄┄┄┄┤ view│ prev│ search│ match├┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┤ search┃ ┃
|
||||
┃ ⇧ ┃ dedent│restore│ line│ change│ cmds│ word│ next│ char│clrsels│ repeat│ ┃ ⇧ ┃
|
||||
┣━━━━━━━━━┻┳━━━━━━┷━━━┳━━━┷━━━━━┱─┴───────┴───────┴───────┴───────┴───────┴─┲━━━━━┷━━━━┳━━┷━━━━━━━╋━━━━━━━━━┳━━━━━━━━━━┫
|
||||
┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
|
||||
┃ ┃ ┃ ┃ user mappings ┃ ┃ ┃ ┃ ┃
|
||||
┃Ctrl ┃ ┃Alt ┃ ┃AltGr ┃ ┃ ┃Ctrl ┃
|
||||
┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┹───────────────────────────────────────────┺━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━━┛
|
||||
┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┲━━━━━━━━━━━━━━┓
|
||||
│ upper│ cmdout│convtab│ │selpipe│sel all│ │ align│pattern│ rotate│ rotate│ trim│ ┃ ⇤ ┃
|
||||
├┄┄CASE┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┨ ┃
|
||||
│ lower│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ │ ┃ ┃
|
||||
┢━━━━━━━┷━━━┱───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┺━━━┳━━━━━━━━━━┫
|
||||
┃ ↹ ┃ record│ ᵐʷ│ ᵐʷ│ paste│ ᵐʳ│ │ redo │ INSERT│ above│ before│ ᵐ│ ᵐ┃ ┃
|
||||
┃ ┠┄MACRO┄┤ next│ word├REPLACE┤to char├┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄OPEN┄┄┼┄PASTE┄┤ object│ object┃ ⏎ ┃
|
||||
┃ ┃ replay│ word│ end│ char│ │ yank │ undo │ insert│ below│ after│ begin│ end┃ ┃
|
||||
┣━━━━━━━━━━━┻━┱─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┴─┬─────┺━┓ ┃
|
||||
┃ ⇬ ┃ APPEND│ split│ │ ᵐʳ│ ᵐᵍ│ ᵐˡ│ ᵐ│ ᵐ│ ᵐˡ│cmdline│use reg│ pipe┃ ┃
|
||||
┃ ┠┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┤ find│ goto │ │ │ │ ├┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┨ ┃
|
||||
┃ ┃ append│ select│ delete│ char│ │ ← │ ↓ │ ↑ │ → │ cursor│ │eschook┃ ┃
|
||||
┣━━━━━━━━━┳━━━┹───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┲━━━┷━━━━━━━┻━━━━━━━━┫
|
||||
┃ ┃ indent│ save│ ᵐ│copysel│ ᵛ│ ᵐʷ│ ᵐʳ│ ᵐʳ│ dedent│ indent│ ᵐʳ┃ ┃
|
||||
┃ ┠┄┄┄┄┄┄┄┼┄MARKS┄┤ select├┄┄┄┄┄┄┄┤ view│ prev│ search│ match├┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┤ search┃ ┃
|
||||
┃ ⇧ ┃ dedent│restore│ line│ change│ cmds│ word│ next│ char│clrsels│ repeat│ ┃ ⇧ ┃
|
||||
┣━━━━━━━━━┻┳━━━━━━┷━━━┳━━━┷━━━━━┱─┴───────┴───────┴───────┴───────┴───────┴─┲━━━━━┷━━━━┳━━┷━━━━━━━╋━━━━━━━━━┳━━━━━━━━━━┫
|
||||
┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃
|
||||
┃ ┃ ┃ ┃ user mappings ┃ ┃ ┃ ┃ ┃
|
||||
┃Ctrl ┃ ┃Alt ┃ ┃AltGr ┃ ┃ ┃Ctrl ┃
|
||||
┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┹───────────────────────────────────────────┺━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━━┛
|
||||
|
||||
ʳ: alt reverses direction
|
||||
ʷ: alt uses WORD instead of word (that is non blank instead of [a-z_])
|
||||
|
|
Loading…
Add table
Reference in a new issue