├── .gitignore
├── LICENSE
├── README.md
├── complete.sh
├── index.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | package-lock.json
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Anton Medvedev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # fx-completion
2 |
3 | Bash completion for [fx](https://github.com/antonmedv/fx)
4 |
5 |

6 |
7 | ## Install
8 |
9 | ```bash
10 | npm i -g fx-completion
11 | ```
12 |
13 | And add to your _.bash_profile_ file next line:
14 | ```bash
15 | source <(fx-completion --bash)
16 | ```
17 |
18 | ## Usage
19 |
20 | Fields of JSON file provided only if _fx_ used with file as first argument.
21 |
22 | ```bash
23 | $ fx data.json
24 | ```
25 |
26 | ## TODO
27 |
28 | - [x] Bash
29 | - [ ] Zsh
30 | - [ ] Fish
31 |
32 | ## License
33 |
34 | MIT
35 |
--------------------------------------------------------------------------------
/complete.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | _fx_complete()
4 | {
5 | local cur prev nb_colon
6 | _get_comp_words_by_ref -n : cur prev
7 | nb_colon=$(grep -o ":" <<< "$COMP_LINE" | wc -l)
8 |
9 | if [[ "$COMP_CWORD" -eq "1" ]]; then
10 | _filedir
11 | fi
12 |
13 | COMPREPLY+=( $(compgen -W '$(fx-completion "$((COMP_CWORD - (nb_colon * 2)))" "$prev" "${COMP_LINE}")' -- "$cur") )
14 | }
15 |
16 | if [[ -n "${BASH_VERSION}" ]]; then
17 | if ! [[ $(uname -s) =~ Darwin* ]]; then
18 | complete -o filenames -F _fx_complete fx
19 | else
20 | complete -F _fx_complete fx
21 | fi
22 | else
23 | echo "Unsupported shell."
24 | exit 1
25 | fi
26 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict'
3 | const os = require('os')
4 | const fs = require('fs')
5 | const path = require('path')
6 | const reduce = require('fx/reduce')
7 |
8 | void function main() {
9 | if (process.argv.includes('--bash')) {
10 | process.stdout.write(fs.readFileSync(path.join(__dirname, './complete.sh')))
11 | return
12 | }
13 |
14 | process.stdout.write(
15 | [
16 | ...globals(),
17 | ...fields(),
18 | ].join('\n')
19 | )
20 | }()
21 |
22 | function globals() {
23 | const defaultGlobals = [
24 | 'clearImmediate',
25 | 'clearTimeout',
26 | 'global',
27 | 'setImmediate',
28 | 'setTimeout',
29 | 'Buffer',
30 | 'clearInterval',
31 | 'process',
32 | 'setInterval',
33 | ]
34 |
35 |
36 | try {
37 | require(path.join(os.homedir(), '.fxrc'))
38 | } catch (err) {
39 | // Ignore
40 | }
41 |
42 | return [
43 | 'select',
44 | ...Object.keys(global)
45 | .filter(x =>
46 | !x.startsWith('DTRACE_')
47 | && !x.startsWith('FX_')
48 | && !defaultGlobals.includes(x)
49 | ),
50 | ]
51 | }
52 |
53 | function fields() {
54 | const compIndex = parseInt(process.argv[2], 10) - 2
55 | const compLine = process.argv[4] || ''
56 | let args = compLine
57 | .trim()
58 | .split(' ')
59 | .slice(1) // Remove fx name
60 |
61 | if (/\.json$/.test(args[0])) {
62 | try {
63 | let filename = args[0]
64 | filename = filename.replace(/^~\//, os.homedir() + '/')
65 | const input = fs.readFileSync(filename).toString('utf8')
66 | const json = JSON.parse(input)
67 | args = args.slice(1) // Remove file name
68 |
69 | if (args[compIndex]) {
70 | args = args.slice(0, compIndex) // Remove current word
71 | }
72 |
73 | const output = args.reduce(reduce, json)
74 | const fields = []
75 | let i = 0
76 | for (let p of paths(output)) {
77 | fields.push(p)
78 | if (i++ > 1000) {
79 | break
80 | }
81 | }
82 | return fields
83 | } catch (e) {
84 | // Ignore
85 | }
86 | }
87 | return []
88 | }
89 |
90 | function* paths(json) {
91 | const queue = []
92 |
93 | if (Array.isArray(json)) {
94 | let i = 0
95 | for (let item of json) {
96 | const path = 'this[' + (i++) + ']'
97 | if (Array.isArray(item) || isObject(item)) {
98 | yield path
99 | }
100 | }
101 | } else {
102 | if (isObject(json)) {
103 | for (let [key, value] of Object.entries(json)) {
104 | const path = /^\w+$/.test(key) ? `.${key}` : `this["${key}"]`
105 | yield path
106 | if (Array.isArray(value)) {
107 | queue.push([value, path])
108 | }
109 | }
110 | }
111 | }
112 |
113 | while (queue.length > 0) {
114 | const [value, path] = queue.shift()
115 | let i = 0
116 | for (let item of value) {
117 | const p = path + '[' + (i++) + ']'
118 | if (Array.isArray(item) || isObject(item)) {
119 | yield p
120 | }
121 | }
122 | }
123 | }
124 |
125 | function isObject(v) {
126 | return typeof v === 'object' && v.constructor === Object
127 | }
128 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fx-completion",
3 | "version": "1.0.5",
4 | "description": "fx completion for bash",
5 | "bin": {
6 | "fx-completion": "index.js"
7 | },
8 | "files": [
9 | "complete.sh",
10 | "index.js"
11 | ],
12 | "repository": "antonmedv/fx-completion",
13 | "homepage": "https://github.com/antonmedv/fx-completion",
14 | "keywords": [
15 | "fx",
16 | "completion",
17 | "bash"
18 | ],
19 | "author": "Anton Medvedev ",
20 | "license": "MIT",
21 | "dependencies": {
22 | "fx": "^12.0.2"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------