def show_command_bar(editor, args): """Show the command bar""" window = editor.project.window if window is None: beep() else: window.command.activate(text=args or "")
def execute(self, text): self.reset() if not text.strip(): return self.failed_command = text editor = self.window.current_editor if editor is None: beep() return command, index = self._find_command(text) if command is None: self.message("unknown command: {}".format(text)) return try: args = self.parser(command).parse(text, index) except Exception: msg = "parse error: {}".format(text) self.message(msg, exc_info=True) return finally: self._cached_parser = (None, None, None) assert args is not None, "invalid command arguments: {}".format(text) try: message = command(editor, args) except CommandError as err: self.message(err) except Exception: msg = "error in command: {} in {}".format(command.__name__, command.__module__) self.message(msg, exc_info=True) else: self.failed_command = None if not text.startswith(" "): self.text_commander.history.append(text) if message is not None: self.message(message, msg_type=const.INFO)
def validate_expression(self): if self.options.regular_expression and self.find_text is not None: ftext = self.find_text.stringValue() flags = re.UNICODE | re.MULTILINE if self.options.ignore_case: flags |= re.IGNORECASE error = None try: regex = re.compile(ftext, flags) if self.options.python_replace: make_found_range_factory(self.options) except re.error as err: title = "Cannot Compile Regular Expression" error = err except InvalidPythonExpression as err: title = "Cannot Compile Python Expression" error = err if error is not None: beep() # Note: if the find dialog type is NSPanel (instead of NSWindow) # the focus will switch back to the main document window rather # than to the find dialog, which is not what we want. Therefore # we set the Custom Class of the find dialog to NSWindow. ak.NSBeginAlertSheet( title, "OK", None, None, self.gui.window, None, None, None, 0, str(error), ); return False return True
def navigate_history(self, command_view, forward=False): # TODO test old_text = command_view.command_text text = self.get_history(old_text, forward) if text is None: beep() return command_view.command_text = text
def find(self, direction): editor = self.get_editor() if editor is not None and self.options.find_text: found = self._find(editor, direction) if found is not None: editor.selection = found.range editor.text_view.scrollRangeToVisible_(found.range) return beep()
def replace_one(self, sender): editor = self.get_editor() if editor is not None: found = self._find(editor, FORWARD, constrain_to_selection=True) if found is not None: rng = found.range rtext = found.expand(self.options.replace_text) if editor.put(rtext, rng): return beep()
def count_occurrences(self, ftext, regex): editor = self.get_editor() if editor is not None and ftext: count = self.finder.mark_occurrences(ftext, regex) if count: self.flash_status_text("%i occurrences" % count) else: self.flash_status_text("Not found") else: beep()
def activate(self, text="", select=False): editor = self.window.current_editor if editor is None: beep() return if not text and self.failed_command: text = self.failed_command select = True self._cached_parser = (None, None, None) editor.command_view.activate(self, text, select) editor.command_view.__last_completions = [None]
def perform_action(self, sender): default = lambda s: log.info("unknown action: %s", s.tag()) try: self.action_registry.get(sender.tag(), default)(sender) except CommandError as err: beep() editor = self.get_editor() if editor is not None: editor.message(str(err), msg_type=const.ERROR) else: log.warn(err)
def join_lines(editor, args): """Join selected lines into a single line""" if args is None: args = join_lines.arg_parser.default_options() eol = editor.document.eol if not editor.selection[1]: beep() return rng = editor.text.line_range(editor.selection) lines = iterlines(editor.text, rng) text = args.delimiter.join(_unsplit(lines, eol)) + eol editor.put(text, rng, select=True)
def goto_line(self, line): # TODO move this into editor if isinstance(line, (tuple, list)): line, select_start, select_len = line else: select_start = 0 select_len = 0 try: index = self.editor.line_numbers.index_of(line) range = (index + select_start, select_len) self.setSelectedRange_(range) self.scrollRangeToVisible_(range) except ValueError: beep()
def replace_one(self, sender): editor = self.get_editor() if editor is not None: found = self._find(editor, FORWARD, constrain_to_selection=True) if found is not None: rng = found.range rtext = found.expand(self.options.replace_text) textview = editor.text_view if textview.shouldChangeTextInRange_replacementString_(rng, rtext): editor.text[rng] = rtext textview.didChangeText() textview.setNeedsDisplay_(True) return beep()
def doc(editor, args): """Navigate the document tree""" if args is None: from editxt.commands import show_command_bar show_command_bar(editor, doc.name + " ") return if args.name is not None: new_editor = args.file if new_editor is None: new_editor = args.name if new_editor is not EditorTreeItem.NO_MATCH and \ editor.window.focus(new_editor): return elif editor.window.focus(args.direction, args.offset): return beep()
def show_help(self, text): """Show help for comment text""" command, index = self._find_command(text) if command is None: message = help.__doc__ else: message = command.__doc__ or "" # if index <= len(text) or " " in text: # msg = [message] # # TODO handle exception # msg.append(self.parser(command).get_help(text, index)) # message = "\n\n".join(m for m in msg if m.strip()) if message: self.message(markdoc(message), msg_type=const.INFO) else: beep()
def _replace_all(self, in_selection=False): editor = self.get_editor() ftext = self.options.find_text range = None if editor is None else editor.selection if editor is None or not ftext or (in_selection and range[1] == 0): beep() return text = editor.text options = self.options if not in_selection: if options.wrap_around: range = (0, 0) else: # Replace all to the end of the file. Logically there should be # another option: replace all (backward) to the beginning of the # file, but there's no way to do that with the interface. range = (range[0], len(text) - range[0]) if options.regular_expression: finditer = self.regexfinditer elif options.match_entire_word: ftext = "\\b" + re.escape(ftext) + "\\b" finditer = self.regexfinditer else: finditer = self.simplefinditer rtext = options.replace_text range0 = None rtexts = [] for found in finditer(text, ftext, range, FORWARD, False): range = found.range if range0 is None: range0 = range else: rtexts.append(text[sum(range1):range[0]]) range1 = range rtexts.append(found.expand(rtext)) if range0 is not None: start = range0[0] range = (start, sum(range1) - start) value = "".join(rtexts) view = editor.text_view if view.shouldChangeTextInRange_replacementString_(range, value): text[range] = value view.didChangeText() view.setNeedsDisplay_(True) return beep()
def message(self, text, exc_info=None, msg_type=const.ERROR): if isinstance(text, AttributedString): assert not exc_info msg = text else: if exc_info: if isinstance(exc_info, (int, bool)): exc_info = sys.exc_info() exc = "\n\n" + "".join(traceback.format_exception(*exc_info)) else: exc = "" msg = "{}{}".format(text, exc) editor = self.window.current_editor if editor is None: log.info(text, exc_info=exc_info) if msg_type == const.ERROR: beep() else: editor.message(msg, msg_type=msg_type)
def grab(editor, args): """Collect lines matching a pattern""" if args is None: from editxt.commands import show_command_bar show_command_bar(editor, "grab ") return elif args.pattern is None: raise CommandError("please specify a pattern to match") if args.invert: norm = lambda m: not m else: norm = lambda m: m scope = editor.selection if args.scope == "selection" else (0,) regex = re.compile(args.pattern, args.pattern.flags) lines = [] for line in iterlines(editor.document.text, scope): if norm(regex.search(line)): lines.append(line) if lines: return "".join(lines) beep()