def apply_smart_comment(editor, opening='/*', closing='*/', line_comment=None): doc = editor.document() c = QTextCursor(editor.textCursor()) c.clearSelection() before_opening = doc.find( opening, c, QTextDocument.FindFlag.FindBackward | QTextDocument.FindFlag.FindCaseSensitively) before_closing = doc.find( closing, c, QTextDocument.FindFlag.FindBackward | QTextDocument.FindFlag.FindCaseSensitively) after_opening = doc.find(opening, c, QTextDocument.FindFlag.FindCaseSensitively) after_closing = doc.find(closing, c, QTextDocument.FindFlag.FindCaseSensitively) in_block_comment = (not before_opening.isNull() and (before_closing.isNull() or before_opening.position() >= before_closing.position())) and \ (not after_closing.isNull() and (after_opening.isNull() or after_closing.position() <= after_opening.position())) if in_block_comment: before_opening.removeSelectedText(), after_closing.removeSelectedText() return c = QTextCursor(editor.textCursor()) left, right = min(c.position(), c.anchor()), max(c.position(), c.anchor()) c.beginEditBlock() c.setPosition(right), c.insertText(closing) c.setPosition(left), c.insertText(opening) c.endEditBlock()
def search(self, query, reverse=False): ''' Search for query, also searching the headers. Matches in headers are not highlighted as managing the highlight is too much of a pain.''' if not query.strip(): return c = self.textCursor() lnum = c.block().blockNumber() cpos = c.positionInBlock() headers = dict(self.headers) if lnum in headers: cpos = self.search_header_pos lines = unicode_type(self.toPlainText()).splitlines() for hn, text in self.headers: lines[hn] = text prefix, postfix = lines[lnum][:cpos], lines[lnum][cpos:] before, after = enumerate(lines[0:lnum]), ((lnum+1+i, x) for i, x in enumerate(lines[lnum+1:])) if reverse: sl = chain([(lnum, prefix)], reversed(tuple(before)), reversed(tuple(after)), [(lnum, postfix)]) else: sl = chain([(lnum, postfix)], after, before, [(lnum, prefix)]) flags = regex.REVERSE if reverse else 0 pat = regex.compile(regex.escape(query, special_only=True), flags=regex.UNICODE|regex.IGNORECASE|flags) for num, text in sl: try: m = next(pat.finditer(text)) except StopIteration: continue start, end = m.span() length = end - start if text is postfix: start += cpos c = QTextCursor(self.document().findBlockByNumber(num)) c.setPosition(c.position() + start) if num in headers: self.search_header_pos = start + length else: c.setPosition(c.position() + length, QTextCursor.MoveMode.KeepAnchor) self.search_header_pos = 0 if reverse: pos, anchor = c.position(), c.anchor() c.setPosition(pos), c.setPosition(anchor, QTextCursor.MoveMode.KeepAnchor) self.setTextCursor(c) self.centerCursor() self.scrolled.emit() break else: info_dialog(self, _('No matches found'), _( 'No matches found for query: %s' % query), show=True)
def find_text(self, pat, cursor, reverse): from calibre.gui2.tweak_book.text_search import find_text_in_chunks chunks = [] cstart = min(cursor.position(), cursor.anchor()) cend = max(cursor.position(), cursor.anchor()) if reverse: cend -= 1 c = QTextCursor(cursor) c.setPosition(cstart) block = c.block() in_text = find_tag_definition(block, 0)[0] is None if in_text: # Check if we are in comment/PI/etc. pb = block.previous() while pb.isValid(): boundaries = pb.userData().non_tag_structures if boundaries: if boundaries[-1].is_start: in_text = False break pb = pb.previous() def append(text, start): text = text.replace(PARAGRAPH_SEPARATOR, '\n') after = start + len(text) if start <= cend and cstart < after: extra = after - (cend + 1) if extra > 0: text = text[:-extra] extra = cstart - start if extra > 0: text = text[extra:] chunks.append((text, start + max(extra, 0))) while block.isValid() and block.position() <= cend: ud = block.userData() boundaries = sorted(chain(ud.tags, ud.non_tag_structures), key=get_offset) if not boundaries: # Add the whole line if in_text: text = block.text() + '\n' append(text, block.position()) else: start = block.position() c.setPosition(start) for b in boundaries: if in_text: c.setPosition(start + b.offset, QTextCursor.MoveMode.KeepAnchor) if c.hasSelection(): append(c.selectedText(), c.anchor()) in_text = not b.is_start c.setPosition(start + b.offset + 1) if in_text: # Add remaining text in block c.setPosition(block.position() + boundaries[-1].offset + 1) c.movePosition(QTextCursor.MoveOperation.EndOfBlock, QTextCursor.MoveMode.KeepAnchor) if c.hasSelection(): append(c.selectedText() + '\n', c.anchor()) block = block.next() s, e = find_text_in_chunks(pat, chunks) return s != -1 and e != -1, s, e