CoolFace
Modelpublic

Codeprocastinator/optimized-tinyllama-covalent

sourceHugging Faceapache-2.0updated 1y agoView on Hugging Face
0likes119downloads
console.cpp505 linesDownload Raw Back to common
1#include "console.h"2#include <vector>3#include <iostream>4 5#if defined(_WIN32)6#define WIN32_LEAN_AND_MEAN7#ifndef NOMINMAX8#define NOMINMAX9#endif10#include <windows.h>11#include <fcntl.h>12#include <io.h>13#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING14#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x000415#endif16#else17#include <climits>18#include <sys/ioctl.h>19#include <unistd.h>20#include <wchar.h>21#include <stdio.h>22#include <stdlib.h>23#include <signal.h>24#include <termios.h>25#endif26 27#define ANSI_COLOR_RED     "\x1b[31m"28#define ANSI_COLOR_GREEN   "\x1b[32m"29#define ANSI_COLOR_YELLOW  "\x1b[33m"30#define ANSI_COLOR_BLUE    "\x1b[34m"31#define ANSI_COLOR_MAGENTA "\x1b[35m"32#define ANSI_COLOR_CYAN    "\x1b[36m"33#define ANSI_COLOR_RESET   "\x1b[0m"34#define ANSI_BOLD          "\x1b[1m"35 36namespace console {37 38    //39    // Console state40    //41 42    static bool      advanced_display = false;43    static bool      simple_io        = true;44    static display_t current_display  = reset;45 46    static FILE*     out              = stdout;47 48#if defined (_WIN32)49    static void*     hConsole;50#else51    static FILE*     tty              = nullptr;52    static termios   initial_state;53#endif54 55    //56    // Init and cleanup57    //58 59    void init(bool use_simple_io, bool use_advanced_display) {60        advanced_display = use_advanced_display;61        simple_io = use_simple_io;62#if defined(_WIN32)63        // Windows-specific console initialization64        DWORD dwMode = 0;65        hConsole = GetStdHandle(STD_OUTPUT_HANDLE);66        if (hConsole == INVALID_HANDLE_VALUE || !GetConsoleMode(hConsole, &dwMode)) {67            hConsole = GetStdHandle(STD_ERROR_HANDLE);68            if (hConsole != INVALID_HANDLE_VALUE && (!GetConsoleMode(hConsole, &dwMode))) {69                hConsole = nullptr;70                simple_io = true;71            }72        }73        if (hConsole) {74            // Check conditions combined to reduce nesting75            if (advanced_display && !(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) &&76                !SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {77                advanced_display = false;78            }79            // Set console output codepage to UTF880            SetConsoleOutputCP(CP_UTF8);81        }82        HANDLE hConIn = GetStdHandle(STD_INPUT_HANDLE);83        if (hConIn != INVALID_HANDLE_VALUE && GetConsoleMode(hConIn, &dwMode)) {84            // Set console input codepage to UTF1685            _setmode(_fileno(stdin), _O_WTEXT);86 87            // Set ICANON (ENABLE_LINE_INPUT) and ECHO (ENABLE_ECHO_INPUT)88            if (simple_io) {89                dwMode |= ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;90            } else {91                dwMode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);92            }93            if (!SetConsoleMode(hConIn, dwMode)) {94                simple_io = true;95            }96        }97        if (simple_io) {98            _setmode(_fileno(stdin), _O_U8TEXT);99        }100#else101        // POSIX-specific console initialization102        if (!simple_io) {103            struct termios new_termios;104            tcgetattr(STDIN_FILENO, &initial_state);105            new_termios = initial_state;106            new_termios.c_lflag &= ~(ICANON | ECHO);107            new_termios.c_cc[VMIN] = 1;108            new_termios.c_cc[VTIME] = 0;109            tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);110 111            tty = fopen("/dev/tty", "w+");112            if (tty != nullptr) {113                out = tty;114            }115        }116 117        setlocale(LC_ALL, "");118#endif119    }120 121    void cleanup() {122        // Reset console display123        set_display(reset);124 125#if !defined(_WIN32)126        // Restore settings on POSIX systems127        if (!simple_io) {128            if (tty != nullptr) {129                out = stdout;130                fclose(tty);131                tty = nullptr;132            }133            tcsetattr(STDIN_FILENO, TCSANOW, &initial_state);134        }135#endif136    }137 138    //139    // Display and IO140    //141 142    // Keep track of current display and only emit ANSI code if it changes143    void set_display(display_t display) {144        if (advanced_display && current_display != display) {145            fflush(stdout);146            switch(display) {147                case reset:148                    fprintf(out, ANSI_COLOR_RESET);149                    break;150                case prompt:151                    fprintf(out, ANSI_COLOR_YELLOW);152                    break;153                case user_input:154                    fprintf(out, ANSI_BOLD ANSI_COLOR_GREEN);155                    break;156                case error:157                    fprintf(out, ANSI_BOLD ANSI_COLOR_RED);158            }159            current_display = display;160            fflush(out);161        }162    }163 164    static char32_t getchar32() {165#if defined(_WIN32)166        HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);167        wchar_t high_surrogate = 0;168 169        while (true) {170            INPUT_RECORD record;171            DWORD count;172            if (!ReadConsoleInputW(hConsole, &record, 1, &count) || count == 0) {173                return WEOF;174            }175 176            if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown) {177                wchar_t wc = record.Event.KeyEvent.uChar.UnicodeChar;178                if (wc == 0) {179                    continue;180                }181 182                if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate183                    high_surrogate = wc;184                    continue;185                }186                if ((wc >= 0xDC00) && (wc <= 0xDFFF)) { // Check if wc is a low surrogate187                    if (high_surrogate != 0) { // Check if we have a high surrogate188                        return ((high_surrogate - 0xD800) << 10) + (wc - 0xDC00) + 0x10000;189                    }190                }191 192                high_surrogate = 0; // Reset the high surrogate193                return static_cast<char32_t>(wc);194            }195        }196#else197        wchar_t wc = getwchar();198        if (static_cast<wint_t>(wc) == WEOF) {199            return WEOF;200        }201 202#if WCHAR_MAX == 0xFFFF203        if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate204            wchar_t low_surrogate = getwchar();205            if ((low_surrogate >= 0xDC00) && (low_surrogate <= 0xDFFF)) { // Check if the next wchar is a low surrogate206                return (static_cast<char32_t>(wc & 0x03FF) << 10) + (low_surrogate & 0x03FF) + 0x10000;207            }208        }209        if ((wc >= 0xD800) && (wc <= 0xDFFF)) { // Invalid surrogate pair210            return 0xFFFD; // Return the replacement character U+FFFD211        }212#endif213 214        return static_cast<char32_t>(wc);215#endif216    }217 218    static void pop_cursor() {219#if defined(_WIN32)220        if (hConsole != NULL) {221            CONSOLE_SCREEN_BUFFER_INFO bufferInfo;222            GetConsoleScreenBufferInfo(hConsole, &bufferInfo);223 224            COORD newCursorPosition = bufferInfo.dwCursorPosition;225            if (newCursorPosition.X == 0) {226                newCursorPosition.X = bufferInfo.dwSize.X - 1;227                newCursorPosition.Y -= 1;228            } else {229                newCursorPosition.X -= 1;230            }231 232            SetConsoleCursorPosition(hConsole, newCursorPosition);233            return;234        }235#endif236        putc('\b', out);237    }238 239    static int estimateWidth(char32_t codepoint) {240#if defined(_WIN32)241        (void)codepoint;242        return 1;243#else244        return wcwidth(codepoint);245#endif246    }247 248    static int put_codepoint(const char* utf8_codepoint, size_t length, int expectedWidth) {249#if defined(_WIN32)250        CONSOLE_SCREEN_BUFFER_INFO bufferInfo;251        if (!GetConsoleScreenBufferInfo(hConsole, &bufferInfo)) {252            // go with the default253            return expectedWidth;254        }255        COORD initialPosition = bufferInfo.dwCursorPosition;256        DWORD nNumberOfChars = length;257        WriteConsole(hConsole, utf8_codepoint, nNumberOfChars, &nNumberOfChars, NULL);258 259        CONSOLE_SCREEN_BUFFER_INFO newBufferInfo;260        GetConsoleScreenBufferInfo(hConsole, &newBufferInfo);261 262        // Figure out our real position if we're in the last column263        if (utf8_codepoint[0] != 0x09 && initialPosition.X == newBufferInfo.dwSize.X - 1) {264            DWORD nNumberOfChars;265            WriteConsole(hConsole, &" \b", 2, &nNumberOfChars, NULL);266            GetConsoleScreenBufferInfo(hConsole, &newBufferInfo);267        }268 269        int width = newBufferInfo.dwCursorPosition.X - initialPosition.X;270        if (width < 0) {271            width += newBufferInfo.dwSize.X;272        }273        return width;274#else275        // We can trust expectedWidth if we've got one276        if (expectedWidth >= 0 || tty == nullptr) {277            fwrite(utf8_codepoint, length, 1, out);278            return expectedWidth;279        }280 281        fputs("\033[6n", tty); // Query cursor position282        int x1;283        int y1;284        int x2;285        int y2;286        int results = 0;287        results = fscanf(tty, "\033[%d;%dR", &y1, &x1);288 289        fwrite(utf8_codepoint, length, 1, tty);290 291        fputs("\033[6n", tty); // Query cursor position292        results += fscanf(tty, "\033[%d;%dR", &y2, &x2);293 294        if (results != 4) {295            return expectedWidth;296        }297 298        int width = x2 - x1;299        if (width < 0) {300            // Calculate the width considering text wrapping301            struct winsize w;302            ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);303            width += w.ws_col;304        }305        return width;306#endif307    }308 309    static void replace_last(char ch) {310#if defined(_WIN32)311        pop_cursor();312        put_codepoint(&ch, 1, 1);313#else314        fprintf(out, "\b%c", ch);315#endif316    }317 318    static void append_utf8(char32_t ch, std::string & out) {319        if (ch <= 0x7F) {320            out.push_back(static_cast<unsigned char>(ch));321        } else if (ch <= 0x7FF) {322            out.push_back(static_cast<unsigned char>(0xC0 | ((ch >> 6) & 0x1F)));323            out.push_back(static_cast<unsigned char>(0x80 | (ch & 0x3F)));324        } else if (ch <= 0xFFFF) {325            out.push_back(static_cast<unsigned char>(0xE0 | ((ch >> 12) & 0x0F)));326            out.push_back(static_cast<unsigned char>(0x80 | ((ch >> 6) & 0x3F)));327            out.push_back(static_cast<unsigned char>(0x80 | (ch & 0x3F)));328        } else if (ch <= 0x10FFFF) {329            out.push_back(static_cast<unsigned char>(0xF0 | ((ch >> 18) & 0x07)));330            out.push_back(static_cast<unsigned char>(0x80 | ((ch >> 12) & 0x3F)));331            out.push_back(static_cast<unsigned char>(0x80 | ((ch >> 6) & 0x3F)));332            out.push_back(static_cast<unsigned char>(0x80 | (ch & 0x3F)));333        } else {334            // Invalid Unicode code point335        }336    }337 338    // Helper function to remove the last UTF-8 character from a string339    static void pop_back_utf8_char(std::string & line) {340        if (line.empty()) {341            return;342        }343 344        size_t pos = line.length() - 1;345 346        // Find the start of the last UTF-8 character (checking up to 4 bytes back)347        for (size_t i = 0; i < 3 && pos > 0; ++i, --pos) {348            if ((line[pos] & 0xC0) != 0x80) {349                break; // Found the start of the character350            }351        }352        line.erase(pos);353    }354 355    static bool readline_advanced(std::string & line, bool multiline_input) {356        if (out != stdout) {357            fflush(stdout);358        }359 360        line.clear();361        std::vector<int> widths;362        bool is_special_char = false;363        bool end_of_stream = false;364 365        char32_t input_char;366        while (true) {367            fflush(out); // Ensure all output is displayed before waiting for input368            input_char = getchar32();369 370            if (input_char == '\r' || input_char == '\n') {371                break;372            }373 374            if (input_char == (char32_t) WEOF || input_char == 0x04 /* Ctrl+D*/) {375                end_of_stream = true;376                break;377            }378 379            if (is_special_char) {380                set_display(user_input);381                replace_last(line.back());382                is_special_char = false;383            }384 385            if (input_char == '\033') { // Escape sequence386                char32_t code = getchar32();387                if (code == '[' || code == 0x1B) {388                    // Discard the rest of the escape sequence389                    while ((code = getchar32()) != (char32_t) WEOF) {390                        if ((code >= 'A' && code <= 'Z') || (code >= 'a' && code <= 'z') || code == '~') {391                            break;392                        }393                    }394                }395            } else if (input_char == 0x08 || input_char == 0x7F) { // Backspace396                if (!widths.empty()) {397                    int count;398                    do {399                        count = widths.back();400                        widths.pop_back();401                        // Move cursor back, print space, and move cursor back again402                        for (int i = 0; i < count; i++) {403                            replace_last(' ');404                            pop_cursor();405                        }406                        pop_back_utf8_char(line);407                    } while (count == 0 && !widths.empty());408                }409            } else {410                int offset = line.length();411                append_utf8(input_char, line);412                int width = put_codepoint(line.c_str() + offset, line.length() - offset, estimateWidth(input_char));413                if (width < 0) {414                    width = 0;415                }416                widths.push_back(width);417            }418 419            if (!line.empty() && (line.back() == '\\' || line.back() == '/')) {420                set_display(prompt);421                replace_last(line.back());422                is_special_char = true;423            }424        }425 426        bool has_more = multiline_input;427        if (is_special_char) {428            replace_last(' ');429            pop_cursor();430 431            char last = line.back();432            line.pop_back();433            if (last == '\\') {434                line += '\n';435                fputc('\n', out);436                has_more = !has_more;437            } else {438                // llama will just eat the single space, it won't act as a space439                if (line.length() == 1 && line.back() == ' ') {440                    line.clear();441                    pop_cursor();442                }443                has_more = false;444            }445        } else {446            if (end_of_stream) {447                has_more = false;448            } else {449                line += '\n';450                fputc('\n', out);451            }452        }453 454        fflush(out);455        return has_more;456    }457 458    static bool readline_simple(std::string & line, bool multiline_input) {459#if defined(_WIN32)460        std::wstring wline;461        if (!std::getline(std::wcin, wline)) {462            // Input stream is bad or EOF received463            line.clear();464            GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);465            return false;466        }467 468        int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), NULL, 0, NULL, NULL);469        line.resize(size_needed);470        WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), &line[0], size_needed, NULL, NULL);471#else472        if (!std::getline(std::cin, line)) {473            // Input stream is bad or EOF received474            line.clear();475            return false;476        }477#endif478        if (!line.empty()) {479            char last = line.back();480            if (last == '/') { // Always return control on '/' symbol481                line.pop_back();482                return false;483            }484            if (last == '\\') { // '\\' changes the default action485                line.pop_back();486                multiline_input = !multiline_input;487            }488        }489        line += '\n';490 491        // By default, continue input if multiline_input is set492        return multiline_input;493    }494 495    bool readline(std::string & line, bool multiline_input) {496        set_display(user_input);497 498        if (simple_io) {499            return readline_simple(line, multiline_input);500        }501        return readline_advanced(line, multiline_input);502    }503 504}505