예제 #1
0
def change_indent(cursor, direction):
    """Changes the indent in the desired direction (-1 for left and +1 for right).
    
    Returns True if the indent operation was applied.
    The cursor may contain a selection.
    
    """
    # get some variables from the document
    indent_vars = indent_variables(cursor.document())
    
    blocks = list(cursortools.blocks(cursor))
    block = blocks[0]
    pos = cursor.selectionStart() - block.position()
    token = tokeniter.tokens(block)[0] if tokeniter.tokens(block) else None
    if cursor.hasSelection() or pos == 0 or (token and isinstance(token, ly.lex.Space) and token.end >= pos):
        # decrease the indent
        state = tokeniter.state(block)
        current_indent = get_indent(block)
        new_indent = current_indent + direction * indent_vars['indent-width']
        if state.mode() in ('lilypond', 'scheme'):
            computed_indent = compute_indent(block)
            if cmp(computed_indent, new_indent) == direction:
                new_indent = computed_indent
        diff = new_indent - current_indent
        with cursortools.compress_undo(cursor):
            for block in blocks:
                set_indent(block, get_indent(block) + diff)
        return True
예제 #2
0
 def html_selection(self, cursor):
     """Return HTML for the cursor's selection."""
     d = cursor.document()
     start = d.findBlock(cursor.selectionStart())
     startpos = cursor.selectionStart() - start.position()
     end = d.findBlock(cursor.selectionEnd())
     endpos = cursor.selectionEnd() - end.position()
     
     html = []
     # first block, skip tokens before selection
     block = start
     source = iter(tokeniter.tokens(block))
     for t in source:
         if t.end > startpos:
             startslice = max(0, startpos - t.pos)
             endslice = None
             if block == end and t.end > endpos:
                 endslice = endpos - t.pos
             html.append(self.html_for_token(t[startslice:endslice], type(t)))
             break
     while block != end:
         html.extend(map(self.html_for_token, source))
         html.append('\n')
         block = block.next()
         source = iter(tokeniter.tokens(block))
     # last block, go to end of selection
     for t in source:
         if t.end > endpos:
             if t.pos < endpos:
                 html.append(self.html_for_token(t[:endpos-t.pos], type(t)))
             break
         html.append(self.html_for_token(t))
     return self.html_wrapper("".join(html))
예제 #3
0
def reformat(cursor):
    """Reformats the selection or the whole document, adjusting the whitespace."""
    def newlinebefore(t):
        editor.insertText(tokeniter.cursor(block, t, end=0), '\n')
    
    def newlineafter(t):
        editor.insertText(tokeniter.cursor(block, t, start=len(t)), '\n')
    
    indent_vars = indent.indent_variables(cursor.document())
    
    with cursortools.compress_undo(cursor):
        indent.re_indent(cursor)
        with cursortools.Editor() as editor:
            for block in get_blocks(cursor):
                
                denters = []
                tokens = tokeniter.tokens(block)
                
                nonspace_index = -1
                for i, t in enumerate(tokens):
                    if isinstance(t, ly.lex.Indent) and t in ('{', '<<'):
                        denters.append(i)
                    elif isinstance(t, ly.lex.Dedent) and t in ('}', '>>'):
                        if denters:
                            denters.pop()
                        elif nonspace_index != -1:
                            newlinebefore(t)
                    elif not isinstance(t, ly.lex.Space):
                        nonspace_index = i
                for i in denters:
                    if i < nonspace_index:
                        newlineafter(tokens[i])
                    
                # TODO: wrap long lines
        
        indent.re_indent(cursor)
        
        with cursortools.Editor() as editor:
            for block in get_blocks(cursor):
                tokens = tokeniter.tokens(block)
                if (len(tokens) == 2
                    and isinstance(tokens[0], ly.lex.Space)
                    and isinstance(tokens[1], (
                        ly.lex.lilypond.LineComment,
                        ly.lex.scheme.LineComment))
                    and len(tokens[1]) > 2
                    and len(set(tokens[1][:3])) == 1):
                    # move commented lines with more than 2 comment characters
                    # to column 0
                    editor.removeSelectedText(tokeniter.cursor(block, tokens[0]))
                else:
                    # remove trialing whitespace
                    for t in tokens[::-1]:
                        if isinstance(t, ly.lex.Space):
                            editor.removeSelectedText(tokeniter.cursor(block, t))
                        else:
                            break
예제 #4
0
def tokens(cursor):
    """Yield the tokens tuple for every block from the beginning of the document until the cursor."""
    end = cursor.block()
    block = cursor.document().firstBlock()
    while block < end:
        yield tokeniter.tokens(block)
        block = block.next()
예제 #5
0
 def actionTriggered(self, name):
     # convert arpeggio_normal to arpeggioNormal, etc.
     name = _arpeggioTypes[name]
     cursor = self.mainwindow().textCursor()
     # which arpeggio type is last used?
     lastused = '\\arpeggioNormal'
     types = set(_arpeggioTypes.values())
     block = cursor.block()
     while block.isValid():
         s = types.intersection(tokeniter.tokens(block))
         if s:
             lastused = s.pop()
             break
         block = block.previous()
     # where to insert
     c = lydocument.cursor(cursor)
     c.select_end_of_block()
     with cursortools.compress_undo(cursor):
         for item in ly.rhythm.music_items(c, partial=ly.document.OUTSIDE):
             c = QTextCursor(cursor.document())
             c.setPosition(item.end)
             c.insertText('\\arpeggio')
             if name != lastused:
                 cursortools.strip_indent(c)
                 indent = c.block().text()[:c.position() -
                                           c.block().position()]
                 c.insertText(name + '\n' + indent)
             # just pick the first place
             return
예제 #6
0
 def fold_events(self, block):
     """Provides folding information by looking at indent/dedent tokens."""
     for t in tokeniter.tokens(block):
         if isinstance(t, ly.lex.Indent):
             yield widgets.folding.START
         elif isinstance(t, ly.lex.Dedent):
             yield widgets.folding.STOP
예제 #7
0
def open_file_at_cursor(cursor, mainwin):
    """Opens the filename mentioned at the text cursor."""
    # take either the selection or the include-args found by ly.parse
    if cursor.hasSelection():
        fnames = [cursor.selection().toPlainText()]
    else:
        fnames = list(ly.parse.includeargs(iter(tokeniter.tokens(cursor.block()))))
    
    # detemine search path: doc dir and other include path names
    filename = cursor.document().url().toLocalFile()
    if filename:
        path = [os.path.dirname(filename)]
    else:
        path = []
    path.extend(documentinfo.info(cursor.document()).includepath())
    
    # load all docs, trying all include paths
    d = None
    for f in fnames:
        for p in path:
            name = os.path.normpath(os.path.join(p, f))
            if os.access(name, os.R_OK):
                d = mainwin.openUrl(QUrl.fromLocalFile(name))
                break
    if d:
        mainwin.setCurrentDocument(d, True)
예제 #8
0
 def actionTriggered(self, name):
     # convert arpeggio_normal to arpeggioNormal, etc.
     name = _arpeggioTypes[name]
     cursor = self.mainwindow().textCursor()
     # which arpeggio type is last used?
     lastused = '\\arpeggioNormal'
     types = set(_arpeggioTypes.values())
     block = cursor.block()
     while block.isValid():
         s = types.intersection(tokeniter.tokens(block))
         if s:
             lastused = s.pop()
             break
         block = block.previous()
     # where to insert
     c = lydocument.cursor(cursor)
     c.select_end_of_block()
     source = lydocument.Source(c, True, ly.document.OUTSIDE, True)
     with cursortools.compress_undo(cursor):
         for p in ly.rhythm.music_tokens(source):
             c = source.cursor(p[-1], start=len(p[-1]))
             c.insertText('\\arpeggio')
             if name != lastused:
                 cursortools.strip_indent(c)
                 indent = c.block().text()[:c.position()-c.block().position()]
                 c.insertText(name + '\n' + indent)
             # just pick the first place
             return
예제 #9
0
 def fold_events(self, block):
     """Provides folding information by looking at indent/dedent tokens."""
     for t in tokeniter.tokens(block):
         if isinstance(t, (ly.lex.Indent, ly.lex.BlockCommentStart)):
             yield widgets.folding.START
         elif isinstance(t, (ly.lex.Dedent, ly.lex.BlockCommentEnd)):
             yield widgets.folding.STOP
예제 #10
0
 def actionTriggered(self, name):
     # convert arpeggio_normal to arpeggioNormal, etc.
     name = _arpeggioTypes[name]
     cursor = self.mainwindow().textCursor()
     # which arpeggio type is last used?
     lastused = '\\arpeggioNormal'
     types = set(_arpeggioTypes.values())
     block = cursor.block()
     while block.isValid():
         s = types.intersection(tokeniter.tokens(block))
         if s:
             lastused = s.pop()
             break
         block = block.previous()
     # where to insert
     source = tokeniter.Source.from_cursor(cursor, True, -1)
     with cursortools.compress_undo(cursor):
         for p in music.music_items(source, tokens=source.tokens):
             c = source.cursor(p[-1], start=len(p[-1]))
             c.insertText('\\arpeggio')
             if name != lastused:
                 cursortools.strip_indent(c)
                 import indent
                 indent.insert_text(c, name + '\n')
             # just pick the first place
             return
예제 #11
0
def back(cursor):
    """Yields per-block token iters in backward direction from the cursor."""
    yield reversed(tokeniter.partition(cursor).left)
    block = cursor.block()
    while block.previous().isValid():
        block = block.previous()
        yield reversed(tokeniter.tokens(block))
예제 #12
0
def cut_assign(cursor):
    """Cuts selected text and assigns it to a LilyPond variable."""
    # ask the variable name
    name = inputdialog.getText(None, _("Cut and Assign"), _(
        "Please enter the name for the variable to assign the selected "
        "text to:"), regexp="[A-Za-z]+")
    if not name:
        return
    
    cursortools.strip_selection(cursor)
    
    # determine state at cursor
    block = cursortools.block(cursor)
    state = tokeniter.state(block)
    for t in tokeniter.partition(cursor).left:
        state.follow(t)
    
    mode = ""
    for p in state.parsers():
        if isinstance(p, ly.lex.lilypond.ParseInputMode):
            if isinstance(p, ly.lex.lilypond.ParseLyricMode):
                mode = " \\lyricmode"
            elif isinstance(p, ly.lex.lilypond.ParseChordMode):
                mode = " \\chordmode"
            elif isinstance(p, ly.lex.lilypond.ParseFigureMode):
                mode = " \\figuremode"
            elif isinstance(p, ly.lex.lilypond.ParseDrumMode):
                mode = " \\drummode"
            break

    # find insertion place:
    found = False
    while block.previous().isValid():
        block = block.previous()
        state = tokeniter.state(block)
        if isinstance(state.parser(), ly.lex.lilypond.ParseGlobal):
            found = True
            break
        tokens = tokeniter.tokens(block)
        for t in tokens:
            if isinstance(t, ly.lex.lilypond.Name):
                found = True
                break
            elif not isinstance(t, (ly.lex.Space, ly.lex.Comment)):
                break
        if found:
            break
    insert = QTextCursor(block)
    text = cursor.selection().toPlainText()
    space = '\n' if '\n' in text else ' '
    text = ''.join((name, ' =', mode, ' {', space, text, space, '}\n\n'))
    with cursortools.compress_undo(cursor):
        cursor.insertText('\\' + name)
        pos = insert.selectionStart()
        insert.insertText(text)
    if metainfo.info(cursor.document()).auto_indent:
        insert.setPosition(pos, QTextCursor.KeepAnchor)
        with cursortools.compress_undo(insert, True):
            indent.re_indent(insert)
