Skip to content

Commit

Permalink
console: add line carrying backslash
Browse files Browse the repository at this point in the history
When using interactive console(stdin) instead of `\set delimiter '\'`,
slash at the end of the line can be used. Works on both server and client
side.

Co-authored-by: Olga Arkhangelskaia <arkholga@tarantool.org>

Closes tarantool#4317
Requires tarantool#7357

@TarantoolBot document
Title: introduce line carrying slash

Now we can use multiline commands with lines ending with '\' by default.
Works only without a set delimiter.

Consider the example:
```
tarantool> a = 10 \
         > + 12
---
...

tarantool> a
---
- 22
...

```
  • Loading branch information
Lord-KA committed Jul 11, 2022
1 parent 45948a5 commit 899a7f1
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## feature/console

* Now multiline commands with each line ending with "\" can be used instead
of `\set delimiter "\"`, is active only without a set delimiter. Works on
both server and client side.
36 changes: 33 additions & 3 deletions src/box/lua/console.lua
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,10 @@ local function local_read(self)
if buf:sub(1, 1) == '\\' then
break
end
if delim == "" then
if delim == "" and line:endswith("\\") then
buf = buf:sub(1, -2)
-- Continue reading.
elseif delim == "" then
local lang = box.session.language
if not lang or lang == 'lua' then
-- stop once a complete Lua statement is entered
Expand Down Expand Up @@ -642,9 +645,12 @@ local function local_print(self, output)
end

--
-- Read command from connected client console.listen()
-- Read a line or a chunk from connected client console.listen().
--
local function client_read(self)
-- The value is returned without delimiter (if any) and trailing
-- newline character.
--
local function client_read_line(self)
--
-- Byte sequences that come over the network and come from
-- the local client console may have a different terminal
Expand All @@ -665,6 +671,30 @@ local function client_read(self)
return buf:sub(1, -#self.delimiter-2)
end

--
-- Read a command from connected client console.listen().
--
local function client_read(self)
local buf = ""
while true do
local line = client_read_line(self)
if line == nil then
-- EOF or error.
--
-- Note: Even if `buf` is not empty, skip unfinished
-- command.
return nil
end
buf = buf .. line
if self.delimiter == "" and line:endswith("\\") then
buf = buf:sub(1, -2)
else
break
end
end
return buf
end

--
-- Print result to connected client from console.listen()
--
Expand Down
51 changes: 51 additions & 0 deletions test/app-luatest/gh_4317_console_backslash_test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
local t = require('luatest')
local g = t.group()

local result_str = [[tarantool> local a = 0 \
> for i = 1, 10 do
> a = a + i
> end \
> print(a)
55
---
...
tarantool> ]]

g.test_local_console = function()
local build_dir = arg[-1]:gsub('tarantool$', '')
local tarantool_command = [[local a = 0 \\\nfor i = 1, 10 do\na = a + i\nend \\\nprint(a)\n]]

local cmd = ("printf '%s' | tarantool -i 2>/dev/null"):format(tarantool_command)
local fh = io.popen(cmd, 'r')

-- Readline on CentOS 7 produces \e[?1034h escape sequence before tarantool> prompt, remove it.
local result = fh:read('*a'):gsub('\x1b%[%?1034h', '')

fh:close()
t.assert_equals(result, result_str)
end

g.test_remote_console = function()
local console = require('console')
local socket = require('socket')
local log = require('log')

-- Suppress console log messages.
log.level(4)
local CONSOLE_SOCKET = '/tmp/tarantool-test-console.sock'
local IPROTO_SOCKET = '/tmp/tarantool-test-iproto.sock'
local EOL = '\n...\n'
console.listen(CONSOLE_SOCKET)
socket.tcp_connect('unix/', CONSOLE_SOCKET)
local tarantool_command = 'local a = 0 \\\nfor i = 1, 10 do\\\n a = a + i \\\n end \\\n print(a)'

local client = socket.tcp_connect('unix/', CONSOLE_SOCKET)
client:read(128)
client:write(('%s\n'):format(tarantool_command))
local result = client:read(EOL)
t.assert_not_str_contains(result, 'error')
client:close()
os.remove(CONSOLE_SOCKET)
os.remove(IPROTO_SOCKET)
end

0 comments on commit 899a7f1

Please sign in to comment.