Skip to content

Pass docstring as org-files to emacs #5

@YueRen

Description

@YueRen

One suggestion: Would it be possible to pass the docstrings as org-files to emacs? That would easily enable things like proper julia syntax highlighting or latex rendering.

Unfortunately, julia doesn't know how to export to org-files natively, so you'd have to teach it. Here's some code for it:

using Markdown

# zero-width space to workaround Org inline code parsing bug
# see https://emacs.stackexchange.com/a/81288
const ZWSP = "\u200B"

# Top-level MD: join blocks with blank line
function org_render(md::Markdown.MD)
    join(org_render.(md.content), "\n\n")
end

# Paragraph: render inline pieces
org_render(x::Markdown.Paragraph) = join(org_render.(x.content))

# Bold: surround with *
org_render(x::Markdown.Bold)      = "*" * join(org_render.(x.content)) * "*"

# Italic: surround with /
org_render(x::Markdown.Italic)    = "/" * join(org_render.(x.content)) * "/"

# Plain text: escape special characters for org-mode
function org_escape(s::AbstractString)
    replace(s, r"([*_/~])" => s"\\\1")
end
org_render(x::Markdown.Text)      = org_escape(x.text)

# Inline code and fenced blocks
function org_render(x::Markdown.Code)
    if isempty(x.language)
        # Inline code: surround with ~ and append ZWSP
        "~" * x.code * "~" * ZWSP
    else
        # Fenced code block: change languages "jldoctest" and "julia-repl" to "julia"
        lang = lowercase(x.language)
        lang = lang == "jldoctest"  ? "julia" : lang
        lang = lang == "julia-repl" ? "julia" : lang
        "#+begin_src $(lang)\n$(x.code)\n#+end_src"
    end
end

# Links: render visible text and ignore URL/@ref
org_render(x::Markdown.Link) = join(org_render.(x.text))

# Lists: prefix items with "- "
org_render(x::Markdown.List) =
    join(["- " * join(org_render.(item)) for item in x.items], "\n")

# Headers: make into org-sections
# WARNING: this might not work on older julia versions
org_render(x::Markdown.Header) = begin
    level = typeof(x).parameters[1]
    stars = repeat("*", level)
    stars * " " * join(org_render.(x.text))
end

# Admonitions: render as org src blocks with title as language
# WARNING: this might not work on older julia versions
function org_render(x::Markdown.Admonition)
    kind = lowercase(x.title)

    # content is a vector of Markdown nodes
    inner = join(org_render.(x.content), "\n\n")

    return """#+begin_src $kind
$inner
#+end_src"""
end

# Fallback for anything else
org_render(x) = string(x)

And here two examples:


doc = Docs.doc(:sin);
docOrg = org_render(doc);
println(docOrg)


doc = Markdown.parse("""
!!! warning
    This function mutates its arguments.

!!! note
    Use with care.
""");
docOrg = org_render(doc);
println(docOrg)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions