aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/search.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
committerJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
commitd5f194ce780c95821a855aca3c19426576d28ae0 (patch)
treed45f461b19f9118ad2bb1f440a7a08973ad18832 /src/nvim/search.c
parentc5d770d311841ea5230426cc4c868e8db27300a8 (diff)
parent44740e561fc93afe3ebecfd3618bda2d2abeafb0 (diff)
downloadrneovim-rahm.tar.gz
rneovim-rahm.tar.bz2
rneovim-rahm.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309HEADrahm
Diffstat (limited to 'src/nvim/search.c')
-rw-r--r--src/nvim/search.c79
1 files changed, 67 insertions, 12 deletions
diff --git a/src/nvim/search.c b/src/nvim/search.c
index debc5697d1..9f8ceae2a0 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -30,10 +30,10 @@
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
-#include "nvim/highlight.h"
#include "nvim/highlight_defs.h"
#include "nvim/indent_c.h"
#include "nvim/insexpand.h"
@@ -41,7 +41,6 @@
#include "nvim/mark.h"
#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
-#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -1203,6 +1202,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, size_t patlen
// Compute msg_row early.
msg_start();
+ msg_ext_set_kind("search_cmd");
// Get the offset, so we know how long it is.
if (!cmd_silent
@@ -1422,7 +1422,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, size_t patlen
cmdline_search_stat(dirc, &pos, &curwin->w_cursor,
show_top_bot_msg, msgbuf, msgbuflen,
(count != 1 || has_offset
- || (!(fdo_flags & FDO_SEARCH)
+ || (!(fdo_flags & kOptFdoFlagSearch)
&& hasFolding(curwin, curwin->w_cursor.lnum, NULL,
NULL))),
SEARCH_STAT_DEF_MAX_COUNT,
@@ -2349,7 +2349,7 @@ void showmatch(int c)
}
if ((lpos = findmatch(NULL, NUL)) == NULL) { // no match, so beep
- vim_beep(BO_MATCH);
+ vim_beep(kOptBoFlagShowmatch);
return;
}
@@ -2534,7 +2534,7 @@ int current_search(int count, bool forward)
}
}
- if (fdo_flags & FDO_SEARCH && KeyTyped) {
+ if (fdo_flags & kOptFdoFlagSearch && KeyTyped) {
foldOpenCursor();
}
@@ -2973,6 +2973,10 @@ typedef struct {
#define CAMEL_BONUS 30
/// bonus if the first letter is matched
#define FIRST_LETTER_BONUS 15
+/// bonus if exact match
+#define EXACT_MATCH_BONUS 100
+/// bonus if case match when no ignorecase
+#define CASE_MATCH_BONUS 25
/// penalty applied for every letter in str before the first match
#define LEADING_LETTER_PENALTY (-5)
/// maximum penalty for leading letters
@@ -2988,11 +2992,21 @@ typedef struct {
/// Compute a score for a fuzzy matched string. The matching character locations
/// are in "matches".
-static int fuzzy_match_compute_score(const char *const str, const int strSz,
- const uint32_t *const matches, const int numMatches)
+static int fuzzy_match_compute_score(const char *const fuzpat, const char *const str,
+ const int strSz, const uint32_t *const matches,
+ const int numMatches)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
assert(numMatches > 0); // suppress clang "result of operation is garbage"
+ const char *p = str;
+ uint32_t sidx = 0;
+ bool is_exact_match = true;
+ const char *const orig_fuzpat = fuzpat - numMatches;
+ const char *curpat = orig_fuzpat;
+ int pat_idx = 0;
+ // Track consecutive camel case matches
+ int consecutive_camel = 0;
+
// Initialize score
int score = 100;
@@ -3010,6 +3024,7 @@ static int fuzzy_match_compute_score(const char *const str, const int strSz,
// Apply ordering bonuses
for (int i = 0; i < numMatches; i++) {
const uint32_t currIdx = matches[i];
+ bool is_camel = false;
if (i > 0) {
const uint32_t prevIdx = matches[i - 1];
@@ -3019,23 +3034,35 @@ static int fuzzy_match_compute_score(const char *const str, const int strSz,
score += SEQUENTIAL_BONUS;
} else {
score += GAP_PENALTY * (int)(currIdx - prevIdx);
+ // Reset consecutive camel count on gap
+ consecutive_camel = 0;
}
}
+ int curr;
// Check for bonuses based on neighbor character value
if (currIdx > 0) {
// Camel case
- const char *p = str;
int neighbor = ' ';
- for (uint32_t sidx = 0; sidx < currIdx; sidx++) {
+ while (sidx < currIdx) {
neighbor = utf_ptr2char(p);
MB_PTR_ADV(p);
+ sidx++;
}
- const int curr = utf_ptr2char(p);
+ curr = utf_ptr2char(p);
+ // Enhanced camel case scoring
if (mb_islower(neighbor) && mb_isupper(curr)) {
- score += CAMEL_BONUS;
+ score += CAMEL_BONUS * 2; // Double the camel case bonus
+ is_camel = true;
+ consecutive_camel++;
+ // Additional bonus for consecutive camel
+ if (consecutive_camel > 1) {
+ score += CAMEL_BONUS;
+ }
+ } else {
+ consecutive_camel = 0;
}
// Bonus if the match follows a separator character
@@ -3047,8 +3074,36 @@ static int fuzzy_match_compute_score(const char *const str, const int strSz,
} else {
// First letter
score += FIRST_LETTER_BONUS;
+ curr = utf_ptr2char(p);
+ }
+
+ // Case matching bonus
+ if (mb_isalpha(curr)) {
+ while (pat_idx < i && *curpat) {
+ MB_PTR_ADV(curpat);
+ pat_idx++;
+ }
+
+ if (curr == utf_ptr2char(curpat)) {
+ score += CASE_MATCH_BONUS;
+ // Extra bonus for exact case match in camel
+ if (is_camel) {
+ score += CASE_MATCH_BONUS / 2;
+ }
+ }
+ }
+
+ // Check exact match condition
+ if (currIdx != (uint32_t)i) {
+ is_exact_match = false;
}
}
+
+ // Boost score for exact matches
+ if (is_exact_match && numMatches == strSz) {
+ score += EXACT_MATCH_BONUS;
+ }
+
return score;
}
@@ -3127,7 +3182,7 @@ static int fuzzy_match_recursive(const char *fuzpat, const char *str, uint32_t s
// Calculate score
if (matched) {
- *outScore = fuzzy_match_compute_score(strBegin, strLen, matches, nextMatch);
+ *outScore = fuzzy_match_compute_score(fuzpat, strBegin, strLen, matches, nextMatch);
}
// Return best result