more entries in the catalog ; more readme and faq ; onging impl

This commit is contained in:
setop 2023-02-15 18:24:14 +01:00
parent d6a31f58f9
commit b5b21f6ca9
6 changed files with 92 additions and 20 deletions

View File

@ -52,13 +52,14 @@ Inspired by envinstall (private), [webinstall](gh:webinstall/webi-installers), [
# conventions and defaults # conventions and defaults
* default status of an entry is "tested" which means the process has been tested under linux-amd64 * default status of an entry in the catalog is "ok" which means the process has been tested under linux-amd64
* entry name in the catalog is the name of the exe ; a prefered name can be added as a property * entry name in the catalog is the name of the exe ; a prefered name can be added as a property
* packages are downloaded in `.cache/cliget`
* tools in unpacked in `~/.local/programs` then symlinked in `~/.local/bin` which must be in PATH * tools in unpacked in `~/.local/programs` then symlinked in `~/.local/bin` which must be in PATH
* semver = semantic versioning : tools are versionned as `major[.minor[.patch[-prerelease[+build]]]]` so versions can be compared * semver = semantic versioning : tools are versionned as `major[.minor[.patch[-prerelease[+build]]]]` so versions can be compared
* installed version is obtained by ruinning `<cli> --version` * installed version is obtained by ruinning `<cli> --version`
* OS and arch are obtained with `os.uname()` python function * OS and arch are obtained with `os.uname()` python function
* default release system is GitHub releases and use `repo` property * default release system is GitHub releases and use `github` property
* default packaging is `.tar.gz` * default packaging is `.tar.gz`
* default structure is to have the exe in the `bin` folder * default structure is to have the exe in the `bin` folder

20
TODO.md
View File

@ -1,10 +1,16 @@
- [ ] implement MVP
- [+] minimal catalog
- [+] search catalog
- [+] local current versions
- [ ] latest version, github strategy
- [ ] intall, github strategy
- [ ] choose forge - [ ] choose forge(s), one will be the golden source of the catalog
* github * github
* gitlab * gitlab
* framagit * framagit
* codeberg * codeberg <= golden source
* source hut * source hut
* my gitea * my gitea
@ -20,3 +26,13 @@
- [ ] communicate on geeks'platform : HN, lobsters, reddit, linuxfr - [ ] communicate on geeks'platform : HN, lobsters, reddit, linuxfr
- [ ] post MVP improvement
- [ ] check local env:
- [ ] existence of `.local`, `.local/programs`, `.local/bin`
- [ ] that permissions are ok
- [ ] that `.local/bin` are in `PATH`
- [ ] allow to force installation version
- [ ] allow to list versions
- [ ] improve search algorithm, fuzzing

View File

@ -41,6 +41,10 @@ cliget:
exa: exa:
desc: enhanced ls desc: enhanced ls
fail:
desc: this entry will fail, for test purpos
github: fail/fail
fd: fd:
desc: A simple, fast and user-friendly alternative to `find` desc: A simple, fast and user-friendly alternative to `find`
github: sharkdp/fd github: sharkdp/fd
@ -100,13 +104,16 @@ hx:
desc: text editor, inspired by vim desc: text editor, inspired by vim
jless: jless:
desc: json document browser desc: a command-line JSON viewer designed for reading, exploring, and searching through JSON data
github: PaulJuliusMartinez/jless
jp: jp:
desc: ploting desc: dead simple terminal plots from JSON data
github: sgreben/jp
jq: jq:
desc: json query desc: json query
github: stedolan/jq
just: just:
desc: a handy way to save and run project-specific commands. desc: a handy way to save and run project-specific commands.
@ -132,13 +139,19 @@ mintproxy:
desc: interactive, SSL/TLS-capable intercepting proxy with a console interface for HTTP/1, HTTP/2, and WebSockets. desc: interactive, SSL/TLS-capable intercepting proxy with a console interface for HTTP/1, HTTP/2, and WebSockets.
pipx: pipx:
mosh:
desc: Remote terminal application that allows roaming, supports intermittent connectivity, and provides intelligent local echo and line editing of user keystrokes.
website: https://mosh.org/
github: mobile-shell/mosho
outrun: outrun:
desc: Delegate execution of a local command to a remote machine. desc: Delegate execution of a local command to a remote machine.
github: Overv/outrun github: Overv/outrun
pip: pip:
pet: pet:
desc: manager snippets desc: Simple command-line snippet manager
github: knqyf263/pet
pylufic: pylufic:
inst: direct inst: direct
@ -221,6 +234,11 @@ up:
name: Ultimate Plumber name: Ultimate Plumber
github: akavel/up github: akavel/up
ups:
desc: Command line tools for manipulating UPS patch files
githb: rameshvarun/ups
tag: language:go
vd: vd:
name: VisiData name: VisiData
desc: interactive multitool for tabular data desc: interactive multitool for tabular data

View File

@ -3,10 +3,12 @@
Usage: Usage:
cliget [-v] [-c URL] list cliget [-v] [-c URL] list
cliget [-v] [-c URL] search PAT cliget [-v] [-c URL] search PAT
cliget [-v] [-c URL] install TOOL ...
cliget [-v] [-c URL] update [--all] [TOOL ...] cliget [-v] [-c URL] update [--all] [TOOL ...]
list list all installed tools list list all installed tools
search search for tools in the catalog with the given pattern search search for tools in the catalog with the given pattern
install TOOL install some tools
update list all updatable tools update list all updatable tools
update TOOL update tools update TOOL update tools
update --all update all updatable tools update --all update all updatable tools
@ -18,6 +20,7 @@ Options:
-v, --verbose -v, --verbose
""" """
import logging
import sys, os import sys, os
from docopt import docopt from docopt import docopt
from yaml import load, SafeLoader from yaml import load, SafeLoader
@ -25,10 +28,14 @@ from semver import VersionInfo
import re import re
from subprocess import run, CalledProcessError, TimeoutExpired from subprocess import run, CalledProcessError, TimeoutExpired
from fuzzywuzzy import fuzz from fuzzywuzzy import fuzz
import requests
def debug(*mess): def trace(*mess):
#print("DEBUG", mess) if "TRACE" in os.environ:
pass print("TRACE", mess)
def warn(*mess):
print(f"WARN {mess[0]}")
class DotDict(dict): class DotDict(dict):
def __getattr__(self, name): def __getattr__(self, name):
@ -36,7 +43,9 @@ class DotDict(dict):
def loadcatalog(options)->dict: def loadcatalog(options)->dict:
catalog=options.get('__catalog', 'catalog.yaml') catalog=options.get('__catalog', 'catalog.yaml')
return load(open(catalog), SafeLoader) o = load(open(catalog), SafeLoader)
trace(o)
return { k:DotDict(v) for k,v in o.items()}
def find_semver(s:str) -> VersionInfo: def find_semver(s:str) -> VersionInfo:
ver = VersionInfo(0,0,0) ver = VersionInfo(0,0,0)
@ -46,7 +55,7 @@ def find_semver(s:str) -> VersionInfo:
try: try:
ver = VersionInfo(*list(i.group(0) for i in re.finditer('\d+', s))[:3]) ver = VersionInfo(*list(i.group(0) for i in re.finditer('\d+', s))[:3])
except Exception as e: except Exception as e:
debug("parse error", e) trace("parse error", e)
return ver return ver
@ -59,14 +68,14 @@ def _internal_list(options) -> tuple[str,VersionInfo]:
# search in path # search in path
try: try:
vers = _version(cli) vers = _version(cli)
debug(cli, vers) trace(cli, vers)
yield cli, props, find_semver(vers) yield cli, props, find_semver(vers)
except CalledProcessError: except CalledProcessError:
debug(cli, "call error") trace(cli, "call error")
except TimeoutExpired: except TimeoutExpired:
debug(cli, "timeout") trace(cli, "timeout")
except FileNotFoundError: except FileNotFoundError:
debug(cli, "not found") trace(cli, "not found")
def dolist(options): def dolist(options):
for (cli, _, ver) in _internal_list(options): for (cli, _, ver) in _internal_list(options):
@ -77,7 +86,7 @@ def dosearch(options):
ctl = loadcatalog(options) ctl = loadcatalog(options)
L = [] L = []
for cli, props in ctl.items(): for cli, props in ctl.items():
debug(cli, props) trace(cli, props)
rtitle = fuzz.ratio(cli, pat) rtitle = fuzz.ratio(cli, pat)
rdesc = fuzz.partial_ratio(props['desc'], pat) rdesc = fuzz.partial_ratio(props['desc'], pat)
score = 2 * rtitle + rdesc score = 2 * rtitle + rdesc
@ -93,17 +102,44 @@ def dolistupdate(options):
if props.github: if props.github:
pass pass
pass pass
def _gh_version(repo:str) -> [VersionInfo|None]:
[owner, repo] = repo.split("/")
url = f'https://api.github.com/repos/{owner}/{repo}/releases/latest'
response = requests.get(url)
return response.json().get("name")
def doinstall(options):
tools = options.TOOL
ctl = loadcatalog(options)
for tool in tools:
if tool in ctl:
props = ctl[tool]
if props.github:
vers = _gh_version(props.github)
trace(vers)
else:
warn(f'{tool} not in catalog')
if __name__ == '__main__': if __name__ == '__main__':
if "DEBUG" in os.environ:
logging.basicConfig(level=logging.DEBUG)
logging.debug("debug is on")
else:
logging.info("not in debug")
options = docopt(__doc__, version='Cliget 0.1.0') options = docopt(__doc__, version='Cliget 0.1.0')
options = DotDict({k.replace('-','_'):v for (k,v) in options.items() if v is not None}) options = DotDict({k.replace('-','_'):v for (k,v) in options.items() if v is not None})
debug(options) trace(options)
if options.list: if options.list:
dolist(options) dolist(options)
elif options.search: elif options.search:
dosearch(options) dosearch(options)
elif options.update: elif options.install or options.update:
if not options.__all and len(options.TOOL)==0: if not options.__all and len(options.TOOL)==0:
dolistupdate(options) dolistupdate(options)
elif len(options.TOOL)>0:
doinstall(options)
else: else:
print("not implemented") print("not implemented")

View File

@ -1,4 +1,4 @@
. ./venv/bin/activate . ./.venv/bin/activate

View File

@ -3,3 +3,4 @@ docopt
semver semver
fuzzywuzzy fuzzywuzzy
python-Levenshtein python-Levenshtein
requests