def lydocinfo(self): """Return the lydocinfo instance for our document.""" if self._lydocinfo is None: doc = lydocument.Document(self.document()) v = variables.manager(self.document()).variables() self._lydocinfo = lydocinfo.DocInfo(doc, v) return self._lydocinfo
def music(self): """Return the music.Document instance for our document.""" if self._music is None: import music doc = lydocument.Document(self.document()) self._music = music.Document(doc) self._music.include_path = self.includepath() return self._music
def html_document(document, scheme='editor', inline=False, number_lines=False, full_html=True): """Return a (by default) css-styled HTML document for the full document.""" c = lydocument.Cursor(lydocument.Document(document)) return html(c, scheme, inline, number_lines, full_html)
def auto_indent_block(block): """Auto-indents the given block.""" i = indenter(block.document()) d = lydocument.Document(block.document()) current_indent = i.get_indent(d, block) if current_indent is False: return indent = i.compute_indent(d, block) d.combine_undo = True with d: d[d.position(block):d.position(block) + len(current_indent)] = indent
def insertOverride(self, x, y): """ Insert the override command. """ doc = lydocument.Document(self.doc) block = doc.block(self.pos) p = block.position() cursor = QtGui.QTextCursor(self.doc) cursor.setPosition(p) cursor.beginEditBlock() cursor.insertText(self.createOffsetOverride(x, y)) cursor.insertBlock() cursor.endEditBlock() reformat.reformat(cursor)
def html_document(document, scheme='editor', inline=False, number_lines=False, full_html=True, wrap_tag="pre", wrap_attrib="id", wrap_attrib_name="document"): """Return a (by default) css-styled HTML document for the full document.""" c = lydocument.Cursor(lydocument.Document(document)) return html(c, scheme, inline, number_lines, full_html, wrap_tag, wrap_attrib, wrap_attrib_name)
def indices(self, cursor): """Return a Python slice object or None or False. If a slice, it specifies the range of destinations (in the destinations() list) that the given QTextCursor points to. The cursor must of course belong to our document. If None or False, it means that there is no object in the cursors neighbourhood. If False, it means that it is e.g. preferred to clear earlier highlighted objects. This method performs quite a bit trickery: it also returns the destination when a cursor points to the _ending_ point of a slur, beam or phrasing slur. """ cursors = self._cursors def findlink(pos): # binary search in list of cursors lo, hi = 0, len(cursors) while lo < hi: mid = (lo + hi) // 2 if pos < cursors[mid].position(): hi = mid else: lo = mid + 1 return lo - 1 if cursor.hasSelection(): end = findlink(cursor.selectionEnd() - 1) if end >= 0: start = findlink(cursor.selectionStart()) if start < 0 or cursors[start].position() < cursor.selectionStart(): start += 1 if start <= end: return slice(start, end+1) return False index = findlink(cursor.position()) if index < 0: return # before all other links cur2 = cursors[index] if cur2.position() < cursor.position(): # is the cursor at an ending token like a slur end? prevcol = -1 if cur2.block() == cursor.block(): prevcol = cur2.position() - cur2.block().position() col = cursor.position() - cursor.block().position() found = False tokens = ly.document.Runner(lydocument.Document(cursor.document())) tokens.move_to_block(cursor.block(), True) for token in tokens.backward_line(): if token.pos <= prevcol: break elif token.pos <= col: if isinstance(token, ly.lex.MatchEnd) and token.matchname in ( 'slur', 'phrasingslur', 'beam'): # YES! now go backwards to find the opening token nest = 1 name = token.matchname for token in tokens.backward(): if isinstance(token, ly.lex.MatchStart) and token.matchname == name: nest -= 1 if nest == 0: found = True break elif isinstance(token, ly.lex.MatchEnd) and token.matchname == name: nest += 1 break if found: index = findlink(tokens.block.position() + token.pos) if index < 0 or cursors[index].block() != tokens.block: return elif cur2.block() != cursor.block(): return False # highlight it! return slice(index, index+1)
def matches(cursor, view=None): """Return a list of zero to two cursors specifying matching tokens. If the list is empty, the cursor was not at a MatchStart/MatchEnd token, if the list only contains one cursor the matching token could not be found, if the list contains two cursors, the first is the token the cursor was at, and the second is the matching token. If view is given, only the visible part of the document is searched. """ block = cursor.block() column = cursor.position() - block.position() tokens = lydocument.Runner(lydocument.Document(cursor.document())) tokens.move_to_block(block) if view is not None: first_block = view.firstVisibleBlock() bottom = view.contentOffset().y() + view.viewport().height() pred_forward = lambda: view.blockBoundingGeometry(tokens.block).top( ) <= bottom pred_backward = lambda: tokens.block >= first_block else: pred_forward = lambda: True pred_backward = lambda: True source = None for token in tokens.forward_line(): if token.pos <= column <= token.end: if isinstance(token, ly.lex.MatchStart): match, other = ly.lex.MatchStart, ly.lex.MatchEnd def source_gen(): while pred_forward(): for t in tokens.forward_line(): yield t if not tokens.next_block(): break source = source_gen() break elif isinstance(token, ly.lex.MatchEnd): match, other = ly.lex.MatchEnd, ly.lex.MatchStart def source_gen(): while pred_backward(): for t in tokens.backward_line(): yield t if not tokens.previous_block(): break source = source_gen() break elif token.pos > column: break cursors = [] if source: # we've found a matcher item cursors.append(tokens.cursor()) nest = 0 for token2 in source: if isinstance(token2, other) and token2.matchname == token.matchname: if nest == 0: # we've found the matching item! cursors.append(tokens.cursor()) break else: nest -= 1 elif isinstance(token2, match) and token2.matchname == token.matchname: nest += 1 return cursors