mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
lsp: Add reference documentation on hover
For most constructs and keywords, show the relevant section of the reference documentation on hover.
This commit is contained in:
parent
b107a85947
commit
e19975e1f8
28 changed files with 326 additions and 21 deletions
136
docs/collect-sections.py
Executable file
136
docs/collect-sections.py
Executable file
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
__all__ = ["get_docs_section"]
|
||||
|
||||
DOCS_ROOT = "https://jwestman.pages.gitlab.gnome.org/blueprint-compiler"
|
||||
|
||||
|
||||
sections: dict[str, "Section"] = {}
|
||||
|
||||
|
||||
@dataclass
|
||||
class Section:
|
||||
link: str
|
||||
lines: str
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"content": rst_to_md(self.lines),
|
||||
"link": self.link,
|
||||
}
|
||||
|
||||
|
||||
def load_reference_docs():
|
||||
for filename in Path(os.path.dirname(__file__), "reference").glob("*.rst"):
|
||||
with open(filename) as f:
|
||||
section_name = None
|
||||
lines = []
|
||||
|
||||
def close_section():
|
||||
if section_name:
|
||||
html_file = re.sub(r"\.rst$", ".html", filename.name)
|
||||
anchor = re.sub(r"[^a-z0-9]+", "-", section_name.lower())
|
||||
link = f"{DOCS_ROOT}/reference/{html_file}#{anchor}"
|
||||
sections[section_name] = Section(link, lines)
|
||||
|
||||
for line in f:
|
||||
if m := re.match(r"\.\.\s+_(.*):", line):
|
||||
close_section()
|
||||
section_name = m.group(1)
|
||||
lines = []
|
||||
else:
|
||||
lines.append(line)
|
||||
|
||||
close_section()
|
||||
|
||||
|
||||
# This isn't a comprehensive rST to markdown converter, it just needs to handle the
|
||||
# small subset of rST used in the reference docs.
|
||||
def rst_to_md(lines: list[str]) -> str:
|
||||
result = ""
|
||||
|
||||
def rst_to_md_inline(line):
|
||||
line = re.sub(r"``(.*?)``", r"`\1`", line)
|
||||
line = re.sub(
|
||||
r":ref:`(.*?)<(.*?)>`",
|
||||
lambda m: f"[{m.group(1)}]({sections[m.group(2)].link})",
|
||||
line,
|
||||
)
|
||||
line = re.sub(r"`([^`]*?) <([^`>]*?)>`_", r"[\1](\2)", line)
|
||||
return line
|
||||
|
||||
i = 0
|
||||
n = len(lines)
|
||||
heading_levels = {}
|
||||
|
||||
def print_block(lang: str = "", code: bool = True, strip_links: bool = False):
|
||||
nonlocal result, i
|
||||
block = ""
|
||||
while i < n:
|
||||
line = lines[i].rstrip()
|
||||
if line.startswith(" "):
|
||||
line = line[3:]
|
||||
elif line != "":
|
||||
break
|
||||
|
||||
if strip_links:
|
||||
line = re.sub(r":ref:`(.*?)<(.*?)>`", r"\1", line)
|
||||
|
||||
if not code:
|
||||
line = rst_to_md_inline(line)
|
||||
|
||||
block += line + "\n"
|
||||
i += 1
|
||||
|
||||
if code:
|
||||
result += f"```{lang}\n{block.strip()}\n```\n\n"
|
||||
else:
|
||||
result += block
|
||||
|
||||
while i < n:
|
||||
line = lines[i].rstrip()
|
||||
i += 1
|
||||
if line == ".. rst-class:: grammar-block":
|
||||
print_block(strip_links=True)
|
||||
elif line == ".. code-block:: blueprint":
|
||||
print_block("blueprint")
|
||||
elif line == ".. note::":
|
||||
result += "#### Note\n"
|
||||
print_block(code=False)
|
||||
elif m := re.match(r"\.\. image:: (.*)", line):
|
||||
result += f"})\n"
|
||||
elif i < n and re.match(r"^((-+)|(~+)|(\++))$", lines[i]):
|
||||
level_char = lines[i][0]
|
||||
if level_char not in heading_levels:
|
||||
heading_levels[level_char] = max(heading_levels.values(), default=1) + 1
|
||||
result += (
|
||||
"#" * heading_levels[level_char] + " " + rst_to_md_inline(line) + "\n"
|
||||
)
|
||||
i += 1
|
||||
else:
|
||||
result += rst_to_md_inline(line) + "\n"
|
||||
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: collect_sections.py <output_file>")
|
||||
sys.exit(1)
|
||||
|
||||
outfile = sys.argv[1]
|
||||
|
||||
load_reference_docs()
|
||||
|
||||
# print the sections to a json file
|
||||
with open(outfile, "w") as f:
|
||||
json.dump(
|
||||
{name: section.to_json() for name, section in sections.items()}, f, indent=2
|
||||
)
|
|
@ -9,3 +9,11 @@ custom_target('docs',
|
|||
)
|
||||
|
||||
endif
|
||||
|
||||
custom_target('reference_docs.json',
|
||||
output: 'reference_docs.json',
|
||||
command: [meson.current_source_dir() / 'collect-sections.py', '@OUTPUT@'],
|
||||
build_always_stale: true,
|
||||
install: true,
|
||||
install_dir: py.get_install_dir() / 'blueprintcompiler',
|
||||
)
|
|
@ -227,7 +227,7 @@ Valid in `Gtk.BuilderListItemFactory <https://docs.gtk.org/gtk4/class.BuilderLis
|
|||
|
||||
The ``template`` block defines the template that will be used to create list items. This block is unique within Blueprint because it defines a completely separate sub-blueprint which is used to create each list item. The sub-blueprint may not reference objects in the main blueprint or vice versa.
|
||||
|
||||
The template type must be `Gtk.ListItem <https://docs.gtk.org/gtk4/class.ListItem.html>`_, `Gtk.ColumnViewRow <https://docs.gtk.org/gtk4/class.ColumnViewRow.html>`_, or `Gtk.ColumnViewCell <https://docs.gtk.org/gtk4/class.ColumnViewCell.html>`_ The template object can be referenced with the ``template`` keyword.
|
||||
The template type must be `Gtk.ListItem <https://docs.gtk.org/gtk4/class.ListItem.html>`_, `Gtk.ColumnViewRow <https://docs.gtk.org/gtk4/class.ColumnViewRow.html>`_, or `Gtk.ColumnViewCell <https://docs.gtk.org/gtk4/class.ColumnViewCell.html>`_. The template object can be referenced with the ``template`` keyword.
|
||||
|
||||
.. code-block:: blueprint
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue