canto-curses.git
4 years ago0.9.1 v0.9.1
Jack Miller [Fri, 9 Jan 2015 21:09:17 +0000 (15:09 -0600)]
0.9.1

4 years agoDon't count items already in interface as pending updates
Jack Miller [Fri, 9 Jan 2015 22:17:01 +0000 (16:17 -0600)]
Don't count items already in interface as pending updates

The data has made a round trip, but this makes the grey update indicator
into an pending new item count instead of something more nebulous.

4 years agoMake tag-list defaults include first_sel
Jack Miller [Wed, 17 Dec 2014 19:06:05 +0000 (13:06 -0600)]
Make tag-list defaults include first_sel

Similar to item-list, tag-list operations should assume the first
visible tag, if there's no selection to base it on.

4 years agoStop locking on variable changes
Jack Miller [Fri, 9 Jan 2015 15:51:17 +0000 (09:51 -0600)]
Stop locking on variable changes

- var_lock was merged with config_lock to avoid having a million
deadlock cases

- locking on vars now really hampers performance

- most vars are accessed by only a single thread (i.e. used as
  out-of-instance storage for classes that need to resize, which would
only be handled by the gui) so the locking for these is totally
unnecessary

- vars that are accessed by multiple threads are probably already
  serialized by sync lock (i.e. input thread holds sync while it
performs a command that changes selection, gui thread holds sync while
the Taglist uses that selection info).

- the GIL prevents any C-like sort of half-way splinched assignment

- config_lock could probably be done away with entirely at this point,
  but I'm more concerned that there could be a reason to do an atomic
change to multiple variables at some point.

I'm taking a wait and see approach on this. The ultimate test for
whether a lock is unnecessary is removing the lock =P.

4 years agoUpdate error box color
Jack Miller [Wed, 17 Dec 2014 18:54:50 +0000 (12:54 -0600)]
Update error box color

4 years agoAdd selection preservation test
Jack Miller [Wed, 17 Dec 2014 18:53:30 +0000 (12:53 -0600)]
Add selection preservation test

- Make sure that selections that disappear from the tagcore remain in
  the tag

- Make sure they are then eliminated when no longer selected and an
  update occurs

4 years agoToss undead former selections faster
Jack Miller [Wed, 17 Dec 2014 18:49:37 +0000 (12:49 -0600)]
Toss undead former selections faster

When preserving the selection, we keep items in the graphical Tag that
are no longer in the TagCore. That's fine, but we need to re-evaluate
that tag next time a sync is requested, despite the fact that the
underlying TagCore may not have changed.

This should make formerly selected items disappear faster.

4 years agoSet working flag earlier
Jack Miller [Tue, 16 Dec 2014 03:18:04 +0000 (21:18 -0600)]
Set working flag earlier

We want to be able to use it with sync_requested to determine if the gui
thread is in progress, so close the window where they're both false.

4 years agoTagcore script should include PING -> PONG
Jack Miller [Tue, 16 Dec 2014 01:58:39 +0000 (19:58 -0600)]
Tagcore script should include PING -> PONG

On refresh, it uses this to know when the old responses have stopped
coming in.

4 years agoFix missing import on exception
Jack Miller [Fri, 12 Dec 2014 02:53:24 +0000 (20:53 -0600)]
Fix missing import on exception

4 years agoMake summarize + collapse tests functional
Jack Miller [Sat, 29 Nov 2014 17:11:55 +0000 (11:11 -0600)]
Make summarize + collapse tests functional

4 years agoUpdate test wait to use gui.working
Jack Miller [Sat, 29 Nov 2014 02:39:00 +0000 (20:39 -0600)]
Update test wait to use gui.working

4 years agoAdd gui.working for testing
Jack Miller [Sat, 29 Nov 2014 02:37:08 +0000 (20:37 -0600)]
Add gui.working for testing

Instead of waiting for needs_refresh et. al. to be cleared, wait on that
and gui.working to make sure that it's actually done. This allows us to
wait until all of the refresh/redrawing is done, but still clear the
needs_* conditions before we run them (which allows them to indirectly
queue up another pass if necessary).

4 years agoMake curses tests output log to stdout
Jack Miller [Sat, 29 Nov 2014 02:03:32 +0000 (20:03 -0600)]
Make curses tests output log to stdout

4 years agoMinor taglist in tags -> is_tag change
Jack Miller [Sat, 29 Nov 2014 02:03:00 +0000 (20:03 -0600)]
Minor taglist in tags -> is_tag change

4 years agoModify "marked" style
Jack Miller [Thu, 27 Nov 2014 19:49:17 +0000 (13:49 -0600)]
Modify "marked" style

4 years agoDon't throw exception on improper theme %0
Jack Miller [Thu, 27 Nov 2014 19:39:54 +0000 (13:39 -0600)]
Don't throw exception on improper theme %0

4 years agoStop locking on WINCH
Jack Miller [Wed, 26 Nov 2014 07:18:27 +0000 (01:18 -0600)]
Stop locking on WINCH

4 years agoReorganize test-screen
Jack Miller [Wed, 26 Nov 2014 04:22:49 +0000 (22:22 -0600)]
Reorganize test-screen

- Push startup into __init__ with some basic sanity testing
- Add some taglist checks
- Move individual command post-condition tests into functions

4 years agoMore screen init tweaks
Jack Miller [Wed, 26 Nov 2014 04:12:00 +0000 (22:12 -0600)]
More screen init tweaks

This is for testing, mostly. Most of the time, the updates are triggered
by items that are arriving over time, but in a test environment with
rigid timing constraints and items pre-loaded, there are no subsequent
events to cause a refresh.

4 years agoTheme + color fixes and tweaks
Jack Miller [Tue, 25 Nov 2014 22:20:13 +0000 (16:20 -0600)]
Theme + color fixes and tweaks

- If you have customized your format strings, you needs to subtract one
  from all color codes (i.e. %3 should now be %2). %1 should now be
erased as well as the default color pair is always applied.

- attron won't overwrite a color if given color_pair(0), so attroff
  needs to be called explicitly on color changes.

4 years agoStrip more selection maintaining logic
Jack Miller [Tue, 25 Nov 2014 22:17:49 +0000 (16:17 -0600)]
Strip more selection maintaining logic

- Was causing the gui loop to never terminate because every refresh was
  setting and unsetting the selection trying to maintain.

4 years agoExpand screen test to test :color
Jack Miller [Tue, 25 Nov 2014 05:29:30 +0000 (23:29 -0600)]
Expand screen test to test :color

4 years agoFix bad pair referencing in fake_curses
Jack Miller [Tue, 25 Nov 2014 04:54:24 +0000 (22:54 -0600)]
Fix bad pair referencing in fake_curses

4 years agoRecord output of TestBackends
Jack Miller [Tue, 25 Nov 2014 04:29:55 +0000 (22:29 -0600)]
Record output of TestBackends

4 years agoLoop gui_thread until no re(draw/fresh/size)s required
Jack Miller [Tue, 25 Nov 2014 04:28:51 +0000 (22:28 -0600)]
Loop gui_thread until no re(draw/fresh/size)s required

4 years agoAdd indicator of pending updates to tag header
Jack Miller [Tue, 25 Nov 2014 03:45:54 +0000 (21:45 -0600)]
Add indicator of pending updates to tag header

4 years agoTrack attributes in fake_curses
Jack Miller [Tue, 25 Nov 2014 03:43:55 +0000 (21:43 -0600)]
Track attributes in fake_curses

4 years agoBasic overall testing environment
Jack Miller [Mon, 24 Nov 2014 08:41:13 +0000 (02:41 -0600)]
Basic overall testing environment

- A replacement main.py that overrides curses and friends to provide a
  print friendly, easily reproducible daemon-less test environment.

4 years agoAdd ability to generate stub item scripts
Jack Miller [Mon, 24 Nov 2014 05:13:22 +0000 (23:13 -0600)]
Add ability to generate stub item scripts

4 years agoAllow scripts to specify multiple responses
Jack Miller [Mon, 24 Nov 2014 03:32:36 +0000 (21:32 -0600)]
Allow scripts to specify multiple responses

- Useful for ITEMS, the responses to which are ITEMS, ITEMSDONE, and
  usually an automatic ATTRIBUTES response.

4 years agoAdd tagcore function test
Jack Miller [Mon, 24 Nov 2014 00:48:23 +0000 (18:48 -0600)]
Add tagcore function test

4 years agoFix del_tagcore
Jack Miller [Mon, 24 Nov 2014 00:12:56 +0000 (18:12 -0600)]
Fix del_tagcore

