Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
* origin/master:
  Add --line-number option
  Add [no-]with-filename/ options
  Only use color setting and remove nocolor setting.
  Make tty only affect the default setting of options
  Remove unused enums
  Add --null option
  Fix include directives
  • Loading branch information
Gary R. Van Sickle committed Dec 27, 2024
2 parents 5289378 + 1b11491 commit b79a8bf
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 127 deletions.
4 changes: 3 additions & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ int main(int argc, char **argv)
arg_parser.m_dirjobs, files_to_scan_queue);

// Set up the output task object.
OutputTask output_task(arg_parser.m_color, arg_parser.m_nocolor, arg_parser.m_column, match_queue);
OutputTask output_task(arg_parser.m_color, arg_parser.m_prefix_file,
arg_parser.m_line_number,
arg_parser.m_column, arg_parser.m_nullsep, match_queue);

// Create the FileScanner object.
std::unique_ptr<FileScanner> file_scanner(FileScanner::Create(files_to_scan_queue, match_queue, arg_parser.m_pattern, arg_parser.m_ignore_case, arg_parser.m_word_regexp, arg_parser.m_pattern_is_literal));
Expand Down
52 changes: 42 additions & 10 deletions src/ArgParse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

#include "../build_info.h"

#include <libext/cpuidex.hpp>
#include "libext/cpuidex.hpp"

// Std C++.
#include <locale>
Expand Down Expand Up @@ -55,7 +55,7 @@ namespace lmcppop = lmcppop_int::option;
#include <pcre.h>
#endif
#if HAVE_LIBPCRE2 == 1
#include <FileScannerPCRE2.h>
#include "FileScannerPCRE2.h"
#endif

