async def install() -> int: cols, _ = get_terminal_size() sep = cols * "=" errors: MutableSequence[str] = [] tasks = chain(_git(), _pip(), _gem(), _npm(), _go(), _script()) for fut in as_completed(tasks): for debug, proc in await fut: args = join(map(str, proc.args)) if proc.returncode == 0: msg = LANG("proc succeeded", args=args) print( msg, debug, decode(proc.stderr), decode(proc.stdout), sep, sep=linesep, ) else: errors.append(args) msg = LANG("proc failed", code=proc.returncode, args=args) print( msg, debug, decode(proc.stderr), decode(proc.stdout), sep, sep=linesep, file=stderr, ) if errors: print(linesep.join(errors)) return bool(errors)
def _word(nvim: Nvim, is_inside: bool) -> None: win = cur_win(nvim) buf = win_get_buf(nvim, win=win) row, col = win_get_cursor(nvim, win=win) line, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1) bline = encode(line) lhs, rhs = decode(bline[:col]), decode(bline[col:]) ctx = gen_split(lhs, rhs, unifying_chars=UNIFIYING_CHARS) if not (ctx.word_lhs + ctx.word_rhs): words_lhs, words_rhs = ctx.syms_lhs, ctx.syms_rhs else: words_lhs, words_rhs = ctx.word_lhs, ctx.word_rhs c_lhs = max(col - len(encode(words_lhs)), 0) c_rhs = max(col + len(encode(words_rhs)) - 1, 0) if is_inside: mark1 = (row, c_lhs) mark2 = (row, c_rhs) else: mark1 = (row, max(0, c_lhs - 1)) mark2 = (row, min(len(bline), c_rhs + 1)) set_visual_selection(nvim, win=win, mode="v", mark1=mark1, mark2=mark2)
def _rename(nvim: Nvim) -> None: win = cur_win(nvim) buf = win_get_buf(nvim, win=win) row, col = win_get_cursor(nvim, win=win) line, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1) b_line = encode(line) lhs, rhs = decode(b_line[:col]), decode(b_line[col:]) split = gen_split(lhs=lhs, rhs=rhs, unifying_chars=UNIFIYING_CHARS) word = split.word_lhs + split.word_rhs ans = ask(nvim, question=LANG("rename: "), default=word) if ans: nvim.lua.vim.lsp.buf.rename(ans)
def _range_edit_trans( unifying_chars: AbstractSet[str], smart: bool, ctx: Context, primary: bool, lines: _Lines, edit: RangeEdit, ) -> EditInstruction: new_lines = edit.new_text.split(ctx.linefeed) if (primary and not isinstance(edit, ParsedEdit) and len(new_lines) <= 1 and edit.begin == edit.end): return _edit_trans(unifying_chars, smart=smart, ctx=ctx, lines=lines, edit=edit) else: (r1, ec1), (r2, ec2) = sorted((edit.begin, edit.end)) if edit.encoding == UTF16: c1 = len( encode(decode(lines.b_lines16[r1][:ec1 * 2], encoding=UTF16))) c2 = len( encode(decode(lines.b_lines16[r2][:ec2 * 2], encoding=UTF16))) elif edit.encoding == UTF8: c1 = len(lines.b_lines8[r1][:ec1]) c2 = len(lines.b_lines8[r2][:ec2]) else: raise ValueError(f"Unknown encoding -- {edit.encoding}") begin = r1, c1 end = r2, c2 lines_before = (edit.new_prefix.split(ctx.linefeed) if isinstance( edit, ParsedEdit) else new_lines) cursor_yoffset = (r2 - r1) + (len(lines_before) - 1) cursor_xpos = ((len(encode(lines_before[-1])) if len(lines_before) > 1 else len(lines.b_lines8[r2][:c1]) + len(encode(lines_before[0]))) if primary else -1) inst = EditInstruction( primary=primary, begin=begin, end=end, cursor_yoffset=cursor_yoffset, cursor_xpos=cursor_xpos, new_lines=new_lines, ) return inst
async def _fmt_output( attr: FmtAttrs, ctx: BufContext, cwd: PurePath, temp: Path ) -> str: arg_info = join(chain((attr.bin,), attr.args)) try: args = arg_subst(attr.args, ctx=ctx, tmp_name=str(temp)) except ParseError: return LANG("grammar error", text=arg_info) else: if not which(attr.bin): return LANG("missing", thing=attr.bin) else: stdin = temp.read_bytes() if attr.type is FmtType.stream else None proc = await call( attr.bin, *args, stdin=stdin, cwd=cwd, check_returncode=set(), ) if attr.type is FmtType.stream: temp.write_bytes(proc.stdout) if proc.returncode == attr.exit_code: return "" else: heading = LANG("proc failed", code=proc.returncode, args=arg_info) print_out = ctx.linefeed.join((heading, decode(proc.stderr))) return print_out
def _toggle_case(nvim: Nvim) -> None: win = cur_win(nvim) row, col = win_get_cursor(nvim, win=win) buf = win_get_buf(nvim, win=win) if writable(nvim, buf=buf): line, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1) bline = encode(line) before, after = bline[:col], bline[col:] if after: cur, *post = after pt = decode(bytes((cur, ))) swapped = _swap_case(pt) new = decode(before) + swapped + decode(bytes(post)) pos = len(before) + len(encode(swapped)) buf_set_lines(nvim, buf=buf, lo=row, hi=row + 1, lines=(new, )) win_set_cursor(nvim, win=win, row=row, col=pos)
def _restore(nvim: Nvim, win: Window, buf: Buffer, pos: NvimPos) -> Tuple[str, Optional[int]]: row, _ = pos ns = create_ns(nvim, ns=NS) marks = tuple(buf_get_extmarks(nvim, buf=buf, id=ns)) if len(marks) != 2: return "", 0 else: m1, m2 = marks after, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1) cur_row, cur_col = win_get_cursor(nvim, win=win) (_, lo), (_, hi) = m1.end, m2.begin binserted = encode(after)[lo:hi] inserted = decode(binserted) movement = cur_col - lo if cur_row == row and lo <= cur_col <= hi else None if inserted: buf_set_text(nvim, buf=buf, begin=m1.end, end=m2.begin, text=("", )) return inserted, movement
def _parse(nvim: Nvim, buf: Buffer, stack: Stack, state: State, comp: Completion) -> Tuple[Edit, Sequence[Mark]]: if isinstance(comp.primary_edit, SnippetEdit): comment_str = buf_commentstr(nvim, buf=buf) clipboard = nvim.funcs.getreg() info = ParseInfo(visual="", clipboard=clipboard, comment_str=comment_str) if isinstance(comp.primary_edit, SnippetRangeEdit): row, col = comp.primary_edit.begin line, *_ = buf_get_lines(nvim, buf=buf, lo=row, hi=row + 1) line_before = decode( encode(line, encoding=comp.primary_edit.encoding)[:col]) edit, marks = parse_range( context=state.context, snippet=comp.primary_edit, info=info, line_before=line_before, ) else: edit, marks = parse_norm( stack.settings.match.unifying_chars, smart=stack.settings.completion.smart, context=state.context, snippet=comp.primary_edit, info=info, ) else: edit, marks = comp.primary_edit, () return edit, marks
def cont() -> Iterator[_Pane]: for line in decode(proc.out).strip().splitlines(): pane_id, pane_active, window_active = line.split(" ") pane = _Pane( uid=pane_id, pane_active=bool(int(pane_active)), window_active=bool(int(window_active)), ) yield pane
def _set_trimmed(nvim: Nvim, win: Window, buf: Buffer) -> None: row, col = win_get_cursor(nvim, win=win) lines = buf_get_lines(nvim, buf=buf, lo=0, hi=-1) new_lines = [ decode(encode(line)[:col]) + decode(encode(line)[col:]).rstrip() if r == row else line.rstrip() for r, line in enumerate(lines) ] while new_lines: line = new_lines.pop() if line or len(new_lines) <= row: new_lines.append(line) break if len(new_lines) < len(lines): new_lines.append("") if new_lines != lines: buf_set_lines(nvim, buf=buf, lo=0, hi=-1, lines=new_lines) win_set_cursor(nvim, win=win, row=row, col=col)
async def run(*args: str) -> str: if not args: return "" else: try: proc = await call( "ctags", "--sort=no", "--output-format=json", f"--fields={_FIELDS}", *args, check_returncode=set(), ) except (FileNotFoundError, PermissionError): return "" else: return decode(proc.out)
async def cont() -> Optional[str]: async with self._lock: if self._bin and not self._proc: self._proc = await _proc(self._bin, cwd=cwd) if self._proc: self._cwd = cwd if not self._proc: return None else: assert self._proc.stdin and self._proc.stdout try: self._proc.stdin.write(encode(json)) self._proc.stdin.write(b"\n") await self._proc.stdin.drain() out = await self._proc.stdout.readline() except (ConnectionError, LimitOverrunError, ValueError): return await self._clean() else: return decode(out)
async def _screenshot( unifying_chars: AbstractSet[str], uid: str ) -> Tuple[str, Iterator[str]]: try: proc = await call( "tmux", "capture-pane", "-p", "-t", uid, check_returncode=set(), ) except OSError: return uid, iter(()) else: if proc.code: return uid, iter(()) else: words = coalesce(decode(proc.out), unifying_chars=unifying_chars) return uid, words
def context( nvim: Nvim, db: BDB, options: MatchOptions, state: State, manual: bool ) -> Context: with Atomic() as (atomic, ns): ns.scr_col = atomic.call_function("screencol", ()) ns.buf = atomic.get_current_buf() ns.name = atomic.buf_get_name(0) ns.line_count = atomic.buf_line_count(0) ns.filetype = atomic.buf_get_option(0, "filetype") ns.commentstring = atomic.buf_get_option(0, "commentstring") ns.fileformat = atomic.buf_get_option(0, "fileformat") ns.tabstop = atomic.buf_get_option(0, "tabstop") ns.expandtab = atomic.buf_get_option(0, "expandtab") ns.cursor = atomic.win_get_cursor(0) atomic.commit(nvim) scr_col = ns.scr_col buf = cast(Buffer, ns.buf) (r, col) = cast(Tuple[int, int], ns.cursor) row = r - 1 pos = (row, col) buf_line_count = ns.line_count filename = normcase(cast(str, ns.name)) filetype = cast(str, ns.filetype) comment_str = cast(str, ns.commentstring) tabstop = ns.tabstop expandtab = cast(bool, ns.expandtab) linefeed = cast(Literal["\n", "\r", "\r\n"], LFfmt[cast(str, ns.fileformat)].value) lo = max(0, row - options.proximate_lines) hi = min(buf_line_count, row + options.proximate_lines + 1) lines = buf_get_lines(nvim, buf=buf, lo=lo, hi=hi) if DEBUG: db_line_count, db_lit = db.lines(buf.number, lo=lo, hi=hi) db_lines = tuple(db_lit) assert db_line_count in { buf_line_count - 1, buf_line_count, buf_line_count + 1, }, (db_line_count, buf_line_count) assert tuple( "" if idx == row else line for idx, line in enumerate(db_lines, start=lo) ) == tuple( "" if idx == row else line for idx, line in enumerate(lines, start=lo) ), linesep.join( unified_diff(lines, db_lines) ) r = row - lo line = lines[r] lines_before, lines_after = lines[:r], lines[r + 1 :] lhs, _, rhs = comment_str.partition("%s") b_line = encode(line) before, after = decode(b_line[:col]), decode(b_line[col:]) split = gen_split(lhs=before, rhs=after, unifying_chars=options.unifying_chars) ctx = Context( manual=manual, change_id=state.change_id, commit_id=state.commit_id, cwd=state.cwd, buf_id=buf.number, filename=filename, filetype=filetype, line_count=buf_line_count, linefeed=linefeed, tabstop=tabstop, expandtab=expandtab, comment=(lhs, rhs), position=pos, scr_col=scr_col, line=split.lhs + split.rhs, line_before=split.lhs, line_after=split.rhs, lines=lines, lines_before=lines_before, lines_after=lines_after, words=split.word_lhs + split.word_rhs, words_before=split.word_lhs, words_after=split.word_rhs, syms=split.syms_lhs + split.syms_rhs, syms_before=split.syms_lhs, syms_after=split.syms_rhs, ws_before=split.ws_lhs, ws_after=split.ws_rhs, ) return ctx
def _version(timeout: float) -> str: with urlopen(_VER, timeout=timeout) as resp: return decode(resp.read())