Re-add FZF config
This commit is contained in:
264
fzf/fzf-at-google.zsh
Normal file
264
fzf/fzf-at-google.zsh
Normal file
@ -0,0 +1,264 @@
|
||||
# See go/fzf-at-google for more on this script.
|
||||
|
||||
export FZF_SOURCE="${HOME}/fzf-relevant-files.zsh"
|
||||
|
||||
function create_fzf_command() {
|
||||
rg --files $(${FZF_SOURCE})
|
||||
}
|
||||
|
||||
# These are weird because they're invoked via `sh -c` or something, so we need
|
||||
# to pass in the functions we use. Man this is ugly af. Also can't set one to
|
||||
# the other, they both need to be as-is. I am bad at zsh.
|
||||
export FZF_DEFAULT_COMMAND="$(functions create_fzf_command); create_fzf_command"
|
||||
export FZF_CTRL_T_COMMAND="$(functions create_fzf_command); create_fzf_command"
|
||||
export FZF_ALT_C_COMMAND="fdfind -t d . $(${FZF_SOURCE})"
|
||||
|
||||
_find_fig_workspaces() {
|
||||
hg citc -l
|
||||
}
|
||||
|
||||
_find_blaze_targets() {
|
||||
# Our tool outputs space-separated directories of interest. Convert these to a
|
||||
# list, which we'll refer to later.
|
||||
local pkg
|
||||
local cleandir
|
||||
local DIRS=( $(${FZF_SOURCE}) )
|
||||
local is_first_iteration=1
|
||||
local query=""
|
||||
|
||||
for dir in "${DIRS[@]}"; do
|
||||
# Here we want:
|
||||
# .* - match all targets
|
||||
# //foo/bar/baz/... - the blaze package we're searching under
|
||||
# Strip any leading // and trailing /. This allows more flexibility in how
|
||||
# people want to define their targets in their FZF_SOURCE file.
|
||||
# Finally we will append each directory's query together with a "+" which
|
||||
# allows us to query all targets with a single blaze query call.
|
||||
if ((is_first_iteration)); then
|
||||
is_first_iteration=0
|
||||
else
|
||||
query+=" + "
|
||||
fi
|
||||
cleandir=`echo $dir | sed 's:^//::; s:/$::'`
|
||||
pkg="//${cleandir}/..."
|
||||
query+="filter(.*, ${pkg})"
|
||||
done
|
||||
|
||||
# We shunt 2>/dev/null to silence its info output, which for some reason
|
||||
# comes out on stderr. This isn't ideal, because we'll swallow real errors.
|
||||
# Looking at `blaze help query`, I can't find any options to turn this off.
|
||||
# `--logging=0` doesn't do it; `--show_loading_progress=false` doesn't do
|
||||
# it.
|
||||
# --keep_going is required in case any of the pkgs have no subtargets, if not
|
||||
# provided the query will exit before evaluating other pkgs.
|
||||
blaze query --keep_going "${query}" 2> /dev/null
|
||||
}
|
||||
|
||||
|
||||
# fzf completion for blaze targets beneath the current directory. Works on
|
||||
# programs that use the blaze CLI eg:
|
||||
#
|
||||
# blaze build **<TAB>
|
||||
# rabbit build **<TAB>
|
||||
# iblaze build **<TAB>
|
||||
#
|
||||
# Syntax for this style of completion is taken from:
|
||||
# https://github.com/junegunn/fzf/wiki/Examples-(completion)#writing-custom-fuzzy-completion
|
||||
_fzf_complete_blaze() {
|
||||
_fzf_complete "" "$@" < <(_find_blaze_targets)
|
||||
}
|
||||
alias _fzf_complete_rabbit="_fzf_complete_blaze"
|
||||
alias _fzf_complete_iblaze="_fzf_complete_blaze"
|
||||
|
||||
_fzf_complete_hgd() {
|
||||
_fzf_complete "" "$@" < <(_find_fig_workspaces)
|
||||
}
|
||||
|
||||
# fzf completion of blaze targets for `hg blaze` and `rabbit` commands. eg:
|
||||
#
|
||||
# hg blaze -r . -- test **<TAB>
|
||||
#
|
||||
_fzf_complete_hg() {
|
||||
ARGS="$@"
|
||||
if [[ $ARGS == 'hg blaze'* ]] || [[ $ARGS == 'hg rabbit'* ]]; then
|
||||
_fzf_complete "" "$@" < <(_find_blaze_targets)
|
||||
elif [[ $ARGS == 'hg citc -d'* ]]; then
|
||||
_fzf_complete "" "$@" < <(_find_fig_workspaces)
|
||||
else
|
||||
eval "zle ${fzf_default_completion:-expand-or-complete}"
|
||||
fi
|
||||
}
|
||||
|
||||
# fzf completion for chrome build targets. eg:
|
||||
#
|
||||
# autoninja -C out/Debug **<TAB>
|
||||
#
|
||||
_fzf_complete_autoninja() {
|
||||
# ${BUFFER} contains all the arguments passed to the command. We assume that
|
||||
# one will be the directory containing the ninja files, and that it begins
|
||||
# with `out/`. It might not be the last command, so we can't use positional
|
||||
# arguments. We'll use rg. No line numbers (`--no-line-number`), print only
|
||||
# the matching part (`-o`).
|
||||
NINJA_DIR="$(echo ${BUFFER} | rg --no-line-number -o 'out/\w*')"
|
||||
|
||||
# We assume that the file is then in `${NINJA_DIR}/build.ninja`. Note that
|
||||
# we're assuming we're not passing with a trailing slash.
|
||||
BUILD_FILE=${NINJA_DIR}/build.ninja
|
||||
|
||||
_fzf_complete "" "$@" < <(
|
||||
# The lines we want look like:
|
||||
#
|
||||
# build target_name: blah something/else.stamp
|
||||
#
|
||||
# Grab those lines.
|
||||
rg --no-line-number "^build \w*:" ${BUILD_FILE} | \
|
||||
# Print the second token, which is `target_name:`.
|
||||
awk ' { print $2 } ' | \
|
||||
# Strip the colon.
|
||||
sed s/://g
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
# This generates a list of flags that have previously been used in history
|
||||
# commands, trying to intelligently parse values for reuse on the prompt. For
|
||||
# example, with the following history entry files (as shown on zsh):
|
||||
#
|
||||
# 1 foo --test --bar=val
|
||||
# 2 foo -f 123 --bar val
|
||||
#
|
||||
# `_find_flags foo` should return:
|
||||
#
|
||||
# --test
|
||||
# --bar
|
||||
# --bar=val
|
||||
# -f
|
||||
# -f 123
|
||||
# --bar val
|
||||
_find_flags() {
|
||||
# $1 is passed to the function and should be the command.
|
||||
local match_prefix=$1
|
||||
fc -rl 1 | \
|
||||
# strip leading command number and trailing slashes. Trailing slashes
|
||||
# somehow confuse fzf or the do while.
|
||||
sed -e 's/^\s*[0-9]*\*\?\s*//' -e 's/\\\+$//' | \
|
||||
rg "^${match_prefix}" --color=never --no-line-number |
|
||||
awk -v match_prefix=${match_prefix} ' { for (i = 1; i <= NF; i++) {
|
||||
flag = ""
|
||||
is_value = ""
|
||||
maybe_value = ""
|
||||
|
||||
if ($i ~ /^\\\\n/) {
|
||||
# Then this begins might be the first line after a continuation and begin
|
||||
# like "\\n--foo". We want this to be interpreted as if fresh, without a new
|
||||
# line.
|
||||
$i = gensub(/^\\\\n/, "", "g", $i)
|
||||
}
|
||||
|
||||
if ($i ~ /^--?[a-zA-Z0-9]/) {
|
||||
# Then it looks like a flag.
|
||||
split($i, parts, "=")
|
||||
if (parts[2] != "") {
|
||||
# It is something like --flag=value
|
||||
flag = parts[1]
|
||||
is_value = parts[2]
|
||||
} else {
|
||||
# It is something like -f, and might be -f val.
|
||||
flag = $i
|
||||
maybe_value = $(i+1)
|
||||
if (maybe_value ~ /^\\\\n/) {
|
||||
# Then we probably consumed the next line in a line continuation.
|
||||
# Newlines in output will confuse a later process, so remove this.
|
||||
maybe_value = gensub(/^\\\\n/, "", "g", maybe_value)
|
||||
}
|
||||
if (maybe_value ~ /^--?[a-zA-Z0-9]/) {
|
||||
# Then we probably consumed another flag, eg `--foo` from
|
||||
# `--foo --bar=val`. Reset to empty string so we do not print that as an
|
||||
# option, as if `-foo` took the value `--bar=val`.
|
||||
maybe_value = ""
|
||||
}
|
||||
}
|
||||
|
||||
# Colorize the part that we will not match in the output to make clear
|
||||
# we are matching only the leading flags.
|
||||
cmd_with_color = "\033[0;35m" $0 "\033[0m"
|
||||
|
||||
# A note on the \xC2\xA0 strings here: we want a nbsp before the command so
|
||||
# that we can split easily and pull out the flag rather than the entire
|
||||
# line. This also allows us to tell fzf --nth and select only the first
|
||||
# column to search on. This is the nbsp notation that awk is able to output.
|
||||
# Fzf wants a \u00a0 format, which we use elsehwere, but note that these are
|
||||
# the same character.
|
||||
if (flag != "") {
|
||||
# Then we parsed a flag.
|
||||
|
||||
# Print the flag itself.
|
||||
if (seen_arr[flag] != 1) {
|
||||
seen_arr[flag] = 1
|
||||
print flag "\xC2\xA0" cmd_with_color
|
||||
}
|
||||
|
||||
if (is_value != "") {
|
||||
# The whole token is a valid value.
|
||||
if (seen_arr[$i] != 1) {
|
||||
seen_arr[$i] = 1
|
||||
print $i "\xC2\xA0" cmd_with_color
|
||||
}
|
||||
}
|
||||
if (maybe_value != "") {
|
||||
# We guessed at a value.
|
||||
output_with_guessed_value = flag " " maybe_value
|
||||
if (seen_arr[output_with_guessed_value] != 1) {
|
||||
seen_arr[output_with_guessed_value] = 1
|
||||
print flag " " maybe_value "\xC2\xA0 " cmd_with_color
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}'
|
||||
|
||||
}
|
||||
|
||||
# CTRL-Q - Paste the selected flags into the command line. Copied from CTRL-T
|
||||
# bindings shown here:
|
||||
# https://github.com/junegunn/fzf/blob/master/shell/key-bindings.zsh
|
||||
__flagsel() {
|
||||
# Normally, BUFFER is adequate. However, if we're in a line continutation, as
|
||||
# indicated by CONTEXT=cont, we want PREBUFFER:
|
||||
# https://linux.die.net/man/1/zshzle.
|
||||
local buffer_with_start_of_cmd=${BUFFER}
|
||||
if [[ $CONTEXT == "cont" ]]; then
|
||||
buffer_with_start_of_cmd=${PREBUFFER}
|
||||
fi
|
||||
# echo "bwsoc: |${buffer_with_start_of_cmd}|"
|
||||
# First we tr to remove new lines. and whitespace, which can trip us up on
|
||||
# multiline input like continuations. Then we use sed to replace white space
|
||||
# with space, which we will use as our delimiter to cut.
|
||||
local match_prefix=`echo ${buffer_with_start_of_cmd} | tr "\n" " " | sed -e "s/[[:space:]]\+/ /g" -e "s/\n/ /g" | cut -d ' ' -f 1`
|
||||
local cmd="_find_flags ${match_prefix}"
|
||||
setopt localoptions pipefail no_aliases 2> /dev/null
|
||||
local item
|
||||
# Need to set this outside the surrounding string to enable $'' notation so
|
||||
# fzf is able to interpret the delimiter correctly.
|
||||
local delimiter_arg=$'--delimiter \u00a0'
|
||||
eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --prompt='${match_prefix}> ' ${delimiter_arg} --nth 1 --reverse --multi --ansi $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS" $(__fzfcmd) -m "$@" | while read item; do
|
||||
echo -n "${item}" | awk -F '\xC2\xA0' '{ if (NF > 1) { printf "%s ", $1 } }'
|
||||
done
|
||||
local ret=$?
|
||||
echo
|
||||
return $ret
|
||||
}
|
||||
|
||||
fzf-flag-widget() {
|
||||
LBUFFER="${LBUFFER}$(__flagsel)"
|
||||
local ret=$?
|
||||
zle reset-prompt
|
||||
return $ret
|
||||
}
|
||||
zle -N fzf-flag-widget
|
||||
bindkey '^F' fzf-flag-widget
|
||||
bindkey '^T' fzf-file-widget
|
||||
bindkey '^R' fzf-history-widget
|
48
fzf/fzf-relevant-files.zsh
Executable file
48
fzf/fzf-relevant-files.zsh
Executable file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/zsh
|
||||
setopt extended_glob
|
||||
|
||||
# See go/fzf-at-google for more on this script.
|
||||
#
|
||||
# Thanks to yoongu@, smithian@ and others for help with the approach. See this
|
||||
# discussion for more history:
|
||||
#
|
||||
# https://groups.google.com/a/google.com/g/zsh-users/c/gLVYmwSy_lg/m/x6wnesDFCAAJ
|
||||
|
||||
# This prints paths we care about. Source it with $(${path_to_file}) and then
|
||||
# feed it to FZF. This assumes that the content will be passed to `rg`, which
|
||||
# means it does things like recursively search the current working directory by
|
||||
# default.
|
||||
|
||||
# These are relative to google3.
|
||||
#
|
||||
# NOTE: These are examples relevant to my own projects. Change replace them with
|
||||
# your own.
|
||||
RELEVANT_FILE_PATHS=(
|
||||
"experimental/users/$USER"
|
||||
"java/com/google/android/gmscore/integ"
|
||||
"javatests/com/google/android/gmscore/integ"
|
||||
)
|
||||
|
||||
SEARCH_REL_PATHS=()
|
||||
|
||||
# If we are in a google3 directory, use our relevant files. Otherwise, assume
|
||||
# we're in something like ~/dotfiles and return everything since we don't need
|
||||
# to be smart.
|
||||
if [[ $PWD == (#b)(/google/src/cloud/${USER}/[^/]##/google3)* ]]; then
|
||||
# Get the google3 absolute path as a backreference (#b).
|
||||
GOOGLE3_ABS_PATH=${match[1]}
|
||||
# Prepend google3 to get absolute whitelists.
|
||||
WHITELIST_ABS_PATHS=(${RELEVANT_FILE_PATHS/#/${GOOGLE3_ABS_PATH}/})
|
||||
# We only search a path if it's either the PWD or descended from it.
|
||||
SEARCH_ABS_PATH=(${(M)WHITELIST_ABS_PATHS:#${PWD}(|/*)})
|
||||
# Remove hte leading / as well
|
||||
SEARCH_REL_PATHS=(${SEARCH_ABS_PATH/${PWD}\//})
|
||||
fi
|
||||
|
||||
# Default to searching the PWD.
|
||||
if [[ ${#SEARCH_REL_PATHS} == 0 ]]; then
|
||||
SEARCH_REL_PATHS=("")
|
||||
fi
|
||||
|
||||
echo $SEARCH_REL_PATHS
|
||||
|
Reference in New Issue
Block a user