4 years agoRemoving an empty tagcore shouldn't cause items_removed
Jack Miller [Sun, 23 Nov 2014 23:36:14 +0000 (17:36 -0600)]
Removing an empty tagcore shouldn't cause items_removed

4 years agoAttributes for items still in tagcore shouldn't be removed
Jack Miller [Sun, 23 Nov 2014 23:28:47 +0000 (17:28 -0600)]
Attributes for items still in tagcore shouldn't be removed

- on the curses_stories_removed hook, which only means that the
  graphical Tag objects have removed it.

4 years agoMove compare functions into Test base
Jack Miller [Sun, 23 Nov 2014 22:16:01 +0000 (16:16 -0600)]
Move compare functions into Test base

4 years agoAdd config function test
Jack Miller [Sun, 23 Nov 2014 22:09:16 +0000 (16:09 -0600)]
Add config function test

Tests hooks getting called, switch_tags, successful config change.

Should probably be expanded to cover the config options that c-c doesn't
honor (that are just relayed to whatever) and tag options, but for now
core functionality is good.

4 years agoChanges to CantoCurses.tags should cause eval_tags()
Jack Miller [Sun, 23 Nov 2014 22:06:53 +0000 (16:06 -0600)]
Changes to CantoCurses.tags should cause eval_tags()

4 years agoFix DELTAGS config change hooks
Jack Miller [Sun, 23 Nov 2014 21:34:29 +0000 (15:34 -0600)]
Fix DELTAGS config change hooks

4 years agoConfig switch_tags should take strings, not Tag objects
Jack Miller [Sun, 23 Nov 2014 21:03:32 +0000 (15:03 -0600)]
Config switch_tags should take strings, not Tag objects

4 years agoWhitespace
Jack Miller [Sun, 23 Nov 2014 20:26:45 +0000 (14:26 -0600)]
Whitespace

4 years agoWe don't need to handle selection re-add anymore
Jack Miller [Sun, 23 Nov 2014 19:47:31 +0000 (13:47 -0600)]
We don't need to handle selection re-add anymore

Since we moved protection to the client side, selection won't just
disappear anymore.

4 years agoCause individual Tag sync when TagCore gets first item
Jack Miller [Sun, 23 Nov 2014 19:47:08 +0000 (13:47 -0600)]
Cause individual Tag sync when TagCore gets first item

This is an optimization for startup and for other reset actions like
changing filters.

4 years agoSort Tags() after a reset has occurred
Jack Miller [Sun, 23 Nov 2014 19:13:55 +0000 (13:13 -0600)]
Sort Tags() after a reset has occurred

This was working on some computers before, but only because a sync()
event may occur while the tags are empty, waiting for the update. So
don't leave it up to chance now.

4 years agoEliminate config-managed alltags
Jack Miller [Sun, 23 Nov 2014 07:31:22 +0000 (01:31 -0600)]
Eliminate config-managed alltags

Instead of issuing the .die() calls to Tag() objects, they can use the
hooks. This has a side-effect of eval_tags being quicker to respond to
tag changes.

4 years agoDefer _all_ graphical logging
Jack Miller [Sun, 23 Nov 2014 07:29:02 +0000 (01:29 -0600)]
Defer _all_ graphical logging

4 years agoUse new hook mass unloading
Jack Miller [Sun, 23 Nov 2014 04:47:04 +0000 (22:47 -0600)]
Use new hook mass unloading

4 years agoAdd config validator test
Jack Miller [Sun, 23 Nov 2014 02:49:43 +0000 (20:49 -0600)]
Add config validator test

Not sure if this is totally anemic and should test every specific
validator or be left as is, just ensuring that when a validator fails
its value is properly rejected.

Definite room for expansion.

4 years agoEnable completion for categories and user tags
Jack Miller [Sun, 23 Nov 2014 02:36:20 +0000 (20:36 -0600)]
Enable completion for categories and user tags

4 years agoCall a hook on tag update cycle completion
Jack Miller [Sun, 23 Nov 2014 01:53:50 +0000 (19:53 -0600)]
Call a hook on tag update cycle completion

Taglist then uses it to force sync when a full barrage of ITEMS calls
has come back in. Works on startup and when requested (i.e. :refresh /
C-r)

4 years agoAdd processed hook to TestBackend, fix inject
Jack Miller [Sat, 22 Nov 2014 21:23:30 +0000 (15:23 -0600)]
Add processed hook to TestBackend, fix inject

Inject now waits until the protocol has been written, read, and
processed.

4 years agoAdd a processed() call for subthread testing
Jack Miller [Sat, 22 Nov 2014 21:23:00 +0000 (15:23 -0600)]
Add a processed() call for subthread testing

This allows us to know when the protocol function has returned.

4 years agoDo basic config variable init earlier
Jack Miller [Sat, 22 Nov 2014 21:22:12 +0000 (15:22 -0600)]
Do basic config variable init earlier

We want tests to have access to them without actually init'ing the
subthread.

4 years agoImprove base test class
Jack Miller [Sat, 22 Nov 2014 20:40:35 +0000 (14:40 -0600)]
Improve base test class

- Catch check exceptions and report them as failures
- Setup a basic logger so internal logging will show up in ouput

4 years agoMinor refactor
Jack Miller [Sat, 22 Nov 2014 19:54:31 +0000 (13:54 -0600)]
Minor refactor

Having separate binaries ensures that the environment is clean between
tests. Need to add a little bash harness to call the various tests and
output information though.

4 years agoBeginning of a test suite
Jack Miller [Sat, 22 Nov 2014 19:43:45 +0000 (13:43 -0600)]
Beginning of a test suite

4 years ago0.9.0 v0.9.0
Jack Miller [Wed, 19 Nov 2014 17:53:23 +0000 (11:53 -0600)]
0.9.0

4 years agoAppend category summary to :categories
Jack Miller [Tue, 18 Nov 2014 02:42:52 +0000 (20:42 -0600)]
Append category summary to :categories

- In addition to listing the categories of the current tag

4 years agoAdd 'tags' command to list tags of a specific item
Jack Miller [Mon, 17 Nov 2014 22:13:52 +0000 (16:13 -0600)]
Add 'tags' command to list tags of a specific item

4 years agoTouch up smartlink docs
Jack Miller [Mon, 17 Nov 2014 19:37:59 +0000 (13:37 -0600)]
Touch up smartlink docs

- Mention in manpage
- Mention using :fetch instead of :goto in the plugin itself

4 years agoRegister gui.py commands in "Base" group
Jack Miller [Mon, 17 Nov 2014 18:27:13 +0000 (12:27 -0600)]
Register gui.py commands in "Base" group

Keeps them from being hidden from :help et. al.

4 years agoMore deferred logging tweaks
Jack Miller [Mon, 17 Nov 2014 16:30:14 +0000 (10:30 -0600)]
More deferred logging tweaks

- Fix emit
- Fix exception on gui thread startup

4 years agoAdd 'update' command
Jack Miller [Sun, 16 Nov 2014 01:50:48 +0000 (19:50 -0600)]
Add 'update' command

This will sync items without throwing away all of the state, the same
mechanism that the update.* config options control.

In addition \ and F5 binds now use this. Refresh is still C-r

4 years agoMinor deferred logging cleanup
Jack Miller [Sun, 16 Nov 2014 01:40:50 +0000 (19:40 -0600)]
Minor deferred logging cleanup

4 years agoFix offset initializations
Jack Miller [Sun, 16 Nov 2014 01:08:23 +0000 (19:08 -0600)]
Fix offset initializations

4 years agoFix update.style maintain
Jack Miller [Sun, 16 Nov 2014 00:16:30 +0000 (18:16 -0600)]
Fix update.style maintain

4 years agosync_requested should init as True
Jack Miller [Sat, 15 Nov 2014 21:04:17 +0000 (15:04 -0600)]
sync_requested should init as True

Now that there's no ticking clock for updates, it should at least do an
initial sync on startup.

4 years agoAdd missing non CC settings to :set completion
Jack Miller [Tue, 11 Nov 2014 18:02:54 +0000 (12:02 -0600)]
Add missing non CC settings to :set completion

4 years agoRe-introduce version compatibility check
Jack Miller [Mon, 10 Nov 2014 17:01:48 +0000 (11:01 -0600)]
Re-introduce version compatibility check

4 years agoBe even lazier on NEWTAG notification
Jack Miller [Thu, 30 Oct 2014 22:54:34 +0000 (17:54 -0500)]
Be even lazier on NEWTAG notification

