From 8a90813957b0f857e5f20285bd091b67da218f8e Mon Sep 17 00:00:00 2001 From: Mykyta Holubakha Date: Sun, 27 Aug 2017 19:40:47 +0300 Subject: Multiple fixes in: zugaina searching, remote fetching, iquery command line interface, remotes --- pomu/cli.py | 4 +++- pomu/data/zugaina.py | 2 +- pomu/repo/remote/remote.py | 29 ++++++++++++++++++++++- pomu/search.py | 58 +++++++++++++++++++++++++++------------------- pomu/util/iquery.py | 27 ++++++++++++--------- 5 files changed, 82 insertions(+), 38 deletions(-) diff --git a/pomu/cli.py b/pomu/cli.py index 8de900f..1d4ce39 100644 --- a/pomu/cli.py +++ b/pomu/cli.py @@ -3,9 +3,11 @@ import click from os import path +from pomu.data.zugaina import ZugainaDataSource from pomu.patch.patch import process_changes from pomu.repo.init import init_plain_repo, init_portage_repo from pomu.repo.repo import portage_repo_path, portage_repos, pomu_active_repo +from pomu.search import PSPrompt from pomu.source import dispatcher from pomu.util.pkg import cpv_split from pomu.util.result import ResultException @@ -149,7 +151,7 @@ def show(package): @main.command() @click.argument('query', required=True) @click.option('--fetch-only', default=False, is_flag=True) -def search(query): +def search(query, fetch_only): """Search gpo.zugaina.org""" ds = ZugainaDataSource(query) p = PSPrompt(ds) diff --git a/pomu/data/zugaina.py b/pomu/data/zugaina.py index 14a3ddd..88f2fbc 100644 --- a/pomu/data/zugaina.py +++ b/pomu/data/zugaina.py @@ -41,7 +41,7 @@ class ZugainaDataSource(DataSource): id_ = div.xpath('li/a')[0].get('href').split('/')[3] pv = div.xpath('li/div/b')[0].text v = cpv_split(pv, True)[2] - overlay = div.xpath('@id') + overlay = div.xpath('@id')[0] res.append((id_, v, overlay)) return res diff --git a/pomu/repo/remote/remote.py b/pomu/repo/remote/remote.py index d057e6f..133c645 100644 --- a/pomu/repo/remote/remote.py +++ b/pomu/repo/remote/remote.py @@ -1,11 +1,38 @@ """A template class for remote repos""" - +from urllib.parse import urlparse class RemoteRepo(): """A class responsible for remotes""" def __init__(self, url): raise NotImplementedError() + @classmethod + def from_url(cls, uri, type_=None): + tp = RemoteRepo.type_for_name(type_) + if not tp: + try: + scheme, *_ = urlparse(uri) + except: + tp = RemoteGitRepo + if (scheme.startswith('http') or scheme.startswith('git') + scheme.startswith('ssh')): + tp = RemoteGitRepo + elif scheme.startswith('svn'): + tp = RemoteSvnRepo + elif scheme.startswith('rsync'): + tp = RemoteRsyncRepo + return tp(uri) + + @classmethod + def type_for_name(type_): + from pomu.repo.remote.git import RemoteGitRepo + from pomu.repo.remote.hg import RemoteHgRepo + from pomu.repo.remote.rsync import RemoteRsyncRepo + from pomu.repo.remote.svn import RemoteSvnRepo + res = {'git': RemoteGitRepo, 'mercurial': RemoteHgRepo, + 'rsync': RemoteRsyncRepo, 'svn': RemoteSvnRepo} + return res.get(type_) + def fetch_package(self, name, category=None, version=None): """Fetches a package, determined by the parametres""" cat, n, ver = get_full_cpv(self.fetch_tree(), name, category, version).unwrap() diff --git a/pomu/search.py b/pomu/search.py index e77ed1a..db8625c 100644 --- a/pomu/search.py +++ b/pomu/search.py @@ -1,7 +1,8 @@ from enum import Enum from pydoc import pager -from curtsies import FullscreenWindow, width, invert, fmtstr +from curtsies import FullscreenWindow, fmtstr, fsarray +from curtsies.fmtfuncs import invert from pomu.util.iquery import Prompt, clamp @@ -12,7 +13,7 @@ class Entry: self.item = item self.children = children - def toggle(self, idx): + def toggle(self, idx=0): if idx == 0: self.expanded = not self.expanded else: @@ -28,7 +29,9 @@ class Entry: return len(self.children) + 1 if self.expanded else 1 def selected(self): - return [child[1] for child in self.children if child[0]] + if self.children: + return [child[1] for child in self.children if child[0]] + return [] class PromptState(Enum): TOP_PREV=0 @@ -44,14 +47,14 @@ class PSPrompt(Prompt): self.state = PromptState.LIST self.set_page(1) - def results(): + def results(self): # (cp, v, overlay, data) res = [] - for k, v in self. itemitems(): + for k, v in self.pages.items(): for entry in v: cp = entry.item[0] for child in entry.selected(): - cid, v, overlay = *child + cid, v, overlay = child data = self.data.get_item(cid) res.append((cp, v, overlay, data)) return res @@ -67,7 +70,7 @@ class PSPrompt(Prompt): self.pages[page] = self.entries def render(self): - title = str(self.page) + title = str(self.page) + '//' + str(self.state.value) if self.page > 1: title = ('[ ' + (invert('Prev') if self.state == 0 else ('Prev')) + @@ -76,28 +79,33 @@ class PSPrompt(Prompt): title = (title + ' [ ' + (invert('Next') if self.state == 1 else ('Next')) + ' ]') - title = center(title) - bottom = ('[ ' + invert('OK') if self.idx == len(self) else 'OK' + ' ]') - bottom = center(bottom) - items = [render_entry(e, idx) for idx, e in enumerate(self.lens())] + title = self.center(title) + bottom = '[ ' + (invert('OK') if self.idx == len(self) else 'OK') + ' ]' + bottom = self.center(bottom) + items = [self.render_entry(e, idx) for idx, e in enumerate(self.lens())] output = fsarray([title] + items + [bottom]) self.window.render_to_terminal(output) + def _refresh(self): + w, h = self.window.width, self.window.height + output = fsarray([' ' * w] * h) + self.window.render_to_terminal(output) + def render_entry(self, entry, idx): winw = self.window.width if entry[1]: - hld, data = *entry[1] + hld, data = entry[1] stt = '*' if hld else ' ' - text = ' [' + invert(stt) if idx == 0 else stt + '] ' + text = ' [' + (invert(stt) if idx == 0 else stt) + '] ' text += '{}::{}'.format(data[1], data[2]) elif entry[0]: - data = entry[0] - exp = 'v' if entry.expanded else '>' - text = '[' + invert(exp) if idx == 0 else exp + '] ' + data = entry[0].item + exp = 'v' if entry[0].expanded else '>' + text = '[' + (invert(exp) if idx == 0 else exp) + '] ' text += data[0] + ' ' strw = fmtstr(text).width insw = fmtstr(data[1]).width - text += data[1][:winw - strw - 2] + '..' if insw + strw > winw else data[1] + text += data[1][:winw - strw - 2] + ('..' if insw + strw > winw else data[1]) else: text = '' return text @@ -107,9 +115,9 @@ class PSPrompt(Prompt): if res: return res elif event == '': - self.state = (self.state + 1) % 2 + self.state = PromptState((self.state.value + 1) % 2) elif event in {'', ''}: - if self.state < 2: + if self.state.value < 2: return -1 else: return False @@ -117,7 +125,7 @@ class PSPrompt(Prompt): def __len__(self): - return sum(lun(y) for y in self.entries) + return sum(len(y) for y in self.entries) def center(self, stri): tw = fmtstr(stri).width @@ -129,13 +137,15 @@ class PSPrompt(Prompt): def toggle(self): item, idx = self.get_idx(self.idx) - item.toggle(idx) + item[0].toggle(idx) def preview(self): target = self.get_target() if target[1]: - data = self.data.get_item(target[1][0]) + data = self.data.get_item(target[1][1][0]) pager(data) + self._refresh() + self.render() def lens(self): h = self.window.height - 2 @@ -144,10 +154,10 @@ class PSPrompt(Prompt): return lst def get_target(self): - return get_idx(self.idx)[0] + return self.get_idx(self.idx)[0] def get_idx(self, idx): - for entry in self.entries(): + for entry in self.entries: if len(entry) > idx: break idx -= len(entry) diff --git a/pomu/util/iquery.py b/pomu/util/iquery.py index d0281a3..8f81e57 100644 --- a/pomu/util/iquery.py +++ b/pomu/util/iquery.py @@ -35,18 +35,23 @@ class Prompt: def run(self, window_type=CursorAwareWindow, **args): with open('/dev/tty', 'r') as tty_in, \ open('/dev/tty', 'w') as tty_out, \ - Input(in_stream=tty_in) as input_, \ - window_type(in_stream=tty_in, - out_stream=tty_out, - hide_cursor=False, - extra_bytes_callback=input_.unget_bytes, - **args) as window: - self.window = window + Input(in_stream=tty_in) as input_: + if window_type == CursorAwareWindow: + iargs = {'in_stream':tty_in, 'out_stream':tty_out, + 'hide_cursor':False, 'extra_bytes_callback':input_.unget_bytes} + else: + iargs = {'out_stream':tty_out} + iargs.update(args) + with window_type(**args) as window: + return self.event_loop(window, input_) + + def event_loop(self, window, input_): + self.window = window + self.render() + for event in input_: + if self.process_event(event) == -1: + break self.render() - for event in input_: - if self.process_event(event) == -1: - break - self.render() return self.results() def clamp(self, x): -- cgit v1.2.3-65-gdbad