2017-12-25 15 views
3

우분투 콘솔에서 실행되는 C로 인터프리터를 작성하고 있습니다. 입력하는 동안 int, double, function과 같은 키워드의 색상을 변경하고 싶습니다.타이핑 중에 리눅스 터미널의 키워드 색상을 변경하십시오.

예 : functio은 흰색이어야하지만 키워드 입력을 마친 후 function의 색은 파란색으로 변경되어야합니다.

간단한 질문에 답할 것입니다. 문자 수가 홀수 일 때 파란색으로 터미널의 텍스트 색을 설정하고 짝수 일 때 빨간색으로 설정하고 입력하는 동안 (입력 후가 아님) 발생해야합니다.

터미널에서 텍스트를 조작하고 타이핑하는 동안 색상을 변경하는 방법은 무엇입니까?

+1

참조가'ncurses' 라이브러리 –

+1

당신이보고 할 수 있습니다 : https://askubuntu.com/questions/558280/changing-colour -of-text-and-background-of-terminal/558422 – everyone

+1

현재 텍스트 입력을 어떻게 처리합니까? 그것이 라인 지향적이라면 ("Enter를 누른 후에"에 의해 제안 된 것처럼), 그 다음 버리고 문자 기반 입력으로 다시 시작하십시오. 그것으로, 그것은 표준 "어떻게 문법 강조 표시합니까"질문입니다. – usr2564301

답변

2

터미널 콘솔에서 실시간 텍스트 편집은 콘솔이 필요한 모든 이스케이프 시퀀스를 지원하는지 신뢰할 수있는 방법이 없기 때문에 대부분 검은 색 예술입니다. 전체 화면 편집기의 경우 ncurses을 사용할 수 있지만 "인라인"은보기보다 어렵습니다. 예를 들면, Mac OS X의 고유 한 터미널은 한 줄 입력을 정상적으로 처리하지만 텍스트 문자열에 터미널의 너비에 맞지 않는 인쇄 할 수없는 문자 또는 범위가 포함되어 있으면 혼란 스럽습니다.

다음과 같이 빠르고 (여전히 더러운) C 프로그램은 매우 기본 입력을 허용합니다. OS X에서 getchar은 입력을 다시 명령 행에 표시합니다. 터미널 자체 (!)는 Enter를 입력 할 때까지 실행중인 프로그램에 입력을 전달하지 않습니다. 다른 콘솔에는 다른 단점이있을 수 있습니다.

단선 편집 작업의 경우 유일하게 주목할만한 점은 부분을 컬러로 표시하기 위해 실행중인 라인을 처리하는 방법입니다. ANSI 이스케이프 코드를 사용하여 문자열이 표시되는 동안 스트링을 따라갈 수 있습니다. 구문 강조 방법은 매우 기본입니다. 더 많은 키워드가있는 경우 키워드를 찾는 더 빠른 방법을 살펴볼 수 있습니다. 와일드 카드도 처리 할 수 ​​없으므로 "10 진수"와 같은 항목을 강조 표시 할 수 없습니다.

#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's 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's 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의 소스를보고 사용자 정의 구문 강조를 허용하도록 다시 그리기 루틴을 조정하는 것이 더 쉬운 지 확인할 수 있습니다. 그 외에는

, 그냥 잘 작동 :

screen recording of live input

관련 문제