We already didn't propagate new tag calls, but now don't refresh the
config without real newtags either.

4 years agoForce a tag reset / update on defaults.global_transform change
Jack Miller [Thu, 30 Oct 2014 22:30:33 +0000 (17:30 -0500)]
Force a tag reset / update on defaults.global_transform change

4 years agoAdd a couple more config hooks
Jack Miller [Thu, 30 Oct 2014 22:30:06 +0000 (17:30 -0500)]
Add a couple more config hooks

Now that we're tracking defaults / feed configuration, this can be
propagated.

4 years agoFix trying to get key config for None window
Jack Miller [Thu, 30 Oct 2014 22:11:16 +0000 (17:11 -0500)]
Fix trying to get key config for None window

Occasionally an event like a resize will occur while the interface is
still taking and processing keys, so screen.focused can be None. Don't
return that None in the focus list.

4 years agoGraphical notification of plugin failures
Jack Miller [Wed, 29 Oct 2014 19:52:01 +0000 (14:52 -0500)]
Graphical notification of plugin failures

When plugins fail to load, that's important information.

4 years agoDeferred graphical logging
Jack Miller [Wed, 29 Oct 2014 19:50:55 +0000 (14:50 -0500)]
Deferred graphical logging

- Keeps log operation from waiting on sync_lock

4 years agoAdd pdf example to smartlink
Jack Miller [Wed, 29 Oct 2014 19:03:39 +0000 (14:03 -0500)]
Add pdf example to smartlink

For anyone that reads LtU =)

4 years agoUncomment smartlink opening notification
Jack Miller [Wed, 29 Oct 2014 18:55:59 +0000 (13:55 -0500)]
Uncomment smartlink opening notification

4 years agoLet pause/unpause be done from anywhere
Jack Miller [Wed, 29 Oct 2014 18:19:23 +0000 (13:19 -0500)]
Let pause/unpause be done from anywhere

- Up until smartlink the pause/unpause callbacks were only used by stuff
  directly initiated by user input, which meant that pause ... wait ...
unpause would work without anybody reading more input.

- Now that smartlink can pause from outside the input thread, there had
  to be a way to get the input thread to stop eating stdin keys.

- Unfortunately this means it needs to wake up. I tried to shift around
  the stdin fd, but I guess that doesn't work in the middle of read and
it caused all manner of nasty bugs anyway.

4 years agoMinor log readability tweaks
Jack Miller [Wed, 29 Oct 2014 05:17:05 +0000 (00:17 -0500)]
Minor log readability tweaks

4 years agoAdd "smartlink" plugin for advanced link fetching
Jack Miller [Tue, 28 Oct 2014 22:14:54 +0000 (17:14 -0500)]
Add "smartlink" plugin for advanced link fetching

- Can specify handlers for specific content either based on URL, or
  based on the output of `file` when a temporary file is downloaded.

- Regex or simple matches.

- Text and graphical handlers ok.

CAVEATS: Right now, text/"pause" handlers are a bit broken because the
pause and unpause callbacks don't work outside of the user input thread
(fetching occurs in its own thread so the interface is responsive while
a potentially slow download occurs). I'm going to have to come up with a
way to wake up the user input thread to get it to stop consuming keys,
or to pass stdin directly to the child process.

4 years agostdin should also be dup'd to /dev/null on graphical fork
Jack Miller [Tue, 28 Oct 2014 19:08:59 +0000 (14:08 -0500)]
stdin should also be dup'd to /dev/null on graphical fork

This probably doesn't cause any trouble with real graphical browsers,
but I came across this little tweak writing the smart link (aka fetch)
plugin and thought it should probably be done here too.

4 years agoSubthread reads also need to be serialized
Jack Miller [Tue, 28 Oct 2014 19:06:15 +0000 (14:06 -0500)]
Subthread reads also need to be serialized

4 years agoDefault update policy is now 'manual'
Jack Miller [Tue, 28 Oct 2014 00:03:55 +0000 (19:03 -0500)]
Default update policy is now 'manual'

Rather than have an unpredictable update cycle (i.e. not knowing when
filtered items are going to disappear, etc.), the user should
voluntarily say "I'm ready for new content"

To get old behavior, you can do

:set update.auto True

Which will return to the 20 second refresh, which can also be tweaked
with

:set update.auto.interval <number>

