Getting search matches count

Context: in my project I need to show search matches count (@codemirror/search) for better UX.

I didn’t find any exposed command / helper for that in @codemirror/search.

Question: is there a way to get search matches count based on SearchQuery or can it be easily exposed from @codemirror/search?

This is not something that @codemirror/search computes, which is why it can’t expose it.

I just wondered that there should be something in state to highlight matches properly, and it would be possible to return length of those matches.

But okay, will try to come up with some workaround…

It does that only for the viewport, to avoid spending too much time searching in big documents.

Can some method be easily created (e.g. findMatches), which returns ranges (or any reasonable data, so it is possible to understand how many matches I have) that selectMatches would select?

Or any hint how I could get all matches count?

What I tried: keep current selection in variable → selectMatches → get state selection ranges length → restore initial selection.
But this solution seems to be ugly for that specific purpose…

You could run the cursor you get from SearchQuery.getCursor over the document and count matches.

Thanks, it helped.

For those who curious, here is the code:

function getSearchMatchesCount(state, config) {
  const searchQuery = new SearchQuery(config)
  
  const cursor = searchQuery.getCursor(state)
  
  let matchesCount = 0
  
  for (const entry of cursor) {
    matchesCount++
  }
  
  return matchesCount
}
1 Like

Yes, it works for me. I want to ask, how to get the current cursor? Like this 2 (current) / 5 (count)

I think this can meet my needs. If there is a better way, please let me know.

/**
 * 获取搜索匹配数量
 * @param state
 * @param config
 */
function getSearchMatchesCount(state: EditorState, config?: SearchQuery) {
	const searchQuery = new SearchQuery(config ?? getSearchQuery(state))

	const cursor = searchQuery.getCursor(state);
	const counter = {count: 0, current: 1}

	// 获取当前光标位置
	const {from, to} = state.selection.main

	let item = cursor.next()
	while (!item.done) {
		// 根据光标位置判断当前匹配项
		if (item.value.from === from && item.value.to === to) {
			counter.current = counter.count + 1
		}

		item = cursor.next()
		counter.count++
	}

	return counter
}
1 Like