-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsjfs-curses-chat
executable file
·149 lines (133 loc) · 3.52 KB
/
sjfs-curses-chat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env lua
require('strict')
os.setlocale('')
local Px = require('posix')
local Cs = require('curses')
-- These constants should be defined in lua-posix, but they're not
local KEY_MIN = 257
local KEY_MAX = 511
local function isempty(var)
return (not var) or (var == '')
end
local SJ_DIR = os.getenv('SJ_DIR')
local SJ_SERVER = os.getenv('SJ_SERVER')
local SJ_USER = os.getenv('SJ_USER')
local current_dir = false
local buddy = nil
local skip = false
for i = 1, #arg do
if skip then
skip = false
else
if arg[i] == '-c' then current_dir = true
elseif arg[i] == '-d' then SJ_DIR = arg[i+1]; skip=true
elseif arg[i] == '-s' then SJ_SERVER = arg[i+1]; skip=true
elseif arg[i] == '-u' then SJ_USER = arg[i+1]; skip=true
elseif arg[i] == '-b' then buddy = arg[i+1]; skip=true
else
print(arg[0]..': invalid option: '..v)
os.exit(false)
end
end
end
local chatdir = nil
if current_dir then
chatdir = './'
else
if isempty(SJ_DIR) then
print('Directory is needed via -d or SJ_DIR')
os.exit(false)
elseif isempty(buddy) then
print('Buddy is needed via -b')
os.exit(false)
else
chatdir = SJ_DIR .. '/' .. buddy .. '/'
end
end
local outfilename = chatdir .. 'out'
local infilename = chatdir .. 'in'
local tail_out = assert(io.popen('tail -f -n0 ' .. outfilename, 'r'))
assert(tail_out:setvbuf('no'))
local tail_out_fd = Px.fileno(tail_out)
local stdin_fd = Px.fileno(io.stdin)
local fds = {
[tail_out_fd] = { events = {IN=true} },
[stdin_fd] = { events = {IN=true} }
}
local in_fifo = assert(io.open(infilename, 'a'))
assert(in_fifo:setvbuf('no'))
Cs.initscr()
Cs.cbreak(true)
Cs.echo(false)
local stdscr = Cs.stdscr()
stdscr:clear()
stdscr:refresh()
local typing_lines = 2 -- size of the input window
local s_lines, s_cols = stdscr:getmaxyx()
local display_win = Cs.newwin(s_lines - typing_lines, s_cols, 0, 0)
local typing_win = Cs.newwin(typing_lines, s_cols, s_lines - typing_lines, 0)
typing_win:keypad(true)
typing_win:scrollok(true)
typing_win:clear()
typing_win:addstr('Type q then Enter to quit\n')
typing_win:refresh()
display_win:scrollok(true)
display_win:clear()
for ll in io.lines(outfilename) do
display_win:addstr(ll .. '\n')
display_win:refresh()
end
display_win:addstr('-------\n')
display_win:refresh()
local line = ''
while true do
local poll_result = Px.poll(fds, -1)
if poll_result == 0 then -- timeout
break
elseif poll_result == 1 then
if fds[tail_out_fd].revents.IN then
display_win:addstr(tail_out:read('*l') .. '\n')
display_win:refresh()
-- Cs.beep()
elseif fds[stdin_fd].revents.IN then
local c = typing_win:getch()
if c == 10 then -- newline
if line == 'q' then break end
in_fifo:write(line)
line = ''
typing_win:clear()
typing_win:addstr('Type q then Enter to quit\n')
elseif c == Cs.KEY_BACKSPACE then
if line == '' then
Cs.beep()
else
line = string.sub(line, 1, #line-1)
local y, x = typing_win:getyx()
typing_win:move(y, x-1)
typing_win:delch()
end
elseif c < 32 or c == 127 then
; -- ignore ascii control characters
elseif c >= KEY_MIN and c <= KEY_MAX then
; -- ignore function keys
else
typing_win:addch(c)
line = line .. string.char(c)
end
typing_win:refresh()
else
typing_win:addstr('What kind of event is this?')
typing_win:refresh()
end
else
display_win:addstr('Polling finished!')
display_win:refresh()
break
end
end
in_fifo:flush()
in_fifo:close()
--tail_out:flush() -- makes the program freeze
--tail_out:close() -- makes the program freeze
Cs.endwin()
os.exit(true)