aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: 210c9f95766286a3a30e1cac58742e873ac9298c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
## What is this?

`cdlog` is a small amount of GNU Bash code that provides a better
interactive experience for directory changes than
Bash's built-in directory stack mechanism (commands `pushd`, `popd`
and `dirs`, plus `~-` expansion).

## How to use

Install the file `cdlog.sh` somewhere, and source it from your
`.bashrc` script.

The user interface consists of three commands:

* `cd` is now an alias which calls the function `cdlog.chdir`.
Every time you change directory, it pushes the previous directory
into a history log which is stored in the `cdlog_fifo` array. The log maintains
nine entries. The ninth entry is erased. The entries are copied into
the variables `c1` through `c9`.  The first four entries are also
copied into the variables `x`, `y`, `z` and `w` for shorter access.

* `cs` (cd swap) is an alias for a command which exchanges
the current directory with a selected `cslog` entry selected
by a numeric argument, which defaults to 1. The current directory
overwrites that entry in the log, and then the shell changes to the directory
which was previously in that entry. If `cs` is given two or more
arguments, it rotates among those. The directory is changed to the
`cdlog` item indicated by the first argument. That item is overwritten
by the second item, the second by the third and so on. The last item
receives the previously current directory.

* `pd` (pop dir) is an alias for a command which changes to (by default) the
most recent directory in the log, and removes that entry from the log. The second most
recent directory becomes most recent and so on. If it is given an argument
value in the range 1 to 9, it changes to the specified entry, and removes it,
moving the others down to close the gap. Thus `pd 1` is equivalent to `pd`.

* `cdlog` function shows a listing of the four most recent entries in the
log, or all nine if given the `-l` argument. The `cl` command is an alias for
for `cdlog` with no arguments and `cll` for `cdlog -l`.

* The `mcd` and `mcs` are menu-selection-based analogs of `cd` and `mcs`.
They print the contents of the history (first nine entries), and you can
pick which directory to change to or swap with. The terminal cursor is then
retraced back to the top of the menu, and the screen is erased from
that point to the bottom.

* The `cdr` command is used for recovering previous sessions. It
presents you with a numbered list of these sessions. You can recover to one of
the sessions, use a `c` prefix on the number to clone the session into
the current session, or press Enter to do nothing.

* The `cdalias` command is used for defining "cd aliases"; see below.

In addition, the `cdlog.sh` script sets the bash `direxpand` option.
With the `direxpand` option, Tab completion on a directory coming
from a variable name will expand that variable into the command line.

The directory changing commands do nothing if you attempt to change into the
same directory you are already in. There is no effect on the history.

## Aliases

`cdlog` provides its own "cd alias" feature. If the argument to
`cd` contains no slashes, then it is used as a key to look up an
alias, which replaces it. The replacement is not considered to
be an alias even if it looks like one. Aliases are defined using
the `cdalias` command which is an alias. It takes two arguments.

Implementation notes: aliases are stored in the `cdlog_alias`
array.  The `cdlog.chdir` function recognizes an alias only if
it is invoked as `cdlog.chdir -p <alias>`, which is the way
`cd` invokes it.

## Persistence

Whenever the history changes, the current directory and the
contents of the history are written to the file `~/.cslog.N.dirs`,
one path per line, where `N` is an internal session number.

When `cdlog` initializes, it allocates a session by finding a free
value `N` in the range 1 to 10. If it cannot find one due to the
session store being full, it erases the one with the oldest time
stamp and chooses its index.

When one or more persisted session are present, `cdlog`'s initialization
mentions this, suggesting that the `cdr` command may be used to recover
to one of the sessions.

## LRU Mode

When the configuration variable `cdlog_lru` is set to the value `y`, LRU mode
is enabled in the `cdlog.chdir` function, affecting the `cd` and `mcd`
commands. LRU mode modifies the history algorithm in the following way.

If the directory change successfully takes place to a directory which
already exists in the history, then the most recent (topmost) occurrence
of that directory is removed from the history before the previous
directory is pushed into the history. Thus, in effect, a rotation is
taking place: the existing entry in the history becomes the current
directory, and is removed; the entries above it shift down to take
its place, and the previous current directory becomes the top of
the history.

LRU mode keeps duplicate directories out of the history and while
promoting recently used directories toward the top.

## Completion

`cdlog` provides its own Tab completion for the `cd` command, overriding
the built-in completion. It includes the cd aliases, while completing
on directories, taking into account `CDPATH`.

## How is this better?

* It's not hard-coded C code inside the shell; it consists of a small amount of
code whose behavior that can be customized by the end-user.

* Uses simple variables, which are better supported for completion
and require fewer keystrokes.

* The `dirs` command for accessing the directory stack in Bash is too
clumsy and won't be discussed here any more.

* Bash's shorthand notation for accessing the nth element, namely `~-n`, takes
more keystrokes than `cdlog`'s aliases for the first four elements, `$x`
through `$w`.

* Bash's shorthand notation requires an explicit slash to be typed
in order for completion to work. `~-n` followed by tab is not sufficient.
You must type a slash and then Tab. Whereas completing on the variable `$x`
just requires Tab. One tab will automatically add the slash and then additional
tabs engage further completion.

* Bash's `direxpand` option does not work for `~-n` notation. Completion
works, but the notation remains unexpanded.

* `cslog` has intuitive, simpler commands. The actions of pushing entries into
the log, and rotating among them aren't conflated into a single command.
The rotating command `cs` is usefully different from `pushd [+/-]n`,
taking only positive integer arguments with no sign, and rotating among
specified places, rather than a contiguous block of top entries.

* The persistence feature recovers the directories from a previous session.

## License

This is under distributed under a modified two-clause BSD license.
See the license block at the bottom of the `cdlog.sh` file.