GNU Readline 라 이브 러 리 및 프로 그래 밍 안내

다음으로 전송:https://www.cnblogs.com/hazir/p/instruction_to_readline.html
참고 문서:http://tiswww.case.edu/php/chet/readline/readline.html#SEC23
간단 한 소개
Bash 명령 행 을 사용 한 적 이 있 는 사람 은 Bash 의 몇 가지 특성 이 있 음 을 알 수 있 습 니 다.
  • TAB 키 를 누 르 면 완성 명령
  • 또는 키 를 누 르 면 과거 명령 을 빠르게 입력 할 수 있 습 니 다
  • 인 터 랙 티 브 줄 편집 단축 키 도 있 습 니 다.
  • C-A / C-E 커서 를 줄 첫머리 / 줄 끝으로 이동
  • C-B / C-F 커서 를 왼쪽으로 / 오른쪽으로 한 위치 이동
  • C-D 커서 의 다음 문자 삭제
  • C-K 커서 와 커서 를 줄 끝까지 삭제 하 는 모든 문자
  • C-U 줄 의 맨 위 에 있 는 모든 문자 삭제
  • ...


  • 같은 조작 은 많은 대화 형 프로그램 에서 비슷 한 조작 을 하 는데 예 를 들 어 ftp, gdb 등 이 있다. 그러면 이런 것들 이 어떻게 실현 되 는 지 생각해 본 적 이 있 습 니까?만약 에 우리 가 명령 행 아래 의 대화 형 오픈 소스 소프트웨어 를 만 들 려 면 이런 명령 보완, 검색 역사 명령, 행 편집 단축 키 등 인성 화 된 상호작용 방식 도 있 기 를 바 랍 니까?
    이 를 실현 하려 면 두 가지 방법 이 있 습 니 다. 프로그램 을 작성 하여 실현 하거나 소스 를 시작 하 는 라 이브 러 리 Readline Lib 를 호출 할 수 있 습 니 다.예 를 들 어 위 에서 소개 한 bash, ftp, gdb 등 소프트웨어 는 모두 GNU 의 오픈 소스 크로스 플랫폼 라 이브 러 리 를 사용 하여 상호작용 적 인 텍스트 편집 기능 을 제공 합 니 다.물론 주의해 야 할 것 은 Readline Library 는 GNU 자유 소프트웨어 로 GNU GPL V3 프로 토 콜 에 의 해 발표 되 기 때문에 프로그램 에 이 라 이브 러 리 가 필요 하 다 면 관련 프로 토 콜 도 지 켜 야 한 다 는 점 이다.
    본 고 는 먼저 이 라 이브 러 리 의 기본 적 인 사용 방법 을 간단하게 소개 하고, 그 다음 에 Readline 을 사용 하여 명령 보완 기능 을 사용자 정의 하 는 방법 을 상세히 소개 할 것 이다.
    Readline 기본 조작
    입력 읽 기
    많은 명령 행 인 터 랙 션 프로그램의 상호작용 방식 이 많 지 않 습 니 다. 출력 프롬프트 는 사용자 가 명령 을 입력 할 때 까지 기 다 립 니 다. 사용자 가 명령 을 입력 한 후에 리 턴 을 누 르 면 프로그램 이 명령 을 분석 하고 실 행 됩 니 다.그러면 이 안에 사용자 의 입력 을 읽 는 동작 이 있 습 니 다. 예전 에 우 리 는 gets() 이라는 함 수 를 사용 하여 이 루어 졌 을 수도 있 습 니 다. 우리 가 Readline 라 이브 러 리 를 사용 할 때 readline() 함 수 를 사용 하여 교체 할 수 있 습 니 다. 이 함 수 는 ANSI C 에서 다음 과 같이 정의 합 니 다.
    char *readline (char *prompt);
    

    이 함 수 는 명령 프롬프트 를 표시 하 는 매개 변수 prompt 를 가지 고 있 습 니 다. 예 를 들 어 ftp 에 서 는 "ftp >" 입 니 다. 사용 자 는 뒤에서 명령 을 입력 할 수 있 습 니 다. Enter 키 를 누 르 면 프로그램 이 이 줄 (마지막 줄 바 꿈 자 는 포함 되 지 않 음) 을 읽 고 문자 버퍼 에 저장 합 니 다. readline 의 반환 값 은 이 줄 텍스트 의 지침 입 니 다.메모: 이 줄 의 텍스트 를 사용 할 필요 가 없 을 때 이 포인터 가 가리 키 는 공간 을 방출 하여 메모리 누 출 을 방지 해 야 합 니 다.읽 기 EOF 를 읽 을 때 다른 문 자 를 읽 지 않 으 면 되 돌아 갑 니 다 (char *) NULL. 그렇지 않 으 면 읽 기 가 끝나 고 읽 기 줄 바 꿈 효과 와 같 습 니 다.
    명령 보완
    사용자 의 입력 을 읽 을 수 있 는 것 을 제외 하고 우 리 는 때때로 상호작용 이 좀 더 간단 하 기 를 원한 다. 예 를 들 어 명령 보완 이다.많은 명령 이 있 을 때 사용자 가 명령 의 맞 춤 법 을 정확하게 기억 하 는 것 이 어렵다 면 일반적인 방법 은 TAB 키 를 누 르 고 명령 알림 과 보완 을 하 는 것 입 니 다. 예 를 들 어 ftp 에서 한 글자 c 를 입력 한 후에 TAB 키 를 누 르 면 c 로 시작 하 는 모든 명령 이 표 시 됩 니 다.
    ftp> c
    case cd cdup chmod   close   cr
    
    readline 함 수 는 사용자 에 게 기본 TAB 으로 보 완 된 기능 입 니 다. 현재 경로 에서 파일 이름 에 따라 보 완 됩 니 다.
    Readline 이 파일 이름 에 따라 완성 되 지 않 으 려 면 rl_bind_key() 함수 로 TAB 키 의 행동 을 바 꿀 수 있 습 니 다.이 함수 의 원형 은:
    int rl_bind_key(int key, int (*function)());
    

    이 함 수 는 두 개의 인 자 를 가지 고 있 습 니 다. key 는 키 를 연결 하고 싶 은 ASCII 코드 문자 입 니 다. function 은 key 키 를 눌 렀 을 때 호출 함 수 를 촉발 하 는 주소 입 니 다.TAB 키 를 누 르 려 면 탭 자 체 를 입력 하고 TAB 함 수 를 rl_insert() 함수 에 연결 할 수 있 습 니 다. 이것 은 Readline 라 이브 러 리 에서 제공 하 는 함수 입 니 다.key 가 유효한 ASCII 코드 값 (0 ~ 255 사이) 이 아니라면 rl_bind_key() 은 0 이 아 닌 것 으로 되 돌아 갑 니 다.
    이렇게 하면 금지 TAB 의 기본 행 위 를 다음 과 같이 하면 된다.
    rl_bind_key('\t', rl_insert);
    

    이 코드 는 프로그램 이 시작 되 자마자 호출 되 어야 합 니 다.사용자 정의 완성 을 설치 하 는 등 필요 한 초기 화 를 수행 하기 위해 서 함수 initialize_readline() 를 쓸 수 있 습 니 다.
    입력 TAB 을 원 할 때 현재 경로 에 있 는 모든 파일 을 보 여 주 는 것 이 아니 라 프로그램 에 내 장 된 명령 을 보 여 줍 니 다. 예 를 들 어 ftp 의 예 를 들 어 사용자 정의 완성 이 라 고 합 니 다.이 조작 은 비교적 복잡 해서 우 리 는 뒷부분 에 남아 서 주로 소개 한다.
    역사 기록
    기본 동작 은 검색 역사 입 니 다.입력 한 명령 행 을 C-p 또는 C-s 을 통 해 검색 할 수 있 습 니 다. 명령 행 을 역사 목록 에 추가 해 야 합 니 다. add_history() 함 수 를 호출 할 수 있 습 니 다.그러나 빈 줄 도 역사 목록 에 넣 으 려 고 합 니 다. 빈 줄 이 역사 목록 의 공간 을 차지 하고 쓸모 가 없 기 때 문 입 니 다.종합 하면 우 리 는 Readline 판 gets() 함수 rl_gets() 를 쓸 수 있다.
    /* A static variable for holding the line. */
    static char *line_read = (char *)NULL;
    
    /* Read a string, and return a pointer to it.  Returns NULL on EOF. */
    char *
    rl_gets ()
    {
      /* If the buffer has already been allocated, return the memory
         to the free pool. */
      if (line_read)
        {
          free (line_read);
          line_read = (char *)NULL;
        }
    
      /* Get a line from the user. */
      line_read = readline ("");
    
      /* If the line has any text in it, save it on the history. */
      if (line_read && *line_read)
        add_history (line_read);
    
      return (line_read);
    }
    

    사용자 정의 완성
    위 에서 도 사용자 정의 보완 이 무엇 인지 언급 했 는데 이것 은 명령 행 인 터 랙 션 프로그램 에서 매우 중요 하고 사용자 체험 에 직접적인 영향 을 미친다.Readline 라 이브 러 리 는 파일 이름 에 따라 보완 하고 사용자 이름 에 따라 보완 하 며 Readline 에서 실 현 된 두 함수 rl_filename_completion_functionrl_username_completion_function 에 대응 하 는 두 가지 방법 을 제공 합 니 다.만약 우리 가 파일 이름과 사용자 이름 에 따라 보완 하 기 를 원 하지 않 는 다 면 프로그램의 명령 에 따라 보완 하 기 를 원한 다 면 어떻게 해 야 합 니까?자신의 보완 함수 만 실현 하면 된다 는 생각 도 쉽게 든다.
    Readline 보완 작업 원 리 는 다음 과 같 습 니 다.
  • 사용자 인터페이스 함수 rl_complete() 호출 rl_completion_matches() 으로 가능 한 보완 목록 을 만 듭 니 다.
  • 내부 함수 rl_completion_matches() 는 프로그램 이 제공 하 는 generator 함 수 를 사용 하여 보완 목록 을 만 들 고 일치 하 는 배열 을 되 돌려 줍 니 다. 그 전에 generator 함수 의 주 소 를 rl_completion_entry_function 변수 에 넣 어야 합 니 다. 예 를 들 어 위 에서 언급 한 파일 이름 이나 사용자 이름 에 따라 보완 함 수 는 서로 다른 generator 입 니 다.
  • generator 함수 가 rl_completion_matches() 에서 계속 호출 되 고 매번 문자열 을 되 돌려 줍 니 다.generator 함 수 는 두 개의 인 자 를 가지 고 있 습 니 다. text 는 보완 해 야 할 단어의 부분 입 니 다. state 는 함수 가 처음 호출 될 때 0 이 고 그 다음 에 호출 할 때 0 이 아 닙 니 다.generator 함수 반환 (char *)NULL 알림 rl_completion_matches() 은 가능 한 일치 가 남지 않 았 습 니 다.

  • Readline 라 이브 러 리 에 변수 rl_attempted_completion_function 가 있 습 니 다. 양 유형 을 바 꾸 는 것 은 함수 포인터 rl_completion_func_t * 입 니 다. 이 변 수 를 사용자 정의 로 일치 하 는 함 수 를 설정 할 수 있 습 니 다. TAB 키 를 누 를 때 이 함 수 를 호출 합 니 다. 함 수 는 세 개의 매개 변 수 를 가지 고 있 습 니 다.
  • text: 이 매개 변 수 는 보완 해 야 할 단어의 부분 입 니 다. 예 를 들 어 Bash 프롬프트 뒤에 c 문 자 를 입력 하고 TAB 를 누 르 면 text 가 가리 키 는 것 은 'c' 문자열 의 지침 입 니 다.Bash 프롬프트 뒤에 cd /home/gu 문자열 을 입력 하고 TAB 을 누 르 십시오. 이때 text 는 '/ home / gu' 문자열 의 지침 을 가리 키 고 있 습 니 다.
  • start: text 문자열 은 이 줄 입력 의 시작 위치 에 있 습 니 다. 예 를 들 어 위의 예 에 대해 첫 번 째 상황 은 0 이 고 두 번 째 상황 은 3 입 니 다.
  • end: text 문자열 은 이 줄 의 입력 에서 끝 나 는 위치 입 니 다. 예 를 들 어 위의 예 에 대해 첫 번 째 상황 에서 1, 두 번 째 상황 에서 11 입 니 다.

  • 우리 가 사용자 정의 완성 함 수 는 들 어 오 는 매개 변수 에 따라 우리 가 어떤 방식 으로 보완 하고 싶 은 지 설정 할 수 있 습 니 다. 예 를 들 어 Bash 에서 내 린 cd 명령 에 대해 우 리 는 시작 이 명령 완성 이 기 를 바 랍 니 다. 명령 이 완 료 된 후에 다음 과 같은 것 은 파일 이름 완성 입 니 다. 그러면 rl_completion_matches() 을 사용 하여 어떤 generator 를 사용 하 는 지 바 인 딩 할 수 있 습 니 다. rl_completion_matches() 함수 의 원형 은 다음 과 같 습 니 다.
    char ** rl_completion_matches (const char *text, rl_compentry_func_t *entry_func)
    

    두 개의 인자 가 있 습 니 다: text 는 위 에서 소개 한 보완 해 야 할 단어 입 니 다. 두 번 째 매개 변수 entryfunc 는 위 에서 반복 적 으로 소개 한 generator 함수 의 지침 입 니 다.이 함수 의 반환 값 은 generator 가 만 든 text 와 일치 할 수 있 는 문자열 배열 지침 입 니 다. 이 배열 의 마지막 항목 은 NULL 지침 입 니 다.
    자, 위 에서 사용자 정의 완성 에 관 한 함수 와 변 수 를 이렇게 많이 말 했 습 니 다. 도대체 어떻게 사용 하 는 지, 아직 모호 할 것 같 습 니 다. 그러면 하나의 예 를 보면 잘 알 수 있 습 니 다. 이 예 는 Readline 이 공식 적 으로 제공 하 는 예제 프로그램 입 니 다. 비교적 길 기 때문에 여기에 붙 이지 않 습 니 다.할 수 있다,...http://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC49 찾 아.
    총결산
    사실, 많은 말 을 했 지만 아직 Readlin e 라 이브 러 리 의 털 일 뿐 입 니 다. 이 라 이브 러 리 의 기능 은 이것 보다 훨씬 강 합 니 다. 깊이 이해 하고 활용 하려 면 세 가지 일 을 해 야 합 니 다.
  • Read The Fucking Manual: 공식 문서 읽 기
  • Read The Fucking Source Code: 공식 적 으로 제공 하 는 예 코드 를 읽 고 더 깊이 알 고 싶 으 면 Readline 의 소스 코드
  • 를 볼 수 있 습 니 다.
  • Show Your Code: 직접 몇 가지 예 를 써 보 세 요. 기회 가 있 으 면 프로젝트 에 활용 하 세 요.
  • 좋은 웹페이지 즐겨찾기