+Tue Jun 27 22:36:38 2006 Ben Pfaff <blp@gnu.org>
+
+ Fix regression in command name completion reported by John
+ Darrington. Now completion is again state-dependent and occurs
+ only on the first line of a command.
+
+ * command.c (do_parse_command): Move reading the first token of
+ the command here, from execute_command and cmd_input_program.
+ Call set_completion_state and getl_set_prompt_style here.
+ (do_parse_command) Use in_correct_state instead of
+ verify_valid_command.
+ (verify_valid_command) Break into two new functions,
+ in_correct_state and report_state_mismatch.
+ (set_completion_state) New function.
+ (cmd_complete) New function.
+ [HAVE_READLINE] (pspp_attempted_completion_function) Removed.
+ [HAVE_READLINE] (command_generator) Removed.
+
+ * line-buffer.c: (struct getl_source) Change `interactive' member
+ signature to take enum getl_prompt_style instead of const char *.
+ (create_interactive_source) Ditto, for parameter type.
+ (getl_append_interactive) Ditto.
+ (read_line_from_source) Pass get_prompt_style() to interactive
+ function instead of get_prompt().
+ (get_prompt) Removed.
+ (get_prompt_style) New function.
+
Sat May 6 13:25:25 2006 Ben Pfaff <blp@gnu.org>
Continue reforming procedure execution. In this phase, remove
#include <data/settings.h>
#include <data/variable.h>
#include <language/lexer/lexer.h>
+#include <language/line-buffer.h>
#include <libpspp/alloc.h>
#include <libpspp/compiler.h>
#include <libpspp/message.h>
static const size_t command_cnt = sizeof commands / sizeof *commands;
-static bool verify_valid_command (const struct command *, enum cmd_state);
+static bool in_correct_state (const struct command *, enum cmd_state);
+static bool report_state_mismatch (const struct command *, enum cmd_state);
static const struct command *find_command (const char *name);
+static void set_completion_state (enum cmd_state);
\f
/* Command parser. */
const struct command *command;
enum cmd_result result;
- /* Null commands can result from extra empty lines. */
- if (token == '.')
- return CMD_SUCCESS;
+ /* Read the command's first token. */
+ getl_set_prompt_style (GETL_PROMPT_FIRST);
+ set_completion_state (state);
+ lex_get ();
+ if (token == T_STOP)
+ return CMD_EOF;
+ else if (token == '.')
+ {
+ /* Null commands can result from extra empty lines. */
+ return CMD_SUCCESS;
+ }
+ getl_set_prompt_style (GETL_PROMPT_LATER);
/* Parse the command name. */
command = parse_command_name ();
command->name);
return CMD_FAILURE;
}
- else if (!verify_valid_command (command, state))
- return CMD_FAILURE;
+ else if (!in_correct_state (command, state))
+ {
+ report_state_mismatch (command, state);
+ return CMD_FAILURE;
+ }
/* Execute command. */
msg_set_command_name (command->name);
}
/* Returns true if COMMAND is allowed in STATE,
- false otherwise.
- If COMMAND is not allowed, emits an appropriate error
- message. */
+ false otherwise. */
static bool
-verify_valid_command (const struct command *command, enum cmd_state state)
+in_correct_state (const struct command *command, enum cmd_state state)
{
- if ((state == CMD_STATE_INITIAL && command->states & S_INITIAL)
- || (state == CMD_STATE_DATA && command->states & S_DATA)
- || (state == CMD_STATE_INPUT_PROGRAM
- && command->states & S_INPUT_PROGRAM)
- || (state == CMD_STATE_FILE_TYPE && command->states & S_FILE_TYPE))
- return true;
+ return ((state == CMD_STATE_INITIAL && command->states & S_INITIAL)
+ || (state == CMD_STATE_DATA && command->states & S_DATA)
+ || (state == CMD_STATE_INPUT_PROGRAM
+ && command->states & S_INPUT_PROGRAM)
+ || (state == CMD_STATE_FILE_TYPE && command->states & S_FILE_TYPE));
+}
+/* Emits an appropriate error message for trying to invoke
+ COMMAND in STATE. */
+static bool
+report_state_mismatch (const struct command *command, enum cmd_state state)
+{
+ assert (!in_correct_state (command, state));
if (state == CMD_STATE_INITIAL || state == CMD_STATE_DATA)
{
const char *allowed[3];
return false;
}
\f
-/* Readline command name completion. */
+/* Command name completion. */
-#if HAVE_READLINE
-static char *command_generator (const char *text, int state);
-
-/* Returns a set of completions for TEXT.
- This is of the proper form for assigning to
- rl_attempted_completion_function. */
-char **
-pspp_attempted_completion_function (const char *text,
- int start, int end UNUSED)
+static enum cmd_state completion_state = CMD_STATE_INITIAL;
+
+static void
+set_completion_state (enum cmd_state state)
{
- if (start == 0)
- {
- /* Complete command name at start of line. */
- return rl_completion_matches (text, command_generator);
- }
- else
- {
- /* Otherwise don't do any completion. */
- rl_attempted_completion_over = 1;
- return NULL;
- }
+ completion_state = state;
}
-/* If STATE is 0, returns the first command name matching TEXT.
- Otherwise, returns the next command name matching TEXT.
- Returns a null pointer when no matches are left. */
-static char *
-command_generator (const char *text, int state)
+/* Returns the next possible completion of a command name that
+ begins with PREFIX, in the current command state, or a null
+ pointer if no completions remain.
+ Before calling the first time, set *CMD to a null pointer. */
+const char *
+cmd_complete (const char *prefix, const struct command **cmd)
{
- static const struct command *cmd;
-
- if (!state)
- cmd = commands;
+ if (*cmd == NULL)
+ *cmd = commands;
- for (; cmd < commands + command_cnt; cmd++)
- if (!memcasecmp (cmd->name, text, strlen (text))
- && (!(cmd->flags & F_TESTING) || get_testing_mode ())
- && (!(cmd->flags & F_ENHANCED) || get_syntax () == ENHANCED))
- return xstrdup (cmd++->name);
+ for (; *cmd < commands + command_cnt; (*cmd)++)
+ if (!memcasecmp ((*cmd)->name, prefix, strlen (prefix))
+ && (!((*cmd)->flags & F_TESTING) || get_testing_mode ())
+ && (!((*cmd)->flags & F_ENHANCED) || get_syntax () == ENHANCED)
+ && ((*cmd)->function != NULL)
+ && in_correct_state (*cmd, completion_state))
+ return (*cmd)++->name;
return NULL;
}
-#endif /* HAVE_READLINE */
\f
/* Simple commands. */
CMD_STATE_FILE_TYPE /* Inside FILE TYPE. */
};
-#if HAVE_READLINE
-char **pspp_attempted_completion_function (const char *, int start, int end);
-#endif
-
enum cmd_result cmd_parse (enum cmd_state);
+struct command;
+const char *cmd_complete (const char *, const struct command **);
+
/* Prototype all the command functions. */
#define DEF_CMD(STATES, FLAGS, NAME, FUNCTION) int FUNCTION (void);
#define UNIMPL_CMD(NAME, DESCRIPTION)
+Tue Jun 27 22:44:28 2006 Ben Pfaff <blp@gnu.org>
+
+ Fix regression in command name completion reported by John
+ Darrington. Now completion is again state-dependent and occurs
+ only on the first line of a command.
+
+ * inpt-pgm.c: (cmd_input_program) Reading of first token in
+ command moved into cmd_parse.
+
Fri Jun 9 13:56:00 2006 Ben Pfaff <blp@gnu.org>
Reform string library.
inside_input_program = true;
for (;;)
{
- enum cmd_result result;
- lex_get ();
- result = cmd_parse (CMD_STATE_INPUT_PROGRAM);
+ enum cmd_result result = cmd_parse (CMD_STATE_INPUT_PROGRAM);
if (result == CMD_END_INPUT_PROGRAM)
break;
else if (result == CMD_END_CASE)
function;
/* INTERACTIVE. */
- bool (*interactive) (struct string *line, const char *prompt);
+ bool (*interactive) (struct string *line, enum getl_prompt_style);
}
u;
static void init_prompts (void);
static void uninit_prompts (void);
-static const char *get_prompt (void);
+static enum getl_prompt_style get_prompt_style (void);
/* Initialize getl. */
void
/* Creates an interactive source with the given FUNCTION. */
static struct getl_source *
create_interactive_source (bool (*function) (struct string *line,
- const char *prompt))
+ enum getl_prompt_style))
{
struct getl_source *s = xmalloc (sizeof *s);
s->fn = NULL;
obtained or false at end of file. */
void
getl_append_interactive (bool (*function) (struct string *line,
- const char *prompt))
+ enum getl_prompt_style))
{
append_source (create_interactive_source (function));
}
case FUNCTION:
return s->u.function.read (line, &s->fn, &s->ln, s->u.function.aux);
case INTERACTIVE:
- return s->u.interactive (line, get_prompt ());
+ return s->u.interactive (line, get_prompt_style ());
}
abort ();
}
/* Returns the current prompt. */
-static const char *
-get_prompt (void)
+static enum getl_prompt_style
+get_prompt_style (void)
{
- return prompts[current_style];
+ return current_style;
}
#include <stdbool.h>
#include <libpspp/str.h>
+enum getl_prompt_style
+ {
+ GETL_PROMPT_FIRST, /* First line of command. */
+ GETL_PROMPT_LATER, /* Second or later line of command. */
+ GETL_PROMPT_DATA, /* Between BEGIN DATA and END DATA. */
+ GETL_PROMPT_CNT
+ };
+
/* Current line. This line may be modified by modules other than
getl.c, and by lexer.c in particular. (Ugh.) */
extern struct string getl_buf;
void (*close) (void *aux),
void *aux);
void getl_append_interactive (bool (*function) (struct string *line,
- const char *prompt));
+ enum getl_prompt_style));
void getl_abort_noninteractive (void);
bool getl_is_interactive (void);
bool getl_read_line (bool *interactive);
void getl_location (const char **, int *);
-\f
-/* Prompting. */
-
-enum getl_prompt_style
- {
- GETL_PROMPT_FIRST, /* First line of command. */
- GETL_PROMPT_LATER, /* Second or later line of command. */
- GETL_PROMPT_DATA, /* Between BEGIN DATA and END DATA. */
- GETL_PROMPT_CNT
- };
const char *getl_get_prompt (enum getl_prompt_style);
void getl_set_prompt (enum getl_prompt_style, const char *);
+Tue Jun 27 22:44:56 2006 Ben Pfaff <blp@gnu.org>
+
+ Fix regression in command name completion reported by John
+ Darrington. Now completion is again state-dependent and occurs
+ only on the first line of a command.
+
+ * main.c (main): Reading of first token in command moved into
+ cmd_parse.
+ (execute_command) Removed.
+
+ * read-line.c: [HAVE_READLINE] (readln_initialize) Postpone
+ setting rl_attempted_completion_function until readln_read.
+ [HAVE_READLINE] (readln_read) Change param from const char * to
+ enum getl_prompt_style. Set rl_attempted_completion_function
+ based on style.
+ [HAVE_READLINE] (complete_command_name) New function.
+ [HAVE_READLINE] (dont_complete) New function.
+ [HAVE_READLINE] (command_generator) New function.
+
Tue Jun 27 08:23:07 2006 Ben Pfaff <blp@gnu.org>
* automake.mk (src_ui_terminal_pspp_LDADD): Add $(LIBICONV).
static void i18n_init (void);
static void fpu_init (void);
-static int execute_command (void);
static void terminate (bool success) NO_RETURN;
/* If a segfault happens, issue a message to that effect and halt */
for (;;)
{
- int result = execute_command ();
+ int result = cmd_parse (proc_has_source ()
+ ? CMD_STATE_DATA : CMD_STATE_INITIAL);
if (result == CMD_EOF || result == CMD_FINISH)
break;
if (result == CMD_CASCADING_FAILURE && !getl_is_interactive ())
terminate (!any_errors ());
}
-
-/* Parses a command and returns the result. */
-static int
-execute_command (void)
-{
- /* Read the command's first token.
- The first token is part of the first line of the command. */
- getl_set_prompt_style (GETL_PROMPT_FIRST);
- lex_get ();
- if (token == T_STOP)
- return CMD_EOF;
-
- /* Parse the command.
- Any lines read after the first token must be continuation
- lines. */
- getl_set_prompt_style (GETL_PROMPT_LATER);
- return cmd_parse (proc_has_source ()
- ? CMD_STATE_DATA : CMD_STATE_INITIAL);
-}
\f
static void
i18n_init (void)
#include <libpspp/version.h>
#include <output/table.h>
+#include "xalloc.h"
+
#include "gettext.h"
#define _(msgid) gettext (msgid)
-
#if HAVE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
static char *history_file;
+
+static char **complete_command_name (const char *, int, int);
+static char **dont_complete (const char *, int, int);
#endif /* HAVE_READLINE */
static bool initialised = false;
#if HAVE_READLINE
rl_basic_word_break_characters = "\n";
- rl_attempted_completion_function = pspp_attempted_completion_function;
#ifdef unix
if (history_file == NULL)
{
Returns true if successful, false at end of file.
Suitable for passing to getl_append_interactive(). */
bool
-readln_read (struct string *line, const char *prompt)
+readln_read (struct string *line, enum getl_prompt_style style)
{
+ const char *prompt = getl_get_prompt (style);
#if HAVE_READLINE
char *string;
#endif
- assert(initialised);
+ assert (initialised);
reset_msg_count ();
welcome ();
#if HAVE_READLINE
+ rl_attempted_completion_function = (style == GETL_PROMPT_FIRST
+ ? complete_command_name
+ : dont_complete);
string = readline (prompt);
if (string == NULL)
return false;
return false;
#endif
}
+
+#ifdef HAVE_READLINE
+static char *command_generator (const char *text, int state);
+
+/* Returns a set of command name completions for TEXT.
+ This is of the proper form for assigning to
+ rl_attempted_completion_function. */
+static char **
+complete_command_name (const char *text, int start, int end UNUSED)
+{
+ if (start == 0)
+ {
+ /* Complete command name at start of line. */
+ return rl_completion_matches (text, command_generator);
+ }
+ else
+ {
+ /* Otherwise don't do any completion. */
+ rl_attempted_completion_over = 1;
+ return NULL;
+ }
+}
+
+/* Do not do any completion for TEXT. */
+static char **
+dont_complete (const char *text UNUSED, int start UNUSED, int end UNUSED)
+{
+ rl_attempted_completion_over = 1;
+ return NULL;
+}
+
+/* If STATE is 0, returns the first command name matching TEXT.
+ Otherwise, returns the next command name matching TEXT.
+ Returns a null pointer when no matches are left. */
+static char *
+command_generator (const char *text, int state)
+{
+ static const struct command *cmd;
+ const char *name;
+
+ if (state == 0)
+ cmd = NULL;
+ name = cmd_complete (text, &cmd);
+ return name ? xstrdup (name) : NULL;
+}
+#endif /* HAVE_READLINE */
#define READLN_H
#include <libpspp/str.h>
+#include <language/line-buffer.h>
void readln_initialize (void);
void readln_uninitialize (void);
-bool readln_read (struct string *line, const char *prompt);
+bool readln_read (struct string *line, enum getl_prompt_style);
#endif /* READLN_H */