Exemple #1
0
    def prepare_payload(self):
        src = src_paths(self.nvim)
        test = test_paths(self.nvim)
        path = current_file(self.nvim)
        root_path = current_path(self.nvim)
        rel_path = os.path.relpath(path, start=root_path).split('/')
        open_with = self.nvim.vars.get(
            'acid_open_alternate_file_with',
            self.nvim.vars.get('acid_open_new_file_with', 'edit')
        )

        if rel_path[0] in src:
            log_debug("Current file is a 'src', changing to 'test'")
            alt_path = to_alt_path(
                rel_path, test, root_path,
                lambda f: '{}_test'.format(f),
                'test'
            )
        else:
            log_debug("Current file is a 'test', changing to 'src'")
            alt_path = to_alt_path(
                rel_path, src, root_path,
                lambda f: f.split('_')[0],
                'src'
            )

        if os.path.exists(alt_path):
            self.nvim.command('silent {} {}'.format(open_with, alt_path))
        else:
            ns = path_to_ns(alt_path, test | src)
            self.nvim.command('AcidNewFile {}'.format(ns))


        return None
Exemple #2
0
def format_dict(d):
    lines = []
    for k, v in d.items():
        if type(v) == dict:
            data = format_dict(v)
        elif type(v) == list:
            data = v
        else:
            data = [v]

        log_debug("Pre-parsed data: {}", str(data))

        if not data:
            lines.append("{: <10} → []".format(k))
        else:
            i, *j = data
            lines.append("{: <10} → {}".format(k, str(i).replace('\n', '')))
            [
                lines.append("{: <12} {}".format("",
                                                 str(l).replace('\n', '')))
                for l in j
            ]
            log_debug("Produced {} lines", len(lines))

    return lines
Exemple #3
0
    def ensure_cmd_win_exists(self):
        use_cmd_win = bool(
            self.nvim.vars.get('acid_meta_repl_use_cmd_window', False))

        log_debug("use cmd win? is {}", self.use_cmd_win)

        if use_cmd_win:
            no_cmd = self.cmd_buf_nr is None
            has_no_cmd_window = self.nvim.funcs.bufwinnr(self.cmd_buf_nr) == -1

            if no_cmd or has_no_cmd_window:
                send = """:call AcidSendNrepl({
                    'op': 'eval', 'code': join(getline(1, '$'), '\\n')
                    }, 'MetaRepl')<CR>""".splitlines()

                send = "map <buffer> <silent> <localleader><CR> {}".format(
                    "".join(map(str.strip, send)))
                meta_repl_window = self.nvim.funcs.bufwinnr(self.buf_nr)
                nvim.command("{} wincmd w".format(meta_repl_window))

                self.cmd_buf_nr = build_window(
                    self.nvim,
                    close=1,
                    throwaway=1,
                    orientation="rightbelow 20 split",
                    commands=[
                        'file acid://meta-repl-{}/scratchpad'.format(
                            self.random), 'set ft=clojure', send,
                        "let b:acid_ns_strategy='ns:user'"
                    ])
Exemple #4
0
 def existing(ap):
     alt_root = os.path.join(root, ap)
     if os.path.exists(alt_root):
         log_debug("Path {} exists", alt_root)
         return os.path.join(alt_root, *path)
     log_debug("Path {} doesn't exist", alt_root)
     return
Exemple #5
0
def path_to_ns(path, stop_paths=None):
    if stop_paths is None:
        stop_paths = ['src', 'test']

    stop_paths = sorted(stop_paths, key=lambda x: x.count('/'))

    raw_path_list = None

    for stop_path in reversed(stop_paths):
        m = re.search(stop_path, path)
        if m:
            raw_path_list = path[m.start():].replace(
                "_", "-").split('/')[stop_path.count('/') + 1:]
            raw_path_list[-1] = raw_path_list[-1].split('.')[0]
            break

    if raw_path_list is None:
        log_debug("Previous check did not work. Attempting project.clj")

        # Look for project.clj
        path = path.replace("_", "-").split('/')[1:]
        path[-1] = path[-1].split('.')[0]
        for ix, _ in enumerate(path):
            if os.path.exists(os.path.join(*["/", *path[:ix], "project.clj"])):
                raw_path_list = path[ix + 1:]
                break

    if raw_path_list is None:
        log_warning("Have not found any viable path")
        return None
    else:
        log_debug("Found path list: {}", raw_path_list)
        return ".".join(raw_path_list)
Exemple #6
0
    def acid_alternate_file(self, args):
        try:
            src = src_paths(self.nvim)
            path = get(args, 0, self.nvim.funcs.expand("%:p"))
            log_info("Finding alternate file for {}", path)
            root_path = self.nvim.funcs.getcwd()
            rel_path = os.path.relpath(path, start=root_path).split('/')

            if rel_path[0] in src:
                paths = alt_paths(
                    rel_path,
                    test_paths(self.nvim),
                    root_path,
                    lambda f: '{}_test'.format(f),
                )
            else:
                paths = alt_paths(rel_path, src, root_path,
                                  lambda f: "_".join(f.split('_')[:-1]), 'src')
        except Exception as e:
            log_debug("error: {}", e)
            paths = []

        log_debug("paths: {}", paths)

        return list(paths)
Exemple #7
0
    def on_handle(self, msg, *_):
        if 'no-info' in msg.get('status', []):
            warning(self.nvim, "No information for symbol")
            return

        try:
            lines = self.transform(msg)
        except Exception as e:
            warning(self.nvim, "Couldn't transform msg into doc.")
            log_error(e)
            return

        no_doc_buffer = self.doc_buf_nr is None
        buf_win_nr = self.nvim.funcs.bufwinnr(self.doc_buf_nr)
        doc_len = len(lines)

        if no_doc_buffer or buf_win_nr == -1:
            cmds = ['file acid://doc', 'wincmd p']

            self.doc_buf_nr = build_window(
                self.nvim,
                close=1,
                commands=cmds,
                throwaway=1,
                orientation="leftabove {} split".format(doc_len))
        else:
            self.nvim.command('{} wincmd w | resize {} | wincmd p'.format(
                buf_win_nr, doc_len))

        log_debug(lines)
        self.nvim.buffers[self.doc_buf_nr][:] = lines
Exemple #8
0
def list_clj_files(nvim):
    rtp = nvim.options.get('runtimepath').split(',')

    for path in rtp:
        match = os.path.join(path, 'clj/acid/**/*.clj')
        log_debug('Attempting path: {}', match)

        yield from glob.iglob(match)
Exemple #9
0
def path_to_ns(nvim, force=False):
    fpath = nvim.funcs.expand("%:p:r")
    if fpath in path_ns_cache and not force:
        ns = path_ns_cache[fpath]
        log_debug("Hitting cache for ns '{}'", ns)
        return ns

    stop_paths = get_stop_paths(nvim)
    ns = pure.path_to_ns(fpath, stop_paths)
    path_ns_cache[fpath] = ns
    return ns
Exemple #10
0
def path_to_ns(nvim, fpath=None, force=False):
    if not fpath:
        fpath = nvim.funcs.expand("%:p:r")

    if fpath in path_ns_cache and not force:
        ns = path_ns_cache[fpath]
        return ns

    log_debug("Namespace is not cached. Finding from path")

    stop_paths = get_stop_paths(nvim)
    ns = pure.path_to_ns(fpath, stop_paths)
    path_ns_cache[fpath] = ns
    return ns
Exemple #11
0
def path_to_ns(path, stop_paths=None, base_files=None):
    log_debug("Supplied path is {}", str(path))

    if not path:
        log_debug("Possibly empty or scratch buffer. Skipping")
        return

    if stop_paths is None:
        stop_paths = ['src', 'test']

    if base_files is None:
        base_files = ['project.clj', 'deps.edn', 'build.boot']

    stop_paths = sorted(stop_paths, key=lambda x: x.count('/'))

    raw_path_list = None

    for stop_path in reversed(stop_paths):
        stop_path = "/{}/".format(stop_path)
        ix = path[::-1].find(stop_path[::-1])
        log_debug("Attempting reverse match: [{}: {}] -> {}",
                  stop_path[::-1], path[::-1], ix)
        if ix > 0:
            startpos = len(path) - ix
            raw_path_list = path[startpos:].replace("_", "-").split('/')
            raw_path_list = [x for x in raw_path_list if x]
            if len(raw_path_list) > 0:
                raw_path_list[-1] = raw_path_list[-1].split('.')[0]
                break

    if raw_path_list is None:
        log_debug("Previous check did not work. Attempting base files")

        # Look for project.clj
        path = path.replace("_", "-").split('/')[1:]
        path[-1] = path[-1].split('.')[0]
        for ix, _ in enumerate(path):
            for bf in base_files:
                if os.path.exists(os.path.join(*["/", *path[:ix], bf])):
                    raw_path_list = path[ix+1:]
                    break

    if not raw_path_list:
        log_warning("Have not found any viable path")
        return ""
    else:
        log_debug("Found path list: {}", raw_path_list)
        return ".".join(raw_path_list)
