Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: custom config file path #255

Closed
wants to merge 9 commits into from
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ node_modules
.DS_Store
npm-debug.log
.idea

tmp/
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ To see tldr pages:
- `tldr --random` show a page at random
- `tldr --random-example` show a single random example
- `tldr --markdown` show the original markdown format page
- `tldr --config <path>` load a custom config file (default ~/.tldrrc)')

The client caches a copy of all pages locally, in `~/.tldr`.
There are more commands to control the local cache:

- `tldr --update` download the latest pages and generate search index
Expand All @@ -61,6 +61,8 @@ As a contributor, you might also need the following commands:

You can configure the `tldr` client by adding a `.tldrrc` file in your HOME directory. You can copy the contents of the `config.json` file from the repo to get the basic structure to start with, and modify it to suit your needs.

### Themes

The default color theme is the one named `"simple"`. You can change the theme by assigning a different value to the `"theme"` variable -- either to one of the pre-configured themes, or to a new theme that you have previously created in the `"themes"` section. Note that the colors and text effects you can choose are limited. Refer to the [chalk documentation](https://github.com/chalk/chalk#styles) for all options.

```json
Expand All @@ -83,8 +85,22 @@ The default color theme is the one named `"simple"`. You can change the theme by
},
"theme": "ocean"
}

```

### Cache

The client caches a copy of all pages locally, in `~/.tldr`,
this line in the config file will override the default behaviour:

```json
{
"cache": "/path/to/cache"
}
```

### Platforms

If you regularly need pages for a different platform (e.g. Linux),
you can put it in the config file:

Expand All @@ -108,6 +124,20 @@ As a contributor, you can also point to your own fork containing the `tldr.zip`
}
```

### Custom config file

You can have differents config files and choose which one to use at runtime with the option:

```bash
tldr --config ".mytldrrc"
```

For practical use you can define an alias:

```bash
alias mytldr='tldr --config ".mytldrrc"'
```

## Command-line Autocompletion

Currently we only support command-line autocompletion for zsh.
Expand Down
9 changes: 7 additions & 2 deletions bin/tldr
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

const program = require('commander');
const pkg = require('../package');
const tldr = require('../lib/tldr');
const config = require('../lib/config');
const platform = require('../lib/platform');
const tldr = require('../lib/tldr');

program
.version(pkg.version)
Expand All @@ -13,6 +13,7 @@ program
//
// BASIC OPTIONS
//
.option('--config <path>', 'Load a custom config file (default ~/.tldrrc)')
.option('-l, --list', 'List all commands for the chosen platform in the cache')
.option('-a, --list-all', 'List all commands in the cache')
.option('-1, --single-column', 'List single command per line (use with options -l or -a)')
Expand Down Expand Up @@ -42,6 +43,7 @@ const help = `
$ tldr --list-all
$ tldr --random
$ tldr --random-example
$ tldr --config ".mytldrrc" tar

To control the cache:

