Sublime Forum

Can I scope a completions file to only display in certain markdown sections?

#1

Lets say I have a markdown file that has a section with header “#### Foo”.

Is there a way I can scope a completions file to only show its completions in this section of a markdown file. I’m hoping I could target the H4 or match the heading text. I’d also be happy if it could be done by targeting an html class or id.

0 Likes

#2

Here is an example completions file that does it. The scope is what tells it to show the completions in what situations. SInce headers have a markup.heading scope, one can use that.

{
    "scope": "markup.heading",
    "completions": [
        { "trigger": "completion_1", "contents": "completion_1", },
        { "trigger": "completion_2", "contents": "completion_2", },
        { "trigger": "completion_3", "contents": "completion_3", }
    ],
}

Do note that, by default, AC completions don’t trigger in markdown files. You need to add the appropriate scope in auto_complete_selector setting of your user preferences to do that.

image

0 Likes

#3

Thank you for the reply. This is not quite what I was asking for. Sorry for lack of detail.

I would like the completion to only show when in a paragraph under a specific heading such as “#### Foo.”

#### Foo

Paragraph 1 …

How can I only show certain completions here?

Paragraph 3 …
0 Likes

#4

Unfortunately, the completions file is not smart enough to detect that it has to trigger under a given heading. It just operates on a given scope. In your example, the scope at that point where you want the completions would be meta.paragraph.markdown but that’s for any paragraph. So the completions will appear for any paragraph under any header.

1 Like

#5

Darn. Thank you for the info!

0 Likes

#6

A plugin could do that. It would require an EventListener for on_query_completions which looks for the next section heading before the caret’s position. The resulting text would needto be used as key to lookup completion items.

The following snippet could be used to iterate through all ATX and SETEXT headings in a markdown file and search the nearest one. The pattern already has groups for hashtags (group 2) and the title text (group 3 and 4), which would need to be evaluated.

HEADINGS_RE = re.compile(
    r"""
    ^( [ \t]* )                                   # leading whitespace
    (?:
      ( \#{1,6} ) [ \t]+ ( [^\n]+ )               # ATX headings
    | ( [^-#\s][^|\n]* ) \n \1 ( -{3,} | ={3,} )  # SETEXT headings
    ) [ \t]*$                                     # maybe trailing whitespace
    """,
    re.X | re.M
)


def all_headings(view, start=0, end=None):
    text = view.substr(sublime.Region(start, end or view.size()))
    for m in HEADINGS_RE.finditer(text):
        title_begin = start + m.start()
        title_end = start + m.end()
        if m.group(2):
            # ATX headings use group 2 (heading) and 3 (leading hashes)
            level = m.end(2) - m.start(2)
        else:
            # SETEXT headings use group 4 (text) and 5 (underlines)
            level = 2 if text[m.start(5)] == "-" else 1
        # ignore front matter and raw code blocks
        if not view.match_selector(title_begin, "front-matter, markup.raw.block.markdown"):
            yield (title_begin, title_end, level)
    return None

The snippet is from MarkdownEditing.

0 Likes

#7

Thank you very much for the comment. I’ll give this a look and see if I can make it work.

0 Likes

#8

You may need to tweak the function as it is designed to only return regions used for folding. Even have the solution in mind but tbh - I am too lazy to type it. :smiley:

0 Likes

#9

Ha. Well, if you feel ever feel a burst of energy, by all means go to town. Though, I can probably hack my way through it with some time. Thanks again.

0 Likes