lhl2617 / VSLilyPond

VSCode Extension for LilyPond
https://marketplace.visualstudio.com/items?itemName=lhl2617.vslilypond
96 stars 7 forks source link

improve format tool #359

Open Levitanus opened 2 years ago

Levitanus commented 2 years ago

As I understand, current format tool is the same as exists in https://github.com/frescobaldi/python-ly/blob/master/ly/reformat.py

I lack the possibility to keep reasonable line width, and making line-breacks in obvious places.

Currently, I've made quick format function for my Reaper lilypond exporter, so I pretty like how it looks like on simple generated code, but it is not as flexible as the original module.

import re
import textwrap

def format_lines(lilypond: str) -> List[str]:
    patterns = {
        re.compile(r'<<(?!\n)'): '<<\n',
        re.compile(r'{(?!\n)'): '{\n',
        re.compile(r'(?!\n)>>'): '\n>>',
        re.compile(r'(?!\n)}'): '\n}',
        re.compile(r'(?=\s)\|(?=\s)'): '|\n',
    }
    idents = re.compile(r'(<<)|{')
    dedents = re.compile(r'(>>)|}')
    for pattern, repl in patterns.items():
        lilypond = re.sub(pattern, repl, lilypond)
    lines = re.split(r'\n', lilypond)
    out = []
    ident = 0
    ident_am = 4
    for line in lines:
        line = line_strip(line)
        if m := re.search(dedents, line):
            ident -= 1
        # if line:
        ident_str = ' ' * ident
        ident_level = ident_str * ident_am
        wraped = textwrap.wrap(
            line,
            width=80 - len(ident_level + ident_str),
            subsequent_indent=ident_level + ident_str,
            # initial_indent=ident_level
        )
        out.append(ident_level + '\n'.join(wraped))
        if m := re.search(idents, line):
            ident += 1
    return out