250303.1 · efc601e4bd731d9ed30c32500922e6b947b459d4
released 7.3
reading declarations
@@ -1245,6 +1245,21 @@ class Pattern { { return opcode & 0xffff; }+ /// check if lower case+ static inline bool islowercase(Char c)+ {+ return (c >= 'a' && c <= 'z');+ }+ /// check if upper case+ static inline bool isuppercase(Char c)+ {+ return (c >= 'A' && c <= 'Z');+ }+ /// check if lower or upper case+ static inline bool isanycase(Char c)+ {+ return islowercase(c) || isuppercase(c);+ } /// convert to lower case if c is a letter a-z, A-Z. static inline Char lowercase(Char c) {
@@ -296,7 +296,7 @@ void Pattern::init(const char *options, const uint8_t *pred) for (DFA::State::Edges::iterator t = state->edges.begin(); t != state->edges.end(); ++t) { Char c = t->first;- if (c >= 'a' && c <= 'z')+ if (islowercase(c)) { state->edges[uppercase(c)] = DFA::State::Edge(uppercase(c), t->second.second); ++eno_;@@ -828,7 +828,7 @@ void Pattern::parse( c = static_cast<Char>(s - abtnvfr + '\a'); } }- else if (c >= 'A' && c <= 'Z' && opt_.i)+ else if (isuppercase(c) && opt_.i) { c = lowercase(c); }@@ -1736,7 +1736,7 @@ void Pattern::compile( Char c = t->first; DFA::State *target_state = last_state = last_state->next = dfa_.state(t->second.second); state->edges[c] = DFA::State::Edge(c, target_state);- if (c >= 'a' && c <= 'z')+ if (islowercase(c)) { state->edges[uppercase(c)] = DFA::State::Edge(uppercase(c), target_state); ++eno_;@@ -1765,7 +1765,7 @@ void Pattern::compile( { Char c = t->first; chars.add(c);- if (c >= 'a' && c <= 'z')+ if (islowercase(c)) chars.add(uppercase(c)); } }@@ -1791,9 +1791,9 @@ void Pattern::compile( { if (common.contains(c)) {- if (std::isalpha(c))+ if (isanycase(c)) {- if (c >= 'a' && c <= 'z')+ if (islowercase(c)) { pos = i->second; DFA::State *target_state = last_state = last_state->next = dfa_.state(state->tnode->edges[c].second, pos);@@ -1853,7 +1853,7 @@ void Pattern::compile( if (chars.contains(c)) { DFA::State *target_state = last_state = last_state->next = dfa_.state(state->tnode->edges[c].second);- if (std::isalpha(c))+ if (isanycase(c)) { state->edges[lowercase(c)] = DFA::State::Edge(lowercase(c), target_state); state->edges[uppercase(c)] = DFA::State::Edge(uppercase(c), target_state);@@ -1893,7 +1893,7 @@ void Pattern::compile( DFA::State *target_state = last_state = last_state->next = dfa_.state(&t->second); state->edges[c] = DFA::State::Edge(c, target_state); ++eno_;- if (opt_.i && c >= 'a' && c <= 'z')+ if (opt_.i && islowercase(c)) { state->edges[uppercase(c)] = DFA::State::Edge(uppercase(c), target_state); ++eno_;@@ -1911,12 +1911,8 @@ void Pattern::compile( for (std::map<Char,Tree::Node>::iterator t = state->tnode->edges.begin(); t != state->tnode->edges.end(); ++t) { Char c = t->first;- if (c >= 'a')- {- if (c > 'z')- break;+ if (islowercase(c)) chars.add(uppercase(c));- } } } Moves::iterator i = moves.begin();@@ -1936,9 +1932,9 @@ void Pattern::compile( { if (common.contains(c)) {- if (std::isalpha(c))+ if (isanycase(c)) {- if (c >= 'a' && c <= 'z')+ if (islowercase(c)) { pos = i->second; DFA::State *target_state = last_state = last_state->next = dfa_.state(&state->tnode->edges[c], pos);@@ -1996,7 +1992,7 @@ void Pattern::compile( if (chars.contains(c)) { DFA::State *target_state = last_state = last_state->next = dfa_.state(&state->tnode->edges[c]);- if (opt_.i && std::isalpha(c))+ if (opt_.i && isanycase(c)) { state->edges[lowercase(c)] = DFA::State::Edge(lowercase(c), target_state); state->edges[uppercase(c)] = DFA::State::Edge(uppercase(c), target_state);@@ -2027,7 +2023,7 @@ void Pattern::compile( { Char c = (i << 4) + j; DFA::State *target_state = last_state = last_state->next = dfa_.state(p[j]);- if (opt_.i && std::isalpha(c))+ if (opt_.i && isanycase(c)) { state->edges[lowercase(c)] = DFA::State::Edge(lowercase(c), target_state); state->edges[uppercase(c)] = DFA::State::Edge(uppercase(c), target_state);@@ -2083,9 +2079,9 @@ void Pattern::compile( { if (common.contains(c)) {- if (std::isalpha(c))+ if (isanycase(c)) {- if (c >= 'a' && c <= 'z')+ if (islowercase(c)) { pos = i->second; DFA::State *target_state = last_state = last_state->next = dfa_.state(state->tnode->edge[c >> 4][c & 0xf], pos);@@ -2143,7 +2139,7 @@ void Pattern::compile( if (chars.contains(c)) { DFA::State *target_state = last_state = last_state->next = dfa_.state(state->tnode->edge[c >> 4][c & 0xf]);- if (opt_.i && std::isalpha(c))+ if (opt_.i && isanycase(c)) { state->edges[lowercase(c)] = DFA::State::Edge(lowercase(c), target_state); state->edges[uppercase(c)] = DFA::State::Edge(uppercase(c), target_state);@@ -2456,10 +2452,10 @@ void Pattern::compile_transition( Chars chars; if (literal) {- if (std::isalpha(c) && is_modified(ModConst::i, modifiers, loc))+ if (isanycase(c) && is_modified(ModConst::i, modifiers, loc)) {- chars.add(uppercase(c)); chars.add(lowercase(c));+ chars.add(uppercase(c)); } else {@@ -2499,10 +2495,10 @@ void Pattern::compile_transition( switch (escape_at(loc)) { case '\0': // no escape at current loc- if (std::isalpha(c) && is_modified(ModConst::i, modifiers, loc))+ if (isanycase(c) && is_modified(ModConst::i, modifiers, loc)) {- chars.add(uppercase(c)); chars.add(lowercase(c));+ chars.add(uppercase(c)); } else {@@ -2539,10 +2535,10 @@ void Pattern::compile_transition( break; default: c = parse_esc(loc, &chars);- if (c <= 'z' && std::isalpha(c) && is_modified(ModConst::i, modifiers, loc))+ if (isanycase(c) && is_modified(ModConst::i, modifiers, loc)) {- chars.add(uppercase(c)); chars.add(lowercase(c));+ chars.add(uppercase(c)); } } }@@ -2667,7 +2663,7 @@ void Pattern::compile_list(Location loc, Chars& chars, const Mods modifiers) con { if (is_modified(ModConst::i, modifiers, loc)) {- if (lo >= 'a' && lo <= 'z' && c >= 'A' && c <= 'Z')+ if (islowercase(lo) && isuppercase(c)) c = lowercase(c); Char a = lo; Char b = c;@@ -2691,10 +2687,10 @@ void Pattern::compile_list(Location loc, Chars& chars, const Mods modifiers) con } else {- if (std::isalpha(c) && is_modified(ModConst::i, modifiers, loc))+ if (isanycase(c) && is_modified(ModConst::i, modifiers, loc)) {- chars.add(uppercase(c)); chars.add(lowercase(c));+ chars.add(uppercase(c)); } else {
@@ -32,10 +32,11 @@ regular expression matches one or more newlines. An empty pattern matches every line. Each input line that matches at least one of the patterns is written to the standard output. .PP-The \fBug\fR command is intended for interactive searching, using a .ugrep-configuration file located in the working directory or home directory, see-CONFIGURATION. \fBug\fR is equivalent to \fBugrep --config --pretty --sort\fR-to load a .ugrep file, enhance the terminal output, and sort files by name.+The \fBug\fR command is intended for interactive searching, using a `.ugrep'+configuration file located in the working directory or, if not found, in the+home directory, see CONFIGURATION. \fBug\fR is equivalent to \fBugrep --config+--pretty --sort\fR to load a configuration file, enhance the terminal output,+and to sort files by name. .PP The \fBugrep+\fR and \fBug+\fR commands are the same as the \fBugrep\fR and \fBug\fR commands, but also use filters to search pdfs, documents, e-books,@@ -179,10 +180,10 @@ An error occurred. If \fB-q\fR or \fB--quiet\fR or \fB--silent\fR is used and a line is selected, the exit status is 0 even if an error occurred. .SH CONFIGURATION-The \fBug\fR command is intended for context-dependent interactive searching-and is equivalent to the \fBugrep --config --pretty --sort\fR command to load-the default configuration file `.ugrep' when present in the working directory-or in the home directory.+The \fBug\fR command is intended for interactive searching and is equivalent to+the \fBugrep --config --pretty --sort\fR command to load the `.ugrep`+configuration file located in the working directory or, when not found, in the+home directory. .PP A configuration file contains `NAME=VALUE' pairs per line, where `NAME` is the name of a long option (without `--') and `=VALUE' is an argument, which is@@ -191,8 +192,8 @@ starting with a `#' are ignored. .PP The \fB--config\fR=\fIFILE\fR option and its abbreviated form \fB---\fR\fIFILE\fR load the specified configuration file located in the-working directory or, when not found, located in the home directory. An error-is produced when \fIFILE\fR is not found or cannot be read.+working directory or, when not found, in the home directory. An error is+produced when \fIFILE\fR is not found or cannot be read. .PP Command line options are parsed in the following order: the configuration file is loaded first, followed by the remaining options and arguments on the command@@ -200,9 +201,10 @@ line. .PP The \fB--save-config\fR option saves a `.ugrep' configuration file to the working directory with a subset of the options specified on the command line.-The \fB--save-config\fR=\fIFILE\fR option saves the configuration to-\fIFILE\fR. The configuration is written to standard output when \fIFILE\fR is-a `-'.+Only part of the specified options are saved that do not cause searches to fail+when combined with other options. The \fB--save-config\fR=\fIFILE\fR option+saves the configuration to \fIFILE\fR. The configuration is written to+standard output when \fIFILE\fR is a `-'. .SH GLOBBING Globbing is used by options \fB-g\fR, \fB--include\fR, \fB--include-dir\fR, \fB--include-from\fR, \fB--exclude\fR, \fB--exclude-dir\fR,
@@ -1,4 +1,4 @@-.TH UGREP "1" "March 01, 2025" "ugrep 7.3.0" "User Commands"+.TH UGREP "1" "March 03, 2025" "ugrep 7.3.0" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS@@ -17,10 +17,11 @@ regular expression matches one or more newlines. An empty pattern matches every line. Each input line that matches at least one of the patterns is written to the standard output. .PP-The \fBug\fR command is intended for interactive searching, using a .ugrep-configuration file located in the working directory or home directory, see-CONFIGURATION. \fBug\fR is equivalent to \fBugrep --config --pretty --sort\fR-to load a .ugrep file, enhance the terminal output, and sort files by name.+The \fBug\fR command is intended for interactive searching, using a `.ugrep'+configuration file located in the working directory or, if not found, in the+home directory, see CONFIGURATION. \fBug\fR is equivalent to \fBugrep --config+--pretty --sort\fR to load a configuration file, enhance the terminal output,+and to sort files by name. .PP The \fBugrep+\fR and \fBug+\fR commands are the same as the \fBugrep\fR and \fBug\fR commands, but also use filters to search pdfs, documents, e-books,@@ -257,8 +258,8 @@ Use configuration FILE. The default FILE is `.ugrep'. The working directory is checked first for FILE, then the home directory. The options specified in the configuration FILE are parsed first, followed by the remaining options specified on the command line.-The ug command automatically loads a `.ugrep' configuration file,-unless \fB\-\-config\fR=\fIFILE\fR or \fB\-\-no\-config\fR is specified.+The ug command automatically loads a `.ugrep' configuration file+when present, unless \fB\-\-config\fR=\fIFILE\fR or \fB\-\-no\-config\fR is specified. .TP \fB\-\-no\-config\fR Do not automatically load the default .ugrep configuration file.@@ -775,8 +776,8 @@ which is automatically loaded by the ug command. When FILE is a OPTIONS are saved that do not cause searches to fail when combined with other options. Additional options may be specified by editing the saved configuration file. A configuration file may be modified-manually to specify one or more config[=\fIFILE\fR] to indirectly load-the specified FILE, but recursive config loading is not allowed.+by adding one or more config=\fIFILE\fR to include configuration files,+but recursive configuration file inclusion is not permitted. .TP \fB\-\-separator\fR[=\fISEP\fR], \fB\-\-context\-separator\fR=\fISEP\fR Use SEP as field separator between file name, line number, column@@ -968,10 +969,10 @@ An error occurred. If \fB-q\fR or \fB--quiet\fR or \fB--silent\fR is used and a line is selected, the exit status is 0 even if an error occurred. .SH CONFIGURATION-The \fBug\fR command is intended for context-dependent interactive searching-and is equivalent to the \fBugrep --config --pretty --sort\fR command to load-the default configuration file `.ugrep' when present in the working directory-or in the home directory.+The \fBug\fR command is intended for interactive searching and is equivalent to+the \fBugrep --config --pretty --sort\fR command to load the `.ugrep`+configuration file located in the working directory or, when not found, in the+home directory. .PP A configuration file contains `NAME=VALUE' pairs per line, where `NAME` is the name of a long option (without `--') and `=VALUE' is an argument, which is@@ -980,8 +981,8 @@ starting with a `#' are ignored. .PP The \fB--config\fR=\fIFILE\fR option and its abbreviated form \fB---\fR\fIFILE\fR load the specified configuration file located in the-working directory or, when not found, located in the home directory. An error-is produced when \fIFILE\fR is not found or cannot be read.+working directory or, when not found, in the home directory. An error is+produced when \fIFILE\fR is not found or cannot be read. .PP Command line options are parsed in the following order: the configuration file is loaded first, followed by the remaining options and arguments on the command@@ -989,9 +990,10 @@ line. .PP The \fB--save-config\fR option saves a `.ugrep' configuration file to the working directory with a subset of the options specified on the command line.-The \fB--save-config\fR=\fIFILE\fR option saves the configuration to-\fIFILE\fR. The configuration is written to standard output when \fIFILE\fR is-a `-'.+Only part of the specified options are saved that do not cause searches to fail+when combined with other options. The \fB--save-config\fR=\fIFILE\fR option+saves the configuration to \fIFILE\fR. The configuration is written to+standard output when \fIFILE\fR is a `-'. .SH GLOBBING Globbing is used by options \fB-g\fR, \fB--include\fR, \fB--include-dir\fR, \fB--include-from\fR, \fB--exclude\fR, \fB--exclude-dir\fR,
@@ -1,4 +1,4 @@-.TH UGREP-INDEXER "1" "March 01, 2025" "ugrep-indexer 7.3.0" "User Commands"+.TH UGREP-INDEXER "1" "March 03, 2025" "ugrep-indexer 7.3.0" "User Commands" .SH NAME \fBugrep-indexer\fR -- file indexer to accelerate recursive searching .SH SYNOPSIS
@@ -1,4 +1,4 @@-.TH UGREP "1" "March 01, 2025" "ugrep 7.3.0" "User Commands"+.TH UGREP "1" "March 03, 2025" "ugrep 7.3.0" "User Commands" .SH NAME \fBugrep\fR, \fBug\fR -- file pattern searcher .SH SYNOPSIS@@ -17,10 +17,11 @@ regular expression matches one or more newlines. An empty pattern matches every line. Each input line that matches at least one of the patterns is written to the standard output. .PP-The \fBug\fR command is intended for interactive searching, using a .ugrep-configuration file located in the working directory or home directory, see-CONFIGURATION. \fBug\fR is equivalent to \fBugrep --config --pretty --sort\fR-to load a .ugrep file, enhance the terminal output, and sort files by name.+The \fBug\fR command is intended for interactive searching, using a `.ugrep'+configuration file located in the working directory or, if not found, in the+home directory, see CONFIGURATION. \fBug\fR is equivalent to \fBugrep --config+--pretty --sort\fR to load a configuration file, enhance the terminal output,+and to sort files by name. .PP The \fBugrep+\fR and \fBug+\fR commands are the same as the \fBugrep\fR and \fBug\fR commands, but also use filters to search pdfs, documents, e-books,@@ -257,8 +258,8 @@ Use configuration FILE. The default FILE is `.ugrep'. The working directory is checked first for FILE, then the home directory. The options specified in the configuration FILE are parsed first, followed by the remaining options specified on the command line.-The ug command automatically loads a `.ugrep' configuration file,-unless \fB\-\-config\fR=\fIFILE\fR or \fB\-\-no\-config\fR is specified.+The ug command automatically loads a `.ugrep' configuration file+when present, unless \fB\-\-config\fR=\fIFILE\fR or \fB\-\-no\-config\fR is specified. .TP \fB\-\-no\-config\fR Do not automatically load the default .ugrep configuration file.@@ -775,8 +776,8 @@ which is automatically loaded by the ug command. When FILE is a OPTIONS are saved that do not cause searches to fail when combined with other options. Additional options may be specified by editing the saved configuration file. A configuration file may be modified-manually to specify one or more config[=\fIFILE\fR] to indirectly load-the specified FILE, but recursive config loading is not allowed.+by adding one or more config=\fIFILE\fR to include configuration files,+but recursive configuration file inclusion is not permitted. .TP \fB\-\-separator\fR[=\fISEP\fR], \fB\-\-context\-separator\fR=\fISEP\fR Use SEP as field separator between file name, line number, column@@ -968,10 +969,10 @@ An error occurred. If \fB-q\fR or \fB--quiet\fR or \fB--silent\fR is used and a line is selected, the exit status is 0 even if an error occurred. .SH CONFIGURATION-The \fBug\fR command is intended for context-dependent interactive searching-and is equivalent to the \fBugrep --config --pretty --sort\fR command to load-the default configuration file `.ugrep' when present in the working directory-or in the home directory.+The \fBug\fR command is intended for interactive searching and is equivalent to+the \fBugrep --config --pretty --sort\fR command to load the `.ugrep`+configuration file located in the working directory or, when not found, in the+home directory. .PP A configuration file contains `NAME=VALUE' pairs per line, where `NAME` is the name of a long option (without `--') and `=VALUE' is an argument, which is@@ -980,8 +981,8 @@ starting with a `#' are ignored. .PP The \fB--config\fR=\fIFILE\fR option and its abbreviated form \fB---\fR\fIFILE\fR load the specified configuration file located in the-working directory or, when not found, located in the home directory. An error-is produced when \fIFILE\fR is not found or cannot be read.+working directory or, when not found, in the home directory. An error is+produced when \fIFILE\fR is not found or cannot be read. .PP Command line options are parsed in the following order: the configuration file is loaded first, followed by the remaining options and arguments on the command@@ -989,9 +990,10 @@ line. .PP The \fB--save-config\fR option saves a `.ugrep' configuration file to the working directory with a subset of the options specified on the command line.-The \fB--save-config\fR=\fIFILE\fR option saves the configuration to-\fIFILE\fR. The configuration is written to standard output when \fIFILE\fR is-a `-'.+Only part of the specified options are saved that do not cause searches to fail+when combined with other options. The \fB--save-config\fR=\fIFILE\fR option+saves the configuration to \fIFILE\fR. The configuration is written to+standard output when \fIFILE\fR is a `-'. .SH GLOBBING Globbing is used by options \fB-g\fR, \fB--include\fR, \fB--include-dir\fR, \fB--include-from\fR, \fB--exclude\fR, \fB--exclude-dir\fR,
@@ -30,7 +30,7 @@ @file cnf.cpp @brief CNF class for normalization of Boolean search queries @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file cnf.hpp @brief CNF class for normalization of Boolean search queries @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file flag.hpp @brief Tri-state Flag class and global flags set by options @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file mmap.hpp @brief class to manage memory-mapped files @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file output.cpp @brief Output management @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file output.hpp @brief Output management @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file query.cpp @brief Query engine TUI @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file query.hpp @brief Query engine and UI @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file screen.cpp @brief ANSI SGR code controlled screen API - static, not thread safe @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file screen.hpp @brief ANSI SGR code controlled screen API - static, not thread safe @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file stats.cpp @brief collect global statistics - static, partially thread-safe @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file stats.hpp @brief collect global statistics - static, partially thread-safe (see below) @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt Thread-safe functions:
@@ -30,7 +30,7 @@ @file ugrep-indexer.cpp @brief file system indexer for the ugrep search utility @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2023,2025 Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2023-2025 Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file ugrep.cpp @brief file pattern searcher @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt User manual:@@ -4550,7 +4550,7 @@ FILE *Static::output = stdout; // redirectable error output destination is standard error by default or a pipe FILE *Static::errout = stderr; -// full home directory path+// full home directory path or NULL to expand ~ in options with path arguments const char *Static::home_dir = NULL; // Grep object handle, to cancel the search with cancel_ugrep()@@ -4859,37 +4859,48 @@ static void load_config(std::list<std::pair<CNF::PATTERN,const char*>>& pattern_ // if config file was parsed before, then only try parsing the home dir config file bool home = flag_config_files.find(flag_config) != flag_config_files.end(); - // open a local config file or in the home directory+ // open a config file in the working dir or in the home directory std::string config_file(flag_config); FILE *file = NULL;+ if (home || fopen_smart(&file, flag_config, "r") != 0) { file = NULL;++ // if not in the working directory, then check the home directory if (Static::home_dir != NULL && *flag_config != '~' && *flag_config != PATHSEPCHR) { // check the home directory for the configuration file, parse only if not parsed before config_file.assign(Static::home_dir).append(PATHSEPSTR).append(flag_config); if (flag_config_files.find(config_file) != flag_config_files.end() || fopen_smart(&file, config_file.c_str(), "r") != 0)- { file = NULL;- }- else- {- // new config file in the home dir to parse, add to the set- flag_config_files.insert(config_file);- } }- }- else- {- // new config file to parse, add to the set- flag_config_files.insert(flag_config);++#if defined(WITH_XDG_CONFIG_HOME) && !defined(OS_WIN)+ // if the default configuration file is to be used, then check XDG_CONFIG_HOME/ugrep/config first+ if (file == NULL && strcmp(flag_config, ".ugrep") == 0)+ {+ // get XDG_CONFIG_HOME path, defaults to $HOME/.config/ugrep/config when present+ const char *xdg_config_home = getenv("XDG_CONFIG_HOME");+ if (xdg_config_home == NULL || *xdg_config_home == '\0')+ xdg_config_home = ".config";++ // check if $XDG_CONFIG_HOME/ugrep/config or $HOME/.config/ugrep/config is present to parse+ config_file.assign(xdg_config_home).append(PATHSEPSTR).append("ugrep").append(PATHSEPSTR).append("config");+ if (flag_config_files.find(config_file) != flag_config_files.end() ||+ fopen_smart(&file, config_file.c_str(), "r") != 0)+ file = NULL;+ }+#endif } // parse config file if (file != NULL) {+ // add config file path to the set+ flag_config_files.insert(config_file);+ reflex::BufferedInput input(file); std::string line;@@ -4993,12 +5004,16 @@ static void save_config() // if not saved to standard output ("-"), then inform user if (!flag_no_messages && strcmp(flag_save_config, "-") != 0) {- if (flag_config == NULL)- fprintf(Static::errout, "ugrep: saving configuration file %s\n", flag_save_config);- else if (exists && strcmp(flag_config, flag_save_config) == 0)- fprintf(Static::errout, "ugrep: updating configuration file %s\n", flag_save_config);- else- fprintf(Static::errout, "ugrep: saving configuration file %s with options based on %s\n", flag_save_config, flag_config);+ fprintf(Static::errout, "ugrep: %s configuration file %s", exists ? "updating" : "saving", flag_save_config);++ if (!flag_config_files.empty())+ {+ fprintf(Static::errout, " with options based on");+ for (const auto& i : flag_config_files)+ fprintf(Static::errout, " %s", i.c_str());+ }++ fprintf(Static::errout, "\n"); } if (fopen_smart(&file, flag_save_config, "w") != 0)@@ -14053,8 +14068,8 @@ void help(std::ostream& out) directory is checked first for FILE, then the home directory. The\n\ options specified in the configuration FILE are parsed first,\n\ followed by the remaining options specified on the command line.\n\- The ug command automatically loads a `.ugrep' configuration file,\n\- unless --config=FILE or --no-config is specified.\n\+ The ug command automatically loads a `.ugrep' configuration file\n\+ when present, unless --config=FILE or --no-config is specified.\n\ --no-config\n\ Do not automatically load the default .ugrep configuration file.\n\ --no-confirm\n\@@ -14531,8 +14546,8 @@ void help(std::ostream& out) OPTIONS are saved that do not cause searches to fail when combined\n\ with other options. Additional options may be specified by editing\n\ the saved configuration file. A configuration file may be modified\n\- manually to specify one or more config[=FILE] to indirectly load\n\- the specified FILE, but recursive config loading is not allowed.\n\+ by adding one or more config=FILE to include configuration files,\n\+ but recursive configuration file inclusion is not permitted.\n\ --separator[=SEP], --context-separator=SEP\n\ Use SEP as field separator between file name, line number, column\n\ number, byte offset and the matched line. The default separator is\n\
@@ -30,7 +30,7 @@ @file ugrep.hpp @brief file pattern searcher @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */ @@ -63,6 +63,9 @@ // modifiers: h=highlight, u=underline, i=invert, f=faint, n=normal, H=highlight off, U=underline off, I=invert off #define WITH_EASY_GREP_COLORS +// use $XDG_CONFIG_HOME/ugrep/config for ug (or ugrep --config) when no .ugrep files are found, migh be confusing!+// #define WITH_XDG_CONFIG_HOME+ // check if we are compiling for a windows OS, but not Cygwin or MinGW #if (defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__BORLANDC__)) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) # define OS_WIN
@@ -30,7 +30,7 @@ @file vkey.cpp @brief Virtual terminal keyboard input API - static, not thread safe @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file vkey.hpp @brief Virtual terminal keyboard input API - static, not thread safe @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt Supports Unix/Linux, MacOS, DOS, and Windows.
@@ -30,7 +30,7 @@ @file zstream.hpp @brief file decompression streams - zstreambuf extends std::streambuf @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */
@@ -30,7 +30,7 @@ @file zthread.hpp @brief file decompression threads @author Robert van Engelen - engelen@genivia.com-@copyright (c) 2019,2025, Robert van Engelen, Genivia Inc. All rights reserved.+@copyright (c) 2019-2025, Robert van Engelen, Genivia Inc. All rights reserved. @copyright (c) BSD-3 License - see LICENSE.txt */