Expand All @@ -59,6 +61,10 @@ program.on('--help', () => {

program.parse(process.argv);

if (program.config) {
config.set(program.config);
}

if (program.linux) {
program.os = 'linux';
}
Expand All @@ -71,7 +77,6 @@ if (program.sunos) {
program.os = 'sunos';
}


if (program.os) {
if (platform.isSupported(program.os)) {
config.get().platform = program.os;
Expand Down
42 changes: 28 additions & 14 deletions lib/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,57 @@ const platform = require('./platform');
const index = require('./index');
const utils = require('./utils');

const CACHE_FOLDER = path.join(config.get().cache, 'cache');
const TEMP_FOLDER = path.join(os.tmpdir(), 'tldr');

exports.CACHE_FOLDER = CACHE_FOLDER;
let cacheFolder = null;

exports.lastUpdated = () => {
return fs.stat(CACHE_FOLDER);
};
function getCacheFolder() {
if (!cacheFolder) {
cacheFolder = path.join(config.get().cache, 'cache');
}
return cacheFolder;
}

function lastUpdated() {
return fs.stat(getCacheFolder());
}

exports.getPage = (page) => {
function getPage(page) {
let preferredPlatform = platform.getPreferredPlatformFolder();
return index.findPlatform(page, preferredPlatform)
.then((folder) => {
if (!folder) {
return;
}
let filePath = path.join(CACHE_FOLDER, 'pages', folder, page + '.md');
let filePath = path.join(getCacheFolder(), 'pages', folder, page + '.md');
return fs.readFile(filePath, 'utf8');
})
.catch((err) => {
console.error(err);
});
};
}

exports.clear = () => {
return fs.remove(CACHE_FOLDER);
};
function clear() {
return fs.remove(getCacheFolder());
}

exports.update = () => {
function update() {
// Temporary folder path: /tmp/tldr/{randomName}
let tempFolder = path.join(TEMP_FOLDER, utils.uniqueId());

// Downloading fresh copy
return Promise.all([
// Create new temporary folder
fs.ensureDir(tempFolder),
fs.ensureDir(CACHE_FOLDER)
fs.ensureDir(getCacheFolder())
])
.then(() => {
// Download and extract cache data to temporary folder
return remote.download(tempFolder);
})
.then(() => {
// Copy data to cache folder
return fs.copy(tempFolder, CACHE_FOLDER);
return fs.copy(tempFolder, getCacheFolder());
})
.then(() => {
return Promise.all([
Expand All @@ -66,4 +72,12 @@ exports.update = () => {
.then(([_, shortIndex]) => {
return shortIndex;
});
}

module.exports = {
clear,
getCacheFolder,
getPage,
lastUpdated,
update,
};
24 changes: 20 additions & 4 deletions lib/config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
'use strict';

const defaults = require('lodash/defaults');
const fs = require('fs');
const fs = require('fs-extra');
const path = require('path');
const osHomedir = require('os-homedir');

let config = null;
const DEFAULT_CONFIG_PATH = path.join(osHomedir(), '.tldrrc');
let configPath = DEFAULT_CONFIG_PATH;

exports.reset = () => {
config = null;
Expand All @@ -18,9 +20,20 @@ exports.get = () => {
return config;
};

exports.set = (newConfigPath) => {
if (newConfigPath) {
try {
fs.accessSync(newConfigPath);
configPath = newConfigPath;
} catch (_ex) {
console.error(`No access to ${newConfigPath}; sticking with default config file (${DEFAULT_CONFIG_PATH})`);
}
}
};

function load() {
const DEFAULT = path.join(__dirname, '..', 'config.json');
const CUSTOM = path.join(osHomedir(), '.tldrrc');
const CUSTOM = configPath;

let defaultConfig = JSON.parse(fs.readFileSync(DEFAULT));
defaultConfig.cache = path.join(osHomedir(), '.tldr');
Expand All @@ -32,8 +45,11 @@ function load() {
try {
customConfig = JSON.parse(fs.readFileSync(CUSTOM));
} catch (ex) {
/*eslint-disable */
/*eslint-enable */
if (configPath !== DEFAULT_CONFIG_PATH) {
console.error(ex);
} else if (ex.code !== 'ENOENT') {
console.error(ex);
}
}

let merged = defaults(customConfig, defaultConfig);
Expand Down
25 changes: 19 additions & 6 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,22 @@ const config = require('./config');
const utils = require('./utils');

let shortIndex = null;
let pagesPath = null;
let shortIndexFile = null;

const pagesPath = path.join(config.get().cache, 'cache/pages');
const shortIndexFile = path.join(pagesPath, 'shortIndex.json');
function getPagesPath() {
if (!pagesPath) {
pagesPath = path.join(config.get().cache, 'cache/pages');
}
return pagesPath;
}

function getShortIndexFile() {
if (!shortIndexFile) {
shortIndexFile = path.join(getPagesPath(), 'shortIndex.json');
}
return shortIndexFile;
}

function findPlatform(page, preferredPlatform) {
// Load the index
Expand Down Expand Up @@ -62,7 +75,7 @@ function commandsFor(platform) {

// Delete the index file.
function clearPagesIndex() {
return fs.unlink(shortIndexFile)
return fs.unlink(getShortIndexFile())
.then(() => {
return clearRuntimeIndex();
})
Expand Down Expand Up @@ -99,7 +112,7 @@ function getShortIndex() {
// If the file does not exist, create the data structure, write the file,
// and load it into memory.
function readShortPagesIndex() {
return fs.readJson(shortIndexFile)
return fs.readJson(getShortIndexFile())
.then((idx) => {
shortIndex = idx;
return shortIndex;
Expand All @@ -111,15 +124,15 @@ function readShortPagesIndex() {
return idx;
}
shortIndex = idx;
return fs.writeJson(shortIndexFile, shortIndex).then(() => {
return fs.writeJson(getShortIndexFile(), shortIndex).then(() => {
return shortIndex;
});
});
});
}

function buildShortPagesIndex() {
return utils.walk(pagesPath)
return utils.walk(getPagesPath())
.then((files) => {
files = files.filter(utils.isPage);
let reducer = (index, file) => {
Expand Down
26 changes: 20 additions & 6 deletions lib/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,23 @@ const utils = require('./utils');
const index = require('./index');
const platform = require('./platform');

const CACHE_FOLDER = path.join(config.get().cache, 'cache');
let cacheFolder = null;

const filepath = CACHE_FOLDER + '/search-corpus.json';
function getCacheFolder() {
if (!cacheFolder) {
cacheFolder = path.join(config.get().cache, 'cache');
}
return cacheFolder;
}

let filePath = null;

function getFilePath() {
if (!filePath) {
filePath = getCacheFolder() + '/search-corpus.json';
}
return filePath;
}

let corpus = {};

Expand Down Expand Up @@ -115,17 +129,17 @@ let createFileLengths = () => {
let writeCorpus = () => {
corpus.allTokens = Array.from(corpus.allTokens);
let json = JSON.stringify(corpus);
return fs.writeFile(filepath, json, 'utf8')
return fs.writeFile(getFilePath(), json, 'utf8')
.then(() => {
return Promise.resolve('JSON written to disk at: ' + filepath);
return Promise.resolve('JSON written to disk at: ' + getFilePath());
})
.catch((err) => {
return Promise.reject(err);
});
};

let readCorpus = () => {
return fs.readFile(filepath, 'utf8')
return fs.readFile(getFilePath(), 'utf8')
.then((data) => {
corpus = JSON.parse(data.toString());
return Promise.resolve();
Expand Down Expand Up @@ -215,7 +229,7 @@ exports.printResults = (results) => {
};

exports.createIndex = () => {
return utils.glob(CACHE_FOLDER + '/pages/**/*.md', {})
return utils.glob(getCacheFolder() + '/pages/**/*.md', {})
.then((files) => {
let promises = [];
files.forEach((file) => {
Expand Down
Loading