Compare commits

...

3 Commits

Author SHA1 Message Date
Přemysl Eric Janouch ba5a6374b6
json-rpc-test-server: add a "wait" method
Considering the server's nature, the global lock-up it causes
shouldn't constitute a major problem.
2022-09-04 15:25:27 +02:00
Přemysl Eric Janouch 67008963cf
Update NEWS 2022-09-04 15:22:46 +02:00
Přemysl Eric Janouch c1b6918db3
Fix libedit history behaviour 2022-09-04 15:22:46 +02:00
5 changed files with 70 additions and 16 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

17
NEWS
View File

@ -1,3 +1,20 @@
Unreleased
* Add a backend for co-processes, such as language servers
* Support reading OpenRPC documents from a file
* Respect the NO_COLOR environment variable
* Miscellaneous libedit (editline) fixes
* json-rpc-test-server: implement OpenRPC discovery
* json-rpc-test-server: only serve regular files
* json-rpc-test-server: miscellaneous WebSocket fixes
1.1.0 (2020-10-13)
* Add method name tab completion using OpenRPC information

View File

@ -140,8 +140,7 @@ the higher-level protocol (the "Sec-Ws-Protocol" HTTP field).
Bugs
----
The editline (libedit) frontend is more of a proof of concept that mostly seems
to work but exhibits bugs that are not our fault.
The editline (libedit) frontend may exhibit some unexpected behaviour.
Examples
--------

View File

@ -1,7 +1,7 @@
/*
* json-rpc-shell.c: a shell for JSON-RPC 2.0
*
* Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name>
* Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@ -515,6 +515,7 @@ struct input_el
char *entered_line; ///< Buffers the entered line
bool active; ///< Interface has been started
bool need_restart; ///< Need to clear history state
char *prompt; ///< The prompt we use
int prompt_shown; ///< Whether the prompt is shown now
@ -540,12 +541,24 @@ input_el_redisplay (struct input_el *self)
{
// See rl_redisplay(), however NetBSD editline's map.c v1.54 breaks VREPRINT
// so we bind redisplay somewhere else in input_el_start()
char x[] = { 'q' & 31, 0 };
el_push (self->editline, x);
wchar_t x[] = { L'q' & 31, 0 };
el_wpush (self->editline, x);
// We have to do this or it gets stuck and nothing is done
int count = 0;
(void) el_wgets (self->editline, &count);
int dummy_count = 0;
(void) el_wgets (self->editline, &dummy_count);
}
// Editline keeping its own history position (look for "eventno" there).
// This is the only sane way of resetting it.
static void
input_el_start_over (struct input_el *self)
{
wchar_t x[] = { L'c' & 31, 0 };
el_wpush (self->editline, x);
int dummy_count = 0;
(void) el_wgets (self->editline, &dummy_count);
}
static char *
@ -603,13 +616,14 @@ input_el_on_return (EditLine *editline, int key)
self->entered_line = xstrndup
(info_mb->buffer, info_mb->lastchar - info_mb->buffer);
// Now we need to force editline to actually print the newline
// Now we need to force editline into actually printing the newline
el_cursor (editline, len++ - point);
el_insertstr (editline, "\n");
input_el_redisplay (self);
// Finally we need to discard the old line's contents
el_wdeletestr (editline, len);
self->need_restart = true;
return CC_NEWLINE;
}
@ -673,8 +687,6 @@ input_el_start (struct input *input, const char *program_name)
el_set (self->editline, EL_BIND, "^w", "ed-delete-prev-word", NULL);
// Just what are you doing?
el_set (self->editline, EL_BIND, "^u", "vi-kill-line-prev", NULL);
// See input_el_redisplay(), functionally important
el_set (self->editline, EL_BIND, "^q", "ed-redisplay", NULL);
// It's probably better to handle these ourselves
input_el_addbind (self->editline, "send-line", "Send line",
@ -690,6 +702,11 @@ input_el_start (struct input *input, const char *program_name)
// Source the user's defaults file
el_source (self->editline, NULL);
// See input_el_redisplay(), functionally important
el_set (self->editline, EL_BIND, "^q", "ed-redisplay", NULL);
// This is what buffered el_wgets() does, functionally important
el_set (self->editline, EL_BIND, "^c", "ed-start-over", NULL);
self->active = true;
self->prompt_shown = 1;
}
@ -977,6 +994,16 @@ input_el_on_tty_readable (struct input *input)
// We bind the return key to process it how we need to
struct input_el *self = (struct input_el *) input;
int unbuffered = 0;
(void) el_get (self->editline, EL_UNBUFFERED, &unbuffered);
// We must invoke ch_reset(), which isn't done for us with EL_UNBUFFERED.
if (unbuffered && self->need_restart)
{
self->need_restart = false;
input_el_start_over (self);
}
// el_gets() with EL_UNBUFFERED doesn't work with UTF-8,
// we must use the wide-character interface
int count = 0;
@ -984,8 +1011,7 @@ input_el_on_tty_readable (struct input *input)
// Editline works in a funny NO_TTY mode when the input is not a tty,
// we cannot use EL_UNBUFFERED and expect sane results then
int unbuffered = 0;
if (!el_get (self->editline, EL_UNBUFFERED, &unbuffered) && !unbuffered)
if (!unbuffered)
{
char *entered_line = buf ? input_el_wcstombs (buf) : NULL;
self->super.on_input (entered_line, self->super.user_data);

View File

@ -1,7 +1,7 @@
/*
* json-rpc-test-server.c: JSON-RPC 2.0 demo server
*
* Copyright (c) 2015 - 2020, Přemysl Eric Janouch <p@janouch.name>
* Copyright (c) 2015 - 2022, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@ -1464,7 +1464,7 @@ json_rpc_discover (struct server_context *ctx, json_t *params)
json_t *info = json_pack ("{ssss}",
"title", PROGRAM_NAME, "version", PROGRAM_VERSION);
json_t *methods = json_pack ("[ooo]",
json_t *methods = json_pack ("[oooo]",
open_rpc_describe ("date", json_pack ("{ssso}", "type", "object",
"properties", json_pack ("{s{ss}s{ss}s{ss}s{ss}s{ss}s{ss}}",
"year", "type", "number",
@ -1475,7 +1475,8 @@ json_rpc_discover (struct server_context *ctx, json_t *params)
"seconds", "type", "number"))),
open_rpc_describe ("ping", json_pack ("{ss}", "type", "string")),
open_rpc_describe ("rpc.discover", json_pack ("{ss}", "$ref",
"https://github.com/open-rpc/meta-schema/raw/master/schema.json")));
"https://github.com/open-rpc/meta-schema/raw/master/schema.json")),
open_rpc_describe ("wait", json_pack ("{ss}", "type", "null")));
return json_rpc_response (NULL, json_pack ("{sssoso}",
"openrpc", "1.2.6", "info", info, "methods", methods), NULL);
}
@ -1492,6 +1493,16 @@ json_rpc_ping (struct server_context *ctx, json_t *params)
return json_rpc_response (NULL, json_string ("pong"), NULL);
}
static json_t *
json_rpc_wait (struct server_context *ctx, json_t *params)
{
(void) ctx;
(void) params;
sleep (1);
return json_rpc_response (NULL, json_null (), NULL);
}
static json_t *
json_rpc_date (struct server_context *ctx, json_t *params)
{
@ -1524,6 +1535,7 @@ process_json_rpc_request (struct server_context *ctx, json_t *request)
{ "date", json_rpc_date },
{ "ping", json_rpc_ping },
{ "rpc.discover", json_rpc_discover },
{ "wait", json_rpc_wait },
};
if (!json_is_object (request))