Skip to content

Instantly share code, notes, and snippets.

@bgamari
Last active November 21, 2017 15:58
Show Gist options
  • Save bgamari/f562b1729db8e0599971b9b4e1f2f89d to your computer and use it in GitHub Desktop.
Save bgamari/f562b1729db8e0599971b9b4e1f2f89d to your computer and use it in GitHub Desktop.
A bash completion script for cabal-install
#!/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