예제 #13
0
def indentable(cursor):
    """Returns True if the cursor is at a dedent token and running the auto-indenter makes sense."""
    block = cursor.block()
    pos = cursor.position() - block.position()
    for token in tokeniter.tokens(block):
        if token.end >= pos:
            return isinstance(token, (ly.lex.Dedent, ly.lex.BlockCommentEnd))
        elif not isinstance(token, (ly.lex.Space, ly.lex.Dedent)):
            return
예제 #14
0
def indentable(cursor):
    """Returns True if the cursor is at a dedent token and running the auto-indenter makes sense."""
    block = cursor.block()
    pos = cursor.position() - block.position()
    for token in tokeniter.tokens(block):
        if token.end >= pos:
            return isinstance(token, (ly.lex.Dedent, ly.lex.BlockCommentEnd))
        elif not isinstance(token, (ly.lex.Space, ly.lex.Dedent)):
            return
예제 #15
0
def get_indent(block):
    """Returns the indent of the given block."""
    
    # get some variables from the document
    indent_vars = indent_variables(block.document())
    
    tokens = tokeniter.tokens(block)
    if tokens and isinstance(tokens[0], ly.lex.Space):
        return column_position(tokens[0], tabwidth = indent_vars['tab-width'])
    return 0
예제 #16
0
def names(cursor):
    """Harvests names from assignments until the cursor."""
    end = cursor.block()
    block = cursor.document().firstBlock()
    while block.isValid() and block != end:
        for t in tokeniter.tokens(block)[:2]:
            if type(t) is ly.lex.lilypond.Name:
                yield t
                break
        block = block.next()
예제 #17
0
def get_definition(cursor):
    block = cursor.block()
    while block.isValid():
        state = tokeniter.state(block)
        if isinstance(state.parser(), ly.lex.lilypond.ParseGlobal):
            for t in tokeniter.tokens(block)[:2]:
                if type(t) is ly.lex.lilypond.Name:
                    return t[:]
                elif isinstance(t, ly.lex.lilypond.Keyword) and t == '\\score':
                    return '\\score'
        block = block.previous()
예제 #18
0
def get_definition(cursor):
    block = cursor.block()
    while block.isValid():
        state = tokeniter.state(block)
        if isinstance(state.parser(), ly.lex.lilypond.ParseGlobal):
            for t in tokeniter.tokens(block)[:2]:
                if type(t) is ly.lex.lilypond.Name:
                    return t[:]
                elif isinstance(t, ly.lex.lilypond.Keyword) and t == '\\score':
                    return '\\score'
        block = block.previous()
예제 #19
0
def state(cursor):
    """Returns the simplestate string for the position of the cursor."""
    import simplestate
    pos = cursor.selectionStart()
    block = cursor.document().findBlock(pos)
    tokens = tokeniter.tokens(block)
    state = tokeniter.state(block)
    column = pos - block.position()
    for t in tokens:
        if t.end > column:
            break
        state.follow(t)
    return simplestate.state(state)
예제 #20
0
def state(cursor):
    """Returns the simplestate string for the position of the cursor."""
    import simplestate
    pos = cursor.selectionStart()
    block = cursor.document().findBlock(pos)
    tokens = tokeniter.tokens(block)
    state = tokeniter.state(block)
    column = pos - block.position()
    for t in tokens:
        if t.end > column:
            break
        state.follow(t)
    return simplestate.state(state)