Exemple #12
0
def to_alt_path(path_arr, alt_paths, root, rename_fn, default):
    # clone array so we don't overwrite last element
    path = list(path_arr)[1:]
    path[-1] = rename_file(path[-1], rename_fn)

    for ap in alt_paths:
        fname = os.path.join(root, ap, *path)
        if os.path.exists(fname):
            log_debug("Alternate file exists. using '{}'", fname)
            return fname


    fname = os.path.join(root, default, *path)
    log_debug("Alternate doesn't exist. using '{}'", fname)
    # Returns default path if no test is found
    return fname
Exemple #13
0
def find_file_in_path(nvim, fname, resource=None):
    log_debug("finding path")
    protocol, *_, fpath = fname.split(':')

    log_debug("Finding path to {}", fname)

    if protocol == 'file':
        if os.path.exists(fpath):
            return fpath
        elif resource != None:
            paths = get_stop_paths(nvim)

            for path in paths:
                attempt = os.path.join(path, resource)
                if os.path.exists(attempt):
                    return attempt

            project = resource.split('/')[0]
            foreign_project_fpath = nvim.vars.get('acid_project_root', None)

            if foreign_project_fpath is None:
                return

            for path in paths:
                attempt = os.path.join(foreign_project_fpath, project, path,
                                       resource)
                if os.path.exists(attempt):
                    return attempt
    elif protocol == 'jar':
        jarpath, fpath = fpath.split('!')
        hashed = '{:X}'.format(
            binascii.crc32(bytes(jarpath, 'ascii')) & 0xffffffff)
        tmppath = os.path.join(tempfile.gettempdir(), hashed)

        if not os.path.exists(tmppath):
            os.mkdir(tmppath)
            zipf = zipfile.ZipFile(jarpath)
            zipf.extractall(tmppath)
            zipf.close()

        fpath = fpath if not os.path.isabs(fpath) else fpath[1:]
        full = os.path.join(tmppath, fpath)
        if os.path.exists(full):
            return full

    return None
Exemple #14
0
def alt_paths(path_arr, alt_paths, root, rename_fn):
    # clone array so we don't overwrite last element
    path = list(path_arr)[1:]
    path[-1] = pure.rename_file(path[-1], rename_fn)

    for ap in alt_paths:
        fname = os.path.join(root, ap, *path)
        if os.path.exists(fname):
            log_debug("Alternate file exists. using '{}'", fname)
            return fname

    def existing(ap):
        alt_root = os.path.join(root, ap)
        if os.path.exists(alt_root):
            return os.path.join(alt_root, *path)

    return filter(lambda i: i is not None, map(existing, alt_paths))
Exemple #15
0
    def print_doc(msg):
        outcome = {}
        lines = []
        for key, value in definition['data'].items():
            log_debug("Working with key {}", key)
            if 'default' in value:
                obj = msg.get(key, value['default'])
            else:
                obj = msg[key]

            if obj:
                if 'transform' in value:
                    this, *other = transform_meta(value['transform'])
                    obj = value['transform'](obj, *[outcome[i] for i in other])

                if 'prepend' in value:
                    prepend = value['prepend']
                    if type(obj) == list:
                        obj = [prepend, *obj]
                    else:
                        obj = '{} {}'.format(prepend, obj)

                if 'rename' in value:
                    key = value['rename']
                outcome[key] = obj

        log_debug("current data: {}", outcome)

        for key in definition['format']:
            if type(key) == list and lines[-1] != '':
                lines.append('')
            elif key in outcome:
                obj = outcome[key]
                if obj:
                    obj_type = type(obj)
                    if obj_type == str:
                        lines.append(obj)
                    elif obj_type == list:
                        lines = [*lines, *obj]
                    else:
                        log_warning('Unknown obj type, skipping.')
        return lines
