mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-14 06:13:47 -05:00
Compare commits
27 Commits
0.24.0-rc1
...
0.24.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
722d66e85a | ||
|
|
f6269f0193 | ||
|
|
520eae817a | ||
|
|
d099941360 | ||
|
|
e3e76fa8c5 | ||
|
|
2553806e79 | ||
|
|
1bcbc5a353 | ||
|
|
15d351b0f0 | ||
|
|
c144c95cda | ||
|
|
f08f4fd87d | ||
|
|
f8aaeef218 | ||
|
|
7915e365b3 | ||
|
|
1c68f81c37 | ||
|
|
d4c9db0a27 | ||
|
|
b5e0e29ec6 | ||
|
|
569be4c6c9 | ||
|
|
e7ca237b07 | ||
|
|
a7d3b72117 | ||
|
|
3ba7b5cf2d | ||
|
|
254e9765fe | ||
|
|
3304f284a5 | ||
|
|
0d5f862daf | ||
|
|
51dfacd542 | ||
|
|
c691d52fa7 | ||
|
|
de3d09fe79 | ||
|
|
eaa413c566 | ||
|
|
407205e52b |
22
BUILD.md
22
BUILD.md
@@ -17,21 +17,19 @@ make
|
|||||||
# Build fzf binary and copy it to bin directory
|
# Build fzf binary and copy it to bin directory
|
||||||
make install
|
make install
|
||||||
|
|
||||||
# Build 32-bit and 64-bit executables and tarballs in target
|
# Build fzf binaries and archives for all platforms using goreleaser
|
||||||
|
make build
|
||||||
|
|
||||||
|
# Publish GitHub release
|
||||||
make release
|
make release
|
||||||
|
|
||||||
# Make release archives for all supported platforms in target
|
|
||||||
make release-all
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using `go get`
|
> :warning: Makefile uses git commands to determine the version and the
|
||||||
|
> revision information for `fzf --version`. So if you're building fzf from an
|
||||||
Alternatively, you can build fzf directly with `go get` command without
|
> environment where its git information is not available, you have to manually
|
||||||
manually cloning the repository.
|
> set `$FZF_VERSION` and `$FZF_REVISION`.
|
||||||
|
>
|
||||||
```sh
|
> e.g. `FZF_VERSION=0.24.0 FZF_REVISION=tarball make`
|
||||||
go get -u github.com/junegunn/fzf
|
|
||||||
```
|
|
||||||
|
|
||||||
Third-party libraries used
|
Third-party libraries used
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|||||||
35
CHANGELOG.md
35
CHANGELOG.md
@@ -1,6 +1,22 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
0.24.3
|
||||||
|
------
|
||||||
|
- Added `--padding` option
|
||||||
|
```sh
|
||||||
|
fzf --margin 5% --padding 5% --border --preview 'cat {}' \
|
||||||
|
--color bg:#222222,preview-bg:#333333
|
||||||
|
```
|
||||||
|
|
||||||
|
0.24.2
|
||||||
|
------
|
||||||
|
- Bug fixes and improvements
|
||||||
|
|
||||||
|
0.24.1
|
||||||
|
------
|
||||||
|
- Fixed broken `--color=[bw|no]` option
|
||||||
|
|
||||||
0.24.0
|
0.24.0
|
||||||
------
|
------
|
||||||
- Real-time rendering of preview window
|
- Real-time rendering of preview window
|
||||||
@@ -29,6 +45,24 @@ CHANGELOG
|
|||||||
```
|
```
|
||||||
- More `--border` options
|
- More `--border` options
|
||||||
- `vertical`, `top`, `bottom`, `left`, `right`
|
- `vertical`, `top`, `bottom`, `left`, `right`
|
||||||
|
- Updated Vim plugin to use these new `--border` options
|
||||||
|
```vim
|
||||||
|
" Floating popup window in the center of the screen
|
||||||
|
let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } }
|
||||||
|
|
||||||
|
" Popup with 100% width
|
||||||
|
let g:fzf_layout = { 'window': { 'width': 1.0, 'height': 0.5, 'border': 'horizontal' } }
|
||||||
|
|
||||||
|
" Popup with 100% height
|
||||||
|
let g:fzf_layout = { 'window': { 'width': 0.5, 'height': 1.0, 'border': 'vertical' } }
|
||||||
|
|
||||||
|
" Similar to 'down' layout, but it uses a popup window and doesn't affect the window layout
|
||||||
|
let g:fzf_layout = { 'window': { 'width': 1.0, 'height': 0.5, 'yoffset': 1.0, 'border': 'top' } }
|
||||||
|
|
||||||
|
" Opens on the right;
|
||||||
|
" 'highlight' option is still supported but it will only take the foreground color of the group
|
||||||
|
let g:fzf_layout = { 'window': { 'width': 0.5, 'height': 1.0, 'xoffset': 1.0, 'border': 'left', 'highlight': 'Comment' } }
|
||||||
|
```
|
||||||
- To indicate if `--multi` mode is enabled, fzf will print the number of
|
- To indicate if `--multi` mode is enabled, fzf will print the number of
|
||||||
selected items even when no item is selected
|
selected items even when no item is selected
|
||||||
```sh
|
```sh
|
||||||
@@ -39,6 +73,7 @@ CHANGELOG
|
|||||||
seq 100 | fzf --multi 5
|
seq 100 | fzf --multi 5
|
||||||
# 100/100 (0/5)
|
# 100/100 (0/5)
|
||||||
```
|
```
|
||||||
|
- Since 0.24.0, release binaries will be uploaded to https://github.com/junegunn/fzf/releases
|
||||||
|
|
||||||
0.23.1
|
0.23.1
|
||||||
------
|
------
|
||||||
|
|||||||
65
Makefile
65
Makefile
@@ -5,9 +5,26 @@ MAKEFILE := $(realpath $(lastword $(MAKEFILE_LIST)))
|
|||||||
ROOT_DIR := $(shell dirname $(MAKEFILE))
|
ROOT_DIR := $(shell dirname $(MAKEFILE))
|
||||||
SOURCES := $(wildcard *.go src/*.go src/*/*.go) $(MAKEFILE)
|
SOURCES := $(wildcard *.go src/*.go src/*/*.go) $(MAKEFILE)
|
||||||
|
|
||||||
VERSION := $(shell git describe --abbrev=0)
|
ifdef FZF_VERSION
|
||||||
REVISION := $(shell git log -n 1 --pretty=format:%h -- $(SOURCES))
|
VERSION := $(FZF_VERSION)
|
||||||
BUILD_FLAGS := -a -ldflags "-X main.version=$(VERSION) -X main.revision=$(REVISION) -w '-extldflags=$(LDFLAGS)'" -tags "$(TAGS)"
|
else
|
||||||
|
VERSION := $(shell git describe --abbrev=0 2> /dev/null)
|
||||||
|
endif
|
||||||
|
ifeq ($(VERSION),)
|
||||||
|
$(error Not on git repository; cannot determine $$FZF_VERSION)
|
||||||
|
endif
|
||||||
|
VERSION_TRIM := $(shell sed "s/-.*//" <<< $(VERSION))
|
||||||
|
VERSION_REGEX := $(subst .,\.,$(VERSION_TRIM))
|
||||||
|
|
||||||
|
ifdef FZF_REVISION
|
||||||
|
REVISION := $(FZF_REVISION)
|
||||||
|
else
|
||||||
|
REVISION := $(shell git log -n 1 --pretty=format:%h -- $(SOURCES) 2> /dev/null)
|
||||||
|
endif
|
||||||
|
ifeq ($(REVISION),)
|
||||||
|
$(error Not on git repository; cannot determine $$FZF_REVISION)
|
||||||
|
endif
|
||||||
|
BUILD_FLAGS := -a -ldflags "-s -w -X main.version=$(VERSION) -X main.revision=$(REVISION)" -tags "$(TAGS)"
|
||||||
|
|
||||||
BINARY64 := fzf-$(GOOS)_amd64
|
BINARY64 := fzf-$(GOOS)_amd64
|
||||||
BINARYARM5 := fzf-$(GOOS)_arm5
|
BINARYARM5 := fzf-$(GOOS)_arm5
|
||||||
@@ -15,7 +32,6 @@ BINARYARM6 := fzf-$(GOOS)_arm6
|
|||||||
BINARYARM7 := fzf-$(GOOS)_arm7
|
BINARYARM7 := fzf-$(GOOS)_arm7
|
||||||
BINARYARM8 := fzf-$(GOOS)_arm8
|
BINARYARM8 := fzf-$(GOOS)_arm8
|
||||||
BINARYPPC64LE := fzf-$(GOOS)_ppc64le
|
BINARYPPC64LE := fzf-$(GOOS)_ppc64le
|
||||||
VERSION := $(shell awk -F= '/version =/ {print $$2}' src/constants.go | tr -d "\" ")
|
|
||||||
|
|
||||||
# https://en.wikipedia.org/wiki/Uname
|
# https://en.wikipedia.org/wiki/Uname
|
||||||
UNAME_M := $(shell uname -m)
|
UNAME_M := $(shell uname -m)
|
||||||
@@ -36,7 +52,7 @@ else ifeq ($(UNAME_M),aarch64)
|
|||||||
else ifeq ($(UNAME_M),ppc64le)
|
else ifeq ($(UNAME_M),ppc64le)
|
||||||
BINARY := $(BINARYPPC64LE)
|
BINARY := $(BINARYPPC64LE)
|
||||||
else
|
else
|
||||||
$(error "Build on $(UNAME_M) is not supported, yet.")
|
$(error Build on $(UNAME_M) is not supported, yet.)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: target/$(BINARY)
|
all: target/$(BINARY)
|
||||||
@@ -50,9 +66,44 @@ test: $(SOURCES)
|
|||||||
|
|
||||||
install: bin/fzf
|
install: bin/fzf
|
||||||
|
|
||||||
release:
|
build:
|
||||||
goreleaser --rm-dist --snapshot
|
goreleaser --rm-dist --snapshot
|
||||||
|
|
||||||
|
release:
|
||||||
|
ifndef GITHUB_TOKEN
|
||||||
|
$(error GITHUB_TOKEN is not defined)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Check if we are on master branch
|
||||||
|
ifneq ($(shell git symbolic-ref --short HEAD),master)
|
||||||
|
$(error Not on master branch)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Check if version numbers are properly updated
|
||||||
|
grep -q ^$(VERSION_REGEX)$$ CHANGELOG.md
|
||||||
|
grep -qF '"fzf $(VERSION_TRIM)"' man/man1/fzf.1
|
||||||
|
grep -qF '"fzf $(VERSION_TRIM)"' man/man1/fzf-tmux.1
|
||||||
|
grep -qF $(VERSION) install
|
||||||
|
grep -qF $(VERSION) install.ps1
|
||||||
|
|
||||||
|
# Make release note out of CHANGELOG.md
|
||||||
|
sed -n '/^$(VERSION_REGEX)$$/,/^[0-9]/p' CHANGELOG.md | tail -r | \
|
||||||
|
sed '1,/^ *$$/d' | tail -r | sed 1,2d | tee tmp/release-note
|
||||||
|
|
||||||
|
# Push to temp branch first so that install scripts always works on master branch
|
||||||
|
git checkout -B temp master
|
||||||
|
git push origin temp --follow-tags --force
|
||||||
|
|
||||||
|
# Make a GitHub release
|
||||||
|
goreleaser --rm-dist --release-notes tmp/release-note
|
||||||
|
|
||||||
|
# Push to master
|
||||||
|
git checkout master
|
||||||
|
git push origin master
|
||||||
|
|
||||||
|
# Delete temp branch
|
||||||
|
git push origin --delete temp
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) -r dist target
|
$(RM) -r dist target
|
||||||
|
|
||||||
@@ -90,4 +141,4 @@ update:
|
|||||||
$(GO) get -u
|
$(GO) get -u
|
||||||
$(GO) mod tidy
|
$(GO) mod tidy
|
||||||
|
|
||||||
.PHONY: all release test install clean docker docker-test update
|
.PHONY: all build release test install clean docker docker-test update
|
||||||
|
|||||||
@@ -298,9 +298,8 @@ following options are allowed:
|
|||||||
- Optional:
|
- Optional:
|
||||||
- `yoffset` [float default 0.5 range [0 ~ 1]]
|
- `yoffset` [float default 0.5 range [0 ~ 1]]
|
||||||
- `xoffset` [float default 0.5 range [0 ~ 1]]
|
- `xoffset` [float default 0.5 range [0 ~ 1]]
|
||||||
- `highlight` [string default `'Comment'`]: Highlight group for border
|
|
||||||
- `border` [string default `rounded`]: Border style
|
- `border` [string default `rounded`]: Border style
|
||||||
- `rounded` / `sharp` / `horizontal` / `vertical` / `top` / `bottom` / `left` / `right` / `none`
|
- `rounded` / `sharp` / `horizontal` / `vertical` / `top` / `bottom` / `left` / `right` / `no[ne]`
|
||||||
|
|
||||||
`fzf#wrap`
|
`fzf#wrap`
|
||||||
----------
|
----------
|
||||||
|
|||||||
4
install
4
install
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
version=0.24.0-rc1
|
version=0.24.3
|
||||||
auto_completion=
|
auto_completion=
|
||||||
key_bindings=
|
key_bindings=
|
||||||
update_config=2
|
update_config=2
|
||||||
@@ -197,7 +197,7 @@ if [ -n "$binary_error" ]; then
|
|||||||
export GOPATH="${TMPDIR:-/tmp}/fzf-gopath"
|
export GOPATH="${TMPDIR:-/tmp}/fzf-gopath"
|
||||||
mkdir -p "$GOPATH"
|
mkdir -p "$GOPATH"
|
||||||
fi
|
fi
|
||||||
if go get -u github.com/junegunn/fzf; then
|
if go get -ldflags "-s -w -X main.version=$version -X main.revision=go-get" github.com/junegunn/fzf; then
|
||||||
echo "OK"
|
echo "OK"
|
||||||
cp "$GOPATH/bin/fzf" "$fzf_base/bin/"
|
cp "$GOPATH/bin/fzf" "$fzf_base/bin/"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
$version="0.24.0-rc1"
|
$version="0.24.3"
|
||||||
|
|
||||||
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
|
||||||
|
|||||||
4
main.go
4
main.go
@@ -5,8 +5,8 @@ import (
|
|||||||
"github.com/junegunn/fzf/src/protector"
|
"github.com/junegunn/fzf/src/protector"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version string
|
var version string = "0.24"
|
||||||
var revision string
|
var revision string = "devel"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
protector.Protect()
|
protector.Protect()
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
..
|
..
|
||||||
.TH fzf-tmux 1 "Oct 2020" "fzf 0.24.0" "fzf-tmux - open fzf in tmux split pane"
|
.TH fzf-tmux 1 "Nov 2020" "fzf 0.24.3" "fzf-tmux - open fzf in tmux split pane"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
fzf-tmux - open fzf in tmux split pane
|
fzf-tmux - open fzf in tmux split pane
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
..
|
..
|
||||||
.TH fzf 1 "Oct 2020" "fzf 0.24.0" "fzf - a command-line fuzzy finder"
|
.TH fzf 1 "Nov 2020" "fzf 0.24.3" "fzf - a command-line fuzzy finder"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
fzf - a command-line fuzzy finder
|
fzf - a command-line fuzzy finder
|
||||||
@@ -233,6 +233,29 @@ e.g.
|
|||||||
\fBfzf --margin 10%
|
\fBfzf --margin 10%
|
||||||
fzf --margin 1,5%\fR
|
fzf --margin 1,5%\fR
|
||||||
.RE
|
.RE
|
||||||
|
.TP
|
||||||
|
.BI "--padding=" PADDING
|
||||||
|
Comma-separated expression for padding inside the border. Padding is
|
||||||
|
distinguishable from margin only when \fB--border\fR option is used.
|
||||||
|
.br
|
||||||
|
|
||||||
|
.br
|
||||||
|
e.g.
|
||||||
|
\fBfzf --margin 5% --padding 5% --border --preview 'cat {}' \\
|
||||||
|
--color bg:#222222,preview-bg:#333333\fR
|
||||||
|
|
||||||
|
.br
|
||||||
|
.RS
|
||||||
|
.BR TRBL " Same padding for top, right, bottom, and left"
|
||||||
|
.br
|
||||||
|
.BR TB,RL " Vertical, horizontal padding"
|
||||||
|
.br
|
||||||
|
.BR T,RL,B " Top, horizontal, bottom padding"
|
||||||
|
.br
|
||||||
|
.BR T,R,B,L " Top, right, bottom, left padding"
|
||||||
|
.br
|
||||||
|
.RE
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "--info=" "STYLE"
|
.BI "--info=" "STYLE"
|
||||||
Determines the display style of finder info.
|
Determines the display style of finder info.
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ endfunction
|
|||||||
|
|
||||||
function! s:default_layout()
|
function! s:default_layout()
|
||||||
return s:popup_support()
|
return s:popup_support()
|
||||||
\ ? { 'window' : { 'width': 0.9, 'height': 0.6, 'highlight': 'Normal' } }
|
\ ? { 'window' : { 'width': 0.9, 'height': 0.6 } }
|
||||||
\ : { 'down': '~40%' }
|
\ : { 'down': '~40%' }
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ function! fzf#exec(...)
|
|||||||
if v:shell_error || empty(output)
|
if v:shell_error || empty(output)
|
||||||
throw printf('Failed to run "%s": %s', command, output)
|
throw printf('Failed to run "%s": %s', command, output)
|
||||||
endif
|
endif
|
||||||
let fzf_version = matchstr(output[0], '[0-9.]\+')
|
let fzf_version = matchstr(output[-1], '[0-9.]\+')
|
||||||
if s:version_requirement(fzf_version, a:1)
|
if s:version_requirement(fzf_version, a:1)
|
||||||
let s:checked[a:1] = 1
|
let s:checked[a:1] = 1
|
||||||
return s:exec
|
return s:exec
|
||||||
@@ -283,7 +283,8 @@ function! s:common_sink(action, lines) abort
|
|||||||
let cwd = exists('w:fzf_pushd') ? w:fzf_pushd.dir : expand('%:p:h')
|
let cwd = exists('w:fzf_pushd') ? w:fzf_pushd.dir : expand('%:p:h')
|
||||||
for item in a:lines
|
for item in a:lines
|
||||||
if item[0] != '~' && item !~ (s:is_win ? '^[A-Z]:\' : '^/')
|
if item[0] != '~' && item !~ (s:is_win ? '^[A-Z]:\' : '^/')
|
||||||
let item = join([cwd, item], (s:is_win ? '\' : '/'))
|
let sep = s:is_win ? '\' : '/'
|
||||||
|
let item = join([cwd, item], cwd[len(cwd)-1] == sep ? '' : sep)
|
||||||
endif
|
endif
|
||||||
if empty
|
if empty
|
||||||
execute 'e' s:escape(item)
|
execute 'e' s:escape(item)
|
||||||
@@ -437,7 +438,7 @@ try
|
|||||||
let prefix = '( '.source.' )|'
|
let prefix = '( '.source.' )|'
|
||||||
elseif type == 3
|
elseif type == 3
|
||||||
let temps.input = s:fzf_tempname()
|
let temps.input = s:fzf_tempname()
|
||||||
call writefile(map(source, '<SID>enc_to_cp(v:val)'), temps.input)
|
call writefile(source, temps.input)
|
||||||
let prefix = (s:is_win ? 'type ' : 'cat ').fzf#shellescape(temps.input).'|'
|
let prefix = (s:is_win ? 'type ' : 'cat ').fzf#shellescape(temps.input).'|'
|
||||||
else
|
else
|
||||||
throw 'Invalid source type'
|
throw 'Invalid source type'
|
||||||
@@ -700,7 +701,7 @@ function! s:border_opt(window)
|
|||||||
if !has_key(a:window, 'border') && !get(a:window, 'rounded', 1)
|
if !has_key(a:window, 'border') && !get(a:window, 'rounded', 1)
|
||||||
let style = 'sharp'
|
let style = 'sharp'
|
||||||
endif
|
endif
|
||||||
if style == 'none'
|
if style == 'none' || style == 'no'
|
||||||
return ''
|
return ''
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -908,23 +909,16 @@ if has('nvim')
|
|||||||
endfunction
|
endfunction
|
||||||
else
|
else
|
||||||
function! s:create_popup(hl, opts) abort
|
function! s:create_popup(hl, opts) abort
|
||||||
let is_frame = has_key(a:opts, 'border')
|
|
||||||
let s:popup_create = {buf -> popup_create(buf, #{
|
let s:popup_create = {buf -> popup_create(buf, #{
|
||||||
\ line: a:opts.row,
|
\ line: a:opts.row,
|
||||||
\ col: a:opts.col,
|
\ col: a:opts.col,
|
||||||
\ minwidth: a:opts.width,
|
\ minwidth: a:opts.width,
|
||||||
|
\ maxwidth: a:opts.width,
|
||||||
\ minheight: a:opts.height,
|
\ minheight: a:opts.height,
|
||||||
\ zindex: 50 - is_frame,
|
\ maxheight: a:opts.height,
|
||||||
|
\ zindex: 1000,
|
||||||
\ })}
|
\ })}
|
||||||
if is_frame
|
|
||||||
let id = s:popup_create('')
|
|
||||||
call setwinvar(id, '&wincolor', a:hl)
|
|
||||||
call setbufline(winbufnr(id), 1, a:opts.border)
|
|
||||||
execute 'autocmd BufWipeout * ++once call popup_close('..id..')'
|
|
||||||
return winbufnr(id)
|
|
||||||
else
|
|
||||||
autocmd TerminalOpen * ++once call s:popup_create(str2nr(expand('<abuf>')))
|
autocmd TerminalOpen * ++once call s:popup_create(str2nr(expand('<abuf>')))
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ const usage = `usage: fzf [options]
|
|||||||
--border[=STYLE] Draw border around the finder
|
--border[=STYLE] Draw border around the finder
|
||||||
[rounded|sharp|horizontal|vertical|
|
[rounded|sharp|horizontal|vertical|
|
||||||
top|bottom|left|right] (default: rounded)
|
top|bottom|left|right] (default: rounded)
|
||||||
--margin=MARGIN Screen margin (TRBL / TB,RL / T,RL,B / T,R,B,L)
|
--margin=MARGIN Screen margin (TRBL | TB,RL | T,RL,B | T,R,B,L)
|
||||||
|
--padding=PADDING Padding inside border (TRBL | TB,RL | T,RL,B | T,R,B,L)
|
||||||
--info=STYLE Finder info style [default|inline|hidden]
|
--info=STYLE Finder info style [default|inline|hidden]
|
||||||
--prompt=STR Input prompt (default: '> ')
|
--prompt=STR Input prompt (default: '> ')
|
||||||
--pointer=STR Pointer to the current line (default: '>')
|
--pointer=STR Pointer to the current line (default: '>')
|
||||||
@@ -221,6 +222,7 @@ type Options struct {
|
|||||||
Header []string
|
Header []string
|
||||||
HeaderLines int
|
HeaderLines int
|
||||||
Margin [4]sizeSpec
|
Margin [4]sizeSpec
|
||||||
|
Padding [4]sizeSpec
|
||||||
BorderShape tui.BorderShape
|
BorderShape tui.BorderShape
|
||||||
Unicode bool
|
Unicode bool
|
||||||
Tabstop int
|
Tabstop int
|
||||||
@@ -281,6 +283,7 @@ func defaultOptions() *Options {
|
|||||||
Header: make([]string, 0),
|
Header: make([]string, 0),
|
||||||
HeaderLines: 0,
|
HeaderLines: 0,
|
||||||
Margin: defaultMargin(),
|
Margin: defaultMargin(),
|
||||||
|
Padding: defaultMargin(),
|
||||||
Unicode: true,
|
Unicode: true,
|
||||||
Tabstop: 8,
|
Tabstop: 8,
|
||||||
ClearOnExit: true,
|
ClearOnExit: true,
|
||||||
@@ -617,7 +620,7 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) *tui.ColorTheme {
|
|||||||
case "16":
|
case "16":
|
||||||
theme = dupeTheme(tui.Default16)
|
theme = dupeTheme(tui.Default16)
|
||||||
case "bw", "no":
|
case "bw", "no":
|
||||||
theme = nil
|
theme = tui.NoColorTheme()
|
||||||
default:
|
default:
|
||||||
fail := func() {
|
fail := func() {
|
||||||
errorExit("invalid color specification: " + str)
|
errorExit("invalid color specification: " + str)
|
||||||
@@ -1076,10 +1079,10 @@ func parsePreviewWindow(opts *previewOpts, input string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseMargin(margin string) [4]sizeSpec {
|
func parseMargin(opt string, margin string) [4]sizeSpec {
|
||||||
margins := strings.Split(margin, ",")
|
margins := strings.Split(margin, ",")
|
||||||
checked := func(str string) sizeSpec {
|
checked := func(str string) sizeSpec {
|
||||||
return parseSize(str, 49, "margin")
|
return parseSize(str, 49, opt)
|
||||||
}
|
}
|
||||||
switch len(margins) {
|
switch len(margins) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -1099,7 +1102,7 @@ func parseMargin(margin string) [4]sizeSpec {
|
|||||||
checked(margins[0]), checked(margins[1]),
|
checked(margins[0]), checked(margins[1]),
|
||||||
checked(margins[2]), checked(margins[3])}
|
checked(margins[2]), checked(margins[3])}
|
||||||
default:
|
default:
|
||||||
errorExit("invalid margin: " + margin)
|
errorExit("invalid " + opt + ": " + margin)
|
||||||
}
|
}
|
||||||
return defaultMargin()
|
return defaultMargin()
|
||||||
}
|
}
|
||||||
@@ -1324,6 +1327,8 @@ func parseOptions(opts *Options, allArgs []string) {
|
|||||||
opts.Height = sizeSpec{}
|
opts.Height = sizeSpec{}
|
||||||
case "--no-margin":
|
case "--no-margin":
|
||||||
opts.Margin = defaultMargin()
|
opts.Margin = defaultMargin()
|
||||||
|
case "--no-padding":
|
||||||
|
opts.Padding = defaultMargin()
|
||||||
case "--no-border":
|
case "--no-border":
|
||||||
opts.BorderShape = tui.BorderNone
|
opts.BorderShape = tui.BorderNone
|
||||||
case "--border":
|
case "--border":
|
||||||
@@ -1335,7 +1340,12 @@ func parseOptions(opts *Options, allArgs []string) {
|
|||||||
opts.Unicode = true
|
opts.Unicode = true
|
||||||
case "--margin":
|
case "--margin":
|
||||||
opts.Margin = parseMargin(
|
opts.Margin = parseMargin(
|
||||||
|
"margin",
|
||||||
nextString(allArgs, &i, "margin required (TRBL / TB,RL / T,RL,B / T,R,B,L)"))
|
nextString(allArgs, &i, "margin required (TRBL / TB,RL / T,RL,B / T,R,B,L)"))
|
||||||
|
case "--padding":
|
||||||
|
opts.Padding = parseMargin(
|
||||||
|
"padding",
|
||||||
|
nextString(allArgs, &i, "padding required (TRBL / TB,RL / T,RL,B / T,R,B,L)"))
|
||||||
case "--tabstop":
|
case "--tabstop":
|
||||||
opts.Tabstop = nextInt(allArgs, &i, "tab stop required")
|
opts.Tabstop = nextInt(allArgs, &i, "tab stop required")
|
||||||
case "--clear":
|
case "--clear":
|
||||||
@@ -1404,7 +1414,9 @@ func parseOptions(opts *Options, allArgs []string) {
|
|||||||
} else if match, value := optString(arg, "--preview-window="); match {
|
} else if match, value := optString(arg, "--preview-window="); match {
|
||||||
parsePreviewWindow(&opts.Preview, value)
|
parsePreviewWindow(&opts.Preview, value)
|
||||||
} else if match, value := optString(arg, "--margin="); match {
|
} else if match, value := optString(arg, "--margin="); match {
|
||||||
opts.Margin = parseMargin(value)
|
opts.Margin = parseMargin("margin", value)
|
||||||
|
} else if match, value := optString(arg, "--padding="); match {
|
||||||
|
opts.Padding = parseMargin("padding", value)
|
||||||
} else if match, value := optString(arg, "--tabstop="); match {
|
} else if match, value := optString(arg, "--tabstop="); match {
|
||||||
opts.Tabstop = atoi(value)
|
opts.Tabstop = atoi(value)
|
||||||
} else if match, value := optString(arg, "--hscroll-off="); match {
|
} else if match, value := optString(arg, "--hscroll-off="); match {
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ type Terminal struct {
|
|||||||
ansi bool
|
ansi bool
|
||||||
tabstop int
|
tabstop int
|
||||||
margin [4]sizeSpec
|
margin [4]sizeSpec
|
||||||
|
padding [4]sizeSpec
|
||||||
strong tui.Attr
|
strong tui.Attr
|
||||||
unicode bool
|
unicode bool
|
||||||
borderShape tui.BorderShape
|
borderShape tui.BorderShape
|
||||||
@@ -472,6 +473,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
|||||||
printQuery: opts.PrintQuery,
|
printQuery: opts.PrintQuery,
|
||||||
history: opts.History,
|
history: opts.History,
|
||||||
margin: opts.Margin,
|
margin: opts.Margin,
|
||||||
|
padding: opts.Padding,
|
||||||
unicode: opts.Unicode,
|
unicode: opts.Unicode,
|
||||||
borderShape: opts.BorderShape,
|
borderShape: opts.BorderShape,
|
||||||
cleanExit: opts.ClearOnExit,
|
cleanExit: opts.ClearOnExit,
|
||||||
@@ -526,7 +528,6 @@ func (t *Terminal) parsePrompt(prompt string) (func(), int) {
|
|||||||
blankState := ansiOffset{[2]int32{int32(loc[0]), int32(loc[1])}, ansiState{-1, -1, tui.AttrClear}}
|
blankState := ansiOffset{[2]int32{int32(loc[0]), int32(loc[1])}, ansiState{-1, -1, tui.AttrClear}}
|
||||||
if item.colors != nil {
|
if item.colors != nil {
|
||||||
lastColor := (*item.colors)[len(*item.colors)-1]
|
lastColor := (*item.colors)[len(*item.colors)-1]
|
||||||
fmt.Println(lastColor.offset[1], int32(loc[1]))
|
|
||||||
if lastColor.offset[1] < int32(loc[1]) {
|
if lastColor.offset[1] < int32(loc[1]) {
|
||||||
blankState.offset[0] = lastColor.offset[1]
|
blankState.offset[0] = lastColor.offset[1]
|
||||||
colors := append(*item.colors, blankState)
|
colors := append(*item.colors, blankState)
|
||||||
@@ -653,7 +654,7 @@ func (t *Terminal) displayWidth(runes []rune) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
minWidth = 16
|
minWidth = 4
|
||||||
minHeight = 4
|
minHeight = 4
|
||||||
|
|
||||||
maxDisplayWidthCalc = 1024
|
maxDisplayWidthCalc = 1024
|
||||||
@@ -670,52 +671,64 @@ func calculateSize(base int, size sizeSpec, occupied int, minSize int, pad int)
|
|||||||
func (t *Terminal) resizeWindows() {
|
func (t *Terminal) resizeWindows() {
|
||||||
screenWidth := t.tui.MaxX()
|
screenWidth := t.tui.MaxX()
|
||||||
screenHeight := t.tui.MaxY()
|
screenHeight := t.tui.MaxY()
|
||||||
marginInt := [4]int{} // TRBL
|
|
||||||
t.prevLines = make([]itemLine, screenHeight)
|
t.prevLines = make([]itemLine, screenHeight)
|
||||||
for idx, sizeSpec := range t.margin {
|
|
||||||
if sizeSpec.percent {
|
marginInt := [4]int{} // TRBL
|
||||||
|
paddingInt := [4]int{} // TRBL
|
||||||
|
sizeSpecToInt := func(index int, spec sizeSpec) int {
|
||||||
|
if spec.percent {
|
||||||
var max float64
|
var max float64
|
||||||
if idx%2 == 0 {
|
if index%2 == 0 {
|
||||||
max = float64(screenHeight)
|
max = float64(screenHeight)
|
||||||
} else {
|
} else {
|
||||||
max = float64(screenWidth)
|
max = float64(screenWidth)
|
||||||
}
|
}
|
||||||
marginInt[idx] = int(max * sizeSpec.size * 0.01)
|
return int(max * spec.size * 0.01)
|
||||||
} else {
|
|
||||||
marginInt[idx] = int(sizeSpec.size)
|
|
||||||
}
|
}
|
||||||
|
return int(spec.size)
|
||||||
|
}
|
||||||
|
for idx, sizeSpec := range t.padding {
|
||||||
|
paddingInt[idx] = sizeSpecToInt(idx, sizeSpec)
|
||||||
|
}
|
||||||
|
|
||||||
|
extraMargin := [4]int{} // TRBL
|
||||||
|
for idx, sizeSpec := range t.margin {
|
||||||
switch t.borderShape {
|
switch t.borderShape {
|
||||||
case tui.BorderHorizontal:
|
case tui.BorderHorizontal:
|
||||||
marginInt[idx] += 1 - idx%2
|
extraMargin[idx] += 1 - idx%2
|
||||||
case tui.BorderVertical:
|
case tui.BorderVertical:
|
||||||
marginInt[idx] += 2 * (idx % 2)
|
extraMargin[idx] += 2 * (idx % 2)
|
||||||
case tui.BorderTop:
|
case tui.BorderTop:
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
marginInt[idx]++
|
extraMargin[idx]++
|
||||||
}
|
}
|
||||||
case tui.BorderRight:
|
case tui.BorderRight:
|
||||||
if idx == 1 {
|
if idx == 1 {
|
||||||
marginInt[idx] += 2
|
extraMargin[idx] += 2
|
||||||
}
|
}
|
||||||
case tui.BorderBottom:
|
case tui.BorderBottom:
|
||||||
if idx == 2 {
|
if idx == 2 {
|
||||||
marginInt[idx]++
|
extraMargin[idx]++
|
||||||
}
|
}
|
||||||
case tui.BorderLeft:
|
case tui.BorderLeft:
|
||||||
if idx == 3 {
|
if idx == 3 {
|
||||||
marginInt[idx] += 2
|
extraMargin[idx] += 2
|
||||||
}
|
}
|
||||||
case tui.BorderRounded, tui.BorderSharp:
|
case tui.BorderRounded, tui.BorderSharp:
|
||||||
marginInt[idx] += 1 + idx%2
|
extraMargin[idx] += 1 + idx%2
|
||||||
}
|
}
|
||||||
|
marginInt[idx] = sizeSpecToInt(idx, sizeSpec) + extraMargin[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
adjust := func(idx1 int, idx2 int, max int, min int) {
|
adjust := func(idx1 int, idx2 int, max int, min int) {
|
||||||
if max >= min {
|
if max >= min {
|
||||||
margin := marginInt[idx1] + marginInt[idx2]
|
margin := marginInt[idx1] + marginInt[idx2] + paddingInt[idx1] + paddingInt[idx2]
|
||||||
if max-margin < min {
|
if max-margin < min {
|
||||||
desired := max - min
|
desired := max - min
|
||||||
marginInt[idx1] = desired * marginInt[idx1] / margin
|
paddingInt[idx1] = desired * paddingInt[idx1] / margin
|
||||||
marginInt[idx2] = desired * marginInt[idx2] / margin
|
paddingInt[idx2] = desired * paddingInt[idx2] / margin
|
||||||
|
marginInt[idx1] = util.Max(extraMargin[idx1], desired*marginInt[idx1]/margin)
|
||||||
|
marginInt[idx2] = util.Max(extraMargin[idx2], desired*marginInt[idx2]/margin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -780,6 +793,14 @@ func (t *Terminal) resizeWindows() {
|
|||||||
marginInt[0]-1, marginInt[3]-2, width+4, height+2,
|
marginInt[0]-1, marginInt[3]-2, width+4, height+2,
|
||||||
false, tui.MakeBorderStyle(t.borderShape, t.unicode))
|
false, tui.MakeBorderStyle(t.borderShape, t.unicode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add padding
|
||||||
|
for idx, val := range paddingInt {
|
||||||
|
marginInt[idx] += val
|
||||||
|
}
|
||||||
|
width = screenWidth - marginInt[1] - marginInt[3]
|
||||||
|
height = screenHeight - marginInt[0] - marginInt[2]
|
||||||
|
|
||||||
noBorder := tui.MakeBorderStyle(tui.BorderNone, t.unicode)
|
noBorder := tui.MakeBorderStyle(tui.BorderNone, t.unicode)
|
||||||
if previewVisible {
|
if previewVisible {
|
||||||
createPreviewWindow := func(y int, x int, w int, h int) {
|
createPreviewWindow := func(y int, x int, w int, h int) {
|
||||||
@@ -801,17 +822,19 @@ func (t *Terminal) resizeWindows() {
|
|||||||
t.pwindow = t.tui.NewWindow(y, x, pwidth, pheight, true, noBorder)
|
t.pwindow = t.tui.NewWindow(y, x, pwidth, pheight, true, noBorder)
|
||||||
}
|
}
|
||||||
verticalPad := 2
|
verticalPad := 2
|
||||||
|
minPreviewHeight := 3
|
||||||
if t.preview.border == tui.BorderNone {
|
if t.preview.border == tui.BorderNone {
|
||||||
verticalPad = 0
|
verticalPad = 0
|
||||||
|
minPreviewHeight = 1
|
||||||
}
|
}
|
||||||
switch t.preview.position {
|
switch t.preview.position {
|
||||||
case posUp:
|
case posUp:
|
||||||
pheight := calculateSize(height, t.preview.size, minHeight, 3, verticalPad)
|
pheight := calculateSize(height, t.preview.size, minHeight, minPreviewHeight, verticalPad)
|
||||||
t.window = t.tui.NewWindow(
|
t.window = t.tui.NewWindow(
|
||||||
marginInt[0]+pheight, marginInt[3], width, height-pheight, false, noBorder)
|
marginInt[0]+pheight, marginInt[3], width, height-pheight, false, noBorder)
|
||||||
createPreviewWindow(marginInt[0], marginInt[3], width, pheight)
|
createPreviewWindow(marginInt[0], marginInt[3], width, pheight)
|
||||||
case posDown:
|
case posDown:
|
||||||
pheight := calculateSize(height, t.preview.size, minHeight, 3, verticalPad)
|
pheight := calculateSize(height, t.preview.size, minHeight, minPreviewHeight, verticalPad)
|
||||||
t.window = t.tui.NewWindow(
|
t.window = t.tui.NewWindow(
|
||||||
marginInt[0], marginInt[3], width, height-pheight, false, noBorder)
|
marginInt[0], marginInt[3], width, height-pheight, false, noBorder)
|
||||||
createPreviewWindow(marginInt[0]+height-pheight, marginInt[3], width, pheight)
|
createPreviewWindow(marginInt[0]+height-pheight, marginInt[3], width, pheight)
|
||||||
@@ -1254,6 +1277,7 @@ func (t *Terminal) renderPreviewText(unchanged bool) {
|
|||||||
}
|
}
|
||||||
var ansi *ansiState
|
var ansi *ansiState
|
||||||
for _, line := range t.previewer.lines {
|
for _, line := range t.previewer.lines {
|
||||||
|
line = strings.TrimSuffix(line, "\n")
|
||||||
if lineNo >= height || t.pwindow.Y() == height-1 && t.pwindow.X() > 0 {
|
if lineNo >= height || t.pwindow.Y() == height-1 && t.pwindow.X() > 0 {
|
||||||
t.previewed.filled = true
|
t.previewed.filled = true
|
||||||
break
|
break
|
||||||
@@ -1284,6 +1308,7 @@ func (t *Terminal) renderPreviewText(unchanged bool) {
|
|||||||
if unchanged && lineNo == 0 {
|
if unchanged && lineNo == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
t.pwindow.Fill("\n")
|
||||||
}
|
}
|
||||||
lineNo++
|
lineNo++
|
||||||
}
|
}
|
||||||
@@ -1855,13 +1880,9 @@ func (t *Terminal) Loop() {
|
|||||||
reader := bufio.NewReader(out)
|
reader := bufio.NewReader(out)
|
||||||
eofChan := make(chan bool)
|
eofChan := make(chan bool)
|
||||||
finishChan := make(chan bool, 1)
|
finishChan := make(chan bool, 1)
|
||||||
reapChan := make(chan bool)
|
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
reaps := 0
|
if err == nil {
|
||||||
if err != nil {
|
reapChan := make(chan bool)
|
||||||
t.reqBox.Set(reqPreviewDisplay, previewResult{version, []string{err.Error()}, 0, ""})
|
|
||||||
} else {
|
|
||||||
reaps = 2
|
|
||||||
lineChan := make(chan eachLine)
|
lineChan := make(chan eachLine)
|
||||||
// Goroutine 1 reads process output
|
// Goroutine 1 reads process output
|
||||||
go func() {
|
go func() {
|
||||||
@@ -1874,6 +1895,7 @@ func (t *Terminal) Loop() {
|
|||||||
}
|
}
|
||||||
eofChan <- true
|
eofChan <- true
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Goroutine 2 periodically requests rendering
|
// Goroutine 2 periodically requests rendering
|
||||||
go func(version int64) {
|
go func(version int64) {
|
||||||
lines := []string{}
|
lines := []string{}
|
||||||
@@ -1915,7 +1937,7 @@ func (t *Terminal) Loop() {
|
|||||||
ticker.Stop()
|
ticker.Stop()
|
||||||
reapChan <- true
|
reapChan <- true
|
||||||
}(version)
|
}(version)
|
||||||
}
|
|
||||||
// Goroutine 3 is responsible for cancelling running preview command
|
// Goroutine 3 is responsible for cancelling running preview command
|
||||||
go func(version int64) {
|
go func(version int64) {
|
||||||
timer := time.NewTimer(previewDelayed)
|
timer := time.NewTimer(previewDelayed)
|
||||||
@@ -1945,12 +1967,17 @@ func (t *Terminal) Loop() {
|
|||||||
timer.Stop()
|
timer.Stop()
|
||||||
reapChan <- true
|
reapChan <- true
|
||||||
}(version)
|
}(version)
|
||||||
<-eofChan
|
|
||||||
|
<-eofChan // Goroutine 1 finished
|
||||||
cmd.Wait() // NOTE: We should not call Wait before EOF
|
cmd.Wait() // NOTE: We should not call Wait before EOF
|
||||||
finishChan <- true
|
finishChan <- true // Tell Goroutine 3 to stop
|
||||||
for i := 0; i < reaps; i++ {
|
<-reapChan // Goroutine 2 and 3 finished
|
||||||
<-reapChan
|
<-reapChan
|
||||||
|
} else {
|
||||||
|
// Failed to start the command. Report the error immediately.
|
||||||
|
t.reqBox.Set(reqPreviewDisplay, previewResult{version, []string{err.Error()}, 0, ""})
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanTemporaryFiles()
|
cleanTemporaryFiles()
|
||||||
} else {
|
} else {
|
||||||
t.reqBox.Set(reqPreviewDisplay, previewResult{version, nil, 0, ""})
|
t.reqBox.Set(reqPreviewDisplay, previewResult{version, nil, 0, ""})
|
||||||
|
|||||||
@@ -554,6 +554,9 @@ func initTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool) {
|
|||||||
|
|
||||||
func initPalette(theme *ColorTheme) {
|
func initPalette(theme *ColorTheme) {
|
||||||
pair := func(fg, bg ColorAttr) ColorPair {
|
pair := func(fg, bg ColorAttr) ColorPair {
|
||||||
|
if fg.Color == colDefault && (fg.Attr&Reverse) > 0 {
|
||||||
|
bg.Color = colDefault
|
||||||
|
}
|
||||||
return ColorPair{fg.Color, bg.Color, fg.Attr}
|
return ColorPair{fg.Color, bg.Color, fg.Attr}
|
||||||
}
|
}
|
||||||
blank := theme.Fg
|
blank := theme.Fg
|
||||||
|
|||||||
Reference in New Issue
Block a user