├── .npmignore ├── snips.gif ├── .husky ├── pre-push └── commit-msg ├── src ├── lib │ ├── helpers.ts │ ├── fuzzy-list.ts │ └── functions.ts ├── declaration.d.ts └── app.ts ├── bin ├── lib │ ├── helpers.js.map │ ├── helpers.js │ ├── fuzzy-list.js.map │ ├── fuzzy-list.js │ ├── functions.js.map │ └── functions.js ├── app.js.map └── app.js ├── .gitignore ├── _snips ├── tsconfig.json ├── LICENSE ├── README.md └── package.json /.npmignore: -------------------------------------------------------------------------------- 1 | .husky 2 | -------------------------------------------------------------------------------- /snips.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/srijanshetty/snips/HEAD/snips.gif -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npm run build 5 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit $1 5 | -------------------------------------------------------------------------------- /src/lib/helpers.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | 3 | // Log errors 4 | function error(statement: string) { 5 | chalk.bold.red('[FAIL] ' + statement); 6 | } 7 | 8 | export default { 9 | error, 10 | }; 11 | -------------------------------------------------------------------------------- /bin/lib/helpers.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/lib/helpers.ts"],"names":[],"mappings":";;;AAAA,0DAA0B;AAG1B,SAAS,KAAK,CAAC,SAAiB;IAC9B,eAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;AACxC,CAAC;AAED,kBAAe;IACb,KAAK;CACN,CAAC"} -------------------------------------------------------------------------------- /src/declaration.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'front-matter' { 2 | interface FrontmatterData { 3 | body: string; 4 | attributes: { 5 | tags: string[]; 6 | language: string; 7 | }; 8 | } 9 | 10 | function frontmatter(data: string): FrontmatterData; 11 | 12 | export default frontmatter; 13 | } 14 | 15 | declare module 'node-fzf'; 16 | -------------------------------------------------------------------------------- /bin/lib/helpers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const tslib_1 = require("tslib"); 4 | const chalk_1 = tslib_1.__importDefault(require("chalk")); 5 | function error(statement) { 6 | chalk_1.default.bold.red('[FAIL] ' + statement); 7 | } 8 | exports.default = { 9 | error, 10 | }; 11 | //# sourceMappingURL=helpers.js.map -------------------------------------------------------------------------------- /bin/lib/fuzzy-list.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"fuzzy-list.js","sourceRoot":"","sources":["../../src/lib/fuzzy-list.ts"],"names":[],"mappings":";;;;AAAA,gEAA4B;AAU5B,MAAM,YAAY,GAAG,CAAC,EAA0B,EAAE,KAAe,EAAE,EAAE;IACnE,IAAA,kBAAI,EAAC,KAAK,EAAE,CAAC,MAAiB,EAAE,EAAE;QAChC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;QAEnC,IAAI,CAAC,QAAQ,EAAE;YACb,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;SACvC;aAAM;YACL,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SACpB;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEO,oCAAY"} -------------------------------------------------------------------------------- /src/lib/fuzzy-list.ts: -------------------------------------------------------------------------------- 1 | import nfzf from 'node-fzf'; 2 | 3 | type fzfResult = { 4 | selected: { 5 | value: string; 6 | index: number; 7 | }; 8 | query: string; 9 | }; 10 | 11 | const fuzzyProcess = (fn: (item: string) => void, items: string[]) => { 12 | nfzf(items, (result: fzfResult) => { 13 | const { selected, query } = result; 14 | 15 | if (!selected) { 16 | console.log('No matches for:', query); 17 | } else { 18 | fn(selected.value); 19 | } 20 | }); 21 | }; 22 | 23 | export { fuzzyProcess }; 24 | -------------------------------------------------------------------------------- /bin/lib/fuzzy-list.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.fuzzyProcess = void 0; 4 | const tslib_1 = require("tslib"); 5 | const node_fzf_1 = tslib_1.__importDefault(require("node-fzf")); 6 | const fuzzyProcess = (fn, items) => { 7 | (0, node_fzf_1.default)(items, (result) => { 8 | const { selected, query } = result; 9 | if (!selected) { 10 | console.log('No matches for:', query); 11 | } 12 | else { 13 | fn(selected.value); 14 | } 15 | }); 16 | }; 17 | exports.fuzzyProcess = fuzzyProcess; 18 | //# sourceMappingURL=fuzzy-list.js.map -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### Node ### 4 | # Logs 5 | logs 6 | *.log 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # node-waf configuration 23 | .lock-wscript 24 | 25 | # Compiled binary addons (http://nodejs.org/api/addons.html) 26 | build/Release 27 | 28 | # Dependency directory 29 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 30 | node_modules 31 | -------------------------------------------------------------------------------- /bin/app.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";;;;AACA,kEAAgC;AAChC,wEAAwC;AAGxC,mBAAS,CAAC,UAAU,EAAE,CAAC;AAEvB,mBAAO;KACJ,OAAO,CAAC,oBAAoB,CAAC;KAC7B,WAAW,CAAC,uCAAuC,CAAC;KACpD,MAAM,CAAC,mBAAS,CAAC,aAAa,CAAC,CAAC;AAEnC,mBAAO;KACJ,OAAO,CAAC,sBAAsB,CAAC;KAC/B,WAAW,CAAC,+BAA+B,CAAC;KAC5C,MAAM,CAAC,mBAAS,CAAC,WAAW,CAAC,CAAC;AAEjC,mBAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,mBAAmB,CAAC;KAChC,MAAM,CAAC,mBAAS,CAAC,YAAY,CAAC,CAAC;AAElC,mBAAO;KACJ,OAAO,CAAC,sBAAsB,CAAC;KAC/B,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,mBAAS,CAAC,WAAW,CAAC,CAAC;AAGjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE;IACjC,mBAAS,CAAC,YAAY,EAAE,CAAC;CAC1B;AAGD,mBAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"} -------------------------------------------------------------------------------- /_snips: -------------------------------------------------------------------------------- 1 | #compdef snips 2 | 3 | local state expl ret=1 4 | local -a snips commands 5 | 6 | snips=( $(command ls -1 --color=never ${HOME}/.snips) ) 7 | 8 | commands=( 9 | 'list:List snips' 10 | 'new:Create a new snip' 11 | 'edit:Edit snip' 12 | 'copy:Copy snip' 13 | ) 14 | 15 | _arguments \ 16 | '1:cmd:->cmds' \ 17 | '*::arg:->args' \ 18 | && ret=0 19 | 20 | case "$state" in 21 | cmds) 22 | _wanted snips expl "snips" compadd "$snips[@]" 23 | _describe -t commands 'commands' commands && ret=0 24 | ;; 25 | args) 26 | case "$words[1]" in 27 | edit|copy) 28 | _arguments \ 29 | '*:snips:($snips)' && ret=0 30 | ;; 31 | new) 32 | _arguments \ 33 | '*:insert new name for your snip:' && ret=0 34 | ;; 35 | *) 36 | (( ret )) && _message 'no more arguments' 37 | ;; 38 | esac 39 | esac 40 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import program from 'commander'; 3 | import functions from './lib/functions'; 4 | 5 | // Check for snippetsRoot and snippetsFolder 6 | functions.checkFiles(); 7 | 8 | program 9 | .command('new [snippet-name]') 10 | .description('Create a code snippet with given name') 11 | .action(functions.createSnippet); 12 | 13 | program 14 | .command('edit [snippet-name?]') 15 | .description('Edit an existing code snippet') 16 | .action(functions.editSnippet); 17 | 18 | program 19 | .command('list') 20 | .description('List all snippets') 21 | .action(functions.listSnippets); 22 | 23 | program 24 | .command('copy [snippet-name?]') 25 | .description('Copy snippet to clipboard if it exists') 26 | .action(functions.copySnippet); 27 | 28 | // By default display all the snips 29 | if (!process.argv.slice(2).length) { 30 | functions.listSnippets(); 31 | } 32 | 33 | // Parse arguments 34 | program.parse(process.argv); 35 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es6", 5 | 6 | "sourceMap": true, 7 | "rootDir": "src", 8 | "outDir": "dist", 9 | "baseUrl": "./src", 10 | "module": "commonjs", 11 | "removeComments": true, 12 | "importHelpers": true, 13 | "esModuleInterop": true, 14 | 15 | "strict": true, 16 | "allowSyntheticDefaultImports": true, 17 | "experimentalDecorators": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "forceConsistentCasingInFileNames": true, 23 | 24 | "experimentalDecorators": true, 25 | "emitDecoratorMetadata": true, 26 | 27 | "typeRoots": [ 28 | "src/declaration.d.ts", 29 | "node_modules/@types" 30 | ], 31 | "paths": {}, 32 | "types": [ 33 | "node" 34 | ] 35 | }, 36 | "include": [ 37 | "src/**/*.ts" 38 | ], 39 | "exclude": [ 40 | "dist/", 41 | "node_modules/*" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /bin/app.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | const tslib_1 = require("tslib"); 5 | const commander_1 = tslib_1.__importDefault(require("commander")); 6 | const functions_1 = tslib_1.__importDefault(require("./lib/functions")); 7 | functions_1.default.checkFiles(); 8 | commander_1.default 9 | .command('new [snippet-name]') 10 | .description('Create a code snippet with given name') 11 | .action(functions_1.default.createSnippet); 12 | commander_1.default 13 | .command('edit [snippet-name?]') 14 | .description('Edit an existing code snippet') 15 | .action(functions_1.default.editSnippet); 16 | commander_1.default 17 | .command('list') 18 | .description('List all snippets') 19 | .action(functions_1.default.listSnippets); 20 | commander_1.default 21 | .command('copy [snippet-name?]') 22 | .description('Copy snippet to clipboard if it exists') 23 | .action(functions_1.default.copySnippet); 24 | if (!process.argv.slice(2).length) { 25 | functions_1.default.listSnippets(); 26 | } 27 | commander_1.default.parse(process.argv); 28 | //# sourceMappingURL=app.js.map -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Srijan R Shetty 3 | * Author: Srijan R Shetty 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | * the Software, and to permit persons to whom the Software is furnished to do so, 10 | * 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, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | 24 | -------------------------------------------------------------------------------- /bin/lib/functions.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"functions.js","sourceRoot":"","sources":["../../src/lib/functions.ts"],"names":[],"mappings":";;;;AAAA,oDAAoB;AACpB,wDAAwB;AACxB,0EAAyC;AAEzC,oEAAoC;AAEpC,gEAA+B;AAE/B,6CAA4C;AAG5C,MAAM,IAAI,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,IAAI,mCAAI,GAAG,CAAC;AACrC,MAAM,MAAM,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,MAAM,mCAAI,KAAK,CAAC;AAC3C,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAE/C,MAAM,UAAU,GAAG,GAAG,EAAE;IACtB,IAAI;QACF,OAAO,YAAE,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;KACrC;IAAC,WAAM;QACN,iBAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;KACnD;AACH,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,WAAmB,EAAE,EAAE;IAExC,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAGtD,uBAAY,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE;QACrC,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,WAAmB,EAAE,EAAE;IAExC,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAGtD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;KAC3D;IAGD,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;IAGlD,oBAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC,CAAC;AAGF,SAAS,aAAa,CAAC,WAAmB;IAExC,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAGtD,MAAM,QAAQ,GAAG,mCAAmC,CAAC;IACrD,YAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAGrC,uBAAY,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE;QACrC,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;AACL,CAAC;AAGD,SAAS,YAAY;IACnB,UAAU,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACpD,CAAC;AAGD,SAAS,WAAW,CAAC,WAA+B;IAClD,IAAI,WAAW,EAAE;QACf,SAAS,CAAC,WAAW,CAAC,CAAC;KACxB;SAAM;QACL,IAAA,yBAAY,EAAC,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;KACvC;AACH,CAAC;AAGD,SAAS,WAAW,CAAC,WAA+B;IAClD,IAAI,WAAW,EAAE;QACf,SAAS,CAAC,WAAW,CAAC,CAAC;KACxB;SAAM;QACL,IAAA,yBAAY,EAAC,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;KACvC;AACH,CAAC;AAGD,SAAS,UAAU;IACjB,IAAI;QACF,YAAE,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;KAC5B;IAAC,OAAO,CAAM,EAAE;QACf,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE;YACvB,MAAM,CAAC,CAAC;SACT;KACF;AACH,CAAC;AAED,kBAAe;IACb,aAAa;IACb,WAAW;IACX,YAAY;IACZ,WAAW;IACX,UAAU;CACX,CAAC"} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | _ 3 | _________ (_)___ _____ 4 | / ___/ __ \/ / __ \/ ___/ 5 | (__ ) / / / / /_/ (__ ) 6 | /____/_/ /_/_/ .___/____/ 7 | /_/ 8 | ``` 9 | 10 | > Easily stash `snip`pet`s` of text and invoke them when needed 11 | 12 | ## Install 13 | 14 | ```bash 15 | npm install -g snips-cli 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```bash 21 | snips # with no arguments it will just list all your snips. 22 | snips list # lists all your snips. 23 | snips new # create snip 24 | snips edit # edit snip, fuzzy completion if snip-name is skipped 25 | snips copy # Copies content of the snip to the clipboard, fuzzy completion if snip-name is skipped 26 | ``` 27 | 28 | ## Live 29 | ![](snips.gif) 30 | 31 | ## Behind the scenes 32 | All snips are stored in `~/.snips` directory. You can play around with them to your hearts content without adversely affecting the functioning of `snips`. 33 | 34 | `snips` looks for the `$EDITOR` global variable, and uses the defined `$EDITOR`. 35 | 36 | ## Recipes 37 | I've refrained from reinventing the wheel and overloading `snips` with unnecessary features. Here are a couple of recipes that I find work well with snips. 38 | 39 | **Search Snippets** 40 | 41 | Use grep or ag. 42 | 43 | grep ~/.snips 44 | ag ~/.snips 45 | 46 | **Fuzzy Search snippet-names** 47 | 48 | copy and edit support fuzzy completion out of the box 49 | 50 | snips copy 51 | snips edit 52 | 53 | **Use snips in multiple machines** 54 | 55 | Backup `.snips` in `git`. 56 | 57 | ## TODO 58 | 59 | ## Non Goals 60 | - gist support. 61 | - git support. 62 | - content search in snips 63 | 64 | ## Credits 65 | I've tried to mimic most of the features of [sheets](https://github.com/oscardelben/sheet), and add a couple on top. While `sheets` is awesome, I didn't know `ruby` enough to directly hack on it. 66 | 67 | ## LICENSE 68 | MIT © [Srijan R Shetty](http://srijanshetty.in) 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "snips-cli", 3 | "version": "4.0.2", 4 | "description": "Gist backed commandline snippet utility", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "eslint -c package.json ./src/**/*.ts", 8 | "build": "tsc --outdir bin", 9 | "deploy": "npm run build && np", 10 | "prepare": "husky install" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/srijanshetty/snips.git" 15 | }, 16 | "keywords": [ 17 | "gist", 18 | "snippets", 19 | "code", 20 | "snips" 21 | ], 22 | "author": "Srijan R Shetty", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/srijanshetty/snips/issues" 26 | }, 27 | "homepage": "https://srijanshetty.in", 28 | "dependencies": { 29 | "chalk": "^3.0.0", 30 | "clipboardy": "^2.2.0", 31 | "commander": "^4.1.0", 32 | "lodash": "^4.17.21", 33 | "node-fzf": "^0.11.0", 34 | "tslib": "^2.4.0" 35 | }, 36 | "devDependencies": { 37 | "@commitlint/cli": "^17.0.3", 38 | "@commitlint/config-conventional": "^17.0.3", 39 | "@types/node": "^18.0.0", 40 | "@typescript-eslint/eslint-plugin": "^5.29.0", 41 | "@typescript-eslint/parser": "^5.29.0", 42 | "eslint": "^8.18.0", 43 | "eslint-config-prettier": "^8.5.0", 44 | "eslint-plugin-prettier": "^4.0.0", 45 | "husky": "^8.0.1", 46 | "np": "^7.6.2", 47 | "prettier": "^2.7.1", 48 | "typescript": "^4.7.4" 49 | }, 50 | "preferGlobal": "true", 51 | "bin": { 52 | "snips": "./bin/app.js" 53 | }, 54 | "eslintConfig": { 55 | "env": { 56 | "es6": true, 57 | "node": true 58 | }, 59 | "parser": "@typescript-eslint/parser", 60 | "plugins": [ 61 | "@typescript-eslint" 62 | ], 63 | "extends": [ 64 | "plugin:@typescript-eslint/recommended", 65 | "plugin:prettier/recommended" 66 | ], 67 | "parserOptions": { 68 | "ecmaVersion": 2022, 69 | "sourceType": "module" 70 | }, 71 | "rules": { 72 | "@typescript-eslint/explicit-function-return-type": 0, 73 | "@typescript-eslint/ban-ts-ignore": 0 74 | } 75 | }, 76 | "prettier": { 77 | "semi": true, 78 | "singleQuote": true, 79 | "trailingComma": "es5" 80 | }, 81 | "commitlint": { 82 | "extends": [ 83 | "@commitlint/config-conventional" 84 | ], 85 | "rules": { 86 | "type-enum": [ 87 | 1, 88 | "always", 89 | [ 90 | "build", 91 | "cfg", 92 | "chore", 93 | "docs", 94 | "feat", 95 | "fix", 96 | "lint", 97 | "refactor", 98 | "revert" 99 | ] 100 | ] 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /bin/lib/functions.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var _a, _b; 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | const tslib_1 = require("tslib"); 5 | const fs_1 = tslib_1.__importDefault(require("fs")); 6 | const path_1 = tslib_1.__importDefault(require("path")); 7 | const child_process_1 = tslib_1.__importDefault(require("child_process")); 8 | const clipboardy_1 = tslib_1.__importDefault(require("clipboardy")); 9 | const helpers_1 = tslib_1.__importDefault(require("./helpers")); 10 | const fuzzy_list_1 = require("./fuzzy-list"); 11 | const HOME = (_a = process.env.HOME) !== null && _a !== void 0 ? _a : '~'; 12 | const EDITOR = (_b = process.env.EDITOR) !== null && _b !== void 0 ? _b : 'vim'; 13 | const snippetsRoot = path_1.default.join(HOME, '.snips'); 14 | const _listSnips = () => { 15 | try { 16 | return fs_1.default.readdirSync(snippetsRoot); 17 | } 18 | catch (_a) { 19 | helpers_1.default.error('snippets root folder not found'); 20 | throw new Error('snippets root folder not found'); 21 | } 22 | }; 23 | const _editSnip = (snippetName) => { 24 | const fileName = path_1.default.join(snippetsRoot, snippetName); 25 | child_process_1.default.spawn(EDITOR, [fileName], { 26 | stdio: 'inherit', 27 | }); 28 | }; 29 | const _copySnip = (snippetName) => { 30 | const fileName = path_1.default.join(snippetsRoot, snippetName); 31 | if (!fs_1.default.existsSync(fileName)) { 32 | throw new Error('Snippet with given name does not exist'); 33 | } 34 | const text = fs_1.default.readFileSync(fileName).toString(); 35 | clipboardy_1.default.writeSync(text); 36 | }; 37 | function createSnippet(snippetName) { 38 | const fileName = path_1.default.join(snippetsRoot, snippetName); 39 | const template = '---\ntags: []\nlanguage:\n---\n\n'; 40 | fs_1.default.writeFileSync(fileName, template); 41 | child_process_1.default.spawn(EDITOR, [fileName], { 42 | stdio: 'inherit', 43 | }); 44 | } 45 | function listSnippets() { 46 | _listSnips().forEach((item) => console.log(item)); 47 | } 48 | function editSnippet(snippetName) { 49 | if (snippetName) { 50 | _editSnip(snippetName); 51 | } 52 | else { 53 | (0, fuzzy_list_1.fuzzyProcess)(_editSnip, _listSnips()); 54 | } 55 | } 56 | function copySnippet(snippetName) { 57 | if (snippetName) { 58 | _copySnip(snippetName); 59 | } 60 | else { 61 | (0, fuzzy_list_1.fuzzyProcess)(_copySnip, _listSnips()); 62 | } 63 | } 64 | function checkFiles() { 65 | try { 66 | fs_1.default.mkdirSync(snippetsRoot); 67 | } 68 | catch (e) { 69 | if (e.code !== 'EEXIST') { 70 | throw e; 71 | } 72 | } 73 | } 74 | exports.default = { 75 | createSnippet, 76 | editSnippet, 77 | listSnippets, 78 | copySnippet, 79 | checkFiles, 80 | }; 81 | //# sourceMappingURL=functions.js.map -------------------------------------------------------------------------------- /src/lib/functions.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import childProcess from 'child_process'; 4 | 5 | import clipboardy from 'clipboardy'; 6 | 7 | import helper from './helpers'; 8 | 9 | import { fuzzyProcess } from './fuzzy-list'; 10 | 11 | // Generate the root folder of snippets 12 | const HOME = process.env.HOME ?? '~'; 13 | const EDITOR = process.env.EDITOR ?? 'vim'; 14 | const snippetsRoot = path.join(HOME, '.snips'); 15 | 16 | const _listSnips = () => { 17 | try { 18 | return fs.readdirSync(snippetsRoot); 19 | } catch { 20 | helper.error('snippets root folder not found'); 21 | throw new Error('snippets root folder not found'); 22 | } 23 | }; 24 | 25 | const _editSnip = (snippetName: string) => { 26 | // Generate fileName 27 | const fileName = path.join(snippetsRoot, snippetName); 28 | 29 | // Open up vim for creating the snippet and then wait for close 30 | childProcess.spawn(EDITOR, [fileName], { 31 | stdio: 'inherit', 32 | }); 33 | }; 34 | 35 | const _copySnip = (snippetName: string) => { 36 | // Generate fileName 37 | const fileName = path.join(snippetsRoot, snippetName); 38 | 39 | // Check if there exists a snippet with the given name 40 | if (!fs.existsSync(fileName)) { 41 | throw new Error('Snippet with given name does not exist'); 42 | } 43 | 44 | // Get the text from the file 45 | const text = fs.readFileSync(fileName).toString(); 46 | 47 | // Copy the text to clipboard 48 | clipboardy.writeSync(text); 49 | }; 50 | 51 | // Function to create a snippet with the given name 52 | function createSnippet(snippetName: string) { 53 | // Generate fileName 54 | const fileName = path.join(snippetsRoot, snippetName); 55 | 56 | // Copy the template file 57 | const template = '---\ntags: []\nlanguage:\n---\n\n'; 58 | fs.writeFileSync(fileName, template); 59 | 60 | // Open up vim for creating the snippet and then wait for close 61 | childProcess.spawn(EDITOR, [fileName], { 62 | stdio: 'inherit', 63 | }); 64 | } 65 | 66 | // Function to list snippets from the snips directory 67 | function listSnippets() { 68 | _listSnips().forEach((item) => console.log(item)); 69 | } 70 | 71 | // Function to edit a snippet 72 | function editSnippet(snippetName: string | undefined) { 73 | if (snippetName) { 74 | _editSnip(snippetName); 75 | } else { 76 | fuzzyProcess(_editSnip, _listSnips()); 77 | } 78 | } 79 | 80 | // Function to copy a snippet 81 | function copySnippet(snippetName: string | undefined) { 82 | if (snippetName) { 83 | _copySnip(snippetName); 84 | } else { 85 | fuzzyProcess(_copySnip, _listSnips()); 86 | } 87 | } 88 | 89 | // Create the snips directory and root 90 | function checkFiles() { 91 | try { 92 | fs.mkdirSync(snippetsRoot); 93 | } catch (e: any) { 94 | if (e.code !== 'EEXIST') { 95 | throw e; 96 | } 97 | } 98 | } 99 | 100 | export default { 101 | createSnippet, 102 | editSnippet, 103 | listSnippets, 104 | copySnippet, 105 | checkFiles, 106 | }; 107 | --------------------------------------------------------------------------------