Exemple #16
0
def repl_host_address(nvim):
    path = current_path(nvim)

    connection = nvim.exec_lua("return require('acid.connections').get(...)",
                               path)
    if connection is not None:
        return connection

    log_debug("Failed to connect from lua connections.")
    host = nvim.vars.get('acid_nrepl_host', '127.0.0.1')
    try:
        addr = [host, get_port_no(nvim)]
        nvim.exec_lua("require('acid.connections').set(...)",
                      path,
                      addr,
                      async_=True)
        log_debug("Found a .nrepl-port file, using that")
        return addr
    except:
        return None
Exemple #17
0
def repl_host_address(nvim):
    path = current_path(nvim)

    if path[-1] != "/":
        path = path + "/"

    ix = nvim.funcs.luaeval("require('acid.connections').current[_A]", path)

    if ix != None:
        connection = nvim.funcs.luaeval(
            "require('acid.connections').store[_A]", ix)
        log_debug("Return from lua: {}", str(connection))

        return connection

    host = nvim.vars.get('acid_lein_host', '127.0.0.1')
    try:
        return [host, get_port_no(nvim)]
    except:
        return None
Exemple #18
0
    def prepare_payload(self, ns):
        files = list(list_clj_files(self.nvim))
        path = '{}.clj'.format(ns_to_path(ns))

        log.log_debug('Found all this clojure files: {}', files)
        log.log_debug('Attempting to match against {}', path)

        match = list(filter(lambda k: k.endswith(path), files))
        if any(match):
            fpath, *_ = match
            fpath = os.path.relpath(fpath, start=current_path(self.nvim))
            with open(fpath, 'r') as source:
                data = '\n'.join(source.readlines())

            return {
                'file': data,
                'file-path': fpath,
                'file-name': os.path.basename(fpath)
            }
        else:
            log.warning(self.nvim, 'no file found!')
Exemple #19
0
    def ensure_win_exists(self):
        no_shared_buffer = self.buf_nr is None
        has_no_window = no_shared_buffer or self.nvim.funcs.bufwinnr(
            self.buf_nr) == -1

        log_debug("buf_nr is {}", self.buf_nr)
        log_debug("has window? {}", has_no_window)

        if no_shared_buffer or has_no_window:
            self.random = random.randint(0, 100)
            cmds = [
                'file acid://meta-repl-{}'.format(self.random),
                'nnoremap <buffer> <localleader><CR> :e<CR>',
                'nnoremap <buffer> <localleader><localleader> kdggjdG',
                'nnoremap <buffer> <localleader>D kdgg',
                'nnoremap <buffer> <localleader>d jdG',
            ]

            self.buf_nr = build_window(
                self.nvim,
                close=1,
                commands=cmds,
                throwaway=1,
            )
            log_debug("Set buf_nr to {}", self.buf_nr)
Exemple #20
0
def path_to_ns(nvim):
    path = nvim.funcs.expand("%:p:r").replace("_", "-").split('/')[1:]
    raw_path_list = None

    for ix, node in enumerate(reversed(path)):
        if node == 'src':
            raw_path_list = path[ix * -1:]
            break

    if raw_path_list is None:
        # Look for project.clj
        for ix, _ in enumerate(path):
            if os.path.exists(os.path.join(*["/", *path[:ix], "project.clj"])):
                raw_path_list = path[ix + 1:]
                break

    if raw_path_list is None:
        log_warning("Have not found any viable path")
    else:
        log_debug("Found path list: {}", raw_path_list)

    return ".".join(raw_path_list)
Exemple #21
0
    def new_file(self, args):
        ns = args[0]
        has_path = len(args) > 1
        if not has_path:
            fname = "{}.clj".format(ns_to_path(ns))
            base = 'test' if ns.endswith('-test') else 'src'
            path = os.path.join(current_path(self.nvim), base, fname)
        else:
            path = args[1]

        if os.path.exists(path):
            log_debug("File already exists. Aborting.")
            return path

        directory = os.path.dirname(path)

        if not os.path.exists(directory):
            os.makedirs(directory)

        with open(path, 'w') as fpath:
            fpath.write('(ns {})'.format(ns))

        return path