예제 #21
0
 def globalStaffSize(self, default=20):
     """Returns the global staff size, if set, else the default value."""
     for block in cursortools.all_blocks(self.document()):
         tokens = tokeniter.tokens(block)
         try:
             i = tokens.index('set-global-staff-size')
         except ValueError:
             continue
         try:
             return int(tokens[i+2], 10)
         except (IndexError, ValueError):
             pass
     return default
예제 #22
0
def get_definition(cursor):
    """Return the variable name the cursor's music expression is assigned to.
    
    If the music is in a \\score instead, "\\score" is returned.
    Returns None if no variable name can be found.
    
    """
    block = cursor.block()
    while block.isValid():
        state = tokeniter.state(block)
        if isinstance(state.parser(), ly.lex.lilypond.ParseGlobal):
            for t in tokeniter.tokens(block)[:2]:
                if type(t) is ly.lex.lilypond.Name:
                    return t[:]
                elif isinstance(t, ly.lex.lilypond.Keyword) and t == '\\score':
                    return '\\score'
        block = block.previous()
예제 #23
0
def get_definition(cursor):
    """Return the variable name the cursor's music expression is assigned to.

    If the music is in a \\score instead, "\\score" is returned.
    Returns None if no variable name can be found.

    """
    block = cursor.block()
    while block.isValid():
        state = tokeniter.state(block)
        if isinstance(state.parser(), ly.lex.lilypond.ParseGlobal):
            for t in tokeniter.tokens(block)[:2]:
                if type(t) is ly.lex.lilypond.Name:
                    return t[:]
                elif isinstance(t, ly.lex.lilypond.Keyword) and t == '\\score':
                    return '\\score'
        block = block.previous()
예제 #24
0
 def pitchLanguage(self):
     """Returns the pitchname language used in the document, if defined."""
     languages = ly.pitch.pitchInfo.keys()
     for block in cursortools.all_blocks(self.document()):
         tokens = tokeniter.tokens(block)
         try:
             i = tokens.index('\\language')
         except ValueError:
             try:
                 i = tokens.index('\\include')
             except ValueError:
                 continue
         if isinstance(tokens[i], ly.lex.lilypond.Keyword):
             for t in tokens[i+1:]:
                 if isinstance(t, ly.lex.Space):
                     continue
                 elif t == '"':
                     continue
                 lang = t[:-3] if t.endswith('.ly') else t[:]
                 if lang in languages:
                     return lang
예제 #25
0
def set_indent(block, indent):
    """Sets the indent of block to tabs/spaces of length indent.
    
    Does not change the document if the indent does not need a change.
    Returns True if the indent was changed.
    
    """
    # get some variables from the document
    indent_vars = indent_variables(block.document())
    
    space = make_indent(indent, indent_vars['tab-width'], indent_vars['indent-tabs'])
    tokens = tokeniter.tokens(block)
    if tokens and isinstance(tokens[0], ly.lex.Space):
        changed = tokens[0] != space
        cursor = tokeniter.cursor(block, tokens[0])
    else:
        changed = indent != 0
        cursor = QTextCursor(block)
    if changed:
        cursor.insertText(space)
    return changed
예제 #26
0
    def analyze(self, cursor):
        """Do the analyzing work; set the attributes column and model."""
        self.cursor = cursor
        block = cursor.block()
        self.column = column = cursor.position() - block.position()
        self.text = text = block.text()[:column]
        self.model = None

        # make a list of tokens exactly ending at the cursor position
        # and let state follow
        state = self.state = tokeniter.state(block)
        tokens = self.tokens = []
        for t in tokeniter.tokens(cursor.block()):
            if t.end > column:
                # cut off the last token and run the parser on it
                tokens.extend(state.tokens(text, t.pos))
                break
            tokens.append(t)
            state.follow(t)
            if t.end == column:
                break

        self.last = tokens[-1] if tokens else ''
        self.lastpos = self.last.pos if self.last else column

        parser = state.parser()

        # Map the parser class to a group of tests to return the model.
        # Try the tests until a model is returned.
        try:
            tests = self.tests[parser.__class__]
        except KeyError:
            return
        else:
            for function in tests:
                model = function(self)
                if model:
                    self.model = model
                    return
