diff --git a/CMakeLists.txt b/CMakeLists.txt index 3606e16..a7c203c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 5.1.12) +set(BLT_VERSION 5.1.13) set(BLT_TARGET BLT) diff --git a/include/blt/fs/filesystem.h b/include/blt/fs/filesystem.h index 17bdbd2..8695f31 100644 --- a/include/blt/fs/filesystem.h +++ b/include/blt/fs/filesystem.h @@ -19,145 +19,49 @@ #ifndef BLT_FILESYSTEM_H #define BLT_FILESYSTEM_H -#include -#include +#include +#include namespace blt::fs { - /** - * A simple interface which provides a way of reading the next block of data from a resource. - * The interface provides a single function "read" which will read a specified number of bytes into the buffer. - * The implementation for this could be fstreams, zlib deflate, or any method filesystem access. - * Reading of a large number of bytes ( > block size) is guaranteed to not significantly increase the read time and will likely result in a - * direct passthrough to the underlying system. Small reads will be buffered, hence the name "block" reader. - */ - class block_reader - { - protected: - // 32768 block size seems the fastest on my system - unsigned long m_bufferSize; - public: - explicit block_reader(size_t bufferSize): m_bufferSize(bufferSize) - {} - - /** - * Reads bytes from the internal filesystem implementation - * @param buffer buffer to copy the read bytes into - * @param bytes number of bytes to read - * @return status code. non-zero return codes indicates a failure has occurred. - */ - virtual int read(char* buffer, size_t bytes) = 0; - - virtual size_t gcount() = 0; - - virtual char get() - { - char c[1]; - read(c, 1); - return c[0]; - } - }; - - /** - * A buffered block writer without a definite backend implementation. Exactly the same as a block_reader but for writing to the filesystem. - */ - class block_writer - { - protected: - unsigned long m_bufferSize; - public: - explicit block_writer(unsigned long bufferSize): m_bufferSize(bufferSize) - {} - - /** - * Writes the bytes to the filesystem backend implementation - * @param buffer bytes to write - * @param bytes number of bytes to write - * @return non-zero code if failure - */ - virtual int write(char* buffer, size_t bytes) = 0; - - virtual int put(char c) - { - char a[1]; - a[0] = c; - return write(a, 1); - } - - /** - * Ensures that the internal buffer is written to the filesystem. - */ - virtual void flush() = 0; - }; - - /** - * fstream implementation of the block reader. - */ - class fstream_block_reader : public block_reader - { - private: - std::fstream& m_stream; - char* m_buffer = nullptr; - size_t readIndex = 0; - public: - explicit fstream_block_reader(std::fstream& stream, size_t bufferSize = 131072); - - explicit fstream_block_reader(fstream_block_reader& copy) = delete; - - explicit fstream_block_reader(fstream_block_reader&& move) = delete; - - fstream_block_reader& operator=(const fstream_block_reader& copy) = delete; - - fstream_block_reader& operator=(const fstream_block_reader&& move) = delete; - - int read(char* buffer, size_t bytes) override; - - size_t gcount() final - { - return m_stream.gcount(); - } - - ~fstream_block_reader() - { - delete[] m_buffer; - } - }; - - class fstream_block_writer : public block_writer - { - private: - std::fstream& m_stream; - char* m_buffer; - size_t writeIndex = 0; - - void flush_internal(); - - public: - explicit fstream_block_writer(std::fstream& stream, size_t bufferSize = 131072): - block_writer(bufferSize), m_stream(stream), m_buffer(new char[bufferSize]) - {} - - explicit fstream_block_writer(fstream_block_writer& copy) = delete; - - explicit fstream_block_writer(fstream_block_writer&& move) = delete; - - fstream_block_writer& operator=(const fstream_block_writer& copy) = delete; - - fstream_block_writer& operator=(const fstream_block_writer&& move) = delete; - - int write(char* buffer, size_t bytes) override; - - inline void flush() override - { - flush_internal(); - } - - ~fstream_block_writer() - { - flush_internal(); - delete[] m_buffer; - } - }; + /** + * reader_t wrapper for fstream + */ + class fstream_reader_t final : public reader_t + { + public: + explicit fstream_reader_t(std::istream& stream); + + explicit fstream_reader_t(fstream_reader_t& copy) = delete; + + fstream_reader_t& operator=(const fstream_reader_t& copy) = delete; + + i64 read(char* buffer, size_t bytes) override; + private: + std::istream* m_stream; + }; + + class fstream_writer_t final : public writer_t + { + public: + explicit fstream_writer_t(std::ostream& stream); + + explicit fstream_writer_t(fstream_writer_t& copy) = delete; + + fstream_writer_t& operator=(const fstream_writer_t& copy) = delete; + + i64 write(char* buffer, size_t bytes) override; + + void flush() override; + + virtual ~fstream_writer_t() override // NOLINT + { + flush(); + } + + private: + std::ostream* m_stream; + }; } #endif //BLT_FILESYSTEM_H diff --git a/include/blt/fs/fwddecl.h b/include/blt/fs/fwddecl.h new file mode 100644 index 0000000..df91679 --- /dev/null +++ b/include/blt/fs/fwddecl.h @@ -0,0 +1,77 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLT_FS_FWDDECL_H +#define BLT_FS_FWDDECL_H + +#include + +namespace blt::fs +{ + /** + * A simple interface which provides a way of reading the next block of data from a resource. This is designed to replace the overly complex + * std::ostream + */ + class reader_t + { + public: + virtual ~reader_t() = default; + explicit reader_t() = default; + + reader_t(const reader_t&) = delete; + reader_t& operator=(const reader_t&) = delete; + + /** + * Reads bytes from the internal filesystem implementation + * @param buffer buffer to copy the read bytes into + * @param bytes number of bytes to read + * @return number of bytes read, or negative value if error. Errors are not required and can just return 0 + */ + virtual i64 read(char* buffer, size_t bytes) = 0; + }; + + /** + * A block writer without a definite backend implementation. Exactly the same as a block_reader but for writing to the filesystem. + * this is designed to replace the overly complex std::istream + */ + class writer_t + { + public: + virtual ~writer_t() = default; + explicit writer_t() = default; + + writer_t(const writer_t&) = delete; + writer_t& operator=(const writer_t&) = delete; + + /** + * Writes the bytes to the filesystem backend implementation + * @param buffer bytes to write + * @param bytes number of bytes to write + * @return number of bytes, or negative value if error. Zero is also a valid return, not indicating error in itself but can be the result of one. + */ + virtual i64 write(char* buffer, size_t bytes) = 0; + + /** + * Optional flush command which syncs the underlying objects + */ + virtual void flush() + {}; + }; +} + +#endif //BLT_FS_FWDDECL_H diff --git a/include/blt/fs/nbt.h b/include/blt/fs/nbt.h index 0a04535..2efa0b7 100644 --- a/include/blt/fs/nbt.h +++ b/include/blt/fs/nbt.h @@ -22,19 +22,19 @@ namespace blt::nbt { - void writeUTF8String(blt::fs::block_writer& stream, const std::string& str); + void writeUTF8String(blt::fs::writer_t& stream, const std::string& str); - std::string readUTF8String(blt::fs::block_reader& stream); + std::string readUTF8String(blt::fs::reader_t& stream); template - inline static void writeData(blt::fs::block_writer& out, const T& d){ + inline static void writeData(blt::fs::writer_t& out, const T& d){ char data[sizeof(T)]; mem::toBytes(d, data); out.write(data, sizeof(T)); } template - inline static void readData(blt::fs::block_reader& in, T& d) { + inline static void readData(blt::fs::reader_t& in, T& d) { char data[sizeof(T)]; in.read(data, sizeof(T)); mem::fromBytes(data, &d); @@ -63,12 +63,12 @@ namespace blt::nbt { public: explicit tag_t(nbt_tag type): type(type) {}; explicit tag_t(nbt_tag type, std::string name): type(type), name(std::move(name)) {} - virtual void writePayload(blt::fs::block_writer& out) = 0; - virtual void readPayload(blt::fs::block_reader& in) = 0; - void writeName(blt::fs::block_writer& out) { + virtual void writePayload(blt::fs::writer_t& out) = 0; + virtual void readPayload(blt::fs::reader_t& in) = 0; + void writeName(blt::fs::writer_t& out) { writeUTF8String(out, name); } - void readName(blt::fs::block_reader& in) { + void readName(blt::fs::reader_t& in) { name = readUTF8String(in); } [[nodiscard]] inline nbt_tag getType() const { @@ -87,11 +87,11 @@ namespace blt::nbt { public: explicit tag(nbt_tag type): tag_t(type) {} tag(nbt_tag type, std::string name, T t): tag_t(type, std::move(name)), t(std::move(t)) {} - void writePayload(blt::fs::block_writer& out) override { + void writePayload(blt::fs::writer_t& out) override { if constexpr(std::is_arithmetic::value) writeData(out, t); } - void readPayload(blt::fs::block_reader& in) override { + void readPayload(blt::fs::reader_t& in) override { if constexpr(std::is_arithmetic::value) readData(in, t); } @@ -102,9 +102,9 @@ namespace blt::nbt { class tag_end : public tag { public: - void writePayload(blt::fs::block_writer&) final {} + void writePayload(blt::fs::writer_t&) final {} // nothing to read - void readPayload(blt::fs::block_reader&) final {} + void readPayload(blt::fs::reader_t&) final {} }; class tag_byte : public tag { @@ -147,13 +147,13 @@ namespace blt::nbt { public: tag_byte_array(): tag(nbt_tag::BYTE_ARRAY) {} tag_byte_array(const std::string& name, const std::vector& v): tag(nbt_tag::BYTE_ARRAY, name, v) {} - void writePayload(blt::fs::block_writer& out) final { + void writePayload(blt::fs::writer_t& out) final { auto length = (int32_t) t.size(); writeData(out, length); // TODO on the writer (remove need for cast + more std::fstream functions) out.write(reinterpret_cast(t.data()), length); } - void readPayload(blt::fs::block_reader& in) final { + void readPayload(blt::fs::reader_t& in) final { int32_t length; readData(in, length); t.reserve(length); @@ -165,10 +165,10 @@ namespace blt::nbt { public: tag_string(): tag(nbt_tag::STRING) {} tag_string(const std::string& name, const std::string& s): tag(nbt_tag::STRING, name, s) {} - void writePayload(blt::fs::block_writer& out) final { + void writePayload(blt::fs::writer_t& out) final { writeUTF8String(out, t); } - void readPayload(blt::fs::block_reader& in) final { + void readPayload(blt::fs::reader_t& in) final { t = readUTF8String(in); } }; @@ -177,13 +177,13 @@ namespace blt::nbt { public: tag_int_array(): tag(nbt_tag::INT_ARRAY) {} tag_int_array(const std::string& name, const std::vector& v): tag(nbt_tag::INT_ARRAY, name, v) {} - void writePayload(blt::fs::block_writer& out) final { + void writePayload(blt::fs::writer_t& out) final { auto length = (int32_t) t.size(); writeData(out, length); for (int i = 0; i < length; i++) writeData(out, t[i]); } - void readPayload(blt::fs::block_reader& in) final { + void readPayload(blt::fs::reader_t& in) final { int32_t length; readData(in, length); t.reserve(length); @@ -196,13 +196,13 @@ namespace blt::nbt { public: tag_long_array(): tag(nbt_tag::LONG_ARRAY) {} tag_long_array(const std::string& name, const std::vector& v): tag(nbt_tag::LONG_ARRAY, name, v) {} - void writePayload(blt::fs::block_writer& out) final { + void writePayload(blt::fs::writer_t& out) final { auto length = (int32_t) t.size(); writeData(out, length); for (int i = 0; i < length; i++) writeData(out, t[i]); } - void readPayload(blt::fs::block_reader& in) final { + void readPayload(blt::fs::reader_t& in) final { int32_t length; readData(in, length); t.reserve(length); @@ -262,7 +262,7 @@ namespace blt::nbt { public: tag_list(): tag(nbt_tag::LIST) {} tag_list(const std::string& name, const std::vector& v): tag(nbt_tag::LIST, name, v) {} - void writePayload(blt::fs::block_writer& out) final { + void writePayload(blt::fs::writer_t& out) final { if (t.empty()) writeData(out, (char)nbt_tag::END); else @@ -273,7 +273,7 @@ namespace blt::nbt { v->writePayload(out); } - void readPayload(blt::fs::block_reader& in) final { + void readPayload(blt::fs::reader_t& in) final { char id; int32_t length; readData(in, id); @@ -356,7 +356,7 @@ namespace blt::nbt { t[tag->getName()] = tag; } - void writePayload(blt::fs::block_writer& out) final { + void writePayload(blt::fs::writer_t& out) final { for (const auto& v : t){ auto tag = v.second; out.put((char) tag->getType()); @@ -365,7 +365,7 @@ namespace blt::nbt { } out.put('\0'); } - void readPayload(blt::fs::block_reader& in) final { + void readPayload(blt::fs::reader_t& in) final { char type; while ((type = in.get()) != (char)nbt_tag::END){ auto* v = _internal_::toType(type); @@ -390,10 +390,10 @@ namespace blt::nbt { class NBTReader { private: - blt::fs::block_reader& reader; + blt::fs::reader_t& reader; tag_compound* root = nullptr; public: - explicit NBTReader(blt::fs::block_reader& reader): reader(reader) {} + explicit NBTReader(blt::fs::reader_t& reader): reader(reader) {} void read(); @@ -419,9 +419,9 @@ namespace blt::nbt { class NBTWriter { private: - blt::fs::block_writer& writer; + blt::fs::writer_t& writer; public: - explicit NBTWriter(blt::fs::block_writer& writer): writer(writer) {} + explicit NBTWriter(blt::fs::writer_t& writer): writer(writer) {} /** * Write a compound tag and then DELETES the tag. If you don't wish for the memory to be freed, please use the reference version! * @param root root NBT tag to write, this function assumes ownership of this pointer. diff --git a/include/blt/logging/fmt_tokenizer.h b/include/blt/logging/fmt_tokenizer.h index 7f98833..136994f 100644 --- a/include/blt/logging/fmt_tokenizer.h +++ b/include/blt/logging/fmt_tokenizer.h @@ -19,11 +19,11 @@ #ifndef BLT_LOGGING_FMT_TOKENIZER_H #define BLT_LOGGING_FMT_TOKENIZER_H +#include #include #include #include #include -#include namespace blt::logging { diff --git a/include/blt/logging/fwddecl.h b/include/blt/logging/fwddecl.h new file mode 100644 index 0000000..5c8b7c0 --- /dev/null +++ b/include/blt/logging/fwddecl.h @@ -0,0 +1,35 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLT_LOGGING_FWDDECL_H +#define BLT_LOGGING_FWDDECL_H + +namespace blt::logging +{ + struct logger_t; + enum class fmt_token_type : u8; + enum class fmt_align_t : u8; + enum class fmt_sign_t : u8; + enum class fmt_type_t : u8; + struct fmt_spec_t; + struct fmt_token_t; + class fmt_tokenizer_t; + class fmt_parser_t; +} + +#endif //BLT_LOGGING_FWDDECL_H diff --git a/include/blt/logging/logging.h b/include/blt/logging/logging.h index f8789d4..b09059b 100644 --- a/include/blt/logging/logging.h +++ b/include/blt/logging/logging.h @@ -19,14 +19,15 @@ #ifndef BLT_LOGGING_LOGGING_H #define BLT_LOGGING_LOGGING_H +#include +#include #include #include #include -#include -#include #include -#include +#include #include +#include namespace blt::logging { diff --git a/include/blt/logging/logging_config.h b/include/blt/logging/logging_config.h index 3447e41..29438f3 100644 --- a/include/blt/logging/logging_config.h +++ b/include/blt/logging/logging_config.h @@ -19,40 +19,48 @@ #ifndef BLT_LOGGING_LOGGING_CONFIG_H #define BLT_LOGGING_LOGGING_CONFIG_H -#include -#include -#include -#include #include +#include +#include +#include +#include +#include namespace blt::logging { - enum class log_level_t - { - TRACE, - DEBUG, - INFO, - WARN, - ERROR, - FATAL - }; + enum class log_level_t : u8 + { + TRACE, + DEBUG, + INFO, + WARN, + ERROR, + FATAL + }; - inline constexpr size_t LOG_LEVEL_COUNT = 6; + inline constexpr size_t LOG_LEVEL_COUNT = 6; - class logging_config_t - { - public: - std::optional log_file_path; - std::string log_format = ""; - std::array log_level_colors = { - - }; - log_level_t level = log_level_t::TRACE; - bool use_color = true; - bool log_to_console = true; - - private: - }; + class logging_config_t + { + friend logger_t; + public: + std::vector log_outputs = get_default_log_outputs(); + std::string log_format = get_default_log_format(); + std::array log_level_colors = get_default_log_level_colors(); + std::array log_level_names = get_default_log_level_names(); + log_level_t level = log_level_t::TRACE; + bool use_color = true; + // if true prints the whole path to the file (eg /home/user/.../.../project/src/source.cpp:line#) + bool print_full_name = false; + // this will attempt to use the maximum possible size for each printed element, then align to that. + // This creates output where the user message always starts at the same column. + bool ensure_alignment = true; + private: + static std::string get_default_log_format(); + static std::vector get_default_log_outputs(); + static std::array get_default_log_level_colors(); + static std::array get_default_log_level_names(); + }; } #endif //BLT_LOGGING_LOGGING_CONFIG_H diff --git a/src/blt/fs/filesystem.cpp b/src/blt/fs/filesystem.cpp index 7fa829b..03bba66 100644 --- a/src/blt/fs/filesystem.cpp +++ b/src/blt/fs/filesystem.cpp @@ -21,59 +21,25 @@ namespace blt::fs { - - fstream_block_reader::fstream_block_reader(std::fstream& stream, size_t bufferSize): - block_reader(bufferSize), m_stream(stream), m_buffer(new char[bufferSize]) - { - if (!m_stream.good() || m_stream.fail()) - BLT_WARN("Provided std::fstream is not good! Clearing!"); - m_stream.clear(); - } - - int fstream_block_reader::read(char* buffer, size_t bytes) - { - if (readIndex == 0) - m_stream.read(m_buffer, (long) m_bufferSize); - if (readIndex + bytes >= m_bufferSize) - { - // copy out all the data from the current buffer - auto bytesLeft = m_bufferSize - readIndex; - memcpy(buffer, m_buffer + readIndex, bytesLeft); - readIndex = 0; - // now to prevent large scale reading in small blocks, we should just read the entire thing into the buffer. - m_stream.read(buffer + bytesLeft, (long) (bytes - bytesLeft)); - } else - { - // but in the case that the size of the data read is small, we should read in blocks and copy from that buffer - // that should be quicker since file operations are slow. - std::memcpy(buffer, m_buffer + readIndex, bytes); - readIndex += bytes; - } - return 0; - } - - int fstream_block_writer::write(char* buffer, size_t bytes) - { - if (writeIndex + bytes >= m_bufferSize) - { - // in an attempt to stay efficient we write out the old buffer and the new buffer - // since there is a good chance there is more than a buffer's worth of data being written - // otherwise the buffer is almost full and can be written anyway. (this might be bad for performance especially if the FS wants round numbers) - m_stream.write(m_buffer, (long) writeIndex); - writeIndex = 0; - m_stream.write(buffer, (long) bytes); - } else - { - std::memcpy(m_buffer + writeIndex, buffer, bytes); - writeIndex += bytes; - } - return 0; - } - - void fstream_block_writer::flush_internal() - { - m_stream.write(m_buffer, (long) writeIndex); - writeIndex = 0; - } - -} \ No newline at end of file + fstream_reader_t::fstream_reader_t(std::istream& stream): m_stream{&stream} + {} + + i64 fstream_reader_t::read(char* buffer, const size_t bytes) + { + return m_stream->readsome(buffer, static_cast(bytes)); + } + + fstream_writer_t::fstream_writer_t(std::ostream& stream): m_stream{&stream} + {} + + i64 fstream_writer_t::write(char* buffer, size_t bytes) + { + m_stream->write(buffer, static_cast(bytes)); + return static_cast(bytes); + } + + void fstream_writer_t::flush() + { + m_stream->flush(); + } +} diff --git a/src/blt/fs/nbt.cpp b/src/blt/fs/nbt.cpp index e127f11..2c0dc1a 100644 --- a/src/blt/fs/nbt.cpp +++ b/src/blt/fs/nbt.cpp @@ -10,13 +10,13 @@ #include namespace blt::nbt { - void writeUTF8String(blt::fs::block_writer& stream, const std::string& str) { + void writeUTF8String(blt::fs::writer_t& stream, const std::string& str) { blt::string::utf8_string str8 = blt::string::createUTFString(str); stream.write(str8.characters, str8.size); delete[] str8.characters; } - std::string readUTF8String(blt::fs::block_reader& stream) { + std::string readUTF8String(blt::fs::reader_t& stream) { int16_t utflen; readData(stream, utflen); diff --git a/src/blt/logging/logging_config.cpp b/src/blt/logging/logging_config.cpp index 06f1880..fcb072d 100644 --- a/src/blt/logging/logging_config.cpp +++ b/src/blt/logging/logging_config.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see . */ #include +#include namespace blt::logging { diff --git a/tests/logger_tests.cpp b/tests/logger_tests.cpp index a120b32..cb159c7 100644 --- a/tests/logger_tests.cpp +++ b/tests/logger_tests.cpp @@ -23,7 +23,7 @@ #include #include #include - +#include struct some_silly_type_t {}; @@ -89,6 +89,43 @@ std::pair compare_strings(const std::string& s1, const std::s return {true, ""}; } +struct seqbuf final : std::streambuf +{ + seqbuf(std::streambuf* destBuf, std::size_t& charCount) : m_dest(destBuf), m_count(charCount) + {} + +protected: + int_type overflow(int_type ch) override + { + if (traits_type::eq_int_type(ch, traits_type::eof())) + return traits_type::eof(); + ++m_count; + blt::logging::println("We are printing a character {:c}", ch); + return m_dest->sputc(static_cast(ch)); + } + + std::streamsize xsputn(const char* s, std::streamsize count) override + { + blt::logging::println("We are printing a series of characters {} {}", count, std::string_view{s, static_cast(count)}); + m_count += static_cast(count); + return m_dest->sputn(s, count); + } + + int_type underflow() override + { + return m_dest->sgetc(); + } + + int sync() override + { + return m_dest->pubsync(); + } + +private: + std::streambuf* m_dest; + std::size_t& m_count; +}; + int main() { std::stringstream ss; @@ -153,16 +190,28 @@ int main() } } blt::logging::println("{}This is a color now with background{}", - build(color::color_mode::BOLD, fg(color::color8::CYAN), color::color_mode::DIM, bg(color::color8::YELLOW)), + build(color::color_mode::BOLD, fg(color::color8::RED), color::color_mode::DIM, bg(color::color_rgb(0, 100, 255))), build(color::color_mode::RESET_ALL)); - std::cout << "\033[2J"; + std::ofstream os("test.txt"); + size_t charCount = 0; + seqbuf hi{os.rdbuf(), charCount}; + dynamic_cast(os).rdbuf(&hi); + os << "This is a println with a stream" << std::endl; + os << "This is a mixed print " << 25 << " with multiple types " << 34.23340 << std::endl; + os << "What about just a new line character?\n"; + + blt::logging::println("Logged {} characters", charCount); + + /*std::cout << "\033[2J"; constexpr int totalRows = 24; - std::cout << "\033[1;" << (totalRows - 1) << "r"; + // std::cout << "\033[1;" << (totalRows - 1) << "r"; + std::cout << use_mode(ansi::mode::color80x25_text); for (int i = 1; i <= 10; ++i) { + std::cout << "\033[1;1H"; std::cout << "printed line " << i << std::endl; std::cout << "\033[" << totalRows << ";1H"; @@ -170,7 +219,7 @@ int main() std::this_thread::sleep_for(std::chrono::milliseconds(500)); } - std::cout << "\033[r"; + std::cout << "\033[r";*/ // blt::logging::println("This is println {}\twith a std::endl in the middle of it"); }