more entries in the catalog ; more readme and faq ; onging impl
This commit is contained in:
parent
d6a31f58f9
commit
b5b21f6ca9
|
@ -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
20
TODO.md
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
24
catalog.yaml
24
catalog.yaml
|
@ -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
|
||||||
|
|
60
cliget.py
60
cliget.py
|
@ -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
|
||||||
|
@ -94,16 +103,43 @@ def dolistupdate(options):
|
||||||
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")
|
||||||
|
|
|
@ -3,3 +3,4 @@ docopt
|
||||||
semver
|
semver
|
||||||
fuzzywuzzy
|
fuzzywuzzy
|
||||||
python-Levenshtein
|
python-Levenshtein
|
||||||
|
requests
|
||||||
|
|
Loading…
Reference in New Issue