예제 #27
0
 def analyze(self, cursor):
     """Do the analyzing work; set the attributes column and model."""
     self.cursor = cursor
     block = cursor.block()
     self.column = column = cursor.position() - block.position()
     self.text = text = block.text()[:column]
     self.model = None
     
     # make a list of tokens exactly ending at the cursor position
     # and let state follow
     state = self.state = tokeniter.state(block)
     tokens = self.tokens = []
     for t in tokeniter.tokens(cursor.block()):
         if t.end > column:
             # cut off the last token and run the parser on it
             tokens.extend(state.tokens(text, t.pos))
             break
         tokens.append(t)
         state.follow(t)
         if t.end == column:
             break
     
     self.last = tokens[-1] if tokens else ''
     self.lastpos = self.last.pos if self.last else column
     
     parser = state.parser()
     
     # Map the parser class to a group of tests to return the model.
     # Try the tests until a model is returned.
     try:
         tests = self.tests[parser.__class__]
     except KeyError:
         return
     else:
         for function in tests:
             model = function(self)
             if model:
                 self.model = model
                 return
예제 #28
0
def insertLanguage(document, language):
    """Inserts a language command in the document.
    
    The command is inserted at the top or just below the version line.
    If the document uses LilyPond < 2.13.38, the \\include command is used,
    otherwise the newer \\language command.
    
    """
    version = (documentinfo.info(document).version()
               or lilypondinfo.preferred().version())
    if version and version < (2, 13, 38):
        text = '\\include "{0}.ly"'
    else:
        text = '\\language "{0}"'
    # insert language command on top of file, but below version
    block = document.firstBlock()
    c = QTextCursor(block)
    if '\\version' in tokeniter.tokens(block):
        c.movePosition(QTextCursor.EndOfBlock)
        text = '\n' + text
    else:
        text += '\n'
    c.insertText(text.format(language))
예제 #29
0
 def tokens(self, block):
     """Return the tuple of tokens of the specified block."""
     return tokeniter.tokens(block)
예제 #30
0
def cut_assign(cursor):
    """Cuts selected text and assigns it to a LilyPond variable."""
    # ask the variable name
    name = inputdialog.getText(
        None,
        _("Cut and Assign"),
        _("Please enter the name for the variable to assign the selected "
          "text to:"),
        regexp="[A-Za-z]+")
    if not name:
        return

    cursortools.strip_selection(cursor)

    # determine state at cursor
    block = cursortools.block(cursor)
    state = tokeniter.state(block)
    for t in tokeniter.partition(cursor).left:
        state.follow(t)

    mode = ""
    for p in state.parsers():
        if isinstance(p, ly.lex.lilypond.ParseInputMode):
            if isinstance(p, ly.lex.lilypond.ParseLyricMode):
                mode = " \\lyricmode"
            elif isinstance(p, ly.lex.lilypond.ParseChordMode):
                mode = " \\chordmode"
            elif isinstance(p, ly.lex.lilypond.ParseFigureMode):
                mode = " \\figuremode"
            elif isinstance(p, ly.lex.lilypond.ParseDrumMode):
                mode = " \\drummode"
            break

    # find insertion place:
    found = False
    while block.previous().isValid():
        block = block.previous()
        state = tokeniter.state(block)
        if isinstance(state.parser(), ly.lex.lilypond.ParseGlobal):
            found = True
            break
        tokens = tokeniter.tokens(block)
        for t in tokens:
            if isinstance(t, ly.lex.lilypond.Name):
                found = True
                break
            elif not isinstance(t, (ly.lex.Space, ly.lex.Comment)):
                break
        if found:
            break
    insert = QTextCursor(block)
    text = cursor.selection().toPlainText()
    space = '\n' if '\n' in text else ' '
    text = ''.join((name, ' =', mode, ' {', space, text, space, '}\n\n'))
    with cursortools.compress_undo(cursor):
        cursor.insertText('\\' + name)
        pos = insert.selectionStart()
        insert.insertText(text)
    if metainfo.info(cursor.document()).auto_indent:
        insert.setPosition(pos, QTextCursor.KeepAnchor)
        with cursortools.compress_undo(insert, True):
            indent.re_indent(insert)
