터미널 콘솔에서 실시간 텍스트 편집은 콘솔이 필요한 모든 이스케이프 시퀀스를 지원하는지 신뢰할 수있는 방법이 없기 때문에 대부분 검은 색 예술입니다. 전체 화면 편집기의 경우 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
의 소스를보고 사용자 정의 구문 강조를 허용하도록 다시 그리기 루틴을 조정하는 것이 더 쉬운 지 확인할 수 있습니다. 그 외에는
, 그냥 잘 작동 :
참조가'ncurses' 라이브러리 –
당신이보고 할 수 있습니다 : https://askubuntu.com/questions/558280/changing-colour -of-text-and-background-of-terminal/558422 – everyone
현재 텍스트 입력을 어떻게 처리합니까? 그것이 라인 지향적이라면 ("Enter를 누른 후에"에 의해 제안 된 것처럼), 그 다음 버리고 문자 기반 입력으로 다시 시작하십시오. 그것으로, 그것은 표준 "어떻게 문법 강조 표시합니까"질문입니다. – usr2564301