TextFinder

recursive, regex-based file-content search tool

Concept:

A recursive, regex-based file-content search tool written in C++17. Given a root directory, a set of file patterns, and a regular expression, it walks the directory tree and prints every file whose content contains a match.

Packages:

The project is composed of several packages linked by relative paths.
PackageKindRole
ProcessCmdLine library Parses /Key [Value] or -Key [Value] command-line arguments
FileSystem library Provides portable file and directory path utilities
DirExplorerT library Generic, event-driven depth-first directory walker
TextSearch library Reads file content and tests it against a compiled regular expression
TextFinder executable Application - wires the packages and drives the search

Quick Start:

# 1. Build with Visual Studio
#    Open TextFinder.sln, select Release x64, press Ctrl+Shift+B

# 2. Search the parent directory for C++ files containing "class"
TextFinder.exe /P ".." /p "h,cpp" /r "class"

# PowerShell / cmd users - the - prefix works equally well
TextFinder.exe -P ".." -p "h,cpp" -r "class"

Command-Line Options:

Options accept either a / prefix (Windows / PowerShell) or a - prefix (bash / Unix); both are equivalent.
OptionArgumentDefaultMeaning
/P path . Root directory for the search
/p patterns (all files) Comma-separated file patterns, e.g. h,cpp,txt
/r regex . (any) Regular expression matched against file content
/s true/false true Recurse into subdirectories
/H true/false true Hide directories that contain no matching files
/v (flag) off Print all resolved options before searching
/h (flag) off Print help and exit
Examples:
# Find all C++ header files containing "template" under the current directory
TextFinder.exe /P "." /p "h,hpp" /r "template"

# Search source and markdown files for a TODO comment, show all directories
TextFinder.exe /P "." /p "cpp,h,md" /r "TODO" /H false

# Verbose output - shows resolved path, patterns, and regex before searching
TextFinder.exe /P ".." /p "h,cpp" /r "virtual" /v

Output:

Matching files are grouped under their containing directory:
  TextFinder ver 2.1.0
 =======================
  searching path: "../"
  patterns: ["h", "cpp"]
  matching files with regex: "class"

  ../TextFinder/src
      "TextFinder.h"
      "TextFinder.cpp"

  ../DirExplorerT/src
      "DirExplorerT.h"

  processed 38 files in 14 dirs

  That's all Folks!
Directories that contain no matching files are hidden by default (/H true). Set /H false to print every directory as it is entered.

Design:

ProcessCmdLine

Parses raw argv tokens into a map of option keys to string values and a vector of file-extension patterns. A token starting with / or - is treated as a key; the next token (if it does not itself start with / or -) becomes its value, otherwise the value is set to "true".

DirExplorerT<App>

Generic depth-first walker. Callers supply an App type that implements two methods:
void doDir(const std::string& dirPath);
void doFile(const std::string& filePath);
DirExplorerT calls doDir when entering a directory and doFile for each file whose extension matches the registered patterns. Build-output and VCS directories (Debug, Release, x64, .git, etc.) are skipped automatically.

TextSearch + Application

TextSearch holds a compiled std::regex and exposes bool searchFile(const std::string& filePath). It reads file content into a std::string buffer and applies std::regex_search to test for a match. Application implements the DirExplorerT callback interface and holds a reference to an ITextFinder pointer so that all searching stays inside TextFinder while all navigation stays inside DirExplorerT<Application>. This separation applies the Single Responsibility Principle cleanly across the two concerns. main wires DirExplorerT<Application> together from the parsed command-line options, then starts the depth-first walk.

Hide/show directory logic

When /H true (the default), a directory header is buffered rather than printed immediately. It is flushed to output only when the first matching file in that directory is found. Directories with no matches are never printed.

Building the Project:

The solution is built with Visual Studio 2019 or later:
# Visual Studio (GUI)
Open TextFinder.sln
Select configuration: Release | x64
Build > Build Solution  (Ctrl+Shift+B)

# MSBuild (command line)
msbuild TextFinder.sln /p:Configuration=Release /p:Platform=x64
The project requires the C++17 standard. Set it in Properties > C/C++ > Language > C++ Language Standard if not already configured.

Testing:

# Unit tests for ProcessCmdLine
cd ProcessCmdLine
TextFinder.exe /t          # runs built-in self-tests with /t flag

# Functional smoke test - search this repo for all files with "TextFinder"
cd TextFinder\Release
TextFinder.exe /P "../../" /p "h,cpp,sln" /r "TextFinder" /v

External Dependencies:

Header / LibrarySourceUsed byPurpose
<regex> C++11 standard library TextSearch Compile and match regular expressions
<filesystem> C++17 standard library FileSystem, DirExplorerT Portable directory iteration and path manipulation
All other functionality uses the C++ standard library only.