4 years agoRemove fetch ( to be implemented in plugin )
Jack Miller [Mon, 27 Oct 2014 23:54:39 +0000 (18:54 -0500)]
Remove fetch ( to be implemented in plugin )

5 years agoDon't print blank remote output
Jack Miller [Fri, 17 Oct 2014 20:08:16 +0000 (15:08 -0500)]
Don't print blank remote output

5 years agoRemove dead keybinds
Jack Miller [Fri, 17 Oct 2014 18:59:39 +0000 (13:59 -0500)]
Remove dead keybinds

5 years agoAdd :reset-config command to reset canto-curses settings
Jack Miller [Fri, 17 Oct 2014 18:58:43 +0000 (13:58 -0500)]
Add :reset-config command to reset canto-curses settings

5 years agoFix empty completions
Jack Miller [Fri, 17 Oct 2014 18:58:06 +0000 (13:58 -0500)]
Fix empty completions

5 years agoDon't crash on die() if window is already dead
Jack Miller [Fri, 17 Oct 2014 18:31:01 +0000 (13:31 -0500)]
Don't crash on die() if window is already dead

Resizes and other mundane stuff can cause a window to be killed and
refreshed, so if a die() is called from a command and the window isn't
being tracked by the Screen, just forget about it.

5 years agoAlias F5/^r to refresh
Jack Miller [Fri, 17 Oct 2014 18:18:44 +0000 (13:18 -0500)]
Alias F5/^r to refresh

Seems like that's what everyone expects them to do anyway...

5 years agoDon't reject unknown remote commands
Jack Miller [Fri, 17 Oct 2014 18:12:28 +0000 (13:12 -0500)]
Don't reject unknown remote commands

Daemon plugins can implement them.

5 years agoKey input flush tweak
Jack Miller [Fri, 17 Oct 2014 18:03:59 +0000 (13:03 -0500)]
Key input flush tweak

- Do it after we get key
- Don't flush if the key was RESIZE

This keeps us from losing an initial key after resize.

5 years agoAdd infobox binds to help output + title case
Jack Miller [Fri, 17 Oct 2014 17:52:50 +0000 (12:52 -0500)]
Add infobox binds to help output + title case

5 years agoClear up :help commands output
Jack Miller [Fri, 17 Oct 2014 17:49:10 +0000 (12:49 -0500)]
Clear up :help commands output

5 years agoStrip remaining old-style commands
Jack Miller [Fri, 17 Oct 2014 16:46:13 +0000 (11:46 -0500)]
Strip remaining old-style commands

5 years agoHandle missing PATH directories silently
Jack Miller [Fri, 17 Oct 2014 16:39:08 +0000 (11:39 -0500)]
Handle missing PATH directories silently

5 years agoProper URL quoting to avoid shell injection
Jack Miller [Fri, 17 Oct 2014 16:33:09 +0000 (11:33 -0500)]
Proper URL quoting to avoid shell injection

5 years agoReplace readline completion
Jack Miller [Sun, 12 Oct 2014 02:34:58 +0000 (21:34 -0500)]
Replace readline completion

It seems like I've been frustrated by readline left and fucking right.

In this case, using readline completion, the completer function gets
called to populate a list of strings. That's cool, but it gets called
every single time the displayed completion changes even if the prefix is
the same.  This falls flat on its face (in terms of performance) with
more than a few hundred completions.

I'm not sure if it's readline interacting with python that's adding so
much overhead, but if it's taking like 30 milliseconds to generate the
completions and over a second to feed it into readline, then there's a
problem.

So, I just stopped using it for completion. Since I had to subsequently
hack in custom getc support, and all of the completion generating
infrastructure was present it was pretty trivial.

If it wasn't for line-editing I'd nix the entire library gladly.

I also got rid of help text on completion because it has started to seem
useless and the hook disappeared now. :help is way better. This might
make a reappearance, however.

5 years agoProperly catch command exceptions
Jack Miller [Sat, 11 Oct 2014 01:15:12 +0000 (20:15 -0500)]
Properly catch command exceptions

Don't hold sync_lock forever if something throws an exception.

5 years agoAdd completion caching
Jack Miller [Sun, 5 Oct 2014 22:00:44 +0000 (17:00 -0500)]
Add completion caching

The PATH completion is a little intensive to do thousands of times, so
add some caching so we don't hit disk every time.