25 #include <boost/algorithm/string/trim.hpp>
40 if(lua_isstring(L, 1)) {
41 std::string str = lua_tostring(L, 1);
55 template<
bool conjunct>
59 auto values = lua_check<std::vector<t_string>>(L, 2);
69 if(lua_type(L, 2) == LUA_TSTRING) {
71 lua_getglobal(L,
"stringx");
75 }
else if(lua_type(L, 2) == LUA_TNUMBER) {
77 int len = lua_rawlen(L, 1);
78 int i = luaL_checkinteger(L, 2);
80 if(
i == 0 || abs(
i) > len) {
103 enum {BASIC, ESCAPED, PAREN, ANIM}
type = BASIC;
104 const std::string& str = luaL_checkstring(L, 1);
105 const std::string& sep = luaL_optstring(L, 2,
",");
106 std::string left, right;
108 if(lua_istable(L, 3)) {
119 return luaL_error(L,
"escape and expand_anim options are incompatible!");
122 left = luaL_checkstring(L, -1);
123 if(left.size() != 1) {
124 return luaL_error(L,
"escape must be a single character");
127 left = right = luaL_checkstring(L, -1);
131 right.push_back(
']');
134 left = luaL_checkstring(L, -2);
135 right = luaL_checkstring(L, -1);
137 if(left.find_first_of(
"[]") != std::string::npos || right.find_first_of(
"[]") != std::string::npos) {
138 return luaL_error(L,
"left and right cannot include square brackets [] if expand_anim is enabled");
142 right.push_back(
']');
149 if(
type != ESCAPED && left.size() != right.size()) {
150 return luaL_error(L,
"left and right need to be strings of the same length");
178 const std::string& str = luaL_checkstring(L, 1);
179 const std::string& left = luaL_optstring(L, 2,
"(");
180 const std::string& right = luaL_optstring(L, 3,
")");
181 if(left.size() != right.size()) {
182 return luaL_error(L,
"left and right need to be strings of the same length");
197 const std::string& str = luaL_checkstring(L, 1);
198 const std::string& sep = luaL_optstring(L, 2,
",");
199 const std::string& kv = luaL_optstring(L, 3,
":");
201 if(sep.size() != 1) {
202 return luaL_error(L,
"separator must be a single character");
205 return luaL_error(L,
"key_value_separator must be a single character");
208 if(lua_istable(L, 4)) {
217 dflt = luaL_checkstring(L, -1);
235 if(lua_istable(L, 1)) {
237 sep = luaL_optstring(L, 2,
",");
238 }
else if(lua_istable(L, 2)) {
239 sep = luaL_checkstring(L, 1);
241 }
else return luaL_error(L,
"invalid arguments to join, should have map and separator");
242 std::vector<std::string> pieces;
243 for(
int i = 1;
i <= luaL_len(L, list_idx);
i++) {
244 lua_getglobal(L,
"tostring");
245 lua_geti(L, list_idx,
i);
247 pieces.push_back(luaL_checkstring(L, -1));
266 if(lua_istable(L, 1)) {
268 sep = luaL_optstring(L, 2,
",");
269 kv = luaL_optstring(L, 3,
":");
270 }
else if(lua_istable(L, 2)) {
271 sep = luaL_checkstring(L, 1);
273 kv = luaL_optstring(L, 3,
":");
274 }
else if(lua_istable(L, 3)) {
275 sep = luaL_checkstring(L, 1);
276 kv = luaL_checkstring(L, 2);
278 }
else return luaL_error(L,
"invalid arguments to join_map, should have map, separator, and key_value_separator");
279 std::map<std::string, std::string> pieces;
280 for(lua_pushnil(L); lua_next(L, map_idx); ) {
281 int key_idx = lua_absindex(L, -2), val_idx = lua_absindex(L, -1);
282 lua_getglobal(L,
"tostring");
283 lua_pushvalue(L, key_idx);
285 std::string& val = pieces[luaL_checkstring(L, -1)];
286 lua_getglobal(L,
"tostring");
287 lua_pushvalue(L, val_idx);
289 val = luaL_checkstring(L, -1);
290 lua_settop(L, key_idx);
301 std::string str = luaL_checkstring(L, 1);
303 lua_pushlstring(L, str.c_str(), str.size());
312 int nargs = lua_gettop(L);
315 lua_getglobal(L,
"tostring");
322 for(
int argument = 2; argument <= nargs; ++argument) {
323 const int type = lua_type(L, argument);
324 if(
type != LUA_TTABLE &&
type != LUA_TUSERDATA) {
328 const int tostring_type = luaL_getmetafield(L, argument,
"__tostring");
329 if(tostring_type != LUA_TNIL) {
334 lua_getglobal(L,
"tostring");
335 lua_pushvalue(L, argument);
337 lua_replace(L, argument);
341 bool in_specifier =
false;
342 std::size_t format_length = 0;
343 const char* str = luaL_checklstring(L, 1, &format_length);
346 in_specifier = !in_specifier;
347 }
else if(in_specifier) {
349 lua_pushstring(L,
"%p format specifier is not supported");
354 if(
c ==
'\0' || std::strchr(
"-+#0 123456789.",
c) ==
nullptr) {
355 in_specifier =
false;
360 lua_pushvalue(L, lua_upvalueindex(1));
364 lua_call(L, nargs, 1);
375 const std::string str = luaL_checkstring(L, 1);
376 if(luaL_opt(L, lua_toboolean, 2,
false)) {
378 lua_pushnumber(L, interval.first);
379 lua_pushnumber(L, interval.second);
382 lua_pushinteger(L, interval.first);
383 lua_pushinteger(L, interval.second);
389 auto& lk = lua_kernel_base::get_lua_kernel<lua_kernel_base>(L);
390 lk.add_log(
"Adding stringx module...\n");
391 static luaL_Reg
const str_callbacks[] = {
400 {
"format_conjunct_list", &intf_format_list<true> },
401 {
"format_disjunct_list", &intf_format_list<false> },
402 {
nullptr,
nullptr },
405 luaL_setfuncs(L, str_callbacks, 0);
407 lua_createtable(L, 0, 1);
408 lua_getglobal(L,
"string");
409 lua_setfield(L, -2,
"__index");
410 lua_setmetatable(L, -2);
413 lua_pushliteral(L,
"");
414 lua_getmetatable(L, -1);
416 lua_setfield(L, -2,
"__index");
417 lua_setmetatable(L, -2);
421 lua_getglobal(L,
"string");
422 lua_getfield(L, -1,
"format");
424 lua_setfield(L, -2,
"format");
A config object defines a single node in a WML file, with access to child nodes.
bool luaW_iststring(lua_State *L, int index)
config luaW_checkconfig(lua_State *L, int index)
Converts an optional table or vconfig to a config object.
bool luaW_toboolean(lua_State *L, int n)
bool luaW_tableget(lua_State *L, int index, const char *key)
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil.
t_string luaW_checktstring(lua_State *L, int index)
Converts a scalar to a translatable string.
static int intf_str_split(lua_State *L)
Splits a string into parts according to options Arg 1: String to split Arg 2: Separator Arg 3: Option...
static int intf_str_map_split(lua_State *L)
Splits a string into a map Arg 1: string to split Arg 2: Separator for items Arg 3: Separator for key...
static int intf_parse_range(lua_State *L)
Parses a range string of the form a-b into an interval pair Accepts the string "infinity" as represen...
static int intf_format(lua_State *L)
Formats a message by interpolating WML variable syntax Arg 1: (optional) Logger Arg 2: Message.
static int intf_str_paren_split(lua_State *L)
Splits a string into parenthesized portions and portions between parenthesized portions Arg 1: String...
static int intf_format_list(lua_State *L)
Formats a list into human-readable format Arg 1: default value, used if the list is empty Arg 2: list...
static int intf_str_trim(lua_State *L)
Trims whitespace from the beginning and end of a string.
static int impl_str_index(lua_State *L)
Enables indexing a string by an integer, while also treating the stringx module as its metatable....
static int intf_str_join(lua_State *L)
Joins a list into a string; calls __tostring and __index metamethods Arg 1: list to join Arg 2: separ...
static int intf_str_format(lua_State *L)
static int intf_str_join_map(lua_State *L)
Joins a map into a string; calls __tostring metamethods (on both key and value) but not __index Arg 1...
int luaW_open(lua_State *L)
@ STRIP_SPACES
REMOVE_EMPTY: remove empty elements.
void trim(std::string_view &s)
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
std::map< std::string, std::string > map_split(const std::string &val, char major, char minor, int flags, const std::string &default_value)
Splits a string based on two separators into a map.
std::vector< std::string > quoted_split(const std::string &val, char c, int flags, char quote)
This function is identical to split(), except it does not split when it otherwise would if the previo...
std::string join_map(const T &v, const std::string &major=",", const std::string &minor=":")
t_string interpolate_variables_into_tstring(const t_string &tstr, const variable_set &variables)
Function that does the same as the above, for t_stringS.
std::vector< std::string > parenthetical_split(std::string_view val, const char separator, std::string_view left, std::string_view right, const int flags)
Splits a string based either on a separator, except then the text appears within specified parenthesi...
std::string join(const Range &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::string format_disjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a disjunctive list.
std::vector< std::string > square_parenthetical_split(const std::string &val, const char separator, const std::string &left, const std::string &right, const int flags)
Similar to parenthetical_split, but also expands embedded square brackets.
std::pair< int, int > parse_range(std::string_view str)
Recognises the following patterns, and returns a {min, max} pair.
std::string format_conjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a conjunctive list.
std::pair< double, double > parse_range_real(std::string_view str)
Recognises similar patterns to parse_range, and returns a {min, max} pair.
std::vector< std::string > split(const config_attribute_value &val)
void lua_push(lua_State *L, const T &val)
std::decay_t< T > luaW_table_get_def(lua_State *L, int index, std::string_view k, const T &def)
returns t[k] where k is the table at index index and k is k or def if it is not convertible to the co...