Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add necessary completion lines in shell config
- Loading branch information
Showing
7 changed files
with
250 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const BASH_LOCATION = '~/.bashrc'; | ||
const FISH_LOCATION = '~/.config/fish/config.fish'; | ||
const ZSH_LOCATION = '~/.zshrc'; | ||
|
||
module.exports = { | ||
BASH_LOCATION, | ||
ZSH_LOCATION, | ||
FISH_LOCATION | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
const debug = require('debug')('tabtab:installer'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const untildify = require('untildify'); | ||
const { promisify } = require('es6-promisify'); | ||
const readFile = promisify(fs.readFile); | ||
const writeFile = promisify(fs.writeFile); | ||
const { BASH_LOCATION, FISH_LOCATION, ZSH_LOCATION } = require('./constants'); | ||
|
||
const shellExtension = location => { | ||
if (location === BASH_LOCATION) return 'bash'; | ||
if (location === FISH_LOCATION) return 'fish'; | ||
if (location === ZSH_LOCATION) return 'zsh'; | ||
}; | ||
|
||
const scriptFromLocation = location => { | ||
if (location === BASH_LOCATION) { | ||
return path.join(__dirname, '../scripts/bash.sh'); | ||
} | ||
|
||
if (location === FISH_LOCATION) { | ||
return path.join(__dirname, '../scripts/fish.sh'); | ||
} | ||
|
||
if (location === ZSH_LOCATION) { | ||
return path.join(__dirname, '../scripts/zsh.sh'); | ||
} | ||
}; | ||
|
||
const writeToShellConfig = ({ name, completer, location }) => { | ||
debug(`Adding tabtab script to ${location}`); | ||
const filename = path.join( | ||
__dirname, | ||
'../.completions', | ||
`${name}.${shellExtension(location)}` | ||
); | ||
debug('Which filename', filename); | ||
|
||
return new Promise((resolve, reject) => { | ||
const stream = fs.createWriteStream(untildify(location), { flags: 'a' }); | ||
stream.on('error', reject); | ||
stream.on('finish', () => resolve()); | ||
|
||
debug('Writing to shell configuration file (%s)', location); | ||
stream.write(`\n# tabtab source for ${name} package`); | ||
stream.write('\n# uninstall by removing these lines'); | ||
|
||
if (location === BASH_LOCATION) { | ||
stream.write(`\n[ -f ${filename} ] && . ${filename} || true`); | ||
} else if (location === FISH_LOCATION) { | ||
debug('Addding fish line'); | ||
stream.write(`\n[ -f ${filename} ]; and . ${filename}; or true`); | ||
} else if (location === ZSH_LOCATION) { | ||
debug('Addding zsh line'); | ||
stream.write(`\n[[ -f ${filename} ]] && . ${filename} || true`); | ||
} | ||
|
||
stream.end('\n'); | ||
}); | ||
}; | ||
|
||
const writeToCompletionScript = ({ name, completer, location }) => { | ||
const filename = path.join( | ||
__dirname, | ||
'../.completions', | ||
`${name}.${shellExtension(location)}` | ||
); | ||
|
||
const script = scriptFromLocation(location); | ||
debug('Writing completion script to', filename); | ||
debug('with', script); | ||
|
||
return readFile(script, 'utf8') | ||
.then(filecontent => { | ||
return filecontent | ||
.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 => writeFile(filename, filecontent)); | ||
}; | ||
|
||
const installer = { | ||
install(options = { name: '', completer: '', location: '' }) { | ||
if (!options.name) { | ||
throw new TypeError('options.name is required'); | ||
} | ||
|
||
if (!options.completer) { | ||
throw new TypeError('options.completer is required'); | ||
} | ||
|
||
if (!options.location) { | ||
throw new TypeError('options.location is required'); | ||
} | ||
|
||
return Promise.all([ | ||
writeToShellConfig(options), | ||
writeToCompletionScript(options) | ||
]); | ||
}, | ||
|
||
uninstall(options = { name: '' }) { | ||
throw new Error('Not yet implemented'); | ||
}, | ||
|
||
writeToShellConfig, | ||
writeToCompletionScript | ||
}; | ||
|
||
module.exports = installer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const { install, uninstall } = require('../../lib/installer'); | ||
|
||
(async () => { | ||
await install({ | ||
name: 'foo', | ||
completer: 'foo-complete', | ||
location: '~/.bashrc' | ||
}); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
const assert = require('assert'); | ||
const { | ||
install, | ||
uninstall, | ||
writeToShellConfig, | ||
writeToCompletionScript | ||
} = require('../lib/installer'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const untildify = require('untildify'); | ||
const { promisify } = require('es6-promisify'); | ||
const readFile = promisify(fs.readFile); | ||
|
||
describe('installer', () => { | ||
it('has install / uninstall functions', () => { | ||
assert.equal(typeof install, 'function'); | ||
assert.equal(typeof uninstall, 'function'); | ||
}); | ||
|
||
it('both throws on missing options', () => { | ||
assert.throws(() => install(), /options.name is required/); | ||
assert.throws( | ||
() => install({ name: 'foo ' }), | ||
/options.completer is required/ | ||
); | ||
|
||
assert.throws( | ||
() => install({ name: 'foo ', completer: 'foo-complete' }), | ||
/options.location is required/ | ||
); | ||
}); | ||
|
||
it('has writeToShellConfig / writeToCompletionScript functions', () => { | ||
assert.equal(typeof writeToShellConfig, 'function'); | ||
assert.equal(typeof writeToCompletionScript, 'function'); | ||
}); | ||
|
||
describe('installer on ~/.bashrc', () => { | ||
const bashrc = fs.readFileSync(untildify('~/.bashrc')); | ||
|
||
afterEach(done => { | ||
fs.writeFile(untildify('~/.bashrc'), bashrc, done); | ||
}); | ||
|
||
it('installs the necessary line into ~/.bashrc', () => { | ||
return install({ | ||
name: 'foo', | ||
completer: 'foo-complete', | ||
location: '~/.bashrc' | ||
}) | ||
.then(() => readFile(untildify('~/.bashrc'), 'utf8')) | ||
.then(filecontent => { | ||
assert.ok(/tabtab source for foo/.test(filecontent)); | ||
assert.ok(/uninstall by removing these lines/.test(filecontent)); | ||
assert.ok( | ||
/\[ -f .+foo.bash ] && \. .+tabtab\/.completions\/foo.bash || true/.test( | ||
filecontent | ||
) | ||
); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters