readline
跳转到导航
跳转到搜索
操作技巧
在交互命令行中,使用Ctrl+Alt+J可切换到 vi 模式。[1]
文件
头文件: <readline/readline.h> ,编译时库文件参数: -lreadline 。如需要使用历史功能,需要头文件 <readline/history.h> 。
示例
简单使用
//=====================================================================
// readline 测试
//=====================================================================
#include<stdio.h>
#include<stdlib.h>
#include<readline/readline.h>
#include<readline/history.h>
/* --------------------------------------------------------------------- */
int main(int argc, char **argv){
char *p;
while((p=readline("\x1b[1;35m>>\x1b[0m ")) != NULL){
if(p[0] != '\0'){
puts(p);
add_history(p);
}else{
free(p);
}
}
putchar('\n');
return 0;
}
//=====================================================================
如果遇到 EOF , readline 返回 NULL 。
使用 rl_callback_read_char
rl_callback_read_char [2]可以在文件描述符准备好时再调用。(这里用到了gcc所支持的嵌套函数。)
#include<stdio.h>
#include<readline/readline.h>
int main(void){
int cont = 1;
void callback(char *text){
if(text == NULL){
rl_callback_handler_remove();
putchar('\n');
cont = 0;
}else{
printf("%s.\n", text);
}
}
rl_callback_handler_install(">> ", callback);
while(cont){
rl_callback_read_char();
}
return 0;
}
C 语言版
注:未做缓冲区溢出检查。
#define _XOPEN_SOURCE 700 /* for wcswidth and 700 is for mbsnrtowcs */
#include<wchar.h>
#include<ncurses.h> /* ncurses.h includes stdio.h */
#include<stdlib.h>
#include<string.h>
#include<readline/readline.h>
#include<locale.h>
int mygetstr(char *str, int y, int x){
WINDOW *win;
int size, col;
int ok = 0;
int width;
wchar_t wstr[80];
char *p;
getmaxyx(stdscr, size, col);
void getaline(char *s){
str = s;
rl_callback_handler_remove();
ok = 1;
}
rl_callback_handler_install("", getaline);
win = newwin(1, col-x, y, x);
while(1){
rl_callback_read_char();
if(ok)
break;
werase(win);
strncpy(str, rl_line_buffer, 80);
p = str;
/* how many column chars before cursor occupies? */
size = mbsnrtowcs(wstr, (const char**)&p, rl_point, 80, NULL);
width = wcswidth(wstr, size);
mvwprintw(win, 0, 0, "%s", str);
/* put the cursor at right column */
wmove(win, 0, width);
wrefresh(win);
}
delwin(win);
return 0;
}
int main(){
char mesg[] = "Enter a string: ";
char str[80];
int row, col;
setlocale(LC_ALL, ""); /* make ncurses handle Chinese correctly */
initscr();
getmaxyx(stdscr, row, col);
mvprintw(row / 2, (col - strlen(mesg)) / 2, "%s", mesg);
refresh();
mygetstr(str, row / 2, (col + strlen(mesg)) / 2);
mvprintw(LINES - 2, 0, "You Entered: %s", str);
getch();
endwin();
return 0;
}
Python 版
#!/usr/bin/env python3
# vim:fileencoding=utf-8
import sys
import readline
import ctypes
import ctypes.util
import curses
import struct
from charset import strwidth
rllib_path = ctypes.util.find_library('readline')
rllib = ctypes.CDLL(rllib_path)
def getstr(win, y, x):
_, col = win.getmaxyx()
inputbox = curses.newwin(1, col-x, y, x)
ret = ''
ok = False
def callback(s):
nonlocal ok, ret
if s is None:
rllib.rl_callback_handler_remove()
raise EOFError
elif not s:
ok = True
else:
ret = s.decode()
ok = True
cbfunc = ctypes.CFUNCTYPE(None, ctypes.c_char_p)
rllib.rl_callback_handler_install.restype = None
rllib.rl_callback_handler_install(ctypes.c_char_p(b""), cbfunc(callback))
while True:
rllib.rl_callback_read_char()
if ok:
break
inputbox.erase()
# 这样获取的值不对。。。
# bbuf = ctypes.string_at(rllib.rl_line_buffer)
buf = readline.get_line_buffer()
bbuf = buf.encode()
inputbox.addstr(0, 0, buf)
rl_point = struct.unpack('I', ctypes.string_at(rllib.rl_point, 4))[0]
w = strwidth(bbuf[:rl_point].decode())
inputbox.move(0, w)
inputbox.refresh()
del inputbox
return ret
msg = '输入字符串:'
win = curses.initscr()
curses.noecho()
row, col = win.getmaxyx()
win.addstr(row // 2, (col - strwidth(msg)) // 2, msg)
win.refresh()
s = getstr(win, row // 2, (col + strwidth(msg)) // 2)
win.addstr(row - 2, 0, '你输入了: ' + s)
win.getch()
curses.endwin()
技巧
在提示符中使用 \001 和 \002 来标识不可见字符[4]。