about
3/05/2022
Introduction
Design Bite - Introduction
Concept, Architecture, TextFinder Spec, TextFinder Impl
- Hannibal
1.0 Prologue
- designing concept, architecture, specification, and documenting the design
- implementing and testing code, and documenting the results
- deploying code and documentation
2.0 Concept Development
2.1 - TextFinder Concept
- Find links in html files, write them to a test page, then click on each link to check for 404s.
- Find all html pages that mention a specific Rust feature, e.g., Arc<T>, to build a glossary of links.
- where did I write about xyz?
- May need to look at thousands of files. So performance is an issue.
- Some uses seem to require using regular expressions to specify text to find.
- How do we build flexibility to handle a variety of uses, e.g., things cited above.
- Are there any existing parts we can reuse?
3.0 Architecture
3.1 TextFinder Architecture
- Accept information from the command line that specifies directories to search, kinds of files to analyze, text to find, and any options that seem appropriate.
- Navigate through the directory tree rooted at an input path, find names of all files that match specified patterns, e.g., extensions like ".html", ".rs", ".h", ".cpp", ..., and the paths where they are found, and send on for text search.
- Open each such file and search for specified text. Send results on for display.
- Extract useful information from the data stream, perform any required post-processing, and display the results.
- TextFinder executive creates instances of the implementation's types and starts the processing flow. It creates CmdlnParser and accepts its parsed output, creates an instance of DirNav and configures it with the TextSearch type. It creates an instance of the Display type, and configures TextSearch with text and a reference to the Display type.
- CmdlnParser accepts the input command line, parses it into an associative list of attributes - path, patterns, text, ... - and returns that information to TextFinder.
- DirNav accepts a starting path and the set of file patterns to find, and recursively visits all directories in the directory tree rooted at the specified path. Each time it enters a directory and finds file names that match one of its patterns it passes that information on for text search, using an eventing interface.
- TextSearch opens each file it's given and searches for the specified text. It then passes that information on for display.
- Display is interesting. What it needs to do is very application specific, as indicated in the Textfinder Concept. Since TextFinder executive configures TextSearch with a reference to its display, the application can provide several display types, one of which is instantiated based on user input.
4.0 TextFinder Specification:
- Identify all files in a directory subtree that match one or more patterns and contain a specified text.
- Specify root path, one or more file patterns (.h, .cpp, .cs, .rs, ...), and search text on command line.
-
Specify options
/s [true|false] ,/v [true|false] ,/H [true|false] /h [true|false] for recursive directory walk, verbose output header, Hidden dirs with no match, and help message, respectively. - Display file name and path, without duplication of path name, e.g., organized by directory, for files containing the search text.
-
Interesting extensions, not required for this implementation:
- Replace text by regular expressions for both search text and file patterns.
- Replace sequential file searches with parallel searches to improve performance and useability.
5.0 Implementation
-
Executive type is defined in the TextFinder package. It creates an instance ofDirNav<Finder> and configures its internalFinder instance with a reference to an instance ofGenOut . This generates a data flow pipe-line which dominates TextFinder processing. -
DirNav<Finder> and theDirEvent interface is defined in the DirNav package. In its constructorDirNav creates an instance ofFinder using a factory function specified in the DirEvent trait and implemented by Finder. It exposes a public methodget_app(&mut self) -> &mut App . The App type is a generic parameter which Executive supplied by constructingDirNav<Finder> .get_app() is called byExecutive to configure theFinder app with an instance ofGenOut and search text.DirNav provides a functionvisit(&mut self, dir: Path) -> io::Result<()> thatExecutive calls to start TextFinder processing flow. -
Finder andSearchEvent are defined in the TextSearch package.Finder creates a file path using file name and current directory, passed byDirNav<Finder> . It attempts to open the file and, if successful it searches the file for text supplied byExecutive . In either case it reports the result toGenOut using theSearchEvent interface. -
GenOut is defined in the Display package. It receives search events fromFinder and builds information for TextFinder users. For simple applications - see uses in the Concept section - it simply formats results information and writes to the console. For more complex applications it may build an internal data structure and do some post processing for each search event, perhaps sending out the entire results data at the end of the program. If so, it will likely indicate search activities, perhaps by displaying directories as they become available, so users know that the application is running as expected.