- Início
- Documentation
- Nativos
- Pipeline Nativa de Texto/Busca
Pipeline Nativa de Texto/Busca
Este documento mapeia a superfície de texto/busca do @f5-sales-demo/pi-natives (grep, glob, text, highlight) desde os wrappers TypeScript até as exportações Rust N-API e de volta aos objetos de resultado JS.
A terminologia segue docs/natives-architecture.md:
- Wrapper: API TS em
packages/natives/src/* - Camada de módulo Rust: exportações N-API em
crates/pi-natives/src/* - Cache de varredura compartilhado: cache de entradas de diretório baseado em
fs_cacheusado pelos fluxos de descoberta/busca
Arquivos de implementação
Seção intitulada “Arquivos de implementação”packages/natives/src/grep/index.tspackages/natives/src/grep/types.tspackages/natives/src/glob/index.tspackages/natives/src/glob/types.tspackages/natives/src/text/index.tspackages/natives/src/text/types.tspackages/natives/src/highlight/index.tspackages/natives/src/highlight/types.tscrates/pi-natives/src/grep.rscrates/pi-natives/src/glob.rscrates/pi-natives/src/glob_util.rscrates/pi-natives/src/fs_cache.rscrates/pi-natives/src/text.rscrates/pi-natives/src/highlight.rscrates/pi-natives/src/fd.rs
Mapeamento API JS ↔ exportação Rust
Seção intitulada “Mapeamento API JS ↔ exportação Rust”| API wrapper JS | Exportação Rust (#[napi], snake_case -> camelCase) | Módulo Rust |
|---|---|---|
grep(options, onMatch?) | grep | grep.rs |
searchContent(content, options) | search | grep.rs |
hasMatch(content, pattern, options?) | hasMatch | grep.rs |
fuzzyFind(options) | fuzzyFind | fd.rs |
glob(options, onMatch?) | glob | glob.rs |
invalidateFsScanCache(path?) | invalidateFsScanCache | fs_cache.rs |
wrapTextWithAnsi(text, width) | wrapTextWithAnsi | text.rs |
truncateToWidth(text, maxWidth, ellipsis, pad) | truncateToWidth | text.rs |
sliceWithWidth(line, startCol, length, strict?) | sliceWithWidth | text.rs |
extractSegments(line, beforeEnd, afterStart, afterLen, strictAfter) | extractSegments | text.rs |
sanitizeText(text) | sanitizeText | text.rs |
visibleWidth(text) | visibleWidth | text.rs |
highlightCode(code, lang, colors) | highlightCode | highlight.rs |
supportsLanguage(lang) | supportsLanguage | highlight.rs |
getSupportedLanguages() | getSupportedLanguages | highlight.rs |
Visão geral da pipeline por subsistema
Seção intitulada “Visão geral da pipeline por subsistema”1) Busca regex (grep, searchContent, hasMatch)
Seção intitulada “1) Busca regex (grep, searchContent, hasMatch)”Fluxo de entrada/opções
Seção intitulada “Fluxo de entrada/opções”- O wrapper TS encaminha as opções para o nativo:
grep/index.tspassaoptionspraticamente sem alterações e converte o callback de(match) => voidpara o formato de callback threadsafe do napi(err, match).searchContentehasMatchpassam string/Uint8Arraydiretamente.
- Structs de opção em Rust em
grep.rsdeserializam campos camelCase (ignoreCase,maxCount,contextBefore,contextAfter,maxColumns,timeoutMs). grepcriaCancelTokena partir detimeoutMs+AbortSignale executa dentro detask::blocking("grep", ...).
Ramificações de execução
Seção intitulada “Ramificações de execução”- Ramificação em memória (utilitário puro)
search→search_sync→run_searchnos bytes de conteúdo fornecidos.- Sem varredura de sistema de arquivos, sem
fs_cache.
- Ramificação de arquivo único (dependente do sistema de arquivos)
grep_syncresolve o caminho, verifica se os metadados são de arquivo, processa atéMAX_FILE_BYTESpor arquivo (4 MiB) através do matcher ripgrep.
- Ramificação de diretório (dependente do sistema de arquivos)
- Consulta opcional ao cache via
fs_cache::get_or_scanquandocache: true. - Varredura nova via
fs_cache::force_rescanquandocache: false. - Reverificação opcional de resultado vazio quando a idade do cache excede
empty_recheck_ms(). - Filtragem de entradas: somente arquivos + filtro glob opcional (
glob_util) + filtro de tipo opcional (js,ts,rust, etc.).
- Consulta opcional ao cache via
Semântica de busca/coleta
Seção intitulada “Semântica de busca/coleta”- Motor de regex:
grep_regex::RegexMatcherBuildercomignoreCaseemultiline. - Resolução de contexto:
contextBefore/contextAftersubstituem o legadocontext.- Modos sem conteúdo zeram a coleta de contexto.
- Modos de saída:
content=> umGrepMatchpor ocorrência.countefilesWithMatchesambos mapeiam para entradas estilo contagem (lineNumber=0,line="",matchCountdefinido).
- Limites:
offsetglobal emaxCountaplicados em todos os arquivos.- O caminho paralelo é usado apenas quando
maxCountnão está definido eoffset == 0; caso contrário, o caminho sequencial preserva a semântica determinística de offset/limite global.
Formatação do resultado de volta para JS
Seção intitulada “Formatação do resultado de volta para JS”- Os campos de
SearchResult/GrepResultdo Rust mapeiam para tipos TS via conversão de campos de objeto N-API. - Contadores são limitados a
u32antes de cruzar a fronteira N-API. - Booleanos opcionais são omitidos a menos que sejam true em alguns caminhos (
limitReached). - O callback de streaming recebe cada
GrepMatchformatado (entrada de conteúdo ou contagem).
Comportamento em caso de falha
Seção intitulada “Comportamento em caso de falha”searchContentretornaSearchResult.errorpara falhas de regex/busca em vez de lançar exceção.greprejeita em erros graves (caminho inválido, glob/regex inválido, timeout/abort de cancelamento).hasMatchretornaResult<bool>e lança exceção em padrão inválido/erros de decodificação UTF-8.- Erros de abertura/busca de arquivo em varreduras multi-arquivo são ignorados por arquivo; a varredura continua.
Tratamento de regex malformado
Seção intitulada “Tratamento de regex malformado”grep.rs sanitiza chaves antes da compilação de regex:
- Chaves semelhantes a repetição inválidas são escapadas (
{/}->\{/\}) quando não podem formar{N},{N,},{N,M}. - Isso impede que fragmentos comuns de template literal (por exemplo
${platform}) falhem como repetição malformada. - Sintaxe de regex inválida remanescente ainda retorna um erro de regex.
2) Descoberta de arquivos (glob) e busca fuzzy de caminhos (fuzzyFind)
Seção intitulada “2) Descoberta de arquivos (glob) e busca fuzzy de caminhos (fuzzyFind)”glob e fuzzyFind compartilham varreduras do fs_cache; a lógica de correspondência difere.
Fluxo do glob
Seção intitulada “Fluxo do glob”- Wrapper TS (
glob/index.ts):path.resolve(options.path).- Padrões:
pattern="*",hidden=false,gitignore=true,recursive=true.
- O Rust
globconstróiGlobConfige compila o padrão viaglob_util::compile_glob. - Fonte de entradas:
cache=true=>get_or_scan+force_rescanopcional para vazio obsoleto.cache=false=>force_rescan(..., store=false)(somente novo).
- Filtragem:
- Sempre ignora
.git. - Ignora
node_modulesa menos que solicitado (includeNodeModulesou padrão mencionando node_modules). - Aplica correspondência glob.
- Aplica filtro de tipo de arquivo; filtros
file/dirde symlink resolvem metadados do alvo.
- Sempre ignora
- Ordenação opcional por mtime decrescente (
sortByMtime) antes de truncar paramaxResults.
Fluxo do fuzzyFind (implementado em fd.rs)
Seção intitulada “Fluxo do fuzzyFind (implementado em fd.rs)”- O wrapper TS é exportado do módulo
grep, mas a implementação Rust reside emfd.rs. - Fonte de varredura compartilhada do
fs_cachecom a mesma divisão cache/sem-cache e política de reverificação de vazio obsoleto. - Pontuação:
- pontuação fuzzy baseada em exata / começa-com / contém / subsequência
- caminho de pontuação normalizado por separador/pontuação
- bônus de diretório e desempate determinístico (
score desc, depoispath asc)
- Entradas de symlink são excluídas dos resultados fuzzy.
Comportamento em caso de falha
Seção intitulada “Comportamento em caso de falha”- Padrão glob inválido => erro de
glob_util::compile_glob. - A raiz da busca deve ser um diretório existente (
resolve_search_path), caso contrário erro. - Cancelamentos/timeouts propagam como erros de abort via verificações de
CancelToken::heartbeat()nos loops.
Tratamento de glob malformado
Seção intitulada “Tratamento de glob malformado”glob_util::build_glob_pattern é tolerante:
- Normaliza
\para/. - Auto-prefixa padrões recursivos simples com
**/quandorecursive=true. - Auto-fecha grupos de alternação
{...desbalanceados antes da compilação.
3) Ciclo de vida do cache/varredura compartilhado (fs_cache)
Seção intitulada “3) Ciclo de vida do cache/varredura compartilhado (fs_cache)”fs_cache armazena resultados de varredura como entradas relativas normalizadas (path, fileType, mtime opcional) indexadas por:
- raiz de busca canônica
include_hiddenuse_gitignore
Transições de estado do cache
Seção intitulada “Transições de estado do cache”- Miss / desabilitado
- TTL é
0ou chave ausente/expirada ->collect_entriesnovo.
- TTL é
- Hit
- Idade da entrada
< cache_ttl_ms()-> retorna entradas em cache +cache_age_ms.
- Idade da entrada
- Reverificação de vazio obsoleto (política do chamador em
glob/grep/fd)- Se a consulta retorna zero correspondências e
cache_age_ms >= empty_recheck_ms(), força uma revarredura.
- Se a consulta retorna zero correspondências e
- Invalidação
invalidateFsScanCache(path?):- sem argumento: limpa todas as chaves
- argumento path: remove chaves cuja raiz é prefixo daquele caminho alvo
Compromisso de resultado obsoleto
Seção intitulada “Compromisso de resultado obsoleto”- O cache favorece varreduras repetidas de baixa latência sobre consistência imediata.
- A janela de TTL pode retornar positivos/negativos obsoletos.
- A reverificação de resultado vazio reduz negativos obsoletos para varreduras em cache mais antigas ao custo de uma varredura extra.
- A invalidação explícita é o mecanismo de correção pretendido após mutações de arquivo.
4) Utilitários de texto ANSI (text)
Seção intitulada “4) Utilitários de texto ANSI (text)”Estes são utilitários puros, em memória (sem varredura de sistema de arquivos).
Limites e responsabilidades
Seção intitulada “Limites e responsabilidades”text.rsé responsável pela semântica de células de terminal:- Análise de sequências ANSI
- Largura e fatiamento conscientes de grafemas
- Comportamento de wrap/truncate/sanitize
- Truncamento de linha do
grep.rs(maxColumns) é separado:- truncamento simples por limite de caractere de linhas correspondentes com
... - não preserva estado ANSI e não é consciente de largura de células de terminal
- truncamento simples por limite de caractere de linhas correspondentes com
Comportamentos principais
Seção intitulada “Comportamentos principais”wrapTextWithAnsi: quebra por largura visível, carrega códigos SGR ativos entre linhas quebradas.truncateToWidth: truncamento por célula visível com política de reticências (Unicode,Ascii,Omit), preenchimento à direita opcional e caminho rápido retornando a string JS original quando inalterada.sliceWithWidth: fatiamento por coluna com aplicação opcional de largura estrita.extractSegments: extrai segmentos antes/depois em torno de uma sobreposição enquanto restaura o estado ANSI para o segmentoafter.sanitizeText: remove escapes ANSI + caracteres de controle, descarta surrogates isolados, normaliza CR/LF removendo\r.visibleWidth: conta células visíveis do terminal (tabs usamTAB_WIDTHfixo da implementação Rust).
Comportamento em caso de falha
Seção intitulada “Comportamento em caso de falha”Funções de texto geralmente retornam saída transformada determinística; erros são limitados às fronteiras de conversão de string JS (falhas de conversão de argumentos N-API).
5) Destaque de sintaxe (highlight)
Seção intitulada “5) Destaque de sintaxe (highlight)”highlight.rs é transformação pura (sem FS, sem cache).
- O wrapper encaminha
code,langopcional e paleta de cores ANSI. - O Rust resolve a sintaxe por:
- busca por token/nome
- busca por extensão
- fallback de tabela de alias (
ts/tsx/js -> JavaScript, etc.) - fallback para sintaxe de texto simples quando não resolvido
- Analisa cada linha com
ParseStatedo syntect e pilha de escopos. - Mapeia escopos para 11 categorias semânticas de cor e injeta/reseta códigos de cor ANSI.
Comportamento em caso de falha
Seção intitulada “Comportamento em caso de falha”- Falha de análise por linha não falha a chamada: aquela linha é adicionada sem destaque e o processamento continua.
- Linguagem desconhecida/não suportada faz fallback para sintaxe de texto simples.
Fluxos de utilitário puro vs dependentes de sistema de arquivos
Seção intitulada “Fluxos de utilitário puro vs dependentes de sistema de arquivos”| Fluxo | Acesso ao sistema de arquivos | Cache compartilhado | Notas |
|---|---|---|---|
searchContent / hasMatch | Não | Não | regex apenas nos bytes/string fornecidos |
Funções do módulo text | Não | Não | Apenas ANSI/largura/sanitização |
Funções do módulo highlight | Não | Não | Apenas sintaxe + coloração ANSI |
glob | Sim | Opcional | varreduras de diretório + filtragem glob |
fuzzyFind | Sim | Opcional | varreduras de diretório + pontuação fuzzy |
grep (caminho de arquivo/diretório) | Sim | Opcional (modo diretório) | ripgrep sobre arquivos, filtros/callback opcionais |
Resumo do ciclo de vida ponta a ponta
Seção intitulada “Resumo do ciclo de vida ponta a ponta”- O chamador invoca o wrapper TS com opções tipadas.
- O wrapper normaliza padrões (notavelmente
glob) e encaminha para a exportaçãonative.*. - O Rust valida/normaliza opções e constrói o matcher/configuração de busca.
- Para fluxos de sistema de arquivos, as entradas são varridas (hit/miss/revarredura do cache) e depois filtradas/pontuadas.
- Loops de workers periodicamente chamam o heartbeat de cancelamento; timeout/abort pode terminar a execução.
- O Rust formata as saídas em objetos N-API (
lineNumber,matchCount,limitReached, etc.). - O wrapper TS retorna objetos JS tipados (e callbacks opcionais por correspondência para
grep/glob).