sprintf added, terminal colors
small code fixes and rearangements
This commit is contained in:
parent
b4862ee196
commit
3f46ae9c94
|
|
@ -1,3 +1,70 @@
|
|||
{
|
||||
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
|
||||
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
|
||||
"files.associations": {
|
||||
"__bit_reference": "cpp",
|
||||
"__config": "cpp",
|
||||
"__debug": "cpp",
|
||||
"__errc": "cpp",
|
||||
"__functional_base": "cpp",
|
||||
"__hash_table": "cpp",
|
||||
"__locale": "cpp",
|
||||
"__mutex_base": "cpp",
|
||||
"__node_handle": "cpp",
|
||||
"__nullptr": "cpp",
|
||||
"__split_buffer": "cpp",
|
||||
"__string": "cpp",
|
||||
"__threading_support": "cpp",
|
||||
"__tree": "cpp",
|
||||
"__tuple": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bitset": "cpp",
|
||||
"cctype": "cpp",
|
||||
"chrono": "cpp",
|
||||
"cmath": "cpp",
|
||||
"complex": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"exception": "cpp",
|
||||
"optional": "cpp",
|
||||
"fstream": "cpp",
|
||||
"functional": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"ios": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"iterator": "cpp",
|
||||
"limits": "cpp",
|
||||
"locale": "cpp",
|
||||
"map": "cpp",
|
||||
"memory": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ratio": "cpp",
|
||||
"regex": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"utility": "cpp",
|
||||
"vector": "cpp"
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,8 @@ set(SOURCE
|
|||
ml_string.cpp
|
||||
clib/csvparser.cpp
|
||||
clib/sslclient.cpp
|
||||
clib/json11.cpp ml_date.h ml_date.cpp)
|
||||
clib/json11.cpp
|
||||
clib/printf.cpp)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCE})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../ml.h"
|
||||
|
||||
#include <string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,216 @@
|
|||
#include "printf.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
std::string mini_sprintf_format(bool left_align, bool sign, bool space_on_left, bool padding_by_zero, int width, int precision, int length, char specifier, const MlValue &value) {
|
||||
std::string s;
|
||||
bool is_positive = false;
|
||||
|
||||
if (specifier == 's') {
|
||||
return value.as_string();
|
||||
}
|
||||
if (specifier == 'i' || specifier == 'd') {
|
||||
int ival = value.as_int();
|
||||
is_positive = ival >= 0;
|
||||
|
||||
s = std::to_string(ival);
|
||||
} else if (specifier == 'f' || specifier == 'e') {
|
||||
double dval = value.as_float();
|
||||
is_positive = dval >= 0;
|
||||
|
||||
std::ostringstream stream_str;
|
||||
if (specifier == 'f')
|
||||
stream_str << std::fixed;
|
||||
else
|
||||
stream_str << std::scientific;
|
||||
|
||||
if (precision >= 0)
|
||||
stream_str << std::setprecision(precision);
|
||||
|
||||
stream_str << dval;
|
||||
s = stream_str.str(); // TODO ??
|
||||
}
|
||||
|
||||
if (width > -1 && s.size() < width) {
|
||||
int new_width = width - (sign && is_positive ? 1 : 0); // spce for + sign
|
||||
if (s.size() < new_width) {
|
||||
char padd = padding_by_zero ? '0' : ' ';
|
||||
if (left_align) {
|
||||
s.insert(0, new_width - s.size(), padd);
|
||||
} else {
|
||||
s.append(new_width - s.size(), ' '); // cannot append 0 because its different number then
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sign && is_positive) {
|
||||
s.insert(0, 1, '+');
|
||||
}
|
||||
if (space_on_left) {
|
||||
s.insert(0, 1, ' ');
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string mini_sprintf(const std::string &format_str, const std::vector<MlValue> ¶meters) {
|
||||
int arg_position = 0;
|
||||
char c, c1;
|
||||
std::string buf;
|
||||
std::string output_str;
|
||||
|
||||
std::string::const_iterator si;
|
||||
for (si = format_str.begin(); si != format_str.end(); ++si) {
|
||||
c = *si;
|
||||
|
||||
// formating directives
|
||||
if (c == '%') {
|
||||
if (++si >= format_str.end()) {
|
||||
return output_str; // end of string, invalid % on last pos
|
||||
}
|
||||
|
||||
c1 = *si;
|
||||
switch (c1) {
|
||||
case '%':
|
||||
output_str += c1;
|
||||
break;
|
||||
case '-':
|
||||
case '+':
|
||||
case ' ':
|
||||
case '#':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '.':
|
||||
case 'i':
|
||||
case 'd':
|
||||
case 'f':
|
||||
case 's':
|
||||
bool left_align = false;
|
||||
bool sign = false;
|
||||
bool space_on_left = false;
|
||||
bool padding_by_zero = false;
|
||||
int width = -1;
|
||||
int precision = -1;
|
||||
int length = -1;
|
||||
// http://www.cplusplus.com/reference/cstdio/printf/
|
||||
// https://www.menie.org/georges/embedded/small_printf_source_code.html
|
||||
//
|
||||
// %[flags][width][.precision][length]specifier
|
||||
|
||||
// flags: - + \_ # 0
|
||||
while ((*si == '-' || *si == '+' || *si == ' ' || *si == '#' || *si == '0') && si < format_str.end()) {
|
||||
switch (*si) {
|
||||
case '-':
|
||||
left_align = true;
|
||||
break;
|
||||
case '+':
|
||||
sign = true;
|
||||
break;
|
||||
case ' ':
|
||||
space_on_left = true;
|
||||
break;
|
||||
case '#':
|
||||
break;
|
||||
case '0':
|
||||
padding_by_zero = true;
|
||||
left_align = true;
|
||||
break;
|
||||
};
|
||||
si++;
|
||||
}
|
||||
// width
|
||||
if (si >= format_str.end())
|
||||
return output_str; // invalid end of string
|
||||
while (*si >= '0' && *si <= '9' && si < format_str.end()) {
|
||||
if (width == -1) {
|
||||
width = 0;
|
||||
}
|
||||
width = width * 10 + (*si - '0');
|
||||
si++;
|
||||
}
|
||||
// precision
|
||||
if (si >= format_str.end())
|
||||
return output_str; // invalid end of string
|
||||
if (*si == '.') {
|
||||
precision = 0;
|
||||
if (++si >= format_str.end())
|
||||
return output_str; // invalid end of string
|
||||
while (*si >= '0' && *si <= '9' && si < format_str.end()) {
|
||||
precision = precision * 10 + (*si - '0');
|
||||
si++;
|
||||
}
|
||||
}
|
||||
// length
|
||||
// specifier
|
||||
if (si >= format_str.end())
|
||||
return output_str; // invalid end of string
|
||||
if (*si == 'i' || *si == 'd' || *si == 'f' || *si == 's') { // TODO more specifiers
|
||||
std::string s = mini_sprintf_format(left_align, sign, space_on_left, padding_by_zero, width, precision, length, *si, parameters[arg_position]);
|
||||
arg_position++;
|
||||
output_str += s;
|
||||
} else {
|
||||
output_str += "UNKNOWN FORMAT SPECIFIER";
|
||||
}
|
||||
};
|
||||
|
||||
// escaping sequences
|
||||
} else if (c == '\\') {
|
||||
if (++si >= format_str.end()) {
|
||||
return output_str; // end of string, invalid % on last pos
|
||||
}
|
||||
|
||||
c1 = *si;
|
||||
switch (c1) {
|
||||
case 't':
|
||||
output_str += '\t';
|
||||
break;
|
||||
case 'r':
|
||||
output_str += '\r';
|
||||
break;
|
||||
case 'n':
|
||||
output_str += '\n';
|
||||
break;
|
||||
case 'x': // hex ie \x1b
|
||||
if (si + 2 >= format_str.end()) return output_str; // end of string, invalid hex constant
|
||||
buf.clear();
|
||||
buf.push_back(*(si + 1));
|
||||
buf.push_back(*(si + 2));
|
||||
output_str.push_back((char)std::strtol( &buf[0], 0, 16));
|
||||
si += 2;
|
||||
break;
|
||||
case '0': // octal ie "\033"
|
||||
if (si + 2 >= format_str.end()) return output_str; // end of string, invalid octal constant
|
||||
buf.clear();
|
||||
buf.push_back(*(si + 1));
|
||||
buf.push_back(*(si + 2));
|
||||
output_str.push_back((char)std::strtol( &buf[0], 0, 8));
|
||||
// TODO maybe octal constant has 3 bytes
|
||||
// if (si + 2 >= format_str.end()) return output_str; // end of string, invalid octal or hex constant
|
||||
// buf.push_back(*(si + 3));
|
||||
// si += 3;
|
||||
si += 2;
|
||||
break;
|
||||
default:
|
||||
output_str += c1;
|
||||
};
|
||||
|
||||
// normal characters
|
||||
} else {
|
||||
output_str += c;
|
||||
}
|
||||
}
|
||||
|
||||
return output_str;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "../ml.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
std::string mini_sprintf(const std::string &format_str, const std::vector<MlValue> ¶meters);
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
|
|
|||
38
debug.lsp
38
debug.lsp
|
|
@ -1,3 +1,35 @@
|
|||
(define json_list (parse-json "{\"k1\":\"v1\", \"k2\":42, \"k3\":[\"a\",123,true,false,null]}"))
|
||||
(print json_list)
|
||||
(for x json_list (print x))
|
||||
|
||||
; (print (sprintf "\033[31mred text"))
|
||||
; (print (sprintf "\x1B[31mred text"))
|
||||
|
||||
(define term-rst-esc "\x1B[0m")
|
||||
(define term-red-esc '"\x1B[31m")
|
||||
(define term-green-esc "\x1B[32m")
|
||||
(define term-yellow-esc "\x1B[33m")
|
||||
(define term-blue-esc "\x1B[34m")
|
||||
(define term-magenta-esc "\x1B[35m")
|
||||
(define term-cyan-esc "\x1B[36m")
|
||||
(define term-white-esc "\x1B[37m")
|
||||
(define term-bold-esc "\x1B[1m")
|
||||
(define term-underline-esc "\x1B[4m")
|
||||
|
||||
(defun term-red (str) (sprintf (+ term-red-esc str term-rst-esc)))
|
||||
(defun term-green (str) (sprintf (+ term-green-esc str term-rst-esc)))
|
||||
(defun term-yellow (str) (sprintf (+ term-yellow-esc str term-rst-esc)))
|
||||
(defun term-blue (str) (sprintf (+ term-blue-esc str term-rst-esc)))
|
||||
(defun term-magenta (str) (sprintf (+ term-magenta-esc str term-rst-esc)))
|
||||
(defun term-cyan (str) (sprintf (+ term-cyan-esc str term-rst-esc)))
|
||||
(defun term-white (str) (sprintf (+ term-white-esc str term-rst-esc)))
|
||||
(defun term-bold (str) (sprintf (+ term-bold-esc str term-rst-esc)))
|
||||
(defun term-underline (str) (sprintf (+ term-underline-esc str term-rst-esc)))
|
||||
|
||||
(print (term-red "red text"))
|
||||
(print (term-green "green text"))
|
||||
(print (term-yellow "yellow text"))
|
||||
(print (term-blue "blue text"))
|
||||
(print (term-magenta "magenta text"))
|
||||
(print (term-cyan "cyan text"))
|
||||
(print (term-white "white text"))
|
||||
(print (term-bold "bold text"))
|
||||
(print (term-underline "underline text"))
|
||||
(print "normal text")
|
||||
|
|
|
|||
26
ml.cpp
26
ml.cpp
|
|
@ -7,6 +7,7 @@
|
|||
#include "clib/csvparser.h"
|
||||
#include "clib/sslclient.h"
|
||||
#include "clib/json11.h"
|
||||
#include "clib/printf.h"
|
||||
|
||||
|
||||
#include <cmath>
|
||||
|
|
@ -176,7 +177,7 @@ int MlValue::as_int() const {
|
|||
|
||||
// Get this item's floating point value
|
||||
double MlValue::as_float() const {
|
||||
return cast_to_int().stack_data.f;
|
||||
return cast_to_float().stack_data.f;
|
||||
}
|
||||
|
||||
// Get this item's string value
|
||||
|
|
@ -728,7 +729,7 @@ MlValue parse(std::string &s, int &ptr) {
|
|||
skip_whitespace(s, ptr);
|
||||
|
||||
if (s[ptr] == ';')
|
||||
throw std::runtime_error("this should never happen!");
|
||||
throw std::runtime_error(INTERNAL_ERROR);
|
||||
|
||||
|
||||
if (s == "") {
|
||||
|
|
@ -1084,8 +1085,7 @@ namespace builtin {
|
|||
|
||||
// TODO add support for more params specifying options
|
||||
if (args.size() != 1)
|
||||
throw MlError(MlValue("parse-json", parse_json), env,
|
||||
args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||
throw MlError(MlValue("parse-json", parse_json), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||
|
||||
std::string str = args[0].as_string();
|
||||
std::string err;
|
||||
|
|
@ -1099,7 +1099,7 @@ namespace builtin {
|
|||
return json.ivalualize();
|
||||
}
|
||||
|
||||
// get current time as secs from epoch
|
||||
// Get current time as secs from epoch
|
||||
MlValue get_universal_time(std::vector<MlValue> args, MlEnvironment &env) {
|
||||
eval_args(args, env);
|
||||
|
||||
|
|
@ -1113,8 +1113,7 @@ namespace builtin {
|
|||
eval_args(args, env);
|
||||
|
||||
if (args.size() != 2)
|
||||
throw MlError(MlValue("date_to_str", date_to_str), env,
|
||||
args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||
throw MlError(MlValue("date_to_str", date_to_str), env, args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||
|
||||
return MlValue::string(date_to_string(args[0].as_int(), args[1].as_string()));
|
||||
}
|
||||
|
|
@ -1498,7 +1497,7 @@ namespace builtin {
|
|||
eval_args(args, env);
|
||||
|
||||
if (args.size() != 4)
|
||||
throw MlError(MlValue("regex_search", regex_search), env, args.size() > 4 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||
throw MlError(MlValue("string_pad", string_pad), env, args.size() > 4 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||
|
||||
// TODO validate len > 0 etc
|
||||
return MlValue::string(string_padd(args[0].as_string(), args[1].as_int(), args[2].as_string()[0], (args[3].as_string()=="rpad")));
|
||||
|
|
@ -1522,6 +1521,16 @@ namespace builtin {
|
|||
return MlValue::string(args[0].debug());
|
||||
}
|
||||
|
||||
MlValue sprintf(std::vector<MlValue> args, MlEnvironment &env) {
|
||||
eval_args(args, env);
|
||||
|
||||
std::string result;
|
||||
if (args.size() < 1 || args.size() > 2)
|
||||
throw MlError(MlValue("sprintf", sprintf), env, args.size() > 2 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||
|
||||
return MlValue::string(mini_sprintf(args[0].as_string(), args.size()==2 ? args[1].as_list() : std::vector<MlValue> {} ));
|
||||
}
|
||||
|
||||
// >>> (map (lambda (x) (+ x 10)) '(1 2 3 4 5 6))
|
||||
// => (11 12 13 14 15 16)
|
||||
MlValue map_list(std::vector<MlValue> args, MlEnvironment &env) {
|
||||
|
|
@ -1741,6 +1750,7 @@ MlValue MlEnvironment::get(const std::string &name) const {
|
|||
|
||||
// String operations
|
||||
if (name == "debug") return MlValue("debug", builtin::debug);
|
||||
if (name == "sprintf") return MlValue("sprintf", builtin::sprintf);
|
||||
if (name == "display") return MlValue("display", builtin::display);
|
||||
if (name == "replace") return MlValue("replace", builtin::replace);
|
||||
if (name == "regex-search?") return MlValue("regex-search?", builtin::regex_search);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
(define term-rst-esc "\x1B[0m")
|
||||
(define term-red-esc '"\x1B[31m")
|
||||
(define term-green-esc "\x1B[32m")
|
||||
(define term-yellow-esc "\x1B[33m")
|
||||
(define term-blue-esc "\x1B[34m")
|
||||
(define term-magenta-esc "\x1B[35m")
|
||||
(define term-cyan-esc "\x1B[36m")
|
||||
(define term-white-esc "\x1B[37m")
|
||||
(define term-bold-esc "\x1B[1m")
|
||||
(define term-underline-esc "\x1B[4m")
|
||||
|
||||
(defun term-red (str) (sprintf (+ term-red-esc str term-rst-esc)))
|
||||
(defun term-green (str) (sprintf (+ term-green-esc str term-rst-esc)))
|
||||
(defun term-yellow (str) (sprintf (+ term-yellow-esc str term-rst-esc)))
|
||||
(defun term-blue (str) (sprintf (+ term-blue-esc str term-rst-esc)))
|
||||
(defun term-magenta (str) (sprintf (+ term-magenta-esc str term-rst-esc)))
|
||||
(defun term-cyan (str) (sprintf (+ term-cyan-esc str term-rst-esc)))
|
||||
(defun term-white (str) (sprintf (+ term-white-esc str term-rst-esc)))
|
||||
(defun term-bold (str) (sprintf (+ term-bold-esc str term-rst-esc)))
|
||||
(defun term-underline (str) (sprintf (+ term-underline-esc str term-rst-esc)))
|
||||
|
||||
|
|
@ -158,4 +158,20 @@
|
|||
(print "list:" l)
|
||||
(print "flatten-ed list:" (flatten l))
|
||||
|
||||
(print (sprintf "%.2f" '(1.23456)))
|
||||
(print (sprintf "%d" '(10000000)))
|
||||
|
||||
|
||||
(print (term-red "red text"))
|
||||
(print (term-green "green text"))
|
||||
(print (term-yellow "yellow text"))
|
||||
(print (term-blue "blue text"))
|
||||
(print (term-magenta "magenta text"))
|
||||
(print (term-cyan "cyan text"))
|
||||
(print (term-white "white text"))
|
||||
(print (term-bold "bold text"))
|
||||
(print (term-underline "underline text"))
|
||||
(print "normal text")
|
||||
|
||||
|
||||
(print "Test ends")
|
||||
Loading…
Reference in New Issue