summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2025-01-26 15:04:30 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2025-01-26 15:37:42 +0900
commitd6584543e993ae74615057cb02c4c831350b75bd (patch)
tree78b7a27f12150a4a20f67e35ab97929a4058fd2a /src
parentc13228f34623b856bd22a963959f4655cbfac947 (diff)
downloadfzf-d6584543e993ae74615057cb02c4c831350b75bd.tar.gz
Make click-header export $FZF_CLICK_HEADER_{NTH,WORD}
Diffstat (limited to 'src')
-rw-r--r--src/actiontype_string.go85
-rw-r--r--src/options.go4
-rw-r--r--src/terminal.go78
-rw-r--r--src/tokenizer.go12
4 files changed, 131 insertions, 48 deletions
diff --git a/src/actiontype_string.go b/src/actiontype_string.go
index 143e02b6..b37446c5 100644
--- a/src/actiontype_string.go
+++ b/src/actiontype_string.go
@@ -93,51 +93,52 @@ func _() {
_ = x[actTransformInputLabel-82]
_ = x[actTransformHeader-83]
_ = x[actTransformHeaderLabel-84]
- _ = x[actTransformPreviewLabel-85]
- _ = x[actTransformPrompt-86]
- _ = x[actTransformQuery-87]
- _ = x[actTransformSearch-88]
- _ = x[actSearch-89]
- _ = x[actPreview-90]
- _ = x[actChangePreview-91]
- _ = x[actChangePreviewWindow-92]
- _ = x[actPreviewTop-93]
- _ = x[actPreviewBottom-94]
- _ = x[actPreviewUp-95]
- _ = x[actPreviewDown-96]
- _ = x[actPreviewPageUp-97]
- _ = x[actPreviewPageDown-98]
- _ = x[actPreviewHalfPageUp-99]
- _ = x[actPreviewHalfPageDown-100]
- _ = x[actPrevHistory-101]
- _ = x[actPrevSelected-102]
- _ = x[actPrint-103]
- _ = x[actPut-104]
- _ = x[actNextHistory-105]
- _ = x[actNextSelected-106]
- _ = x[actExecute-107]
- _ = x[actExecuteSilent-108]
- _ = x[actExecuteMulti-109]
- _ = x[actSigStop-110]
- _ = x[actFirst-111]
- _ = x[actLast-112]
- _ = x[actReload-113]
- _ = x[actReloadSync-114]
- _ = x[actDisableSearch-115]
- _ = x[actEnableSearch-116]
- _ = x[actSelect-117]
- _ = x[actDeselect-118]
- _ = x[actUnbind-119]
- _ = x[actRebind-120]
- _ = x[actBecome-121]
- _ = x[actShowHeader-122]
- _ = x[actHideHeader-123]
- _ = x[actBell-124]
+ _ = x[actTransformNth-85]
+ _ = x[actTransformPreviewLabel-86]
+ _ = x[actTransformPrompt-87]
+ _ = x[actTransformQuery-88]
+ _ = x[actTransformSearch-89]
+ _ = x[actSearch-90]
+ _ = x[actPreview-91]
+ _ = x[actChangePreview-92]
+ _ = x[actChangePreviewWindow-93]
+ _ = x[actPreviewTop-94]
+ _ = x[actPreviewBottom-95]
+ _ = x[actPreviewUp-96]
+ _ = x[actPreviewDown-97]
+ _ = x[actPreviewPageUp-98]
+ _ = x[actPreviewPageDown-99]
+ _ = x[actPreviewHalfPageUp-100]
+ _ = x[actPreviewHalfPageDown-101]
+ _ = x[actPrevHistory-102]
+ _ = x[actPrevSelected-103]
+ _ = x[actPrint-104]
+ _ = x[actPut-105]
+ _ = x[actNextHistory-106]
+ _ = x[actNextSelected-107]
+ _ = x[actExecute-108]
+ _ = x[actExecuteSilent-109]
+ _ = x[actExecuteMulti-110]
+ _ = x[actSigStop-111]
+ _ = x[actFirst-112]
+ _ = x[actLast-113]
+ _ = x[actReload-114]
+ _ = x[actReloadSync-115]
+ _ = x[actDisableSearch-116]
+ _ = x[actEnableSearch-117]
+ _ = x[actSelect-118]
+ _ = x[actDeselect-119]
+ _ = x[actUnbind-120]
+ _ = x[actRebind-121]
+ _ = x[actBecome-122]
+ _ = x[actShowHeader-123]
+ _ = x[actHideHeader-124]
+ _ = x[actBell-125]
}
-const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeListLabelactChangeInputLabelactChangeHeaderactChangeHeaderLabelactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactChangeNthactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformListLabelactTransformInputLabelactTransformHeaderactTransformHeaderLabelactTransformPreviewLabelactTransformPromptactTransformQueryactTransformSearchactSearchactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactShowHeaderactHideHeaderactBell"
+const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeListLabelactChangeInputLabelactChangeHeaderactChangeHeaderLabelactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactChangeNthactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformListLabelactTransformInputLabelactTransformHeaderactTransformHeaderLabelactTransformNthactTransformPreviewLabelactTransformPromptactTransformQueryactTransformSearchactSearchactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactShowHeaderactHideHeaderactBell"
-var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 245, 264, 279, 299, 313, 334, 349, 363, 375, 389, 402, 419, 427, 440, 456, 468, 476, 490, 504, 515, 526, 544, 561, 568, 587, 599, 613, 622, 637, 649, 662, 673, 684, 696, 710, 731, 746, 759, 777, 793, 808, 825, 832, 837, 846, 857, 868, 881, 896, 907, 920, 935, 942, 955, 968, 985, 1000, 1013, 1027, 1041, 1057, 1077, 1089, 1112, 1133, 1155, 1173, 1196, 1220, 1238, 1255, 1273, 1282, 1292, 1308, 1330, 1343, 1359, 1371, 1385, 1401, 1419, 1439, 1461, 1475, 1490, 1498, 1504, 1518, 1533, 1543, 1559, 1574, 1584, 1592, 1599, 1608, 1621, 1637, 1652, 1661, 1672, 1681, 1690, 1699, 1712, 1725, 1732}
+var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 245, 264, 279, 299, 313, 334, 349, 363, 375, 389, 402, 419, 427, 440, 456, 468, 476, 490, 504, 515, 526, 544, 561, 568, 587, 599, 613, 622, 637, 649, 662, 673, 684, 696, 710, 731, 746, 759, 777, 793, 808, 825, 832, 837, 846, 857, 868, 881, 896, 907, 920, 935, 942, 955, 968, 985, 1000, 1013, 1027, 1041, 1057, 1077, 1089, 1112, 1133, 1155, 1173, 1196, 1211, 1235, 1253, 1270, 1288, 1297, 1307, 1323, 1345, 1358, 1374, 1386, 1400, 1416, 1434, 1454, 1476, 1490, 1505, 1513, 1519, 1533, 1548, 1558, 1574, 1589, 1599, 1607, 1614, 1623, 1636, 1652, 1667, 1676, 1687, 1696, 1705, 1714, 1727, 1740, 1747}
func (i actionType) String() string {
if i < 0 || i >= actionType(len(_actionType_index)-1) {
diff --git a/src/options.go b/src/options.go
index 2b9a5196..5865f0ea 100644
--- a/src/options.go
+++ b/src/options.go
@@ -1332,7 +1332,7 @@ const (
func init() {
executeRegexp = regexp.MustCompile(
- `(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|transform)-(?:query|prompt|(?:border|list|preview|input|header)-label|header|search)|transform|change-(?:preview-window|preview|multi|nth)|(?:re|un)bind|pos|put|print|search)`)
+ `(?si)[:+](become|execute(?:-multi|-silent)?|reload(?:-sync)?|preview|(?:change|transform)-(?:query|prompt|(?:border|list|preview|input|header)-label|header|search|nth)|transform|change-(?:preview-window|preview|multi)|(?:re|un)bind|pos|put|print|search)`)
splitRegexp = regexp.MustCompile("[,:]+")
actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+")
}
@@ -1740,6 +1740,8 @@ func isExecuteAction(str string) actionType {
return actTransformHeaderLabel
case "transform-header":
return actTransformHeader
+ case "transform-nth":
+ return actTransformNth
case "transform-prompt":
return actTransformPrompt
case "transform-query":
diff --git a/src/terminal.go b/src/terminal.go
index 4d58ca8c..56b70e9b 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -531,6 +531,7 @@ const (
actTransformInputLabel
actTransformHeader
actTransformHeaderLabel
+ actTransformNth
actTransformPreviewLabel
actTransformPrompt
actTransformQuery
@@ -1065,6 +1066,7 @@ func (t *Terminal) environImpl(forPreview bool) []string {
env = append(env, fmt.Sprintf("FZF_POS=%d", util.Min(t.merger.Length(), t.cy+1)))
env = append(env, fmt.Sprintf("FZF_CLICK_HEADER_LINE=%d", t.clickHeaderLine))
env = append(env, fmt.Sprintf("FZF_CLICK_HEADER_COLUMN=%d", t.clickHeaderColumn))
+ env = t.addClickHeaderWord(env)
// Add preview environment variables if preview is enabled
pwindowSize := t.pwindowSize()
@@ -1393,6 +1395,8 @@ func (t *Terminal) changeHeader(header string) bool {
}
needFullRedraw := len(t.header0) != len(lines)
t.header0 = lines
+ t.clickHeaderLine = 0
+ t.clickHeaderColumn = 0
return needFullRedraw
}
@@ -4089,6 +4093,64 @@ func (t *Terminal) currentIndex() int32 {
return minItem.Index()
}
+func (t *Terminal) addClickHeaderWord(env []string) []string {
+ /*
+ * echo $'HL1\nHL2' | fzf --header-lines 3 --header $'H1\nH2' --header-lines-border --bind 'click-header:preview:env | grep FZF_CLICK'
+ *
+ * REVERSE DEFAULT
+ * H1 1 1
+ * H2 2 HL2 2
+ * ------- HL1 3
+ * HL1 3 -------
+ * HL2 4 H1 4
+ * 5 H2 5
+ */
+ lineNum := t.clickHeaderLine - 1
+ if lineNum < 0 {
+ // Never clicked on the header
+ return env
+ }
+
+ var line string
+ if t.layout == layoutReverse {
+ if lineNum < len(t.header0) {
+ line = t.header0[lineNum]
+ } else if lineNum-len(t.header0) < len(t.header) {
+ line = t.header[lineNum-len(t.header0)]
+ }
+ } else {
+ // NOTE: t.header is padded with empty strings so that its size is equal to t.headerLines
+ if lineNum < len(t.header) {
+ line = t.header[len(t.header)-lineNum-1]
+ } else if lineNum-len(t.header) < len(t.header0) {
+ line = t.header0[lineNum-len(t.header)]
+ }
+ }
+ if len(line) == 0 {
+ return env
+ }
+
+ colNum := t.clickHeaderColumn - 1
+ words := Tokenize(line, t.delimiter)
+ for idx, token := range words {
+ prefixWidth := int(token.prefixLength)
+ word := token.text.ToString()
+ trimmed := strings.TrimSpace(word)
+ trimWidth, _ := util.RunesWidth([]rune(trimmed), prefixWidth, t.tabstop, math.MaxInt32)
+
+ if colNum >= prefixWidth && colNum < prefixWidth+trimWidth {
+ env = append(env, fmt.Sprintf("FZF_CLICK_HEADER_WORD=%s", trimmed))
+ nth := fmt.Sprintf("FZF_CLICK_HEADER_NTH=%d", idx+1)
+ if idx == len(words)-1 {
+ nth += ".."
+ }
+ env = append(env, nth)
+ return env
+ }
+ }
+ return env
+}
+
// Loop is called to start Terminal I/O
func (t *Terminal) Loop() error {
// prof := profile.Start(profile.ProfilePath("/tmp/"))
@@ -4833,11 +4895,14 @@ func (t *Terminal) Loop() error {
}
t.multi = multi
req(reqList, reqInfo)
- case actChangeNth:
- changed = true
+ case actChangeNth, actTransformNth:
+ expr := a.a
+ if a.t == actTransformNth {
+ expr = t.captureLine(a.a)
+ }
// Split nth expression
- tokens := strings.Split(a.a, "|")
+ tokens := strings.Split(expr, "|")
if nth, err := splitNth(tokens[0]); err == nil {
// Changed
newNth = &nth
@@ -4845,12 +4910,15 @@ func (t *Terminal) Loop() error {
// The default
newNth = &t.nth
}
- t.nthCurrent = *newNth
// Cycle
if len(tokens) > 1 {
a.a = strings.Join(append(tokens[1:], tokens[0]), "|")
}
- t.forceRerenderList()
+ if !compareRanges(t.nthCurrent, *newNth) {
+ changed = true
+ t.nthCurrent = *newNth
+ t.forceRerenderList()
+ }
case actChangeQuery:
t.input = []rune(a.a)
t.cx = len(t.input)
diff --git a/src/tokenizer.go b/src/tokenizer.go
index e5a8e977..f5d1483b 100644
--- a/src/tokenizer.go
+++ b/src/tokenizer.go
@@ -22,6 +22,18 @@ func (r Range) IsFull() bool {
return r.begin == rangeEllipsis && r.end == rangeEllipsis
}
+func compareRanges(r1 []Range, r2 []Range) bool {
+ if len(r1) != len(r2) {
+ return false
+ }
+ for idx := range r1 {
+ if r1[idx] != r2[idx] {
+ return false
+ }
+ }
+ return true
+}
+
func RangesToString(ranges []Range) string {
strs := []string{}
for _, r := range ranges {