UNPKG

5.68 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`: Makes the current working directory be the top of the stack, and 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//@ ### popd([options,] ['-N' | '+N'])
106//@
107//@ Available options:
108//@
109//@ + `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated.
110//@ + `-q`: Supresses output to the console.
111//@
112//@ Arguments:
113//@
114//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.
115//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.
116//@
117//@ Examples:
118//@
119//@ ```javascript
120//@ echo(process.cwd()); // '/usr'
121//@ pushd('/etc'); // '/etc /usr'
122//@ echo(process.cwd()); // '/etc'
123//@ popd(); // '/usr'
124//@ echo(process.cwd()); // '/usr'
125//@ ```
126//@
127//@ 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.
128function _popd(options, index) {
129 if (_isStackIndex(options)) {
130 index = options;
131 options = '';
132 }
133
134 options = common.parseOptions(options, {
135 'n': 'no-cd',
136 'q': 'quiet',
137 });
138
139 if (!_dirStack.length) {
140 return common.error('directory stack empty');
141 }
142
143 index = _parseStackIndex(index || '+0');
144
145 if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) {
146 index = index > 0 ? index - 1 : index;
147 _dirStack.splice(index, 1);
148 } else {
149 var dir = path.resolve(_dirStack.shift());
150 _cd('', dir);
151 }
152
153 return _dirs(options.quiet ? '-q' : '');
154}
155exports.popd = _popd;
156
157//@
158//@ ### dirs([options | '+N' | '-N'])
159//@
160//@ Available options:
161//@
162//@ + `-c`: Clears the directory stack by deleting all of the elements.
163//@ + `-q`: Supresses output to the console.
164//@
165//@ Arguments:
166//@
167//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.
168//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.
169//@
170//@ 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.
171//@
172//@ See also: pushd, popd
173function _dirs(options, index) {
174 if (_isStackIndex(options)) {
175 index = options;
176 options = '';
177 }
178
179 options = common.parseOptions(options, {
180 'c': 'clear',
181 'q': 'quiet',
182 });
183
184 if (options.clear) {
185 _dirStack = [];
186 return _dirStack;
187 }
188
189 var stack = _actualDirStack();
190
191 if (index) {
192 index = _parseStackIndex(index);
193
194 if (index < 0) {
195 index = stack.length + index;
196 }
197
198 if (!options.quiet) {
199 common.log(stack[index]);
200 }
201 return stack[index];
202 }
203
204 if (!options.quiet) {
205 common.log(stack.join(' '));
206 }
207
208 return stack;
209}
210exports.dirs = _dirs;