Last active
November 21, 2017 15:58
-
-
Save bgamari/f562b1729db8e0599971b9b4e1f2f89d to your computer and use it in GitHub Desktop.
A bash completion script for cabal-install
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
""" | |
Configure with | |
complete -C /path/to/script cabal | |
""" | |
import os.path | |
import json | |
import collections | |
import subprocess | |
import sys | |
import os | |
def find_project(): | |
p = os.path.realpath('.') | |
while not os.path.ismount(p): | |
dist = os.path.join(p, 'dist-newstyle') | |
if os.path.exists(dist): | |
return dist | |
return None | |
def list_components(project_root, type_filter=None): | |
plan = json.load(open(os.path.join(project_root, "cache", "plan.json"))) | |
components = collections.defaultdict(lambda: 0) | |
for c in plan['install-plan']: | |
pkg = c['pkg-name'] | |
if c.get('type') == 'pre-existing': | |
continue | |
comp = c.get('component-name') | |
if comp is None: | |
continue | |
if type_filter is not None and not comp.startswith(type_filter): | |
continue | |
components['%s:%s' % (comp, pkg)] += 1 | |
components[comp] += 1 | |
components[pkg] = 1 | |
return [c for c,v in components.items() if v == 1] | |
valid_modes = { | |
'new-build': None, | |
'new-run': 'exe', | |
'new-test': 'test', | |
'new-bench': 'bench' | |
} | |
def main(): | |
# determine mode | |
prev = os.environ['COMP_LINE'].split() | |
mode = None | |
type_filter = None | |
for opt in prev: | |
x = valid_modes.get(opt) | |
if x is not None: | |
mode = opt | |
type_filter = x | |
break | |
# Find components | |
prefix = sys.argv[2] | |
proj = find_project() | |
if proj is None: raise RuntimeError("no project found") | |
comps = list_components(proj, type_filter) | |
opts = subprocess.check_output(['cabal', '--list-options']).decode('UTF-8').split() | |
# Exclude modes if one was already given | |
if mode is not None: | |
opts = [ opt for opt in opts if opt.startswith('-') ] | |
# Build completions | |
for opt in opts + comps: | |
if opt.startswith(prefix): | |
print(opt) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment