gboolean bang; /* if the command was called with a bang ! */
GString *lhs; /* left hand side of the command - single word */
GString *rhs; /* right hand side of the command - multiple words */
+ int flags; /* flags for the already parsed command */
} ExArg;
typedef gboolean (*ExFunc)(const ExArg *arg);
#define EX_FLAG_BANG 0x001 /* command uses the bang ! after command name */
#define EX_FLAG_LHS 0x002 /* command has a single word after the command name */
#define EX_FLAG_RHS 0x004 /* command has a right hand side */
+#define EX_FLAG_EXP 0x008 /* expand pattern like % or %:p in rhs */
int flags;
} ExInfo;
static gboolean parse_bang(const char **input, ExArg *arg);
static gboolean parse_lhs(const char **input, ExArg *arg);
static gboolean parse_rhs(const char **input, ExArg *arg);
+static void expand_input(const char **input, ExArg *arg);
static void skip_whitespace(const char **input);
static void free_cmdarg(ExArg *arg);
static gboolean execute(const ExArg *arg);
-static char *expand_string(const char *str);
static gboolean ex_bookmark(const ExArg *arg);
static gboolean ex_eval(const ExArg *arg);
{"qpop", EX_QPOP, ex_queue, EX_FLAG_NONE},
{"qpush", EX_QPUSH, ex_queue, EX_FLAG_RHS},
{"qunshift", EX_QUNSHIFT, ex_queue, EX_FLAG_RHS},
- {"save", EX_SAVE, ex_save, EX_FLAG_RHS},
+ {"save", EX_SAVE, ex_save, EX_FLAG_RHS|EX_FLAG_EXP},
#if 0
{"sca", EX_SCA, ex_shortcut, EX_FLAG_RHS},
{"scd", EX_SCD, ex_shortcut, EX_FLAG_RHS},
{"scr", EX_SCR, ex_shortcut, EX_FLAG_RHS},
#endif
{"set", EX_SET, ex_set, EX_FLAG_RHS},
- {"shellcmd", EX_SHELLCMD, ex_shellcmd, EX_FLAG_RHS},
+ {"shellcmd", EX_SHELLCMD, ex_shellcmd, EX_FLAG_RHS|EX_FLAG_EXP},
{"shortcut-add", EX_SCA, ex_shortcut, EX_FLAG_RHS},
{"shortcut-default", EX_SCD, ex_shortcut, EX_FLAG_RHS},
{"shortcut-remove", EX_SCR, ex_shortcut, EX_FLAG_RHS},
*/
static gboolean parse(const char **input, ExArg *arg)
{
- ExInfo *cmd = NULL;
if (!*input || !**input) {
return false;
}
return false;
}
- /* get the command and it's flags to decide what to parse */
- cmd = &(commands[arg->idx]);
-
/* parse the bang if this is allowed */
- if (cmd->flags & EX_FLAG_BANG) {
+ if (arg->flags & EX_FLAG_BANG) {
parse_bang(input, arg);
}
/* parse the lhs if this is available */
skip_whitespace(input);
- if (cmd->flags & EX_FLAG_LHS) {
+ if (arg->flags & EX_FLAG_LHS) {
parse_lhs(input, arg);
}
/* parse the rhs if this is available */
skip_whitespace(input);
- if (cmd->flags & EX_FLAG_RHS) {
+ if (arg->flags & EX_FLAG_RHS) {
parse_rhs(input, arg);
}
return false;
}
- arg->idx = first;
- arg->code = commands[first].code;
- arg->name = commands[first].name;
+ arg->idx = first;
+ arg->code = commands[first].code;
+ arg->name = commands[first].name;
+ arg->flags = commands[first].flags;
return true;
}
g_string_append_c(arg->rhs, quote);
g_string_append_c(arg->rhs, **input);
}
- } else {
- /* unquoted char */
- g_string_append_c(arg->rhs, **input);
+ } else { /* unquoted char */
+ /* check for expansion placeholder */
+ if (arg->flags & EX_FLAG_EXP && strchr("%~", **input)) {
+ /* handle expansion */
+ expand_input(input, arg);
+ } else {
+ g_string_append_c(arg->rhs, **input);
+ }
}
(*input)++;
}
return true;
}
+static void expand_input(const char **input, ExArg *arg)
+{
+ const char *uri;
+ switch (**input) {
+ case '%':
+ if ((uri = GET_URI())) {
+ /* TODO check for modifiers like :h:t:r:e */
+ g_string_append(arg->rhs, uri);
+ }
+ break;
+
+ case '~':
+ (*input)++;
+ /* expand only ~/ because ~user is not handled at the moment */
+ if (**input == '/') {
+ g_string_append(arg->rhs, g_get_home_dir());
+ g_string_append_c(arg->rhs, **input);
+ }
+ break;
+ }
+}
+
/**
* Executes the command given by ExArg.
*/
}
}
-/**
- * Expands paceholders in given string.
- * % - expanded to current uri
- * TODO allow modifiers like :p :h :e :r like in vim expand()
- *
- * Returned string must be freed.
- */
-static char *expand_string(const char *str)
-{
- if (!str) {
- return NULL;
- }
- return util_str_replace("%", GET_URI(), str);
-}
-
static void free_cmdarg(ExArg *arg)
{
if (arg->lhs) {
static gboolean ex_shellcmd(const ExArg *arg)
{
int status, argc;
- char *cmd, *exp, *error = NULL, *out = NULL, **argv;
+ char *cmd, *error = NULL, *out = NULL, **argv;
if (!*arg->rhs->str) {
return false;
}
- exp = expand_string(arg->rhs->str);
- cmd = g_strdup_printf(SHELL_CMD, exp);
- g_free(exp);
+ cmd = g_strdup_printf(SHELL_CMD, arg->rhs->str);
if (!g_shell_parse_argv(cmd, &argc, &argv, NULL)) {
vb_echo(VB_MSG_ERROR, true, "Could not parse command args");
g_free(cmd);