33 std::ifstream stream ;
36 throw Error(
"cannot open batch file" , path.
str() ) ;
37 m_line = readFrom( stream , path.
str() ,
true ) ;
38 m_args = split( m_line ) ;
43 std::ifstream stream ;
47 m_line = readFrom( stream , path.
str() ,
false ) ;
48 m_args = split( m_line ) ;
54 m_line = readFrom( stream , name ,
true ) ;
55 m_args = split( m_line ) ;
58bool G::BatchFile::ignorable(
const std::string & trimmed_line )
61 trimmed_line.empty() ||
62 Str::lower(trimmed_line+
" ").find(
"@echo ") == 0U ||
63 Str::lower(trimmed_line+
" ").find(
"rem ") == 0U ;
66bool G::BatchFile::relevant(
const std::string & trimmed_line )
68 return ! ignorable( trimmed_line ) ;
71std::string G::BatchFile::join(
const std::string & file_name ,
unsigned int line_number )
73 std::ostringstream ss ;
74 ss << file_name <<
"(" << line_number <<
")" ;
78std::string G::BatchFile::readFrom( std::istream & stream ,
const std::string & stream_name ,
bool strict )
81 unsigned int line_number = 1U ;
82 for( ; stream.good() ; line_number++ )
94 throw Error(
"too many lines in batch file" , join(stream_name,line_number) ) ;
98 if( strict && line.empty() )
99 throw Error(
"batch file is empty" , join(stream_name,line_number) ) ;
105 using size_type = std::string::size_type ;
106 size_type
const npos = std::string::npos ;
107 std::string ws = sv_to_string(
Str::ws() ) ;
109 std::string start =
"start " ;
110 size_type start_pos =
Str::lower(line).find(start) ;
111 size_type command_pos = start_pos == npos ? 0U : line.find_first_not_of( ws , start_pos+start.size() ) ;
113 bool named = start_pos != npos && line.at(command_pos) ==
'"' ;
116 std::size_t name_start_pos = command_pos ;
117 std::size_t name_end_pos = line.find(
'\"' , name_start_pos+1U ) ;
118 if( name_end_pos == npos )
119 throw Error(
"mismatched quotes in batch file" , stream_name ) ;
120 if( (name_end_pos+2U) >= line.size() || line.at(name_end_pos+1U) !=
' ' )
121 throw Error(
"invalid window name in batch file" , stream_name ) ;
123 m_name = line.substr( name_start_pos+1U , name_end_pos-(name_start_pos+1U) ) ;
127 command_pos = line.find_first_not_of( ws , name_end_pos+2U ) ;
130 if( command_pos != npos )
131 line.erase( 0U , command_pos ) ;
158 const std::string ws = sv_to_string(
Str::ws() ) ;
159 const char qq =
'\"' ;
160 const char esc =
'\\' ;
161 bool in_quote = false ;
162 bool escaped = false ;
164 for( ; i < m_line.size() ; i++ )
167 if( c == esc && !escaped )
173 if( c == qq && !escaped && !in_quote )
175 else if( c == qq && !escaped )
177 else if( ws.find(c) != std::string::npos && !in_quote )
184void G::BatchFile::dequote( std::string & s )
186 if( s.size() >= 2U && s.find(
'\"') == 0U && (s.rfind(
'\"')+1U) == s.size() )
187 s = s.substr( 1U , s.size()-2U ) ;
192 G_ASSERT( !args.empty() ) ;
194 throw Error(
"invalid contents for startup batch file" ) ;
196 std::string name = name_in ;
204 std::ofstream stream ;
207 throw Error(
"cannot create batch file" , path.
str() ) ;
209 stream <<
"start \"" << name <<
"\"" ;
210 for(
const auto & arg : args )
212 stream <<
" " << percents(quote(arg)) ;
218 throw Error(
"cannot write batch file" , path.
str() ) ;
227 return args.
array() ;
230std::string G::BatchFile::percents(
const std::string & s )
232 std::string result( s ) ;
237std::string G::BatchFile::quote(
const std::string & s )
240 s.find(
'\"') == std::string::npos && s.find_first_of(
" \t") != std::string::npos ?
241 "\"" + s +
"\"" : s ;
A class which holds a represention of the argc/argv command line array, and supports simple command-l...
StringArray array(unsigned int shift=0U) const
Returns the arguments as a string array, with an optional shift.
void parse(HINSTANCE hinstance, const std::string &command_line_tail)
Parses the given command-line tail, splitting it up into an array of tokens.
static void write(const Path &, const StringArray &args, const std::string &start_window_name=std::string())
Writes a startup batch file, including a "start" prefix.
const StringArray & args() const
Returns the startup command-line broken up into de-quoted pieces.
std::size_t lineArgsPos() const
Returns the position in line() where the arguments start.
std::string name() const
Returns the "start" window name, if any.
BatchFile(const Path &)
Constructor that reads from a file.
std::string line() const
Returns the main command-line from within the batchfile, with normalised spaces, without any "start" ...
An overload discriminator for G::File::open().
static void open(std::ofstream &, const Path &)
Calls open() on the given output file stream.
A Path object represents a file system path.
std::string basename() const
Returns the rightmost part of the path, ignoring "." parts.
Path withoutExtension() const
Returns a path without the basename extension, if any.
std::string str() const
Returns the path string.
static string_view ws()
Returns a string of standard whitespace characters.
static std::string unique(const std::string &s, char c, char r)
Returns a string with repeated 'c' characters replaced by one 'r' character.
static unsigned int replaceAll(std::string &s, const std::string &from, const std::string &to)
Does a global replace on string 's', replacing all occurrences of sub-string 'from' with 'to'.
static std::string lower(const std::string &s)
Returns a copy of 's' in which all Latin-1 upper-case characters have been replaced by lower-case cha...
static std::string readLineFrom(std::istream &stream, const std::string &eol=std::string())
Reads a line from the stream using the given line terminator.
static std::string & trim(std::string &s, string_view ws)
Trims both ends of s, taking off any of the 'ws' characters.
std::vector< std::string > StringArray
A std::vector of std::strings.