Exemple #22
0
    def add_persistent_watch(self, url, handler, matches={}):
        "Adds a callback to all messages in a connection."
        watcher_key = "{}-persistent".format(handler.name)
        conn = self.get_or_create(url)

        if not watcher_key in self.persistent[url]:
            log.log_info('Adding new persisntent watcher fn: {}', handler.name)

            self.persistent[url].add(watcher_key)

            log.log_debug('persistent handler -> {}', str(handler))
            log.log_debug('connection -> {}', str(url))
            log.log_debug('key -> {}', str(watcher_key))

            patched_handler = handler.gen_handler(finalize_watch)
            conn.watch(watcher_key, matches, patched_handler)
Exemple #23
0
def format_payload(payload):
    if type(payload) == str:
        return [payload]

    ls = []
    try:
        msg_id = payload.get('id', '****')
        for k, v in payload.items():
            key = k.lower()
            if key not in {'ns', 'session', 'id', 'op'}:
                if type(v) == list:
                    log_debug('v is a list')
                    header, trailer = v[0], v[1:]
                elif type(v) == dict:
                    log_debug('v is a dict')
                    formatted = format_dict(v)
                    log_debug('Got {}', str(formatted))
                    if len(formatted) > 0:
                        header, *trailer = formatted
                    else:
                        header = []
                elif '\n' in v:
                    header, *trailer = v.split('\n')
                else:
                    header, trailer = v, []

                if not header:
                    next

                if header.isspace() or header is "":
                    header, trailer = trailer[0], trailer[1:]

                ls.append("[{}][{: <9}] => {}".format(
                    str(msg_id)[-4:], key.upper(), str(header)
                ).strip())

                for i in trailer:
                    ls.append("{: <20} {}".format("", str(i)))
    except e:
        log_error("Couldn't finish producing output: {}", str(e))
    finally:
        if len(ls) == 0:
            log_warning("Empty output for ls: {}", str(payload))
        return ls
Exemple #24
0
    def on_handle(self, msg, *_):
        if not 'no-info' in msg.get('status', []):
            name = msg['name']
            ns = msg.get('ns', '')

            arglist = msg.get('arglists-str', [])
            doc = msg.get('doc', '')
            javadoc = msg.get('javadoc', '')
            added = msg.get('added', '')
            super_ = msg.get('super', '')
            modifiers = msg.get('modifiers', [])
            see_also = msg.get('see-also', [])
            interfaces = msg.get('interfaces', [])

            if arglist:
                fn_calls = ["({}{})".format(name, " {}".format(i) if i else "")
                           for i in arglist[2:-2].split('] [')]
            else:
                fn_calls = [name]

            if see_also:
                see_also = ["https://clojuredocs.org/{}".format(i)
                            for i in see_also]

            docl = [i for i in [
                " ".join(fn_calls),
                ns,
                modifiers,
                " ",
                javadoc,
                *doc.split('\n'),
                " ",
                added and "Since version {}".format(added),
                interfaces and "Implements: {}".format(
                    ",".join(interfaces)
                ) or "",
                super_ and "Extends: {}".format(super_) or "",
                see_also and "See also:" or "",
                *see_also,
            ] if i ]

            no_doc_buffer = self.doc_buf_nr is None
            buf_win_nr = self.nvim.funcs.bufwinnr(self.doc_buf_nr)
            doc_len = len(docl)

            if no_doc_buffer or buf_win_nr == -1:
                cmds = ['file acid://doc',
                        'wincmd p',
                        ]

                self.doc_buf_nr = build_window(
                    self.nvim, close=1, commands=cmds, throwaway=1,
                    orientation="leftabove {} split".format(doc_len)
                )
            else:
                self.nvim.command('{} wincmd w | resize {} | wincmd p'.format(
                        buf_win_nr, doc_len
                ))

            info(self.nvim, "Documentation  for {}/{}".format(ns, name))
            log_debug(docl)
            exec_cmd = "bd {} | au! AcidDoc".format(self.doc_buf_nr)

            self.nvim.buffers[self.doc_buf_nr][:] = docl
            self.nvim.command('augroup AcidDoc')
            self.nvim.command('au!')
            self.nvim.command(
                'au CursorMoved * exec "{}"'.format(exec_cmd))
            self.nvim.command('augroup END')

        else:
            warning(self.nvim, "No information for symbol")
Exemple #25
0
 def on_configure(self, *_a, **_k):
     log.log_debug('Passing spec transformation fn')
     return [doc_transform(definition)]
Exemple #26
0
 def on_configure(self, transform, *args, **kwargs):
     log_debug('Got {} as transform fn', transform)
     self.transform = transform