Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Add fzf support #38

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 42 additions & 18 deletions bin/dasht
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,47 @@ if test $count -eq 0; then
fi

trap 'exit 44' USR1 # exit with a nonzero status when no results are found
if ! dasht-query-html "$pattern" "$@"; then
# notify user when no results are found so they can refine their search
echo "dasht: '$pattern' not found in $count docsets matching '${*:-.*}'" >&2
if [ "$DASHT_USE_FZF" -ne 0 ]; then
url="$(if ! ./dasht-query-fzf "$pattern" "$@"; then
# notify user when no results are found so they can refine their search
echo "dasht: '$pattern' not found in $count docsets matching '${*:-.*}'" >&2

# emulate pipefail (which POSIX lacks) by killing off the w3m(1) process
# below (which starts up simultaneously alongside this pipeline segment)
kill $(ps -e -o comm,ppid,pid | sed -n "s/^w3m *$$ //p")
# emulate pipefail (which POSIX lacks) by killing off the w3m(1) process
# below (which starts up simultaneously alongside this pipeline segment)
kill $(ps -e -o comm,ppid,pid | sed -n "s/^w3m *$$ //p")

# and then proceed to tell this script to generate a nonzero exit status
kill -s USR1 $$
fi |
w3m -T text/html \
-o confirm_qq=false \
-o color=true \
-o active_style=true \
-o visited_anchor=true \
-o label_topline=true \
-o meta_refresh=true \
-o wrap_search=true \
-o ignorecase_search=true
# and then proceed to tell this script to generate a nonzero exit status
kill -s USR1 $$
fi)"
w3m -T text/html \
-o confirm_qq=false \
-o color=true \
-o active_style=true \
-o visited_anchor=true \
-o label_topline=true \
-o meta_refresh=true \
-o wrap_search=true \
-o ignorecase_search=true \
"$url"
else
if ! dasht-query-html "$pattern" "$@"; then
# notify user when no results are found so they can refine their search
echo "dasht: '$pattern' not found in $count docsets matching '${*:-.*}'" >&2

# emulate pipefail (which POSIX lacks) by killing off the w3m(1) process
# below (which starts up simultaneously alongside this pipeline segment)
kill $(ps -e -o comm,ppid,pid | sed -n "s/^w3m *$$ //p")

# and then proceed to tell this script to generate a nonzero exit status
kill -s USR1 $$
fi |
w3m -T text/html \
-o confirm_qq=false \
-o color=true \
-o active_style=true \
-o visited_anchor=true \
-o label_topline=true \
-o meta_refresh=true \
-o wrap_search=true \
-o ignorecase_search=true
fi
107 changes: 107 additions & 0 deletions bin/dasht-query-fzf
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/sh -e
#
# # DASHT-QUERY-HTML 1 2018-10-09 2.3.0
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All mentions of the old dasht-query-html should be changed to dasht-query-fzf.

#
# ## NAME
# dasht-query-html - searches [Dash] docsets and emits HTML table rows
#
# ## SYNOPSIS
#
# `dasht-query-html` [*PATTERN*] [*DOCSET*]...
#
# ### Examples
#
# `dasht-query-html`
# Topics (A-Z) from each installed docset.
#
# `dasht-query-html` 'c - x'
# Search for "c - x" in all installed docsets.
#
# `dasht-query-html` 'c - x' bash
# Search for "c - x" only in the "bash" docset.
#
# `dasht-query-html` 'c - x' bash css
# Search for "c - x" only in the "bash" and "css" docsets.
#
# ## DESCRIPTION
#
# Searches for *PATTERN* in all installed [Dash] docsets, optionally searching
# only in those whose names match *DOCSET*s, by calling dasht-query-line(1).
# The results are then printed, one per line, to stdout as HTML table rows.
# However, if no results were found, this program exits with a nonzero status.
#
# ### Searching
#
# Whitespace characters in *PATTERN* are treated as wildcards, whereas the
# SQL LIKE wildcard characters `%` and `_` are not: they are taken literally.
#
# Before searching, *PATTERN* is surrounded by whitespace wildcards so that it
# can match anywhere: beginning, middle, or end. As a result, if *PATTERN* is
# undefined, it becomes a whitespace wildcard and thereby matches everything.
#
# ## ENVIRONMENT
#
# `DASHT_DOCSETS_DIR`
# Defines the filesystem location where your [Dash] docsets are installed.
# If undefined, its value is assumed to be `$XDG_DATA_HOME/dasht/docsets/`
# or, if `XDG_DATA_HOME` is undefined, `$HOME/.local/share/dasht/docsets/`.
#
# ## EXIT STATUS
#
# 44
# No results were found.
#
# ## SEE ALSO
#
# dasht-query-line(1), dasht-docsets(1), dasht(1), [Dash]
#
# [Dash]: https://kapeli.com/dash
#
# ## AUTHOR
#
# Written in 2016 by Suraj N. Kurapati <https://github.com/sunaku/dasht>
# Distributed under the terms of the ISC license (see the LICENSE file).

trap 'exit 44' USR1 # exit with a nonzero status when no results found
{ dasht-query-line "$@" || kill -s USR1 $$ ;} | awk \
-v style_reset="$(tput sgr 0)" \
-v style_name="$(tput bold)$(tput setaf 2)" \
-v style_from="$(tput setaf 4)" \
-v style_type="$(tput setaf 3)" \
-v pattern="$1" '
# Transforms alphabetical characters into bracketed regular expressions
# that match either lowercase or uppercase versions of those characters.
# This basically emulates the IGNORECASE feature in a POSIX environment.
function ignorecase(regex) {
buf = ""
tmp = regex
while (pos = match(tmp, "[[:alpha:]]")) {
chr = substr(tmp, pos, 1)
buf = buf substr(tmp, 1, pos - 1) "[" tolower(chr) toupper(chr) "]"
tmp = substr(tmp, pos + 1)
}
return buf tmp
}
BEGIN {
gsub("[\\^.[$()|*+?{]", "\\\\&", pattern) # escape normal regex(7) syntax
sub("^[[:space:]]+", "", pattern) # strip leading whitespace
sub("[[:space:]]+$", "", pattern) # strip trailing whitespace
gsub("[[:space:]]+", ".*", pattern) # treat whitespace as wildcards
pattern = ignorecase(pattern) # emulate IGNORECASE=1 for POSIX
if (pattern == "") pattern = "^." # grouped by leading character
}
NR == 1 {}
$2 == "=" { result[$1] = substr($0, index($0, $2) + length($2) + 1) }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to share this AWK preamble (all of the lines above this one) with the dasht-query-html script to avoid copy/paste duplication. 🤔 Perhaps we can write a separate script that just does this preamble and emits the search results in an intermediate format, which the *-html and this *-fzf scripts can then transform into their final output formats.

$1 == "name" {
# mark search terms with STX and ETX bytes which are ignored by escape()
if (pattern) {
gsub(pattern, "\002&\003", result["name"])
}
}
$1 == "url" { print \
result["url"] "\t" \
style_name result["name"] style_reset " " \
style_from "[" result["from"] "]" style_reset " " \
style_type "[" result["type"] "]" style_reset
}
' | { fzf --with-nth=2,3,4 --ansi || kill -s USR1 $$ ; } | cut -f 1