예제 #31
0
def compute_indent(block):
    """Returns the indent the given block should have."""
    
    # get some variables from the document
    indent_vars = indent_variables(block.document())
    
    # count the dedent tokens at the beginning of the block
    indents = 0
    for token in tokeniter.tokens(block):
        # dont dedent scheme dedent tokens at beginning of lines (unusual)
        if isinstance(token, ly.lex.Dedent) and not isinstance(token, ly.lex.scheme.CloseParen):
            indents -= 1
        elif not isinstance(token, ly.lex.Space):
            break

    # these variables control the position (yet to be translated to tabbed (real) columns)
    # and how much to add
    indent_pos = None
    indent_add = 0
    
    # look backwards for the token that starts this indent
    prev = block.previous()
    while prev.isValid():
        
        # skip empty blocks
        if prev.length() <= 1:
            prev = prev.previous()
            continue
        
        closers = 0
        found = False
        lasttokens = []
        
        token = None # in case of empty line
        for token in reversed(tokeniter.tokens(prev)):
            if isinstance(token, ly.lex.Dedent):
                indents -= 1
                if isinstance(token, ly.lex.scheme.CloseParen):
                    closers = 0 # scheme close parens are not moved
                else:
                    closers += 1
            elif isinstance(token, ly.lex.Indent):
                indents += 1
                closers = 0
                if not found:
                    if indents == 1:
                        found = token
                    else:
                        lasttokens.append(token)
            elif not isinstance(token, ly.lex.Space):
                closers = 0
                if not found:
                    lasttokens.append(token)
        
        if found:
            # the token that started the current indent has been found
            # if there are no tokens after the indent-opener, take indent of current line and increase,
            # else set indent to the same indent of the token after the indent-opener.
            if isinstance(found, ly.lex.scheme.OpenParen):
                # scheme
                if lasttokens:
                    if len(lasttokens) == 1 or isinstance(lasttokens[-1], ly.lex.Indent):
                        indent_pos = lasttokens[-1].pos
                    elif lasttokens[-1] in scheme_sync_args:
                        indent_pos = lasttokens[-2].pos
                    else:
                        indent_pos = found.pos
                        indent_add = indent_vars['indent-width']
                else:
                    indent_pos = found.pos
                    indent_add = 1
            else:
                # no scheme (lilypond)
                if lasttokens:
                    indent_pos = lasttokens[-1].pos
                else:
                    # just use current indent + INDENT_WIDTH
                    indent_pos = token.end if isinstance(token, ly.lex.Space) else 0
                    indent_add = indent_vars['indent-width']
        elif indents + closers == 0:
            # take over indent of current line
            indent_pos = token.end if isinstance(token, ly.lex.Space) else 0
        else:
            prev = prev.previous()
            continue
        
        # translate indent to real columns (expanding tabs)
        return column_position(prev.text(), indent_pos, indent_vars['tab-width']) + indent_add
    # e.g. on first line
    return 0
예제 #32
0
 def tokens(self, block):
     """Return the tuple of tokens of the specified block."""
     return tokeniter.tokens(block)
예제 #33
0
 def tokens():
     end = cursor.block()
     block = cursor.document().firstBlock()
     while block < end:
         yield tokeniter.tokens(block)
         block = block.next()
예제 #34
0
 def html():
     block = doc.firstBlock()
     while block.isValid():
         yield "".join(map(self.html_for_token, tokeniter.tokens(block)))
         block = block.next()