Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"extends": "mklabs",

"parserOptions": {
"ecmaVersion": 2019
},
"rules": {
"no-param-reassign": "off",
"no-console": "off",
Expand Down
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI

on:
push:
pull_request:
workflow_dispatch:

env:
FORCE_COLOR: 2

jobs:
test:
name: Node ${{ matrix.node }}
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
node: [12, 14, 16]

steps:
- name: Clone repository
uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
cache: npm

- name: Install npm dependencies
run: npm ci

- name: Run tests
run: npm test

- name: Run Coveralls
uses: coverallsapp/github-action@1.1.3
if: matrix.node == 16
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
src/
.completions/
node_modules/
.nyc_output/

note.txt
quick-test.js
Expand Down
20 changes: 0 additions & 20 deletions .travis.yml

This file was deleted.

1 change: 0 additions & 1 deletion examples/tabtab-test-complete/.gitignore

This file was deleted.

7 changes: 4 additions & 3 deletions examples/tabtab-test-complete/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#! /usr/bin/env node

const opts = require('minimist')(process.argv.slice(2), {
const minimist = require('minimist');
const tabtab = require('../..');

const opts = minimist(process.argv.slice(2), {
string: ['foo', 'bar'],
boolean: ['help', 'version', 'loglevel']
});

const tabtab = require('../..');

const args = opts._;

const completion = env => {
Expand Down
62 changes: 51 additions & 11 deletions examples/tabtab-test-complete/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions examples/tabtab-test-complete/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"name": "tabtab-test-complete",
"version": "1.0.0",
"private": true,
"main": "index.js",
"bin": {
"tabtab-test": "index.js"
},
Expand All @@ -11,7 +13,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"debug": "^4.0.1",
"minimist": "^1.2.0"
"debug": "^4.3.3",
"minimist": "^1.2.5"
}
}
8 changes: 6 additions & 2 deletions examples/tabtab-test-complete/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ A simple package to test out tabtab against real completions.

To install, simply run `npm link`

npm link
```sh
npm link
```

It'll install the following binary system-wide:

Expand All @@ -30,7 +32,9 @@ Those steps are not required if testing against your system shell (possibly usin

In this example package, simply run:

tabtab-test install-completion
```sh
tabtab-test install-completion
``

You'll need to do this for each and every shell you're testing against. Follow
the `Shell notes` described above for details.
9 changes: 5 additions & 4 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,14 @@ const log = args => {
const shell = systemShell();

if (!Array.isArray(args)) {
throw new Error('log: Invalid arguments, must be an array');
throw new TypeError('log: Invalid arguments, must be an array');
}

// Normalize arguments if there are some Objects { name, description } in them.
args = args.map(completionItem).map(item => {
const { name, description } = item;
args = args.map(item => {
const { name, description } = completionItem(item);
let str = name;

if (shell === 'zsh' && description) {
str = `${name.replace(/:/g, '\\:')}:${description}`;
} else if (shell === 'fish' && description) {
Expand All @@ -171,7 +172,7 @@ const log = args => {

if (shell === 'bash') {
const env = parseEnv(process.env);
args = args.filter(arg => arg.indexOf(env.last) === 0);
args = args.filter(arg => arg.startsWith(env.last));
}

for (const arg of args) {
Expand Down
42 changes: 19 additions & 23 deletions lib/installer.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
const fs = require('fs');
const path = require('path');
const untildify = require('untildify');
const { promisify } = require('es6-promisify');
const mkdirp = promisify(require('mkdirp'));
const { tabtabDebug, systemShell, exists } = require('./utils');

const debug = tabtabDebug('tabtab:installer');

const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
const unlink = promisify(fs.unlink);

const {
BASH_LOCATION,
FISH_LOCATION,
Expand Down Expand Up @@ -111,7 +105,7 @@ const checkFilenameForLine = async (filename, line) => {

let filecontent = '';
try {
filecontent = await readFile(untildify(filename), 'utf8');
filecontent = await fs.promises.readFile(untildify(filename), 'utf8');
} catch (err) {
if (err.code !== 'ENOENT') {
return console.error(
Expand All @@ -122,7 +116,7 @@ const checkFilenameForLine = async (filename, line) => {
}
}

return !!filecontent.match(`${line}`);
return Boolean(filecontent.match(`${line}`));
};

/**
Expand All @@ -141,7 +135,8 @@ const writeLineToFilename = ({ filename, scriptname, name }) => (
const filepath = untildify(filename);

debug('Creating directory for %s file', filepath);
mkdirp(path.dirname(filepath))
fs.promises
.mkdir(path.dirname(filepath), { recursive: true })
.then(() => {
const stream = fs.createWriteStream(filepath, { flags: 'a' });
stream.on('error', reject);
Expand All @@ -152,7 +147,7 @@ const writeLineToFilename = ({ filename, scriptname, name }) => (

const inShellConfig = isInShellConfig(filename);
if (inShellConfig) {
stream.write(`\n# tabtab source for packages`);
stream.write('\n# tabtab source for packages');
} else {
stream.write(`\n# tabtab source for ${name} package`);
}
Expand All @@ -164,7 +159,7 @@ const writeLineToFilename = ({ filename, scriptname, name }) => (
console.log('=> Added tabtab source line in "%s" file', filename);
})
.catch(err => {
console.error('mkdirp ERROR', err);
console.error('mkdir ERROR', err);
reject(err);
});
};
Expand Down Expand Up @@ -244,18 +239,19 @@ const writeToCompletionScript = ({ name, completer }) => {
debug('Writing completion script to', filename);
debug('with', script);

return readFile(script, 'utf8')
return fs.promises
.readFile(script, 'utf8')
.then(filecontent =>
filecontent
.replace(/\{pkgname\}/g, name)
.replace(/{pkgname}/g, name)
.replace(/{completer}/g, completer)
// on Bash on windows, we need to make sure to remove any \r
.replace(/\r?\n/g, '\n')
)
.then(filecontent =>
mkdirp(path.dirname(filename)).then(() =>
writeFile(filename, filecontent)
)
fs.promises
.mkdir(path.dirname(filename), { recursive: true })
.then(() => fs.promises.writeFile(filename, filecontent))
)
.then(() => console.log('=> Wrote completion script to %s file', filename))
.catch(err => console.error('ERROR:', err));
Expand Down Expand Up @@ -311,20 +307,19 @@ const install = async (options = { name: '', completer: '', location: '' }) => {
* @param {String} name - The package name to look for
*/
const removeLinesFromFilename = async (filename, name) => {
/* eslint-disable no-unused-vars */
debug('Removing lines from %s file, looking for %s package', filename, name);
if (!(await exists(filename))) {
return debug('File %s does not exist', filename);
}

const filecontent = await readFile(filename, 'utf8');
const filecontent = await fs.promises.readFile(filename, 'utf8');
const lines = filecontent.split(/\r?\n/);

const sourceLine = isInShellConfig(filename)
? `# tabtab source for packages`
? '# tabtab source for packages'
: `# tabtab source for ${name} package`;

const hasLine = !!filecontent.match(`${sourceLine}`);
const hasLine = Boolean(filecontent.match(`${sourceLine}`));
if (!hasLine) {
return debug('File %s does not include the line: %s', filename, sourceLine);
}
Expand Down Expand Up @@ -356,7 +351,7 @@ const removeLinesFromFilename = async (filename, name) => {
.join('\n')
.trim();

await writeFile(filename, buffer);
await fs.promises.writeFile(filename, buffer);
console.log('=> Removed tabtab source lines from %s file', filename);
};

Expand Down Expand Up @@ -384,7 +379,7 @@ const uninstall = async (options = { name: '' }) => {

// First, lets remove the completion script itself
if (await exists(completionScript)) {
await unlink(completionScript);
await fs.promises.unlink(completionScript);
console.log('=> Removed completion script (%s)', completionScript);
}

Expand All @@ -395,7 +390,8 @@ const uninstall = async (options = { name: '' }) => {
await removeLinesFromFilename(tabtabScript, name);

// Then, check if __tabtab.shell is empty, if so remove the last source line in SHELL config
const isEmpty = (await readFile(tabtabScript, 'utf8')).trim() === '';
const isEmpty =
(await fs.promises.readFile(tabtabScript, 'utf8')).trim() === '';
if (isEmpty) {
const shellScript = locationFromShell();
debug(
Expand Down
Loading