UNPKG

5.7 kBJavaScriptView Raw
1var common = require('./common');
2var _cd = require('./cd');
3var path = require('path');
4
5common.register('dirs', _dirs, {
6 wrapOutput: false,
7});
8common.register('pushd', _pushd, {
9 wrapOutput: false,
10});
11common.register('popd', _popd, {
12 wrapOutput: false,
13});
14
15// Pushd/popd/dirs internals
16var _dirStack = [];
17
18function _isStackIndex(index) {
19 return (/^[\-+]\d+$/).test(index);
20}
21
22function _parseStackIndex(index) {
23 if (_isStackIndex(index)) {
24 if (Math.abs(index) < _dirStack.length + 1) { // +1 for pwd
25 return (/^-/).test(index) ? Number(index) - 1 : Number(index);
26 }
27 common.error(index + ': directory stack index out of range');
28 } else {
29 common.error(index + ': invalid number');
30 }
31}
32
33function _actualDirStack() {
34 return [process.cwd()].concat(_dirStack);
35}
36
37//@
38//@ ### pushd([options,] [dir | '-N' | '+N'])
39//@
40//@ Available options:
41//@
42//@ + `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated.
43//@ + `-q`: Supresses output to the console.
44//@
45//@ Arguments:
46//@
47//@ + `dir`: Sets the current working directory to the top of the stack, then executes the equivalent of `cd dir`.
48//@ + `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
49//@ + `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
50//@
51//@ Examples:
52//@
53//@ ```javascript
54//@ // process.cwd() === '/usr'
55//@ pushd('/etc'); // Returns /etc /usr
56//@ pushd('+1'); // Returns /usr /etc
57//@ ```
58//@
59//@ Save the current directory on the top of the directory stack and then `cd` to `dir`. With no arguments, `pushd` exchanges the top two directories. Returns an array of paths in the stack.
60function _pushd(options, dir) {
61 if (_isStackIndex(options)) {
62 dir = options;
63 options = '';
64 }
65
66 options = common.parseOptions(options, {
67 'n': 'no-cd',
68 'q': 'quiet',
69 });
70
71 var dirs = _actualDirStack();
72
73 if (dir === '+0') {
74 return dirs; // +0 is a noop
75 } else if (!dir) {
76 if (dirs.length > 1) {
77 dirs = dirs.splice(1, 1).concat(dirs);
78 } else {
79 return common.error('no other directory');
80 }
81 } else if (_isStackIndex(dir)) {
82 var n = _parseStackIndex(dir);
83 dirs = dirs.slice(n).concat(dirs.slice(0, n));
84 } else {
85 if (options['no-cd']) {
86 dirs.splice(1, 0, dir);
87 } else {
88 dirs.unshift(dir);
89 }
90 }
91
92 if (options['no-cd']) {
93 dirs = dirs.slice(1);
94 } else {
95 dir = path.resolve(dirs.shift());
96 _cd('', dir);
97 }
98
99 _dirStack = dirs;
100 return _dirs(options.quiet ? '-q' : '');
101}
102exports.pushd = _pushd;
103
104//@
105//@
106//@ ### popd([options,] ['-N' | '+N'])
107//@
108//@ Available options:
109//@
110//@ + `-n`: Suppress the normal directory change when removing directories from the stack, so that only the stack is manipulated.
111//@ + `-q`: Supresses output to the console.
112//@
113//@ Arguments:
114//@
115//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.
116//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.
117//@
118//@ Examples:
119//@
120//@ ```javascript
121//@ echo(process.cwd()); // '/usr'
122//@ pushd('/etc'); // '/etc /usr'
123//@ echo(process.cwd()); // '/etc'
124//@ popd(); // '/usr'
125//@ echo(process.cwd()); // '/usr'
126//@ ```
127//@
128//@ When no arguments are given, `popd` removes the top directory from the stack and performs a `cd` to the new top directory. The elements are numbered from 0, starting at the first directory listed with dirs (i.e., `popd` is equivalent to `popd +0`). Returns an array of paths in the stack.
129function _popd(options, index) {
130 if (_isStackIndex(options)) {
131 index = options;
132 options = '';
133 }
134
135 options = common.parseOptions(options, {
136 'n': 'no-cd',
137 'q': 'quiet',
138 });
139
140 if (!_dirStack.length) {
141 return common.error('directory stack empty');
142 }
143
144 index = _parseStackIndex(index || '+0');
145
146 if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) {
147 index = index > 0 ? index - 1 : index;
148 _dirStack.splice(index, 1);
149 } else {
150 var dir = path.resolve(_dirStack.shift());
151 _cd('', dir);
152 }
153
154 return _dirs(options.quiet ? '-q' : '');
155}
156exports.popd = _popd;
157
158//@
159//@
160//@ ### dirs([options | '+N' | '-N'])
161//@
162//@ Available options:
163//@
164//@ + `-c`: Clears the directory stack by deleting all of the elements.
165//@ + `-q`: Supresses output to the console.
166//@
167//@ Arguments:
168//@
169//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.
170//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.
171//@
172//@ Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if `+N` or `-N` was specified.
173//@
174//@ See also: `pushd`, `popd`
175function _dirs(options, index) {
176 if (_isStackIndex(options)) {
177 index = options;
178 options = '';
179 }
180
181 options = common.parseOptions(options, {
182 'c': 'clear',
183 'q': 'quiet',
184 });
185
186 if (options.clear) {
187 _dirStack = [];
188 return _dirStack;
189 }
190
191 var stack = _actualDirStack();
192
193 if (index) {
194 index = _parseStackIndex(index);
195
196 if (index < 0) {
197 index = stack.length + index;
198 }
199
200 if (!options.quiet) {
201 common.log(stack[index]);
202 }
203 return stack[index];
204 }
205
206 if (!options.quiet) {
207 common.log(stack.join(' '));
208 }
209
210 return stack;
211}
212exports.dirs = _dirs;