Added redis-cli interactive help support

updated via commands.json in redis-doc repo. Currently
use `make src/help.h` to re-generate. The following
are valid from the REPL:

  help
  help [command]
  help [group]
  help groups

ex:

  help sort
  help hash
This commit is contained in:
Tj Holowaychuk
2010-11-16 05:50:26 -08:00
parent 21dbc6499a
commit 5397f2b596
5 changed files with 995 additions and 17 deletions

56
utils/generate-command-help.rb Executable file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env ruby
require 'net/http'
require 'net/https'
require 'json'
require 'uri'
dest = ARGV[0]
tmpl = File.read './utils/help.h'
url = URI.parse 'https://github.com/antirez/redis-doc/raw/master/commands.json'
client = Net::HTTP.new url.host, url.port
client.use_ssl = true
res = client.get url.path
def argument arg
name = arg['name'].is_a?(Array) ? arg['name'].join(' ') : arg['name']
name = arg['enum'].join '|' if 'enum' == arg['type']
name = arg['command'] + ' ' + name if arg['command']
if arg['multiple']
name = "(#{name})"
name += arg['optional'] ? '*' : '+'
elsif arg['optional']
name = "(#{name})?"
end
name
end
def arguments command
return '-' unless command['arguments']
command['arguments'].map do |arg|
argument arg
end.join ' '
end
case res
when Net::HTTPSuccess
first = true
commands = JSON.parse(res.body)
c = commands.map do |key, command|
buf = if first
first = false
' '
else
"\n ,"
end
buf += " { \"#{key}\"\n" +
" , \"#{arguments(command)}\"\n" +
" , \"#{command['summary']}\"\n" +
" , COMMAND_GROUP_#{command['group'].upcase}\n" +
" , \"#{command['since']}\" }"
end.join("\n")
puts "\n// Auto-generated, do not edit.\n" + tmpl.sub('__COMMANDS__', c)
else
res.error!
end

119
utils/help.h Normal file
View File

@ -0,0 +1,119 @@
#include <stdio.h>
#include <string.h>
/*
* List command groups.
*/
#define GROUPS \
G(UNKNOWN, "unknown") \
G(SET, "set") \
G(LIST, "list") \
G(HASH, "hash") \
G(GENERIC, "generic") \
G(PUBSUB, "pubsub") \
G(STRING, "string") \
G(SERVER, "server") \
G(CONNECTION, "connection") \
G(TRANSACTIONS, "transactions") \
G(SORTED_SET, "sorted_set")
/*
* Command group types.
*/
typedef enum {
#define G(GROUP, _) COMMAND_GROUP_##GROUP,
GROUPS
#undef G
COMMAND_GROUP_LENGTH
} command_group_type_t;
/*
* Command group type names.
*/
static char *command_group_type_names[] = {
#define G(_, STR) STR,
GROUPS
#undef G
};
/*
* Command help struct.
*/
struct command_help {
char *name;
char *params;
char *summary;
command_group_type_t group;
char *since;
} command_help[] = {
__COMMANDS__
};
/*
* Output command help to stdout.
*/
static void
output_command_help(struct command_help *help) {
printf("\n \x1b[1m%s\x1b[0m \x1b[90m%s\x1b[0m\n", help->name, help->params);
printf(" \x1b[33msummary:\x1b[0m %s\n", help->summary);
printf(" \x1b[33msince:\x1b[0m %s\n", help->since);
printf(" \x1b[33mgroup:\x1b[0m %s\n", command_group_type_names[help->group]);
}
/*
* Return command group type by name string.
*/
static command_group_type_t
command_group_type_by_name(const char *name) {
for (int i = 0; i < COMMAND_GROUP_LENGTH; ++i) {
const char *group = command_group_type_names[i];
if (0 == strcasecmp(name, group)) return i;
}
return 0;
}
/*
* Output group names.
*/
static void
output_group_help() {
for (int i = 0; i < COMMAND_GROUP_LENGTH; ++i) {
if (COMMAND_GROUP_UNKNOWN == i) continue;
const char *group = command_group_type_names[i];
printf(" \x1b[90m-\x1b[0m %s\n", group);
}
}
/*
* Output all command help, filtering by group or command name.
*/
static void
output_help(int argc, const char **argv) {
int len = sizeof(command_help) / sizeof(struct command_help);
if (argc && 0 == strcasecmp("groups", argv[0])) {
output_group_help();
return;
}
command_group_type_t group = argc
? command_group_type_by_name(argv[0])
: COMMAND_GROUP_UNKNOWN;
for (int i = 0; i < len; ++i) {
struct command_help help = command_help[i];
if (argc && !group && 0 != strcasecmp(help.name, argv[0])) continue;
if (group && group != help.group) continue;
output_command_help(&help);
}
puts("");
}