initial
[zsh.git] / .zsh / plugins / per-directory-history.plugin.zsh
1 #!/usr/bin/env zsh
2 #
3 # This is a implementation of per directory history for zsh, some
4 # implementations of which exist in bash[1,2]. It also implements
5 # a per-directory-history-toggle-history function to change from using the
6 # directory history to using the global history. In both cases the history is
7 # always saved to both the global history and the directory history, so the
8 # toggle state will not effect the saved histories. Being able to switch
9 # between global and directory histories on the fly is a novel feature as far
10 # as I am aware.
11 #
12 #-------------------------------------------------------------------------------
13 # Configuration
14 #-------------------------------------------------------------------------------
15 #
16 # HISTORY_BASE a global variable that defines the base directory in which the
17 # directory histories are stored
18 #
19 #-------------------------------------------------------------------------------
20 # History
21 #-------------------------------------------------------------------------------
22 #
23 # The idea/inspiration for a per directory history is from Stewart MacArthur[1]
24 # and Dieter[2], the implementation idea is from Bart Schaefer on the the zsh
25 # mailing list[3]. The implementation is by Jim Hester in September 2012.
26 #
27 # [1]: http://www.compbiome.com/2010/07/bash-per-directory-bash-history.html
28 # [2]: http://dieter.plaetinck.be/per_directory_bash
29 # [3]: http://www.zsh.org/mla/users/1997/msg00226.html
30 #
31 ################################################################################
32 #
33 # Copyright (c) 2012 Jim Hester
34 #
35 # This software is provided 'as-is', without any express or implied warranty.
36 # In no event will the authors be held liable for any damages arising from the
37 # use of this software.
38 #
39 # Permission is granted to anyone to use this software for any purpose,
40 # including commercial applications, and to alter it and redistribute it
41 # freely, subject to the following restrictions:
42 #
43 # 1. The origin of this software must not be misrepresented; you must not claim
44 # that you wrote the original software. If you use this software in a product,
45 # an acknowledgment in the product documentation would be appreciated but is
46 # not required.
47 #
48 # 2. Altered source versions must be plainly marked as such, and must not be
49 # misrepresented as being the original software.
50 #
51 # 3. This notice may not be removed or altered from any source distribution..
52 #
53 ################################################################################
54
55 #-------------------------------------------------------------------------------
56 # configuration, the base under which the directory histories are stored
57 #-------------------------------------------------------------------------------
58
59 [[ -z $HISTORY_BASE ]] && HISTORY_BASE="$HOME/.directory_history"
60
61 #-------------------------------------------------------------------------------
62 # toggle global/directory history used for searching - ctrl-G by default
63 #-------------------------------------------------------------------------------
64
65 function per-directory-history-toggle-history() {
66 if [[ $_per_directory_history_is_global == true ]]; then
67 _per-directory-history-set-directory-history
68 print "\nusing local history\n"
69 else
70 _per-directory-history-set-global-history
71 print "\nusing global history\n"
72 fi
73 zle .push-line
74 zle .accept-line
75 }
76
77 autoload per-directory-history-toggle-history
78 zle -N per-directory-history-toggle-history
79 bindkey '^G' per-directory-history-toggle-history
80
81 #-------------------------------------------------------------------------------
82 # implementation details
83 #-------------------------------------------------------------------------------
84
85 _per_directory_history_directory="$HISTORY_BASE${PWD:A}/history"
86
87 function _per-directory-history-change-directory() {
88 _per_directory_history_directory="$HISTORY_BASE${PWD:A}/history"
89 mkdir -p ${_per_directory_history_directory:h}
90 if [[ $_per_directory_history_is_global == false ]]; then
91 #save to the global history
92 fc -AI $HISTFILE
93 #save history to previous file
94 local prev="$HISTORY_BASE${OLDPWD:A}/history"
95 mkdir -p ${prev:h}
96 fc -AI $prev
97
98 #discard previous directory's history
99 local original_histsize=$HISTSIZE
100 HISTSIZE=0
101 HISTSIZE=$original_histsize
102
103 #read history in new file
104 if [[ -e $_per_directory_history_directory ]]; then
105 fc -R $_per_directory_history_directory
106 fi
107 fi
108 }
109
110 function _per-directory-history-addhistory() {
111 print -sr -- ${1%%$'\n'}
112 fc -p $_per_directory_history_directory
113 }
114
115
116 function _per-directory-history-set-directory-history() {
117 if [[ $_per_directory_history_is_global == true ]]; then
118 fc -AI $HISTFILE
119 local original_histsize=$HISTSIZE
120 HISTSIZE=0
121 HISTSIZE=$original_histsize
122 if [[ -e "$_per_directory_history_directory" ]]; then
123 fc -R "$_per_directory_history_directory"
124 fi
125 fi
126 _per_directory_history_is_global=false
127 }
128 function _per-directory-history-set-global-history() {
129 if [[ $_per_directory_history_is_global == false ]]; then
130 fc -AI $_per_directory_history_directory
131 local original_histsize=$HISTSIZE
132 HISTSIZE=0
133 HISTSIZE=$original_histsize
134 if [[ -e "$HISTFILE" ]]; then
135 fc -R "$HISTFILE"
136 fi
137 fi
138 _per_directory_history_is_global=true
139 }
140
141
142 #add functions to the exec list for chpwd and zshaddhistory
143 chpwd_functions=(${chpwd_functions[@]} "_per-directory-history-change-directory")
144 zshaddhistory_functions=(${zshaddhistory_functions[@]} "_per-directory-history-addhistory")
145
146 #start in directory mode
147 mkdir -p ${_per_directory_history_directory:h}
148 _per_directory_history_is_global=false
149 _per-directory-history-set-global-history