diff --git a/src/notebook.cpp b/src/notebook.cpp index 7172583..6ca1a86 100644 --- a/src/notebook.cpp +++ b/src/notebook.cpp @@ -254,7 +254,7 @@ bool Notebook::open(const boost::filesystem::path &file_path_, Position position }); boost::optional exit_status; std::string command = "rustup component add rust-analyzer"; - Terminal::get().print("\e[2mRunning: " + command + "\e[m\n"); + Terminal::get().print("\e[37mRunning: " + command + "\e[m\n"); auto process = Terminal::get().async_process(command, "", [&exit_status](int exit_status_) { exit_status = exit_status_; }); @@ -627,7 +627,7 @@ void Notebook::install_rust() { }); boost::optional exit_status; std::string command = "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"; - Terminal::get().print("\e[2mRunning: " + command + "\e[m\n"); + Terminal::get().print("\e[37mRunning: " + command + "\e[m\n"); auto process = Terminal::get().async_process(command, "", [&exit_status](int exit_status_) { exit_status = exit_status_; }); diff --git a/src/project.cpp b/src/project.cpp index 3c77ccb..cf7dc15 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -397,7 +397,7 @@ void Project::LLDB::debug_compile_and_start() { if(Config::get().terminal.clear_on_compile) Terminal::get().clear(); - Terminal::get().print("\e[2mCompiling and debugging: " + run_arguments + "\e[m\n"); + Terminal::get().print("\e[37mCompiling and debugging: " + run_arguments + "\e[m\n"); Terminal::get().async_process(build->get_compile_command(), debug_build_path, [self = shared_from_this(), debug_build_path, run_arguments, project_path = build->project_path, remote_host](int exit_status) { if(exit_status != 0) { debugging = false; @@ -428,7 +428,7 @@ void Project::LLDB::debug_start(const std::string &command, const boost::filesys Debug::LLDB::get().on_exit.erase(on_exit_it); Debug::LLDB::get().on_exit.emplace_back([self = shared_from_this(), command](int exit_status) { debugging = false; - Terminal::get().async_print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().async_print("\e[37m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); self->dispatcher.post([] { debug_update_status(""); }); @@ -728,7 +728,7 @@ void Project::Clang::compile() { if(Config::get().terminal.clear_on_compile) Terminal::get().clear(); - Terminal::get().print("\e[2mCompiling project: " + filesystem::get_short_path(build->project_path).string() + "\e[m\n"); + Terminal::get().print("\e[37mCompiling project: " + filesystem::get_short_path(build->project_path).string() + "\e[m\n"); Terminal::get().async_process(build->get_compile_command(), default_build_path, [self = shared_from_this(), default_build_path](int exit_status) { compiling = false; if(exit_status != 0 && !self->build->is_valid(default_build_path)) @@ -773,12 +773,12 @@ void Project::Clang::compile_and_run(const boost::filesystem::path &file_path) { if(Config::get().terminal.clear_on_compile) Terminal::get().clear(); - Terminal::get().print("\e[2mCompiling and running: " + arguments + "\e[m\n"); + Terminal::get().print("\e[37mCompiling and running: " + arguments + "\e[m\n"); Terminal::get().async_process(build->get_compile_command(), default_build_path, [self = shared_from_this(), arguments, project_path, default_build_path](int exit_status) { compiling = false; if(exit_status == 0) { Terminal::get().async_process(arguments, project_path, [arguments](int exit_status) { - Terminal::get().print("\e[2m" + arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } else if(!self->build->is_valid(default_build_path)) @@ -896,9 +896,9 @@ void Project::Python::compile_and_run(const boost::filesystem::path &file_path) if(Config::get().terminal.clear_on_compile) Terminal::get().clear(); - Terminal::get().print("\e[2mRunning: " + command + "\e[m\n"); + Terminal::get().print("\e[37mRunning: " + command + "\e[m\n"); Terminal::get().async_process(command, path, [command](int exit_status) { - Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } @@ -923,9 +923,9 @@ void Project::JavaScript::compile_and_run(const boost::filesystem::path &file_pa if(Config::get().terminal.clear_on_compile) Terminal::get().clear(); - Terminal::get().print("\e[2mRunning: " + command + "\e[m\n"); + Terminal::get().print("\e[37mRunning: " + command + "\e[m\n"); Terminal::get().async_process(command, path, [command](int exit_status) { - Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } @@ -936,9 +936,9 @@ void Project::HTML::compile_and_run(const boost::filesystem::path &file_path) { if(Config::get().terminal.clear_on_compile) Terminal::get().clear(); - Terminal::get().print("\e[2mRunning: " + command + "\e[m\n"); + Terminal::get().print("\e[37mRunning: " + command + "\e[m\n"); Terminal::get().async_process(command, build->project_path, [command](int exit_status) { - Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } else if(!file_path.empty()) @@ -966,7 +966,7 @@ void Project::Rust::compile() { if(Config::get().terminal.clear_on_compile) Terminal::get().clear(); - Terminal::get().print("\e[2mCompiling project: " + filesystem::get_short_path(build->project_path).string() + "\e[m\n"); + Terminal::get().print("\e[37mCompiling project: " + filesystem::get_short_path(build->project_path).string() + "\e[m\n"); Terminal::get().async_process(build->get_compile_command(), build->project_path, [](int exit_status) { compiling = false; @@ -980,14 +980,14 @@ void Project::Rust::compile_and_run(const boost::filesystem::path &file_path) { Terminal::get().clear(); auto arguments = get_run_arguments().second; - Terminal::get().print("\e[2mCompiling and running: " + arguments + "\e[m\n"); + Terminal::get().print("\e[37mCompiling and running: " + arguments + "\e[m\n"); auto self = this->shared_from_this(); Terminal::get().async_process(build->get_compile_command(), build->project_path, [self, arguments = std::move(arguments)](int exit_status) { compiling = false; if(exit_status == 0) { Terminal::get().async_process(arguments, self->build->project_path, [arguments](int exit_status) { - Terminal::get().print("\e[2m" + arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + arguments + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } }); @@ -1014,9 +1014,9 @@ void Project::Go::compile_and_run(const boost::filesystem::path &file_path) { if(Config::get().terminal.clear_on_compile) Terminal::get().clear(); - Terminal::get().print("\e[2mRunning: " + command + "\e[m\n"); + Terminal::get().print("\e[37mRunning: " + command + "\e[m\n"); Terminal::get().async_process(command, path, [command](int exit_status) { - Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } @@ -1037,8 +1037,8 @@ void Project::Julia::compile_and_run(const boost::filesystem::path &file_path) { if(Config::get().terminal.clear_on_compile) Terminal::get().clear(); - Terminal::get().print("\e[2mRunning: " + command + "\e[m\n"); + Terminal::get().print("\e[37mRunning: " + command + "\e[m\n"); Terminal::get().async_process(command, path, [command](int exit_status) { - Terminal::get().print("\e[2m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + command + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } diff --git a/src/terminal.cpp b/src/terminal.cpp index 097c235..9bbc543 100644 --- a/src/terminal.cpp +++ b/src/terminal.cpp @@ -17,6 +17,15 @@ Terminal::Terminal() : Source::CommonView() { bold_tag = get_buffer()->create_tag(); bold_tag->property_weight() = Pango::WEIGHT_BOLD; + light_tag = get_buffer()->create_tag(); + light_tag->property_weight() = Pango::WEIGHT_LIGHT; + + italic_tag = get_buffer()->create_tag(); + italic_tag->property_style() = Pango::STYLE_ITALIC; + underline_tag = get_buffer()->create_tag(); + underline_tag->property_underline() = Pango::Underline::UNDERLINE_SINGLE; + strikethrough_tag = get_buffer()->create_tag(); + strikethrough_tag->property_strikethrough() = true; red_tag = get_buffer()->create_tag(); green_tag = get_buffer()->create_tag(); @@ -24,7 +33,7 @@ Terminal::Terminal() : Source::CommonView() { blue_tag = get_buffer()->create_tag(); magenta_tag = get_buffer()->create_tag(); cyan_tag = get_buffer()->create_tag(); - gray_tag = get_buffer()->create_tag(); + white_tag = get_buffer()->create_tag(); link_tag = get_buffer()->create_tag(); link_tag->property_underline() = Pango::Underline::UNDERLINE_SINGLE; @@ -110,7 +119,38 @@ Terminal::Terminal() : Source::CommonView() { return {}; } }; - get_buffer()->signal_insert().connect([this, detect_possible_link = DetectPossibleLink(), parse_ansi_escape_sequence = ParseAnsiEscapeSequence(), last_color = -1, last_color_sequence_mark = std::shared_ptr()](const Gtk::TextIter &iter, const Glib::ustring &text_, int /*bytes*/) mutable { + class Code { + public: + int code = -1; + std::shared_ptr start_mark; + }; + auto code_to_color_tag = [this](int code) { + if(code == 31) + return red_tag; + else if(code == 32) + return green_tag; + else if(code == 33) + return yellow_tag; + else if(code == 34) + return blue_tag; + else if(code == 35) + return magenta_tag; + else if(code == 36) + return cyan_tag; + else if(code == 37) + return white_tag; + return Glib::RefPtr(); + }; + auto code_to_weight_tag = [this](int code) { + if(code == 1) + return bold_tag; + else if(code == 2) + return light_tag; + return Glib::RefPtr(); + }; + get_buffer()->signal_insert().connect([this, code_to_color_tag, code_to_weight_tag, + detect_possible_link = DetectPossibleLink(), parse_ansi_escape_sequence = ParseAnsiEscapeSequence(), + color_code = Code(), weight_code = Code(), italic_code = Code(), underline_code = Code(), strikethrough_code = Code()](const Gtk::TextIter &iter, const Glib::ustring &text_, int /*bytes*/) mutable { boost::optional start_of_text; int line_nr_offset = 0; auto get_line_nr = [&] { @@ -144,9 +184,31 @@ Terminal::Terminal() : Source::CommonView() { start.backward_chars(sequence->length); get_buffer()->apply_tag(invisible_tag, start, end); if(sequence->command == 'm') { - int color = -1; - if(sequence->arguments.empty()) - color = 0; + auto reset = [&] { + if(color_code.start_mark) { + auto tag = code_to_color_tag(color_code.code); + if(tag) + get_buffer()->apply_tag(tag, (*color_code.start_mark)->get_iter(), start); + } + if(weight_code.start_mark) { + auto tag = code_to_weight_tag(weight_code.code); + if(tag) + get_buffer()->apply_tag(tag, (*weight_code.start_mark)->get_iter(), start); + } + if(italic_code.start_mark) + get_buffer()->apply_tag(italic_tag, (*italic_code.start_mark)->get_iter(), start); + if(underline_code.start_mark) + get_buffer()->apply_tag(underline_tag, (*underline_code.start_mark)->get_iter(), start); + if(strikethrough_code.start_mark) + get_buffer()->apply_tag(strikethrough_tag, (*strikethrough_code.start_mark)->get_iter(), start); + color_code = {}; + weight_code = {}; + italic_code = {}; + underline_code = {}; + strikethrough_code = {}; + }; + if(sequence->arguments.empty()) // Reset + reset(); else { size_t pos = 0; size_t start_pos = pos; @@ -154,16 +216,74 @@ Terminal::Terminal() : Source::CommonView() { pos = sequence->arguments.find(";", pos); try { auto code = std::stoi(sequence->arguments.substr(start_pos, pos != std::string::npos ? pos - start_pos : pos)); - if(code == 39) - color = 0; - else if(code == 38) { - color = 0; - break; // Do not read next arguments + if(code == 0) // Reset + reset(); + else if(code == 1 || code == 2) { // Bold or faint + if(weight_code.start_mark) { + auto tag = code_to_weight_tag(weight_code.code); + if(tag) + get_buffer()->apply_tag(tag, (*weight_code.start_mark)->get_iter(), start); + } + weight_code = {code, std::make_shared(end)}; + } + else if(code == 3) // Italic + italic_code = {code, std::make_shared(end)}; + else if(code == 4) // Underline + underline_code = {code, std::make_shared(end)}; + else if(code == 9) // Strikethrough + strikethrough_code = {code, std::make_shared(end)}; + else if(code == 22) { // Normal intensity + if(weight_code.start_mark) { + auto tag = code_to_weight_tag(weight_code.code); + if(tag) + get_buffer()->apply_tag(tag, (*weight_code.start_mark)->get_iter(), start); + } + weight_code = {}; + } + else if(code == 23) { // No italic + if(italic_code.start_mark) + get_buffer()->apply_tag(italic_tag, (*italic_code.start_mark)->get_iter(), start); + italic_code = {}; } - else if(code == 48 || code == 58) - break; // Do not read next arguments - else if(code == 0 || code == 2 || code == 22 || (code >= 30 && code <= 37)) - color = code; + else if(code == 24) { // No underline + if(underline_code.start_mark) + get_buffer()->apply_tag(underline_tag, (*underline_code.start_mark)->get_iter(), start); + underline_code = {}; + } + else if(code == 29) { // No strikethrough + if(strikethrough_code.start_mark) + get_buffer()->apply_tag(strikethrough_tag, (*strikethrough_code.start_mark)->get_iter(), start); + strikethrough_code = {}; + } + else if(code >= 30 && code <= 37) { // Foreground color + if(color_code.start_mark) { + auto tag = code_to_color_tag(color_code.code); + if(tag) + get_buffer()->apply_tag(tag, (*color_code.start_mark)->get_iter(), start); + } + color_code = {code, std::make_shared(end)}; + } + else if(code == 38) { // Set specific color not supported + if(color_code.start_mark) { + auto tag = code_to_color_tag(color_code.code); + if(tag) + get_buffer()->apply_tag(tag, (*color_code.start_mark)->get_iter(), start); + } + color_code = {}; + break; + } + else if(code == 39) { // Default color + if(color_code.start_mark) { + auto tag = code_to_color_tag(color_code.code); + if(tag) + get_buffer()->apply_tag(tag, (*color_code.start_mark)->get_iter(), start); + } + color_code = {}; + } + else if(code == 48) // Set specific background color not supported + break; + else if(code == 58) // Set specific underline color not supported + break; } catch(...) { } @@ -173,27 +293,6 @@ Terminal::Terminal() : Source::CommonView() { start_pos = pos; } } - if(last_color >= 0) { - if(last_color == 31) - get_buffer()->apply_tag(red_tag, (*last_color_sequence_mark)->get_iter(), start); - else if(last_color == 32) - get_buffer()->apply_tag(green_tag, (*last_color_sequence_mark)->get_iter(), start); - else if(last_color == 33) - get_buffer()->apply_tag(yellow_tag, (*last_color_sequence_mark)->get_iter(), start); - else if(last_color == 34) - get_buffer()->apply_tag(blue_tag, (*last_color_sequence_mark)->get_iter(), start); - else if(last_color == 35) - get_buffer()->apply_tag(magenta_tag, (*last_color_sequence_mark)->get_iter(), start); - else if(last_color == 36) - get_buffer()->apply_tag(cyan_tag, (*last_color_sequence_mark)->get_iter(), start); - else if(last_color == 37 || last_color == 2) - get_buffer()->apply_tag(gray_tag, (*last_color_sequence_mark)->get_iter(), start); - } - - if(color >= 0) { - last_color = color; - last_color_sequence_mark = std::make_shared(end); - } } } if(text[i] == '\n') @@ -540,11 +639,11 @@ void Terminal::configure() { cyan_tag->property_foreground_rgba() = rgba; rgba.set_rgba(0.5, 0.5, 0.5); - factor = light_theme ? 0.6 : 0.4; + factor = light_theme ? 0.7 : 0.4; rgba.set_red(normal_color.get_red() + factor * (rgba.get_red() - normal_color.get_red())); rgba.set_green(normal_color.get_green() + factor * (rgba.get_green() - normal_color.get_green())); rgba.set_blue(normal_color.get_blue() + factor * (rgba.get_blue() - normal_color.get_blue())); - gray_tag->property_foreground_rgba() = rgba; + white_tag->property_foreground_rgba() = rgba; // Set search match style: get_buffer()->get_tag_table()->foreach([](const Glib::RefPtr &tag) { diff --git a/src/terminal.hpp b/src/terminal.hpp index 100046f..e678199 100644 --- a/src/terminal.hpp +++ b/src/terminal.hpp @@ -46,10 +46,10 @@ protected: private: Dispatcher dispatcher; - Glib::RefPtr bold_tag; + Glib::RefPtr bold_tag, light_tag, italic_tag, underline_tag, strikethrough_tag; Glib::RefPtr link_tag; Glib::RefPtr invisible_tag; - Glib::RefPtr red_tag, green_tag, yellow_tag, blue_tag, magenta_tag, cyan_tag, gray_tag; + Glib::RefPtr red_tag, green_tag, yellow_tag, blue_tag, magenta_tag, cyan_tag, white_tag; Glib::RefPtr link_mouse_cursor; Glib::RefPtr default_mouse_cursor; diff --git a/src/window.cpp b/src/window.cpp index 3507e3d..36580a2 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1453,10 +1453,10 @@ void Window::set_menu_actions() { auto directory_folder = Project::get_preferably_directory_folder(); if(Config::get().terminal.clear_on_run_command) Terminal::get().clear(); - Terminal::get().async_print("\e[2mRunning: " + content + "\e[m\n"); + Terminal::get().async_print("\e[37mRunning: " + content + "\e[m\n"); Terminal::get().async_process(content, directory_folder, [content](int exit_status) { - Terminal::get().print("\e[2m" + content + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + content + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } if(Config::get().terminal.hide_entry_on_run_command) @@ -1975,19 +1975,19 @@ bool Window::on_key_press_event(GdkEventKey *event) { if(!command.debug) { Project::compiling = true; - Terminal::get().print("\e[2mCompiling and running: " + label + "\e[m\n"); + Terminal::get().print("\e[37mCompiling and running: " + label + "\e[m\n"); Terminal::get().async_process(compile, run_path, [run, run_path, label](int exit_status) { Project::compiling = false; if(exit_status == 0) { Terminal::get().async_process(run, run_path, [label](int exit_status) { - Terminal::get().print("\e[2m" + label + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + label + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } }); } else { // Debug Project::debugging = true; - Terminal::get().print("\e[2mCompiling and debugging: " + label + "\e[m\n"); + Terminal::get().print("\e[37mCompiling and debugging: " + label + "\e[m\n"); Terminal::get().async_process(compile, run_path, [project = project->shared_from_this(), run, run_path, debug_remote_host = command.debug_remote_host](int exit_status) { if(exit_status != EXIT_SUCCESS) Project::debugging = false; @@ -1997,14 +1997,14 @@ bool Window::on_key_press_event(GdkEventKey *event) { } } else if(!command.debug) { - Terminal::get().async_print("\e[2mRunning: " + label + "\e[m\n"); + Terminal::get().async_print("\e[37mRunning: " + label + "\e[m\n"); Terminal::get().async_process(run, run_path, [label](int exit_status) { - Terminal::get().print("\e[2m" + label + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); + Terminal::get().print("\e[37m" + label + " returned: " + (exit_status == 0 ? "\e[32m" : "\e[31m") + std::to_string(exit_status) + "\e[m\n"); }); } else { // Debug Project::debugging = true; - Terminal::get().async_print("\e[2mDebugging: " + label + "\e[m\n"); + Terminal::get().async_print("\e[37mDebugging: " + label + "\e[m\n"); project->debug_start(run, run_path, command.debug_remote_host); } return true; diff --git a/tests/terminal_test.cpp b/tests/terminal_test.cpp index 946d8ae..0c7101a 100644 --- a/tests/terminal_test.cpp +++ b/tests/terminal_test.cpp @@ -252,8 +252,10 @@ int main() { auto iter = buffer->begin(); iter.forward_chars(15); assert(iter.starts_tag(terminal.red_tag)); + assert(iter.starts_tag(terminal.bold_tag)); iter.forward_chars(7); assert(iter.ends_tag(terminal.red_tag)); + assert(iter.ends_tag(terminal.bold_tag)); } { terminal.clear(); @@ -276,9 +278,15 @@ int main() { iter.forward_visible_cursor_positions(3); assert(iter.get_tags().empty()); iter.forward_visible_cursor_positions(1); - assert(iter.get_tags() == std::vector>{terminal.red_tag}); + auto tags = iter.get_tags(); + assert(tags.size() == 2); + assert(std::find(tags.begin(), tags.end(), Glib::RefPtr{terminal.red_tag}) != tags.end()); + assert(std::find(tags.begin(), tags.end(), Glib::RefPtr{terminal.bold_tag}) != tags.end()); iter.forward_visible_cursor_positions(3); - assert(iter.get_tags() == std::vector>{terminal.red_tag}); + tags = iter.get_tags(); + assert(tags.size() == 2); + assert(std::find(tags.begin(), tags.end(), Glib::RefPtr{terminal.red_tag}) != tags.end()); + assert(std::find(tags.begin(), tags.end(), Glib::RefPtr{terminal.bold_tag}) != tags.end()); iter.forward_visible_cursor_positions(1); assert(iter.get_tags().empty()); } @@ -295,6 +303,72 @@ int main() { iter.forward_visible_cursor_positions(1); assert(iter.get_tags().empty()); } + { + terminal.clear(); + terminal.print("test\e[02mtest\e[0mtest"); + assert(buffer->get_text(true) == "test\e[02mtest\e[0mtest"); + assert(buffer->get_text(false) == "testtesttest"); + auto iter = buffer->begin(); + iter.forward_chars(9); + assert(iter.starts_tag(terminal.light_tag)); + iter.forward_chars(4); + assert(iter.ends_tag(terminal.light_tag)); + } + { + terminal.clear(); + terminal.print("test\e[02mtest\e[22mtest"); + assert(buffer->get_text(true) == "test\e[02mtest\e[22mtest"); + assert(buffer->get_text(false) == "testtesttest"); + auto iter = buffer->begin(); + iter.forward_chars(9); + assert(iter.starts_tag(terminal.light_tag)); + iter.forward_chars(4); + assert(iter.ends_tag(terminal.light_tag)); + } + { + terminal.clear(); + terminal.print("test\e[03mtest\e[23mtest"); + assert(buffer->get_text(true) == "test\e[03mtest\e[23mtest"); + assert(buffer->get_text(false) == "testtesttest"); + auto iter = buffer->begin(); + iter.forward_chars(9); + assert(iter.starts_tag(terminal.italic_tag)); + iter.forward_chars(4); + assert(iter.ends_tag(terminal.italic_tag)); + } + { + terminal.clear(); + terminal.print("test\e[04mtest\e[24mtest"); + assert(buffer->get_text(true) == "test\e[04mtest\e[24mtest"); + assert(buffer->get_text(false) == "testtesttest"); + auto iter = buffer->begin(); + iter.forward_chars(9); + assert(iter.starts_tag(terminal.underline_tag)); + iter.forward_chars(4); + assert(iter.ends_tag(terminal.underline_tag)); + } + { + terminal.clear(); + terminal.print("test\e[09mtest\e[29mtest"); + assert(buffer->get_text(true) == "test\e[09mtest\e[29mtest"); + assert(buffer->get_text(false) == "testtesttest"); + auto iter = buffer->begin(); + iter.forward_chars(9); + assert(iter.starts_tag(terminal.strikethrough_tag)); + iter.forward_chars(4); + assert(iter.ends_tag(terminal.strikethrough_tag)); + } + { + terminal.clear(); + terminal.print("test\e[31mtest\e[32mtest\e[0m"); + assert(buffer->get_text(true) == "test\e[31mtest\e[32mtest\e[0m"); + assert(buffer->get_text(false) == "testtesttest"); + auto iter = buffer->begin(); + iter.forward_chars(9); + assert(iter.starts_tag(terminal.red_tag)); + iter.forward_chars(4); + assert(iter.ends_tag(terminal.red_tag)); + } // async_process tests {