@button format -- format @language code

25 views
Skip to first unread message

zhaohe wang

unread,
May 4, 2026, 12:14:45 AMMay 4
to leo-editor
@language python
"""
Format the current node or selected code snippet using Prettier.

[Dependency Installation]
To support all configured languages, it is recommended to install globally using pnpm (saves disk space):

    pnpm add -g prettier @prettier/plugin-pug prettier-plugin-java @prettier/plugin-clang-format

Note: Formatting C/C++ requires clang-format to be installed and available in your system PATH.
"""
import subprocess
import shutil
import re

prettier_bin = shutil.which('prettier')

if not prettier_bin:
    g.es("Prettier not found. Please refer to the [Dependency Installation] instructions at the top.", color='red')
else:
    # 1. Get the node's default language
    d = g.get_directives_dict(p)
    node_lang = d.get('language')

    # 2. Language-to-parser mapping
    parser_map = {
        'html': 'html',
        'javascript': 'babel',
        'typescript': 'typescript',
        'css': 'css',
        'scss': 'scss',
        'pug': 'pug',
        'java': 'java',
        'cplusplus': 'clang-format',
        'cpp': 'clang-format',
        'c': 'clang-format',
    }

    w = c.frame.body.wrapper
    has_sel = w.hasSelection()

    # 3. Determine the parser to use
    parser = None

    if has_sel:
        i, j = w.getSelectionRange()
        raw_text = w.getSelectedText()
        target_desc = "selected snippet"

        # Sniff for @language directive inside the selected text
        match = re.search(r'@language\s+([a-zA-Z0-9_-]+)', raw_text, re.IGNORECASE)
        if match:
            fragment_lang = match.group(1).lower()
            parser = parser_map.get(fragment_lang, fragment_lang)
            g.es(f"Auto-detected snippet language: {fragment_lang}", color='purple')
        else:
            parser = parser_map.get(node_lang)
    else:
        raw_text = p.b
        target_desc = "entire body"
        parser = parser_map.get(node_lang)

    # ----------------------------------------------------------------
    # [Key Fix]: Strip Leo's @language directives to prevent Prettier errors
    # ----------------------------------------------------------------
    directives = []

    def extract_directive(m):
        directives.append(m.group(0))
        return ""  # Remove the line from the text sent to Prettier

    # Match whole lines starting with @language (supports multiline and leading whitespace)
    text_to_format = re.sub(r'^[ \t]*@language\s+[a-zA-Z0-9_-]+[ \t]*\n?', extract_directive, raw_text, flags=re.IGNORECASE | re.MULTILINE)

    if not parser:
        g.es(f"Skipped: Cannot determine parser. Node language is '{node_lang}'.", color='orange')
    elif not text_to_format.strip():
        g.es(f"The {target_desc} is empty or contains only directives. Nothing to format.")
    else:
        try:
            # 4. Run Prettier (enforcing 4-space indentation)
            proc = subprocess.Popen(
                [prettier_bin, '--parser', parser, '--tab-width', '4'],
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                shell=False
            )
            stdout, stderr = proc.communicate(input=text_to_format)

            # 5. Handle the result based on the return code
            if proc.returncode == 0:
                # [Key Fix]: Re-attach the stripped directives to the top of the formatted code
                final_text = "".join(directives) + stdout

                if raw_text != final_text:
                    if has_sel:
                        p.b = p.b[:i] + final_text + p.b[j:]
                        w.setSelectionRange(i, i + len(final_text))
                    else:
                        p.b = final_text

                    c.redraw()
                    g.es(f"Formatted {target_desc} (Prettier - {parser})", color='green')
                else:
                    g.es(f"The {target_desc} is already properly formatted (Prettier - {parser})", color='blue')
            else:
                g.es(f"Formatting failed: {stderr.strip()}", color='red')
        except Exception as e:
            g.es(f"Execution error: {e}", color='red')

Edward K. Ream

unread,
May 4, 2026, 5:31:58 AMMay 4
to leo-editor
On Sunday, May 3, 2026 at 11:14:45 PM UTC-5 wangz...@gmail.com wrote:

> Format the current node or selected code snippet using Prettier.

Thanks for this script. And thanks to the anonymous 'e' for the idea, in Leo's earliest days, that lead directly to `@button` nodes.

Edward
Reply all
Reply to author
Forward
0 new messages