mostly replace wcd with self made script
[distro-setup] / brc
diff --git a/brc b/brc
index 2a770ae0e416297add55e9293f1779907f44681e..b0f8846bef148f95392839e8e32808ef66893b54 100644 (file)
--- a/brc
+++ b/brc
@@ -259,11 +259,6 @@ if [[ $SOE ]]; then
   fi
 fi
 
-# based on readme.debian. dunno if this will break on other distros.
-if [[ -s /usr/share/wcd/wcd-include.sh ]]; then
-  source /usr/share/wcd/wcd-include.sh
-fi
-
 
 mysrc() {
   local path dir file
@@ -391,11 +386,6 @@ for num in {1..9}; do
 done
 
 
-b() {
-  # backwards
-  c -
-}
-
 hexipv4() {
   printf '%d.%d.%d.%d\n' $(echo $1 | sed 's/../0x& /g')
 }
@@ -425,21 +415,222 @@ utcl() { # utc 24 hour time to local hour 24 hour time
   echo "print( ($1  $(date +%z | sed -r 's/..$//;s/^(-?)0*/\1/')) % 24)"|python3
 }
 
-# c. better cd
-if ! type -t c &>/dev/null; then
-  if type -p wcd &>/dev/null; then
-    if [[ $LC_INSIDE_EMACS ]]; then
-      c() { wcd -c -z 50 -o "$@"; }
-    else
-      # lets see what the fancy terminal does from time to time
-      c() { wcd -c -z 50 "$@"; }
+declare -a _iankdirf _iankdirb
+
+
+# ## old wcd, to be deleted
+# b() {
+#   # backwards
+#   c -
+# }
+# # shellcheck disable=SC2032
+# f() {
+#   # cd forward
+#   c +
+# }
+# cl() {
+#   # choose recent directory. cl = cd list
+#   c =
+# }
+# # c. better cd
+# if ! type -t c &>/dev/null; then
+#   if type -p wcd &>/dev/null; then
+#     if [[ $LC_INSIDE_EMACS ]]; then
+#       c() { wcd -c -z 50 -o "$@"; }
+#     else
+#       # lets see what the fancy terminal does from time to time
+#       c() { wcd -c -z 50 "$@"; }
+#     fi
+#   else
+#     c() { cd "$@"; }
+#   fi
+# fi
+
+# c. better cd.
+# keep 2 stacks, forward and back. the top of the back is $PWD
+# as long as the last directory change was due to c,b,or cl.
+c() {
+  # normally, the top of dirb is our current dir. if it isn't,
+  # put it on there, except we don't want to do that when we
+  # just launched a shell
+  if [[ $OLDPWD ]]; then
+    if (( ${#_iankdirb[@]} == 0 )) || [[ ${_iankdirb[-1]} != "$PWD" ]]; then
+      _iankdirb+=("$PWD")
     fi
-  else
-    c() { cd "$@"; }
   fi
-fi
+  cd "$@"
+  if (( ${#_iankdirb[@]} == 0 )) || [[ ${_iankdirb[-1]} != "$PWD" ]]; then
+    _iankdirb+=("$PWD")
+  fi
+  echo "$PWD" >> ~/.iankdirs
+}
 ccomp cd c
 
+b() {
+  local topb
+  if (( ${#_iankdirb[@]} == 0 )); then
+    echo "nothing left to go back to" >&2
+    return 0
+  fi
+  topb="${_iankdirb[-1]}"
+
+  if [[ $topb == "$PWD" ]] && (( ${#_iankdirb[@]} == 1 )); then
+    echo "already on last back entry" >&2
+    return 0
+  fi
+
+
+  if [[ $topb == "$PWD" ]]; then
+    # add to dirf if not already there
+    if (( ${#_iankdirf[@]} == 0 )) || [[ ${_iankdirf[-1]} != "$topb" ]]; then
+      _iankdirf+=("$topb")
+    fi
+    unset "_iankdirb[-1]"
+    cd "${_iankdirb[-1]}"
+  else
+    if (( ${#_iankdirf[@]} == 0 )) || [[ ${_iankdirf[-1]} != "$PWD" ]]; then
+      _iankdirf+=("$PWD")
+    fi
+    cd "$topb"
+  fi
+
+  # give us a peek at what is next in the list
+  # if (( ${#_iankdirb[@]} >= 2 )); then
+  #   printf "%s\n" "${_iankdirb[-2]}"
+  # fi
+}
+
+f() {
+  local topf
+  if (( ${#_iankdirf[@]} == 0 )); then
+    echo "no forward dir left" >&2
+    return 0
+  fi
+  topf="${_iankdirf[-1]}"
+  unset "_iankdirf[-1]"
+  c "$topf"
+
+  # give us a peek at what is next in the list
+  # if (( ${#_iankdirf[@]} )); then
+  #   printf "%s\n" "${_iankdirf[-1]}"
+  # fi
+}
+
+# a b c (d)
+## back
+# a b (c)
+# d
+#back
+#a (b)
+#d c
+#back
+#(a)
+#d c b
+#forward
+#a (b)
+#d c
+#
+# a b c
+## back
+# a b
+# (c)
+## forward
+
+cl() {
+  local i line input start tmpfile
+  local -A buttondirs alines
+  local -a buttons dirs lines
+  buttons=( {a..z} {2..9} )
+  if [[ ! -s ~/.iankdirs ]]; then
+    echo nothing in ~/.iankdirs
+    return 0
+  fi
+
+  i=0
+
+  # note, alternate approach like this, made the following read fail
+  # done < <(tac ~/.iankdirs | awk '!seen[$0]++')
+  # bash: read: read error: 0: Input/output error
+  # which went away by adding a sleep 1 after it.
+
+  mapfile -t lines <~/.iankdirs
+  start=$(( ${#lines[@]} - 1 ))
+
+  # we have ~33 buttons as of this writing, so lets
+  # prune down the history every once in a while.
+  if (( start > 500 )); then
+    tmpfile=$(mktemp)
+    tac ~/.iankdirs | awk '!seen[$0]++' | head -n 200 >$tmpfile
+    cat $tmpfile > ~/.iankdirs
+  fi
+
+  for (( j=$start; j >= 0; j-- )); do
+    line="${lines[$j]}"
+    if [[ ! $line || ${alines[$line]} || ! -d "$line" || $line == "$PWD" || line == "$HOME"  ]]; then
+      continue
+    fi
+    alines[$line]=t
+    buttondirs[${buttons[i]}]="$line"
+    printf "%s %s\n" ${buttons[i]} "$line"
+    if (( i == ${#buttons[@]} - 1 )); then
+      break
+    fi
+    i=$(( i + 1 ))
+  done
+
+  if (( i == 0 )); then
+    echo "no dirs in ~/.iankdirs"
+    return 0
+  fi
+  read -r -N 1 input
+  if [[ $input != $'\n' ]]; then
+    c ${buttondirs[$input]}
+  fi
+}
+bl() {
+  local start i j max
+  max=10
+  start=$(( ${#_iankdirb[@]} - 1 ))
+
+  # cleanup possible repeating of pwd
+  if (( start >= 0 )) && [[ ${_iankdirb[$start]} == "$PWD" ]]; then
+    start=$(( start - 1 ))
+  fi
+  j=1
+  if (( start >= 0 )); then
+    for (( i=$start; i >= 0 ; i-- )); do
+      printf "%s %s\n" $j ${_iankdirb[i]}
+      j=$(( j + 1 ))
+      if (( j >= max )); then
+        break
+      fi
+    done
+  fi
+
+  max=10
+
+  start=$(( ${#_iankdirf[@]} - 1 ))
+
+  # cleanup possible repeating of pwd
+  if (( start >= 0 )) && [[ ${_iankdirf[$start]} == "$PWD" ]]; then
+    start=$(( start - 1 ))
+  fi
+  if (( start < 0 )); then
+    return 0
+  fi
+  echo --
+  j=1
+  for (( i=$start; i >= 0 ; i-- )); do
+    printf "%s %s\n" $j ${_iankdirf[i]}
+    j=$(( j + 1 ))
+    if (( j >= max )); then
+      break
+    fi
+  done
+}
+
+
+
 c4() { c /var/log/exim4; }
 
 caa() { git commit --amend --no-edit -a; }
@@ -544,8 +735,8 @@ cdiff() {
 cat-new-files() {
   local start=$SECONDS
   local dir="$1"
-  inotifywait -m "$dir" -e create -e moved_to |
-    # shellcheck disable=SC2030
+  # shellcheck disable=SC2030
+  inotifywait -m "$dir" -e create -e moved_to | \
     while read -r filedir _ file; do
       cat "$filedir$file"
       hr
@@ -571,10 +762,6 @@ cim() {
   git commit -m "$*"
 }
 
-cl() {
-  # choose recent directory. cl = cd list
-  c =
-}
 
 d() { builtin bg "$@"; }
 ccomp bg d
@@ -757,11 +944,6 @@ econfdev() {
 
 
 
-# shellcheck disable=SC2032
-f() {
-  # cd forward
-  c +
-}
 
 fa() {
   # find array. make an array of file names found by find into $x
@@ -778,18 +960,6 @@ faf() { # find all files. use -L to follow symlinks
        -o -name .undo-tree-history -prune \) -type f 2>/dev/null
 }
 
-# todo: id like to do maybe a daily or hourly cronjob to
-# check that my history file size is increasing. Ive had it
-# inexplicably truncated in the past.
-histrm() {
-  history -n
-  history | awk -v IGNORECASE=1 '{ a=$1; sub(/^( *[^ ]+){4} */, "") }; /'"$*"'/'
-  read -p "press anything but contrl-c to delete"
-  for entry in $(history | awk -v IGNORECASE=1 '{ a=$1; sub(/^( *[^ ]+){4} */, "") }; /'"$*"'/ { print a }' | tac); do
-    history -d $entry
-  done
-  history -w
-}
 
 # mail related
 frozen() {
@@ -1144,10 +1314,28 @@ lower() { # make first letter of filenames lowercase.
 k() { # history search
   grep -iP --binary-files=text "$@" ${HISTFILE:-~/.bash_history}  | tail -n 80 || [[ $? == 1 ]];
 }
-ks() { # history search
+ks() { # history search with context
+  # args are an extended regex used by sed
+  history | sed -nr "h;s/^\s*(\S+\s+){4}//;/$*/{g;p}" | tail -n 80 || [[ $? == 1 ]];
+}
+ksu() { # history search unique
   grep -P --binary-files=text "$@" ${HISTFILE:-~/.bash_history}  | uniq || [[ $? == 1 ]];
 }
-ccomp grep k ks
+
+# todo: id like to do maybe a daily or hourly cronjob to
+# check that my history file size is increasing. Ive had it
+# inexplicably truncated in the past.
+histrm() {
+  history -n
+  HISTTIMEFORMAT= history | awk -v IGNORECASE=1 '{ a=$1; sub(/^ *[^ ]+ */, "") }; /'"$*"'/'
+  read -p "press anything but contrl-c to delete"
+  for entry in $(HISTTIMEFORMAT= history | awk -v IGNORECASE=1 '{ a=$1; sub(/^ *[^ ]+ */, "") }; /'"$*"'/ { print a }' | tac); do
+    history -d $entry
+  done
+  history -w
+}
+
+ccomp grep k ks ksu histrm
 
 
 make-targets() {