#include <fcntl.h>
Expand Down Expand Up @@ -112,19 +112,17 @@ enum OPT
OPT_SECTION = 255,
OPT_IGNORE_CASE = 1,
OPT_SMART_CASE,
OPT_NO_SMART_CASE,
OPT_HANDLE_CASE,
OPT_LITERAL,
OPT_WORDREGEX,
OPT_COLOR,
OPT_NOCOLOR,
OPT_PREFIX_FILE,
OPT_NULLSEP,
OPT_IGNORE_DIR,
OPT_NOIGNORE_DIR,
OPT_IGNORE_FILE,
OPT_INCLUDE,
OPT_EXCLUDE,
OPT_FOLLOW,
OPT_NOFOLLOW,
OPT_RECURSE_SUBDIRS,
OPT_ONLY_KNOWN_TYPES,
OPT_TYPE,
Expand All @@ -138,8 +136,8 @@ enum OPT
OPT_HELP_TYPES,
OPT_USAGE,
OPT_VERSION,
OPT_LINE_NUMBER,
OPT_COLUMN,
OPT_NOCOLUMN,
OPT_TEST_LOG_ALL,
OPT_TEST_NOENV_USER,
OPT_TEST_USE_MMAP,
Expand Down Expand Up @@ -524,11 +522,17 @@ static const std::array f_raw_options = std::to_array<PreDescriptor>({
{ OPT_WORDREGEX, 0, "w", "word-regexp", Arg::None, "PATTERN must match a complete word."},
{ OPT_LITERAL, 0, "Q", "literal", Arg::None, "Treat all characters in PATTERN as literal."},
{ "Search Output:" },
{ OPT_PREFIX_FILE, ENABLE, "H", "with-filename", Arg::None, "Prefix the result with the file name."},
{ OPT_PREFIX_FILE, DISABLE, "h", "no-with-filename", Arg::None, "Prefix the file name on a separate line before matches (default)."},
{ OPT_LINE_NUMBER, ENABLE, "n", "line-number", Arg::None, "Print the line number of each match (default)."},
{ OPT_LINE_NUMBER, DISABLE, "", "no-line-number", Arg::None, "Don't print the line number."},
{ OPT_COLUMN, ENABLE, "", "column", Arg::None, "Print column of first match after line number."},
{ OPT_COLUMN, DISABLE, "", "nocolumn", Arg::None, "Don't print column of first match (default)."},
{ "File presentation:" },
{ OPT_COLOR, ENABLE, "", "color,colour", Arg::None, "Render the output with ANSI color codes."},
{ OPT_COLOR, DISABLE, "", "nocolor,nocolour", Arg::None, "Render the output without ANSI color codes."},
{ OPT_NULLSEP, ENABLE, "", "null", Arg::None,
"Print a zero character '\0' instead of a colon ':' after a file name."},
{ "File/directory inclusion/exclusion:" },
{ OPT_IGNORE_DIR, ENABLE, DISABLE, "", "[no]ignore-dir,[no]ignore-directory", "NAME", Arg::NonEmpty, "[Do not] exclude directories with NAME."},
// grep-style --include=glob and --exclude=glob
Expand All @@ -538,7 +542,7 @@ static const std::array f_raw_options = std::to_array<PreDescriptor>({
// ack-style --ignore-file=FILTER:FILTERARGS
{ OPT_IGNORE_FILE, 0, "", "ignore-file", "FILTER:FILTERARGS", Arg::NonEmpty, "Files matching FILTER:FILTERARGS (e.g. ext:txt,cpp) will be ignored." },
{ OPT_RECURSE_SUBDIRS, ENABLE, "r,R", "recurse", Arg::None, "Recurse into subdirectories (default: on)." },
{ OPT_RECURSE_SUBDIRS, DISABLE, "n", "no-recurse", Arg::None, "Do not recurse into subdirectories."},
{ OPT_RECURSE_SUBDIRS, DISABLE, "", "no-recurse", Arg::None, "Do not recurse into subdirectories."},
{ OPT_FOLLOW, ENABLE, DISABLE, "", "[no]follow", "", Arg::None, "[Do not] follow symlinks (default: nofollow)." },
{ OPT_ONLY_KNOWN_TYPES, ENABLE, "k", "known-types", Arg::None, "Only search in files of recognized types (default: on)."},
{ OPT_TYPE, ENABLE, "", "type", "[no]TYPE", Arg::NonEmpty, "Include only [exclude all] TYPE files. Types may also be specified as --[no]TYPE."},
Expand Down Expand Up @@ -763,13 +767,41 @@ void ArgParse::Parse(int argc, char **argv)

m_word_regexp = options[OPT_WORDREGEX];
m_pattern_is_literal = options[OPT_LITERAL];
m_column = (options[OPT_COLUMN].last()->type() == ENABLE);

// If the output is going to a terminal, use color and group
// the matches under the filename. So for the TTY, by
// default, we print:
// filename
// lineno:column:match
// [...]
// while for non-TTY we print:
// filename:lineno:column:match
// [...]
if(!isatty(fileno(stdout)))
{
m_prefix_file = true;
m_color=false;
}

if(options[OPT_COLOR]) // If not specified on command line, defaults to both == false.
{
m_color = (options[OPT_COLOR].last()->type() == ENABLE);
m_nocolor = !m_color;
}

if(options[OPT_PREFIX_FILE])
{
m_prefix_file = (options[OPT_PREFIX_FILE].last()->type() == ENABLE);
}
if(options[OPT_LINE_NUMBER])
{
m_line_number = (options[OPT_LINE_NUMBER].last()->type() == ENABLE);
}
m_column = (options[OPT_COLUMN].last()->type() == ENABLE);
if(m_column)
{
m_line_number = true;
}

if(options[OPT_RECURSE_SUBDIRS]) // m_recurse defaults to true, so only assign if option was really given.
{
m_recurse = (options[OPT_RECURSE_SUBDIRS].last()->type() == ENABLE);
Expand Down
15 changes: 12 additions & 3 deletions src/ArgParse.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ class ArgParse
bool m_pattern_is_literal { false };

/// true if we should print the column of the first match after the line number.
bool m_line_number { true };

/// true if we should print the column of the first match
/// after the line number. Setting this to true implies will
/// also set m_line_number to true.
bool m_column { false };

/// The file and directory paths given on the command line.
Expand All @@ -138,9 +143,13 @@ class ArgParse
int m_dirjobs { 0 };

/// Whether to use color output or not.
/// both false == not specified on command line.
bool m_color { false };
bool m_nocolor { false };
bool m_color { true };

/// Whether to prefix each match with the filename
bool m_prefix_file { false };

/// Whether to write a null after a filename instead of ':'.
bool m_nullsep { false };

/// Whether to recurse into subdirectories or not.
bool m_recurse { true };
Expand Down
133 changes: 52 additions & 81 deletions src/MatchList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

#include <iostream>
#include <sstream>
#include <future/string.hpp>
#include "future/string.hpp"


void MatchList::SetFilename(std::string filename)
Expand Down Expand Up @@ -74,86 +74,57 @@ void MatchList::Print(std::ostream &sstrm, OutputContext &output_context) const

std::string composition_buffer;
composition_buffer.reserve(256);

// The only real difference between TTY vs. non-TTY printing here is that for TTY we print:
// filename
// lineno:column:match
// [...]
// while for non-TTY we print:
// filename:lineno:column:match
// [...]
if(output_context.is_output_tty())
{
// Render to a TTY device.

// Print file header.
if(color) composition_buffer += *color_filename;
composition_buffer += no_dotslash_fn;
if(color) composition_buffer += *color_default;
composition_buffer += '\n';
sstrm << composition_buffer;

// Print the individual matches.
for(const Match& it : m_match_list)
{
composition_buffer.clear();
if(color) composition_buffer += *color_lineno;
composition_buffer += std::to_string(it.m_line_number);
if(color) composition_buffer += *color_default;
composition_buffer += ':';
sstrm << composition_buffer;
if(output_context.is_column_print_enabled())
{
sstrm << it.m_pre_match.length()+1 << ':';
}
composition_buffer.clear();
composition_buffer += it.m_pre_match;
if(color) composition_buffer += *color_match;
composition_buffer += it.m_match;
if(color) composition_buffer += *color_default;
composition_buffer += it.m_post_match;
composition_buffer += '\n';
sstrm << composition_buffer;
}
}
else
{
// Render to a pipe or file.

for(const Match& it : m_match_list)
{
// Print file name at the beginning of each line.
composition_buffer.clear();
if(color) composition_buffer += *color_filename;
composition_buffer += no_dotslash_fn;
if(color) composition_buffer += *color_default;
composition_buffer += ':';

// Line number.
if(color) composition_buffer += *color_lineno;
composition_buffer += std::to_string(it.m_line_number);
if(color) composition_buffer += *color_default;
composition_buffer += ':';

sstrm << composition_buffer;

// The column, if enabled.
if(output_context.is_column_print_enabled())
{
sstrm << it.m_pre_match.length()+1 << ':';
}

// The match text.
composition_buffer.clear();
composition_buffer += it.m_pre_match;
if(color) composition_buffer += *color_match;
composition_buffer += it.m_match;
if(color) composition_buffer += *color_default;
composition_buffer += it.m_post_match;
composition_buffer += '\n';
sstrm << composition_buffer;
}
}

const char file_separator(output_context.use_nullsep()
? '\0': (output_context.prefix_file() ? ':' : '\n'));

if(!output_context.prefix_file())
{
// Print file header.
if(color) composition_buffer += *color_filename;
composition_buffer += no_dotslash_fn;
if(color) composition_buffer += *color_default;
composition_buffer += file_separator;
sstrm << composition_buffer;
}

// Print the individual matches.
for(const Match& it : m_match_list)
{
// Print file prefix.
if(output_context.prefix_file())
{
composition_buffer.clear();
if(color) composition_buffer += *color_filename;
composition_buffer += no_dotslash_fn;
if(color) composition_buffer += *color_default;
composition_buffer += file_separator;
sstrm << composition_buffer;
}
// Print line and column numbers.
if(output_context.is_line_print_enabled())
{
composition_buffer.clear();
if(color) composition_buffer += *color_lineno;
composition_buffer += std::to_string(it.m_line_number);
if(color) composition_buffer += *color_default;
composition_buffer += ':';
sstrm << composition_buffer;
if(output_context.is_column_print_enabled())
{
sstrm << it.m_pre_match.length()+1 << ':';
}
}
// Print match
composition_buffer.clear();
composition_buffer += it.m_pre_match;
if(color) composition_buffer += *color_match;
composition_buffer += it.m_match;
if(color) composition_buffer += *color_default;
composition_buffer += it.m_post_match;
composition_buffer += '\n';
sstrm << composition_buffer;
}
}

std::vector<Match>::size_type MatchList::GetNumberOfMatchedLines() const noexcept
Expand Down
7 changes: 5 additions & 2 deletions src/OutputContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@

#include "OutputContext.h"

OutputContext::OutputContext(bool output_is_tty, bool enable_color, bool print_column)
: m_output_is_tty(output_is_tty), m_enable_color(enable_color), m_print_column(print_column)
OutputContext::OutputContext(bool enable_color, bool prefix_file, bool print_line_number,
bool print_column, bool nullsep)
: m_enable_color(enable_color), m_prefix_file(prefix_file),
m_print_line_number(print_line_number),
m_print_column(print_column), m_nullsep(nullsep)
{
if(m_enable_color)
{
Expand Down
17 changes: 13 additions & 4 deletions src/OutputContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@
class OutputContext
{
public:
OutputContext(bool output_is_tty, bool enable_color, bool print_column);
OutputContext(bool enable_color, bool prefix_file, bool print_line_number, bool print_column, bool nullsep);
~OutputContext();

[[nodiscard]] inline bool is_output_tty() const noexcept { return m_output_is_tty; };
[[nodiscard]] inline bool is_color_enabled() const noexcept { return m_enable_color; };
[[nodiscard]] inline bool prefix_file() const noexcept { return m_prefix_file; };
[[nodiscard]] inline bool is_line_print_enabled() const noexcept { return m_print_line_number; };
[[nodiscard]] inline bool is_column_print_enabled() const noexcept { return m_print_column; };
[[nodiscard]] inline bool use_nullsep() const noexcept { return m_nullsep; };

/// @name Active colors.
/// @{
Expand All @@ -47,14 +49,21 @@ class OutputContext

private:

bool m_output_is_tty;

/// Whether to output color or not. Determined by logic in OutputTask's constructor.
bool m_enable_color;

/// Whether to prefix each match with the filename
bool m_prefix_file;

/// Whether to print the line number of the match or not
bool m_print_line_number;

/// Whether to print the column number of the first match or not.
bool m_print_column;

/// Whether to write a null after a filename instead of ':'.
bool m_nullsep;

/// @name Default output colors.
/// @{
// ANSI SGR parameter setting sequences for setting the color and boldness of the output text.
Expand Down
Loading

0 comments on commit b79a8bf

Please sign in to comment.