Changing the color of keywords in linux terminal while typing

I am writing an interpreter in C that runs in the ubuntu console. I want to change the color of keywords, such as int, double, functionin the input time.

Example: it functioshould be white, but as soon as I finish typing a keyword function, its color should be changed to blue.

A simple example that would answer my question: I want the text color in the terminal to be blue when the number of letters is odd and red when it is even, and this should happen when typing (not after pressing input).

How to work with text in the terminal and change its colors during input?

+4
source share
1 answer

- , , escape-, . ncurses, "inline" , . : , Mac OS X , , , .

( ) C . , , : OS X, getchar ; (!) Enter. .

, . , ANSI Escape Codes . ; , . , , " ".

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include <unistd.h>
#include <termios.h>

#define PP_INVERSE  "\x1b[7m"

#define PP_RED      "\x1b[31m"
#define PP_BLUE     "\x1b[34m"

#define PP_RESET    "\x1b[39m\x1b[0m"

const char *keyword_list[] = {
    "int",
    "double",
    "function"
};


/* ha ha */
#define SURELY_LARGE_ENOUGH 256

char line_buf[SURELY_LARGE_ENOUGH] = "";

void display_line (char *text, int cursor)
{
    char *startptr, *endptr;
    int i;

    printf ("\r>");

    startptr = text;

    do
    {
        /* hop from one 'word' to another */

        /* check for non-word first */
        while (*startptr && !isalnum(*startptr))
        {
            putchar (*startptr);
            startptr++;
        }

        if (*startptr)
        {
            endptr = startptr;

            /* gather next word */
            while (*endptr && isalnum(*endptr))
                endptr++;

            /* check if it a known keyword */
            for (i=0; i<sizeof(keyword_list)/sizeof(keyword_list[0]); i++)
            {
                if (keyword_list[i][0] == *startptr && strlen(keyword_list[i]) == endptr - startptr)
                {
                    if (!strncmp (startptr, keyword_list[i], strlen(keyword_list[i])))
                    {
                        break;
                    }
                }
            }

            if (i<sizeof(keyword_list)/sizeof(keyword_list[0]))
            {
                printf (PP_INVERSE "%s" PP_RESET, keyword_list[i]);
                startptr = endptr;
            } else
            {
                if ((endptr - startptr) & 1)
                {
                    printf (PP_BLUE);
                } else
                {
                    printf (PP_RED);
                }
                while (startptr < endptr)
                {
                    putchar (*startptr);
                    startptr++;
                }
                printf (PP_RESET);
            }
        }
    } while (*startptr);

    /* erase any following leftovers */
    printf ("\x1B[K");

    /* position cursor */
    printf ("\r\x1B[%dC", cursor+1);
    fflush (stdout);
}

/* turn off echo for getchar
    see https://stackoverflow.com/questions/558009/ansi-c-no-echo-keyboard-input
*/
void getch_disable_echo (void)
{
    struct termios t;

    tcgetattr(STDIN_FILENO, &t);
    t.c_lflag &= ~ECHO;
    t.c_lflag &= ~ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &t);
}

void getch_enable_echo (void)
{
    struct termios t;

    tcgetattr(STDIN_FILENO, &t);
    t.c_lflag |= ECHO;
    t.c_lflag |= ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &t);
}

int get_input (void)
{
    int cursor_pos = 0;
    int key;

    do
    {
        display_line (line_buf, cursor_pos);
        key = getchar();
        if (isprint(key))
        {
            if (!line_buf[cursor_pos])
                line_buf[cursor_pos+1] = 0;
            line_buf[cursor_pos] = key;
            cursor_pos++;
        }
        /* poor man backspace */
        if (key == 127)
        {
            if (cursor_pos)
            {
                cursor_pos--;
                line_buf[cursor_pos] = 0;
            }
        }
        if (key == '\n')
        {
            printf ("\r%s \n", line_buf);
            line_buf[0] = 0;
            cursor_pos = 0;
        }
    } while (key != EOF);

    return 0;
}

int main (void)
{
    getch_disable_echo();

    strcpy (line_buf, "this is a function test");
    get_input ();

    getch_enable_echo();
    return 0;
}

, , . , , , . , , GNU readline , , .

, :

live input screen recording

+3

Source: https://habr.com/ru/post/1691325/


All Articles