├── bin └── yaml ├── libexec ├── yaml-t ├── yaml-sh-shell ├── yaml-json ├── yaml-template ├── yaml-completions ├── yaml-get ├── yaml-set ├── yaml ├── yaml-commands ├── yaml-env └── yaml-help ├── test ├── template.txt ├── bad.yaml ├── test.yaml ├── test.json └── test.coffee ├── share └── yaml │ └── example ├── .gitignore ├── completions ├── yaml.zsh └── yaml.bash ├── src ├── template.coffee ├── get.coffee ├── set.coffee ├── errors.coffee ├── yaml.coffee └── json.coffee ├── .github └── FUNDING.yml ├── LICENSE ├── lib ├── reference.js ├── template.js ├── errors.js ├── set.js ├── get.js ├── read.js ├── yaml.js ├── json.js └── update.js ├── package.json └── README.md /bin/yaml: -------------------------------------------------------------------------------- 1 | ../libexec/yaml -------------------------------------------------------------------------------- /libexec/yaml-t: -------------------------------------------------------------------------------- 1 | yaml-template -------------------------------------------------------------------------------- /test/template.txt: -------------------------------------------------------------------------------- 1 | I'd like to say {{foo.baz.1}} 2 | -------------------------------------------------------------------------------- /libexec/yaml-sh-shell: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | echo $1 5 | -------------------------------------------------------------------------------- /test/bad.yaml: -------------------------------------------------------------------------------- 1 | foo: 2 | bar 7 3 | baz: 4 | 17 5 | "hello world" 6 | -------------------------------------------------------------------------------- /test/test.yaml: -------------------------------------------------------------------------------- 1 | foo: 2 | bar: 7 3 | baz: 4 | - 17 5 | - "hello world" 6 | -------------------------------------------------------------------------------- /test/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": { 3 | "bar": 7, 4 | "baz": [ 5 | 17, 6 | "hello world" 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /share/yaml/example: -------------------------------------------------------------------------------- 1 | here's an example file you could read 2 | it has stuff in it 3 | maybe you want some config values 4 | or even some YAML? 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Dependency directory 7 | node_modules 8 | 9 | # Optional npm cache directory 10 | .npm 11 | 12 | # Optional REPL history 13 | .node_repl_history 14 | -------------------------------------------------------------------------------- /libexec/yaml-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: yaml json [read|write] 4 | # Summary: Import/export YAML to/from JSON 5 | # Help: Read a JSON file and dump YAML. 6 | # 7 | # yaml json read test.json 8 | # 9 | # Read a YAML file and dump JSON 10 | # 11 | # yaml json write test.yaml 12 | # 13 | exec node $_YAML_ROOT/lib/json.js $@ 14 | -------------------------------------------------------------------------------- /libexec/yaml-template: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: yaml [template | t] 4 | # Summary: Instantiate a template file with a YAML file. 5 | # Help: Instantiate a template file with a YAML file. 6 | # Returns the instantiated template on stdout. 7 | # 8 | # yaml template test.yaml test.tmpl 9 | # 10 | exec node $_YAML_ROOT/lib/template.js $@ 11 | -------------------------------------------------------------------------------- /libexec/yaml-completions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | COMMAND="$1" 5 | if [ -z "$COMMAND" ]; then 6 | echo "usage: yaml completions COMMAND [arg1 arg2...]" >&2 7 | exit 1 8 | fi 9 | 10 | COMMAND_PATH="$(command -v "yaml-$COMMAND")" 11 | if grep -i "^# provide yaml completions" "$COMMAND_PATH" >/dev/null; then 12 | shift 13 | exec "$COMMAND_PATH" --complete "$@" 14 | fi 15 | -------------------------------------------------------------------------------- /completions/yaml.zsh: -------------------------------------------------------------------------------- 1 | if [[ ! -o interactive ]]; then 2 | return 3 | fi 4 | 5 | compctl -K _yaml yaml 6 | 7 | _yaml() { 8 | local word words completions 9 | read -cA words 10 | word="${words[2]}" 11 | 12 | if [ "${#words}" -eq 2 ]; then 13 | completions="$(yaml commands)" 14 | else 15 | completions="$(yaml completions "${word}")" 16 | fi 17 | 18 | reply=("${(ps:\n:)completions}") 19 | } 20 | -------------------------------------------------------------------------------- /libexec/yaml-get: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: yaml get 4 | # Summary: Get a value from a YAML file 5 | # Help: Get a value from a YAML file using a dot-notation reference. 6 | # 7 | # yaml get test.yaml foo.bar 8 | # 9 | # Array references use the same notation, but with numeric keys. 10 | # 11 | # yaml get test.yaml foo.baz.1 12 | # 13 | exec node $_YAML_ROOT/lib/get.js $@ 14 | -------------------------------------------------------------------------------- /completions/yaml.bash: -------------------------------------------------------------------------------- 1 | _yaml() { 2 | COMPREPLY=() 3 | local word="${COMP_WORDS[COMP_CWORD]}" 4 | 5 | if [ "$COMP_CWORD" -eq 1 ]; then 6 | COMPREPLY=( $(compgen -W "$(yaml commands)" -- "$word") ) 7 | else 8 | local command="${COMP_WORDS[1]}" 9 | local completions="$(yaml completions "$command")" 10 | COMPREPLY=( $(compgen -W "$completions" -- "$word") ) 11 | fi 12 | } 13 | 14 | complete -F _yaml yaml 15 | -------------------------------------------------------------------------------- /libexec/yaml-set: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Usage: yaml set 4 | # Summary: Set a value in a YAML file 5 | # Help: Set a value in a YAML file using a dot-notation reference. 6 | # Returns the update file on stdout. 7 | # 8 | # yaml set test.yaml foo.bar 7 9 | # 10 | # Array references use the same notation, but with numeric keys. 11 | # 12 | # yaml get test.yaml foo.baz.1 goodbye 13 | # 14 | exec node $_YAML_ROOT/lib/set.js $@ 15 | -------------------------------------------------------------------------------- /src/template.coffee: -------------------------------------------------------------------------------- 1 | {call, read} = require "fairmont" 2 | YAML = require "./yaml" 3 | {get, set} = require "./reference" 4 | 5 | 6 | [path, template] = process.argv[2..] 7 | 8 | if path? && template? 9 | call -> 10 | context = yield YAML.read path 11 | console.log ((require "markup-js").up (yield read template), context) 12 | 13 | else 14 | console.error "yaml template: insufficient arguments" 15 | console.error "yaml template " 16 | process.exit -1 17 | -------------------------------------------------------------------------------- /src/get.coffee: -------------------------------------------------------------------------------- 1 | {call, isDefined, isObject, isArray} = require "fairmont" 2 | YAML = require "./yaml" 3 | 4 | [path, reference] = process.argv[2..] 5 | 6 | if path? && reference? 7 | call -> 8 | root = current = yield YAML.read path 9 | [keys..., last] = reference.split "." 10 | for key in keys 11 | current = current[key] 12 | result = current[last] 13 | YAML.write result 14 | else 15 | console.error "yaml get: insufficient arguments" 16 | console.error "yaml get " 17 | process.exit -1 18 | -------------------------------------------------------------------------------- /src/set.coffee: -------------------------------------------------------------------------------- 1 | {call} = require "fairmont" 2 | YAML = require "./yaml" 3 | 4 | [path, reference, value...] = process.argv[2..] 5 | 6 | if path? && reference? && value? 7 | call -> 8 | root = current = yield YAML.read path 9 | [keys..., last] = reference.split "." 10 | for key in keys 11 | current = current[key] 12 | current[last] = value.join(" ") 13 | YAML.write root 14 | else 15 | console.error "yaml set: insufficient arguments" 16 | console.error "yaml set " 17 | process.exit -1 18 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: dyoder # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Daniel Yoder 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /lib/reference.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | module.exports = { 4 | get: function(object, key) { 5 | var index, match, ref; 6 | if ((match = key.match(/^([^\[]+)\[(\d+)\]$/)) != null) { 7 | ref = match.slice(1), key = ref[0], index = ref[1]; 8 | return object[key][index]; 9 | } else { 10 | return object[key]; 11 | } 12 | }, 13 | set: function(object, key, value) { 14 | var index, match, ref; 15 | if ((match = key.match(/^([^\[]+)\[(\d+)\]$/)) != null) { 16 | ref = match.slice(1), key = ref[0], index = ref[1]; 17 | return object[key][index] = value; 18 | } else { 19 | return object[key] = value; 20 | } 21 | } 22 | }; 23 | 24 | }).call(this); 25 | -------------------------------------------------------------------------------- /src/errors.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 2 | 3 | readingPath: (error, path) -> 4 | if path == "-" 5 | console.error "yaml: error reading from stdin" 6 | else 7 | console.error "yaml: error reading from #{path}" 8 | process.exit -1 9 | 10 | parsingYAML: (error) -> 11 | console.error "yaml: error parsing YAML\n#{error.message}" 12 | process.exit -1 13 | 14 | formattingYAML: (error) -> 15 | console.error "yaml: unable to format result as YAML\n#{error.message}" 16 | process.exit -1 17 | 18 | parsingJSON: (error) -> 19 | console.error "yaml: error parsing JSON\n#{error.message}" 20 | process.exit -1 21 | 22 | formattingJSON: (error) -> 23 | console.error "yaml: unable to format result as JSON\n#{error.message}" 24 | process.exit -1 25 | -------------------------------------------------------------------------------- /lib/template.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | var YAML, call, get, path, read, ref, ref1, ref2, set, template; 4 | 5 | ref = require("fairmont"), call = ref.call, read = ref.read; 6 | 7 | YAML = require("./yaml"); 8 | 9 | ref1 = require("./reference"), get = ref1.get, set = ref1.set; 10 | 11 | ref2 = process.argv.slice(2), path = ref2[0], template = ref2[1]; 12 | 13 | if ((path != null) && (template != null)) { 14 | call(function*() { 15 | var context; 16 | context = (yield YAML.read(path)); 17 | return console.log((require("markup-js")).up((yield read(template)), context)); 18 | }); 19 | } else { 20 | console.error("yaml template: insufficient arguments"); 21 | console.error("yaml template "); 22 | process.exit(-1); 23 | } 24 | 25 | }).call(this); 26 | -------------------------------------------------------------------------------- /libexec/yaml: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | resolve_link() { 5 | $(type -p greadlink readlink | head -1) "$1" 6 | } 7 | 8 | abs_dirname() { 9 | local cwd="$(pwd)" 10 | local path="$1" 11 | 12 | while [ -n "$path" ]; do 13 | cd "${path%/*}" 14 | local name="${path##*/}" 15 | path="$(resolve_link "$name" || true)" 16 | done 17 | 18 | pwd 19 | cd "$cwd" 20 | } 21 | 22 | libexec_path="$(abs_dirname "$0")" 23 | export _YAML_ROOT="$(abs_dirname "$libexec_path")" 24 | export PATH="${libexec_path}:$PATH" 25 | 26 | command="$1" 27 | case "$command" in 28 | "" | "-h" | "--help" ) 29 | exec yaml-help 30 | ;; 31 | * ) 32 | command_path="$(command -v "yaml-$command" || true)" 33 | if [ ! -x "$command_path" ]; then 34 | echo "yaml: no such command \`$command'" >&2 35 | exit 1 36 | fi 37 | 38 | shift 39 | exec "$command_path" "$@" 40 | ;; 41 | esac 42 | -------------------------------------------------------------------------------- /src/yaml.coffee: -------------------------------------------------------------------------------- 1 | {async, read, isObject, isArray} = require "fairmont" 2 | YAML = require "js-yaml" 3 | errors = require "./errors" 4 | 5 | module.exports = 6 | 7 | read: async (_path) -> 8 | 9 | path = if _path == "-" then process.stdin else _path 10 | 11 | try 12 | yaml = yield read path 13 | catch error 14 | errors.readingPath error, path 15 | 16 | try 17 | data = YAML.safeLoad yaml 18 | catch error 19 | errors.parsingYAML error 20 | 21 | data 22 | 23 | write: (data) -> 24 | 25 | result = 26 | if data? 27 | if (isObject data) 28 | try 29 | YAML.safeDump data 30 | catch error 31 | errors.formatYAML error 32 | else if (isArray data) 33 | data.join "\n" 34 | else 35 | data.toString() 36 | else 37 | "" 38 | 39 | console.log result 40 | -------------------------------------------------------------------------------- /lib/errors.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | module.exports = { 4 | readingPath: function(error, path) { 5 | if (path === "-") { 6 | console.error("yaml: error reading from stdin"); 7 | } else { 8 | console.error("yaml: error reading from " + path); 9 | } 10 | return process.exit(-1); 11 | }, 12 | parsingYAML: function(error) { 13 | console.error("yaml: error parsing YAML\n" + error.message); 14 | return process.exit(-1); 15 | }, 16 | formattingYAML: function(error) { 17 | console.error("yaml: unable to format result as YAML\n" + error.message); 18 | return process.exit(-1); 19 | }, 20 | parsingJSON: function(error) { 21 | console.error("yaml: error parsing JSON\n" + error.message); 22 | return process.exit(-1); 23 | }, 24 | formattingJSON: function(error) { 25 | console.error("yaml: unable to format result as JSON\n" + error.message); 26 | return process.exit(-1); 27 | } 28 | }; 29 | 30 | }).call(this); 31 | -------------------------------------------------------------------------------- /lib/set.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | var YAML, call, path, ref, reference, value, 4 | slice = [].slice; 5 | 6 | call = require("fairmont").call; 7 | 8 | YAML = require("./yaml"); 9 | 10 | ref = process.argv.slice(2), path = ref[0], reference = ref[1], value = 3 <= ref.length ? slice.call(ref, 2) : []; 11 | 12 | if ((path != null) && (reference != null) && (value != null)) { 13 | call(function*() { 14 | var current, i, j, key, keys, last, len, ref1, root; 15 | root = current = (yield YAML.read(path)); 16 | ref1 = reference.split("."), keys = 2 <= ref1.length ? slice.call(ref1, 0, i = ref1.length - 1) : (i = 0, []), last = ref1[i++]; 17 | for (j = 0, len = keys.length; j < len; j++) { 18 | key = keys[j]; 19 | current = current[key]; 20 | } 21 | current[last] = value.join(" "); 22 | return YAML.write(root); 23 | }); 24 | } else { 25 | console.error("yaml set: insufficient arguments"); 26 | console.error("yaml set "); 27 | process.exit(-1); 28 | } 29 | 30 | }).call(this); 31 | -------------------------------------------------------------------------------- /libexec/yaml-commands: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: yaml commands 3 | # Summary: List all yaml commands 4 | # Help: This command is mostly used for autocompletion in various shells, and for `yaml help`. 5 | # Also, this command helps find commands that are named the same as potentially builtin shell commands (which, cd, etc) 6 | 7 | set -e 8 | 9 | # Provide yaml completions 10 | if [ "$1" = "--complete" ]; then 11 | echo --sh 12 | echo --no-sh 13 | exit 14 | fi 15 | 16 | if [ "$1" = "--sh" ]; then 17 | sh=1 18 | shift 19 | elif [ "$1" = "--no-sh" ]; then 20 | nosh=1 21 | shift 22 | fi 23 | 24 | shopt -s nullglob 25 | 26 | { for path in ${PATH//:/$'\n'}; do 27 | for command in "${path}/yaml-"*; do 28 | command="${command##*yaml-}" 29 | if [ -n "$sh" ]; then 30 | if [ ${command:0:3} = "sh-" ]; then 31 | echo ${command##sh-} 32 | fi 33 | elif [ -n "$nosh" ]; then 34 | if [ ${command:0:3} != "sh-" ]; then 35 | echo ${command##sh-} 36 | fi 37 | else 38 | echo ${command##sh-} 39 | fi 40 | done 41 | done 42 | } | sort | uniq 43 | -------------------------------------------------------------------------------- /lib/get.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | var YAML, call, isArray, isDefined, isObject, path, ref, ref1, reference, 4 | slice = [].slice; 5 | 6 | ref = require("fairmont"), call = ref.call, isDefined = ref.isDefined, isObject = ref.isObject, isArray = ref.isArray; 7 | 8 | YAML = require("./yaml"); 9 | 10 | ref1 = process.argv.slice(2), path = ref1[0], reference = ref1[1]; 11 | 12 | if ((path != null) && (reference != null)) { 13 | call(function*() { 14 | var current, i, j, key, keys, last, len, ref2, result, root; 15 | root = current = (yield YAML.read(path)); 16 | ref2 = reference.split("."), keys = 2 <= ref2.length ? slice.call(ref2, 0, i = ref2.length - 1) : (i = 0, []), last = ref2[i++]; 17 | for (j = 0, len = keys.length; j < len; j++) { 18 | key = keys[j]; 19 | current = current[key]; 20 | } 21 | result = current[last]; 22 | return YAML.write(result); 23 | }); 24 | } else { 25 | console.error("yaml get: insufficient arguments"); 26 | console.error("yaml get "); 27 | process.exit(-1); 28 | } 29 | 30 | }).call(this); 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yaml-cli", 3 | "version": "1.1.8", 4 | "description": "A simple CLI for querying and updating YAML files", 5 | "files": [ 6 | "completions", 7 | "libexec", 8 | "lib", 9 | "share" 10 | ], 11 | "bin": { 12 | "yaml": "libexec/yaml" 13 | }, 14 | "scripts": { 15 | "test": "coffee -o lib/ -c src/*.*coffee && coffee test/test.coffee", 16 | "prepublish": "coffee -o lib/ -c src/*.*coffee", 17 | "postpublish": "(node_modules/.bin/json -f package.json version | xargs -I version git tag -am version version) && git push --tags" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/pandastrike/yaml-cli.git" 22 | }, 23 | "keywords": [ 24 | "yaml", 25 | "cli" 26 | ], 27 | "author": "Dan Yoder", 28 | "license": "ISC", 29 | "bugs": { 30 | "url": "https://github.com/pandastrike/yaml-cli/issues" 31 | }, 32 | "homepage": "https://github.com/pandastrike/yaml-cli#readme", 33 | "dependencies": { 34 | "fairmont": "^1.0.0-beta-40", 35 | "js-yaml": "^3.5.3", 36 | "markup-js": "^1.5.21" 37 | }, 38 | "devDependencies": { 39 | "amen": "^1.0.0-alpha-06", 40 | "coffee-script": "^1.10.0", 41 | "json": "^9.0.3" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/json.coffee: -------------------------------------------------------------------------------- 1 | {async, call, read, isObject, isArray} = require "fairmont" 2 | YAML = require "./yaml" 3 | errors = require "./errors" 4 | 5 | [subcommand, path] = process.argv[2..] 6 | 7 | _JSON = 8 | 9 | read: async (_path) -> 10 | 11 | path = if _path == "-" then process.stdin else _path 12 | 13 | try 14 | json = yield read path 15 | catch error 16 | errors.readingPath error, path 17 | 18 | try 19 | data = JSON.parse json 20 | catch error 21 | errors.parsingJSON error 22 | 23 | data 24 | 25 | write: (data) -> 26 | 27 | result = 28 | if data? 29 | if (isObject data) || (isArray data) 30 | try 31 | JSON.stringify data, null, 2 32 | catch error 33 | errors.formatJSON error 34 | else 35 | data.toString() 36 | else 37 | "" 38 | 39 | console.log result 40 | 41 | if subcommand? && subcommand in ["read", "write"] && path? 42 | call -> 43 | if subcommand == "write" 44 | _JSON.write yield YAML.read path 45 | else 46 | YAML.write yield _JSON.read path 47 | 48 | else 49 | console.error "yaml json: invalid arguments" 50 | console.error "yaml json [read|write] " 51 | process.exit -1 52 | -------------------------------------------------------------------------------- /lib/read.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | var YAML, _read, async, get, isArray, isObject, path, read, ref, ref1, reference, 4 | slice = [].slice; 5 | 6 | ref = require("fairmont"), async = ref.async, read = ref.read, isObject = ref.isObject, isArray = ref.isArray; 7 | 8 | YAML = require("js-yaml"); 9 | 10 | get = require("./reference").get; 11 | 12 | _read = async(function*(arg) { 13 | var current, i, j, key, keys, last, len, path, ref1, reference, result, root; 14 | path = arg.path, reference = arg.reference; 15 | root = current = YAML.safeLoad((yield read(path))); 16 | ref1 = reference.split("."), keys = 2 <= ref1.length ? slice.call(ref1, 0, i = ref1.length - 1) : (i = 0, []), last = ref1[i++]; 17 | for (j = 0, len = keys.length; j < len; j++) { 18 | key = keys[j]; 19 | current = get(current, key); 20 | } 21 | result = get(current, last); 22 | if ((isObject(result)) || (isArray(result))) { 23 | return YAML.safeDump(result); 24 | } else { 25 | return result; 26 | } 27 | }); 28 | 29 | ref1 = process.argv.slice(2), path = ref1[0], reference = ref1[1]; 30 | 31 | if ((path != null) && (reference != null)) { 32 | _read({ 33 | path: path, 34 | reference: reference 35 | }).then(function(result) { 36 | return console.log(result); 37 | }); 38 | } else { 39 | console.error("yaml: insufficient arguments"); 40 | console.error("yaml "); 41 | process.exit(-1); 42 | } 43 | 44 | module.exports = _read; 45 | 46 | }).call(this); 47 | -------------------------------------------------------------------------------- /lib/yaml.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | var YAML, async, errors, isArray, isObject, read, ref; 4 | 5 | ref = require("fairmont"), async = ref.async, read = ref.read, isObject = ref.isObject, isArray = ref.isArray; 6 | 7 | YAML = require("js-yaml"); 8 | 9 | errors = require("./errors"); 10 | 11 | module.exports = { 12 | read: async(function*(_path) { 13 | var data, error, error1, error2, path, yaml; 14 | path = _path === "-" ? process.stdin : _path; 15 | try { 16 | yaml = (yield read(path)); 17 | } catch (error1) { 18 | error = error1; 19 | errors.readingPath(error, path); 20 | } 21 | try { 22 | data = YAML.safeLoad(yaml); 23 | } catch (error2) { 24 | error = error2; 25 | errors.parsingYAML(error); 26 | } 27 | return data; 28 | }), 29 | write: function(data) { 30 | var error, result; 31 | result = (function() { 32 | var error1; 33 | if (data != null) { 34 | if (isObject(data)) { 35 | try { 36 | return YAML.safeDump(data); 37 | } catch (error1) { 38 | error = error1; 39 | return errors.formatYAML(error); 40 | } 41 | } else if (isArray(data)) { 42 | return data.join("\n"); 43 | } else { 44 | return data.toString(); 45 | } 46 | } else { 47 | return ""; 48 | } 49 | })(); 50 | return console.log(result); 51 | } 52 | }; 53 | 54 | }).call(this); 55 | -------------------------------------------------------------------------------- /libexec/yaml-env: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | print="" 5 | if [ "$1" = "-" ]; then 6 | print=1 7 | shift 8 | fi 9 | 10 | shell="$1" 11 | if [ -z "$shell" ]; then 12 | shell="$(basename "$SHELL")" 13 | fi 14 | 15 | resolve_link() { 16 | $(type -p greadlink readlink | head -1) $1 17 | } 18 | 19 | abs_dirname() { 20 | local cwd="$(pwd)" 21 | local path="$1" 22 | 23 | while [ -n "$path" ]; do 24 | cd "${path%/*}" 25 | local name="${path##*/}" 26 | path="$(resolve_link "$name" || true)" 27 | done 28 | 29 | pwd 30 | cd "$cwd" 31 | } 32 | 33 | root="$(abs_dirname "$0")/.." 34 | 35 | if [ -z "$print" ]; then 36 | case "$shell" in 37 | bash ) 38 | profile='~/.bash_profile' 39 | ;; 40 | zsh ) 41 | profile='~/.zshenv' 42 | ;; 43 | * ) 44 | profile='your profile' 45 | ;; 46 | esac 47 | 48 | { echo "# Load yaml automatically by adding" 49 | echo "# the following to ${profile}:" 50 | echo 51 | echo "eval \"\$(${_YAML_ROOT}/bin/yaml init -)\"" 52 | echo 53 | } >&2 54 | 55 | exit 1 56 | fi 57 | 58 | echo "export PATH=\"\${PATH}:${_YAML_ROOT}/bin\"" 59 | 60 | case "$shell" in 61 | bash | zsh ) 62 | echo "source \"$root/completions/yaml.${shell}\"" 63 | ;; 64 | esac 65 | 66 | commands=(`yaml commands --sh`) 67 | IFS="|" 68 | cat <"); 65 | process.exit(-1); 66 | } 67 | 68 | }).call(this); 69 | -------------------------------------------------------------------------------- /lib/update.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.10.0 2 | (function() { 3 | var YAML, _query, async, get, isArray, isObject, path, query, read, ref, ref1, set, value, 4 | slice = [].slice; 5 | 6 | ref = process.argv.slice(2), path = ref[0], query = ref[1], value = ref[2]; 7 | 8 | if ((path != null) && (query != null)) { 9 | _query({ 10 | path: path, 11 | query: query, 12 | value: value 13 | }).then(function(result) { 14 | return console.log(result); 15 | }); 16 | } else { 17 | console.error("yaml: insufficient arguments"); 18 | console.error("yaml "); 19 | process.exit(-1); 20 | } 21 | 22 | ref1 = require("fairmont"), async = ref1.async, read = ref1.read, isObject = ref1.isObject, isArray = ref1.isArray; 23 | 24 | YAML = require("js-yaml"); 25 | 26 | get = function(object, key) { 27 | var index, match, ref2; 28 | if ((match = key.match(/^([^\[]+)\[(\d+)\]$/)) != null) { 29 | ref2 = match.slice(1), key = ref2[0], index = ref2[1]; 30 | return object[key][index]; 31 | } else { 32 | return object[key]; 33 | } 34 | }; 35 | 36 | set = function(object, key, value) { 37 | var index, match, ref2; 38 | if ((match = key.match(/^([^\[]+)\[(\d+)\]$/)) != null) { 39 | ref2 = match.slice(1), key = ref2[0], index = ref2[1]; 40 | return object[key][index] = value; 41 | } else { 42 | return object[key] = value; 43 | } 44 | }; 45 | 46 | _query = async(function*(arg) { 47 | var current, i, j, key, keys, last, len, path, query, ref2, result, root, value; 48 | path = arg.path, query = arg.query, value = arg.value; 49 | root = current = YAML.safeLoad((yield read(path))); 50 | ref2 = query.split("."), keys = 2 <= ref2.length ? slice.call(ref2, 0, i = ref2.length - 1) : (i = 0, []), last = ref2[i++]; 51 | for (j = 0, len = keys.length; j < len; j++) { 52 | key = keys[j]; 53 | current = get(current, key); 54 | } 55 | if (value != null) { 56 | set(current, last, value); 57 | return YAML.safeDump(root); 58 | } else { 59 | result = get(current, last); 60 | if ((isObject(result)) || (isArray(result))) { 61 | return YAML.safeDump(result); 62 | } else { 63 | return result; 64 | } 65 | } 66 | }); 67 | 68 | module.exports = _query; 69 | 70 | }).call(this); 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # yaml-cli 2 | 3 | > **Important** This project has been deprecated. We recommend [yq](https://github.com/mikefarah/yq). 4 | 5 | A simple CLI for working with YAML files. 6 | 7 | ## Installation 8 | 9 | ```bash 10 | $ npm install -g yaml-cli 11 | ``` 12 | 13 | ## Shell Completion 14 | 15 | You can set up shell completion like this: 16 | 17 | ```bash 18 | $ eval $(yaml env -) 19 | ``` 20 | 21 | ## Examples 22 | 23 | Given the following `test.yml` file: 24 | 25 | ```yaml 26 | foo: 27 | bar: 7 28 | baz: 29 | - 17 30 | - "hello world" 31 | ``` 32 | 33 | ### get 34 | 35 | You can get properties: 36 | 37 | ```bash 38 | $ yaml get test.yaml foo.bar 39 | 7 40 | ``` 41 | 42 | or array accessors: 43 | 44 | ```bash 45 | $ yaml get test.yaml foo.baz.1 46 | hello world 47 | ``` 48 | 49 | ### set 50 | 51 | You can set values, too. 52 | 53 | ```bash 54 | $ yaml set test.yaml foo.baz.1 goodbye 55 | foo: 56 | bar: 7 57 | baz: 58 | - 17 59 | - "goodbye" 60 | ``` 61 | 62 | ### template 63 | 64 | You can instantiate template files, too. Given the following template: 65 | 66 | ``` 67 | I would like to say {{foo.baz.1}} 68 | ``` 69 | 70 | you can instantiate it like this: 71 | 72 | ```bash 73 | $ yaml t test.yaml test.template 74 | I would like to say hello world 75 | ``` 76 | 77 | ### json 78 | 79 | You can read and write JSON. 80 | 81 | To convert from JSON to YAML: 82 | 83 | ```tty 84 | $ yaml json read test.json 85 | foo: 86 | bar: 7 87 | baz: 88 | - 17 89 | - "hello world" 90 | ``` 91 | 92 | To convert from YAML to JSON: 93 | 94 | ```tty 95 | $ yaml json write test.yaml 96 | { 97 | "foo": { 98 | "bar": 7, 99 | "baz": [ 100 | 17, 101 | "hello world" 102 | ] 103 | } 104 | } 105 | ``` 106 | 107 | You can get more help by just typing `yaml`. 108 | 109 | ```bash 110 | $ yaml 111 | Usage: yaml [] 112 | 113 | Some useful yaml commands are: 114 | commands List all yaml commands 115 | get Get a value from a YAML file 116 | set Set a value in a YAML file 117 | template Instantiate a template file with a YAML file. 118 | 119 | See 'yaml help ' for information on a specific command. 120 | ``` 121 | 122 | ## Limitations 123 | 124 | See the [issues list](https://github.com/pandastrike/yaml-cli/issues)—and please open your own or `+1` your favorites. 125 | -------------------------------------------------------------------------------- /libexec/yaml-help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | print_summaries() { 5 | local commands=() 6 | local summaries=() 7 | local longest_command=0 8 | local command 9 | 10 | for command in $(yaml-commands); do 11 | local file="$(command_path "$command")" 12 | if [ ! -h "$file" ]; then 13 | local summary="$(summary "$file")" 14 | if [ -n "$summary" ]; then 15 | commands["${#commands[@]}"]="$command" 16 | summaries["${#summaries[@]}"]="$summary" 17 | 18 | if [ "${#command}" -gt "$longest_command" ]; then 19 | longest_command="${#command}" 20 | fi 21 | fi 22 | fi 23 | done 24 | 25 | local index 26 | local columns="$(tput cols)" 27 | local summary_length=$(( $columns - $longest_command - 5 )) 28 | 29 | for (( index=0; index < ${#commands[@]}; index++ )); do 30 | printf " %-${longest_command}s %s\n" "${commands[$index]}" \ 31 | "$(truncate "$summary_length" "${summaries[$index]}")" 32 | done 33 | } 34 | 35 | print_help() { 36 | local file="$1" 37 | local usage="$(usage "$file")" 38 | 39 | if [ -n "$usage" ]; then 40 | echo "$usage" 41 | 42 | local help="$(help "$file")" 43 | [ -n "$help" ] && echo && echo "$help" 44 | else 45 | echo "Sorry, this command isn't documented yet." 46 | fi 47 | } 48 | 49 | command_path() { 50 | command -v "yaml-$command" || command -v "yaml-sh-$command" || true 51 | } 52 | 53 | summary() { 54 | sed -n "s/^# Summary: \(.*\)/\1/p" "$1" 55 | } 56 | 57 | usage() { 58 | sed -n "s/^# \(Usage: .*\)/\1/p" "$1" 59 | } 60 | 61 | help() { 62 | awk '/^[^#]/{p=0} /^# Help:/{p=1} p' "$1" | sed "s/^# Help: //;s/^# //;s/^#//" 63 | } 64 | 65 | truncate() { 66 | local max_length="$1" 67 | local string="$2" 68 | 69 | if [ "${#string}" -gt "$max_length" ]; then 70 | local length=$(( $max_length - 3 )) 71 | echo "${string:0:$length}..." 72 | else 73 | echo "$string" 74 | fi 75 | } 76 | 77 | # Provide yaml completions 78 | if [ "$1" = "--complete" ]; then 79 | exec "yaml-commands" 80 | exit 81 | fi 82 | 83 | command="$1" 84 | case "$command" in 85 | "") echo "Usage: yaml [] 86 | 87 | Some useful yaml commands are: 88 | $(print_summaries) 89 | 90 | See 'yaml help ' for information on a specific command." 91 | ;; 92 | *) 93 | file="$(command_path "$command")" 94 | 95 | if [ -n "$file" ]; then 96 | print_help "$file" 97 | else 98 | echo "yaml: no such command \`$command'" >&2 99 | exit 1 100 | fi 101 | esac 102 | -------------------------------------------------------------------------------- /test/test.coffee: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env coffee 2 | os = require "os" 3 | {join} = require "path" 4 | assert = require "assert" 5 | Amen = require "amen" 6 | {shell, async, read} = require "fairmont" 7 | 8 | # convenience functions to make it easier to call the CLI 9 | sh = async (command) -> 10 | {stdout} = yield shell command 11 | stdout.trim() 12 | 13 | Amen.describe "YAML CLI", (context) -> 14 | 15 | context.test "get", (context) -> 16 | 17 | context.test "a property", -> 18 | assert.equal '7', 19 | yield sh "bin/yaml get test/test.yaml foo.bar" 20 | 21 | context.test "an array element", -> 22 | assert.equal 'hello world', 23 | yield sh "bin/yaml get test/test.yaml foo.baz.1" 24 | 25 | context.test "undefined as blank", -> 26 | assert.equal '', 27 | yield sh "bin/yaml get test/test.yaml foo.blurg" 28 | 29 | context.test "read from stdin", -> 30 | assert.equal '7', 31 | yield sh "cat test/test.yaml | bin/yaml get - foo.bar" 32 | 33 | context.test "bad path", -> 34 | # TODO: seems like there should be a better way to do this 35 | fails = undefined 36 | yield (sh "bin/yaml get test/fubar.yaml foo.bar" 37 | .then -> fails = false 38 | .catch -> fails = true) 39 | assert.equal fails, true, "expected bad path error" 40 | 41 | context.test "bad YAML", -> 42 | # TODO: seems like there should be a better way to do this 43 | fails = undefined 44 | yield (sh "bin/yaml get test/bad.yaml foo.bar" 45 | .then -> fails = false 46 | .catch -> fails = true) 47 | assert.equal fails, true, "expected parse error" 48 | 49 | context.test "set", (context) -> 50 | 51 | context.test "a property", -> 52 | assert.equal '3', 53 | yield sh "bin/yaml set test/test.yaml foo.bar 3 | 54 | bin/yaml get - foo.bar" 55 | 56 | context.test "an array element", -> 57 | assert.equal 'goodbye world', 58 | yield sh "bin/yaml set test/test.yaml foo.baz.1 goodbye world | 59 | bin/yaml get - foo.baz.1" 60 | 61 | context.test "read from stdin", -> 62 | assert.equal '3', 63 | yield sh "cat test/test.yaml | 64 | bin/yaml set - foo.bar 3 | 65 | bin/yaml get - foo.bar" 66 | 67 | 68 | context.test "template", (context) -> 69 | 70 | context.test "instantiation", -> 71 | assert.equal "I'd like to say hello world", 72 | yield sh "bin/yaml template test/test.yaml test/template.txt" 73 | 74 | context.test "json", (context) -> 75 | 76 | context.test "read", -> 77 | YAML = require "js-yaml" 78 | data = YAML.safeLoad yield sh "bin/yaml json read test/test.json" 79 | assert.equal "7", data.foo.bar 80 | assert.equal "hello world", data.foo.baz[1] 81 | 82 | 83 | context.test "write", -> 84 | data = JSON.parse yield sh "bin/yaml json write test/test.yaml" 85 | assert.equal "7", data.foo.bar 86 | assert.equal "hello world", data.foo.baz[1] 87 | --------------------------------------------------------------------------------