def open_(editor, args): """Open file""" if args is None: from editxt.commands import show_command_bar show_command_bar(editor, "open ") elif all(p is None for p in args.paths): raise CommandError("please specify a file path") else: open_files(args.paths, editor.project)
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 pathfind(editor, args): """Find file by path""" if args is None and editor is not None: args = Options( path_pattern=get_selection_regex(editor), search_path=base_path(editor), unrestricted=False, ) if not (args and args.path_pattern): from editxt.commands import show_command_bar return show_command_bar(editor, "pathfind ") pattern = args.path_pattern search_path = args.search_path if not search_path: return "please specify search path" ag_path = editor.app.config.for_command("ag")["path"] view = editor.get_output_view() line_proc = make_path_processor(view, pattern, ag_path, search_path, editor) command = [ ag_path, '--files-with-matches', '--file-search-regex', pattern, '.', # match every file (even empty files when unrestricted) ] if args.unrestricted: command.insert(-1, "--unrestricted") view.process = threaded_exec_shell(command, cwd=search_path, **line_proc)
def python(editor, args): """Run the contents of the editor or selection in Python executable may be a python interpreter executable or a directory such as a virtualenv containing `bin/python`. """ if args is None: from editxt.commands import show_command_bar show_command_bar(editor, "python ") return python = args.executable if not python: raise CommandError("please specify python executable") if os.path.isdir(python): bin = os.path.join(python, "bin", "python") if os.path.exists(bin): python = bin else: raise CommandError("not found: %s" % bin) if args.scope == "selection": code = editor.document.text_storage[editor.selection] else: code = editor.document.text code = print_last_line(dedent(code)) cwd = editor.dirname() command = [python] + [o for o in args.options if o] + ["-c", code] env = dict(os.environ) env.pop("PYTHONHOME", None) env.pop("PYTHONPATH", None) env.pop("PYTHONDONTWRITEBYTECODE", None) env.pop("EXECUTABLEPATH", None) env.pop("RESOURCEPATH", None) result = exec_shell(command, cwd=cwd, env=env) if result.returncode == 0: msg_type = const.INFO message = str(result) if message.endswith("\n"): message = message[:-1] else: msg_type = const.ERROR message = result or result.err if message: editor.message(message, msg_type=msg_type) else: return "no output"
def python(editor, args): """Run the contents of the editor or selection in Python executable may be a python interpreter executable or a directory such as a virtualenv containing `bin/python`. """ if args is None: from editxt.commands import show_command_bar show_command_bar(editor, "python ") return if not args.executable: try: python = editor.app.config.for_command("python")["executable"] except KeyError: python = "python" else: python = args.executable if os.path.isdir(python): bin = os.path.join(python, "bin", "python") if os.path.exists(bin): python = bin if args.scope == "selection": code = editor.document.text_storage[editor.selection] else: code = editor.document.text cwd = editor.dirname() command = [python] + [o for o in args.options if o] + ["-c", code] env = dict(os.environ) env.pop("PYTHONHOME", None) env.pop("PYTHONPATH", None) env.pop("PYTHONDONTWRITEBYTECODE", None) env.pop("EXECUTABLEPATH", None) env.pop("RESOURCEPATH", None) result = exec_shell(command, cwd=cwd, env=env) if result.returncode == 0: msg_type = const.INFO message = str(result) else: msg_type = const.ERROR message = result or result.err if message: editor.message(message, msg_type=msg_type) else: return "no output"
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()
def ag(editor, args): """Search for files matching pattern""" if args is None: from editxt.commands import show_command_bar show_command_bar(editor, "ag ") return elif args.pattern is None: raise CommandError("please specify a pattern to match") pattern = args.pattern if "-i" in args.options or "--ignore-case" in args.options: pattern = RegexPattern(pattern, pattern.flags | re.IGNORECASE) elif pattern.flags & re.IGNORECASE: args.options.append("--ignore-case") ag_path = editor.app.config.for_command("ag")["path"] options = editor.app.config.for_command("ag")["options"] options = DEFAULT_OPTIONS + shlex.split(options) cwd = args.path or editor.dirname() view = editor.get_output_view() line_processor = make_line_processor(view, pattern, ag_path, cwd) command = [ag_path, pattern] + [o for o in args.options if o] + options view.process = threaded_exec_shell(command, cwd=cwd, **line_processor)
def pathfind(editor, args): """Find file by path""" if args is None and editor is not None: args = Options( path_pattern=get_selection_regex(editor), search_path=base_path(editor), open="open-single-match", ) if not (args and args.path_pattern): from editxt.commands import show_command_bar return show_command_bar(editor, "pathfind ") pattern = args.path_pattern search_path = args.search_path regex = re.compile(pattern, pattern.flags) if not search_path: return "please specify search path" paths = [] exclude = editor.app.config.for_command("pathfind")["exclude_patterns"] if args.open == "all-matched-paths": is_excluded = lambda path: False else: excluders = [make_matcher(pattern) for pattern in exclude] def is_excluded(path): filename = basename(path) return any(x(filename) for x in excluders) for dirpath, dirnames, filenames in os.walk(search_path): if is_excluded(dirpath): continue for name in filenames: path = join(dirpath, name) if regex.search(path) and not is_excluded(path): paths.append(path) if len(paths) == 1 and args.open == "open-single-match": editor.project.window.open_paths(paths, focus=True) elif paths and args.open == "open-first-match": editor.project.window.open_paths(paths[:1], focus=True) elif paths: link = partial(path_link, editor=editor) message = markdown("\n".join(link(path) for path in paths), pre=True) editor.message(message) else: return "no match for pattern: {}".format(args.path_pattern)
def blame(editor, args): """Invoke `git gui blame` on file path Example configuration: command: blame: git_path: /opt/local/bin/git """ if not args: from editxt.commands import show_command_bar return show_command_bar(editor, "blame ") if not (args.path and isfile(args.path)): raise CommandError("cannot blame file without path") git_path = editor.app.config.for_command("blame")["git_path"] command = [git_path, "gui", "blame", args.path] output = [] def got_output(text, returncode): if returncode is None: output.append(text) else: if returncode: if git_path == "git": try: command[0] = subprocess.check_output( ["which", "git"], universal_newlines=True).strip() except subprocess.CalledProcessError: pass output.insert(0, " ".join(command) + "\n") output.append("\nexit code: {}".format(returncode)) view.append_message("".join(output), msg_type=const.ERROR) view.process_completed() view = editor.get_output_view() view.process = threaded_exec_shell( command, cwd=dirname(realpath(args.path)), got_output=got_output, kill_on_cancel=False, )
def github_url(editor, args): """Get GitHub URL""" if not args: from editxt.commands import show_command_bar return show_command_bar(editor, "github-url ") if not (editor and editor.file_path): raise CommandError("cannot get github URL without path") info = get_git_info(editor) if not args.remote: if info.remotes: remote = info.remotes[0] else: raise CommandError("cannot get github URL without remote name") else: remote = {r.name: r for r in info.remotes}.get(args.remote) if remote is None: raise CommandError("unknown remote: {}".format(args.remote)) if args.rev == "HEAD": rev = rev_parse(info.git_dir, "--abbrev-ref") if rev == "HEAD": rev = rev_parse(info.git_dir) else: rev = args.rev lines = get_selected_lines(editor) if lines: if ":" in lines: lines = lines.replace(":", "-L") lines = "#L" + lines link = "https://github.com/{user}/{repo}/blob/{rev}/{path}{line}".format( user=remote.user, repo=remote.repo, rev=rev, path=git_relative_path(editor.file_path, info), line=lines, ) editor.message(html_string("<a href='{0}'>{0}</a>".format(link)))