Skip to content

Instantly share code, notes, and snippets.

@johnbintz
Created July 15, 2011 01:28
Show Gist options
  • Save johnbintz/1083859 to your computer and use it in GitHub Desktop.
Save johnbintz/1083859 to your computer and use it in GitHub Desktop.
+++ bind.c 2010-10-28 23:09:12.788260925 +0200
@@ -1508,6 +1508,9 @@
static int sv_histsize PARAMS((const char *));
static int sv_isrchterm PARAMS((const char *));
static int sv_keymap PARAMS((const char *));
+static int sv_vi_insert_prompt PARAMS((const char *));
+static int sv_vi_command_prompt PARAMS((const char *));
+static int sv_vi_mode_changed_bin PARAMS((const char *));
static const struct {
const char * const name;
@@ -1522,6 +1525,9 @@
{ "history-size", V_INT, sv_histsize },
{ "isearch-terminators", V_STRING, sv_isrchterm },
{ "keymap", V_STRING, sv_keymap },
+ { "vi-insert-prompt", V_STRING, sv_vi_insert_prompt },
+ { "vi-command-prompt", V_STRING, sv_vi_command_prompt },
+ { "vi-mode-changed-bin", V_STRING, sv_vi_mode_changed_bin },
{ (char *)NULL, 0 }
};
@@ -1694,6 +1700,30 @@
}
static int
+sv_vi_insert_prompt (value)
+ const char *value;
+{
+ _rl_set_vi_insert_prompt (value);
+ return 0;
+}
+
+static int
+sv_vi_command_prompt (value)
+ const char *value;
+{
+ _rl_set_vi_command_prompt (value);
+ return 0;
+}
+
+static int
+sv_vi_mode_changed_bin (value)
+ const char *value;
+{
+ _rl_set_vi_mode_changed_bin (value);
+ return 0;
+}
+
+static int
sv_bell_style (value)
const char *value;
{
+++ rlprivate.h 2010-10-28 23:09:45.788262324 +0200
@@ -361,6 +361,9 @@
extern int (_rl_digit_value) PARAMS((int));
/* vi_mode.c */
+extern void _rl_set_vi_insert_prompt PARAMS((const char *));
+extern void _rl_set_vi_command_prompt PARAMS((const char *));
+extern void _rl_set_vi_mode_changed_bin PARAMS((const char *));
extern void _rl_vi_initialize_line PARAMS((void));
extern void _rl_vi_reset_last PARAMS((void));
extern void _rl_vi_set_last PARAMS((int, int, int));
+++ vi_mode.c 2010-10-28 23:21:54.038261767 +0200
@@ -49,6 +49,8 @@
#include <stdio.h>
+#include <fcntl.h>
+
/* Some standard library routines. */
#include "rldefs.h"
#include "rlmbutil.h"
@@ -128,16 +130,121 @@
static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
#endif
+#define _RL_PROMPT_INITIAL_SIZE 256
+#define _VI_MODE_PROMPT_FORMAT_SIZE 256
+#define _VI_MODE_PROMPT_SIZE _RL_PROMPT_INITIAL_SIZE + _VI_MODE_PROMPT_FORMAT_SIZE
+static char _rl_prompt_initial[_RL_PROMPT_INITIAL_SIZE] = "\0";
+static char *_rl_prompt_initial_last_line;
+static char _rl_vi_insert_prompt[_VI_MODE_PROMPT_FORMAT_SIZE] = "\0";
+static char _rl_vi_command_prompt[_VI_MODE_PROMPT_FORMAT_SIZE] = "\0";
+#define _VI_MODE_CHANGED_BIN_SIZE 256
+static char _rl_vi_mode_changed_bin[_VI_MODE_CHANGED_BIN_SIZE] = "\0";
+
+void _rl_set_vi_insert_prompt PARAMS((const char *));
+void _rl_set_vi_command_prompt PARAMS((const char *));
+void _rl_set_vi_mode_changed_bin PARAMS((const char *));
+
+static void vi_mode_changed_prompt PARAMS((void));
+static void vi_mode_changed_bin PARAMS((void));
+static void vi_mode_changed PARAMS((void));
+
+static char *
+safe_strncpy (dest, src, n)
+ char *dest;
+ const char *src;
+ int n;
+{
+ if (src) {
+ strncpy (dest, src, n);
+ dest[n - 1] = '\0';
+ }
+ else {
+ dest[0] = '\0';
+ }
+ return dest;
+}
+
+static char *
+parse_prompt_format_escapes (src)
+ char *src;
+{
+ char *r, *w, c, o;
+ static char buf[4] = "000";
+
+ r = src;
+ w = r;
+ while (*r) {
+ c = *r;
+ if (c == '\\') {
+ r++;
+ if (*r == '\\') {
+ c = '\\';
+ }
+ else if (*r == '0') {
+ c = *r;
+ buf[1] = *(r + 1);
+ buf[2] = *(r + 2);
+ o = strtol (buf, NULL, 8);
+ if (o > 0) {
+ r += 2;
+ c = o;
+ }
+ }
+ }
+ r++;
+ if (c > 0) {
+ *w = c;
+ w++;
+ }
+ }
+ *w = '\0';
+ return src;
+}
+
+void
+_rl_set_vi_insert_prompt (value)
+ const char *value;
+{
+ safe_strncpy (_rl_vi_insert_prompt, value, _VI_MODE_PROMPT_FORMAT_SIZE);
+ parse_prompt_format_escapes (_rl_vi_insert_prompt);
+}
+
+void
+_rl_set_vi_command_prompt (value)
+ const char *value;
+{
+ safe_strncpy (_rl_vi_command_prompt, value, _VI_MODE_PROMPT_FORMAT_SIZE);
+ parse_prompt_format_escapes (_rl_vi_command_prompt);
+}
+
+void
+_rl_set_vi_mode_changed_bin (value)
+ const char *value;
+{
+ safe_strncpy (_rl_vi_mode_changed_bin, value, _VI_MODE_CHANGED_BIN_SIZE);
+}
+
void
_rl_vi_initialize_line ()
{
register int i, n;
+ char *p;
n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]);
for (i = 0; i < n; i++)
vi_mark_chars[i] = -1;
RL_UNSETSTATE(RL_STATE_VICMDONCE);
+
+ safe_strncpy (_rl_prompt_initial, rl_prompt, _RL_PROMPT_INITIAL_SIZE);
+ p = strrchr (_rl_prompt_initial, '\n');
+ if (p) {
+ p++;
+ }
+ else {
+ p = _rl_prompt_initial;
+ }
+ _rl_prompt_initial_last_line = p;
}
void
@@ -655,6 +762,86 @@
/* Insertion mode stuff. */
+/* This is meant to be called after vi mode changes. */
+static void
+vi_mode_changed_prompt ()
+{
+ char *prompt, *p;
+ char pattern[] = "{}";
+ static char buf[_VI_MODE_PROMPT_SIZE];
+ int i, j;
+
+ if (VI_INSERT_MODE()) {
+ prompt = _rl_vi_insert_prompt;
+ }
+ else if (VI_COMMAND_MODE()) {
+ prompt = _rl_vi_command_prompt;
+ }
+ if (strlen (prompt)) {
+ i = _rl_prompt_initial_last_line - _rl_prompt_initial;
+ memcpy (buf, _rl_prompt_initial, i);
+ buf[i] = '\0';
+ p = strstr (prompt, pattern);
+ if (p) {
+ j = p - prompt;
+ memcpy (buf + i, prompt, j);
+ buf[i + j] = '\0';
+ strcat (buf, _rl_prompt_initial_last_line);
+ strcat (buf, p + strlen (pattern));
+ }
+ else {
+ strcat (buf, prompt);
+ }
+ prompt = buf;
+ }
+ else {
+ prompt = _rl_prompt_initial;
+ }
+ rl_set_prompt (prompt);
+ _rl_redisplay_after_sigwinch ();
+}
+
+static void
+vi_mode_changed_bin ()
+{
+ pid_t pid;
+ int status, fd_devnull;
+ char *bin = _rl_vi_mode_changed_bin;
+
+ if (!strlen (bin)) {
+ return;
+ }
+ pid = fork ();
+ if (pid < 0) {
+ perror ("vi_mode_changed_bin: fork failed");
+ return;
+ }
+ else if (pid == 0) {
+ close (STDIN_FILENO);
+ fd_devnull = open ("/dev/null", O_RDONLY);
+ dup2 (fd_devnull, STDIN_FILENO);
+ if (VI_INSERT_MODE()) {
+ execl (bin, bin, "insert", NULL);
+ }
+ else if (VI_COMMAND_MODE()) {
+ execl (bin, bin, "command", NULL);
+ }
+ perror ("vi_mode_changed_bin: execv failed");
+ exit (1);
+ }
+ waitpid (pid, &status, 0);
+}
+
+static void
+vi_mode_changed ()
+{
+ if (!isatty (STDIN_FILENO) || !isatty (STDOUT_FILENO)) {
+ return;
+ }
+ vi_mode_changed_prompt ();
+ vi_mode_changed_bin ();
+}
+
/* Switching from one mode to the other really just involves
switching keymaps. */
int
@@ -663,6 +850,9 @@
{
_rl_keymap = vi_insertion_keymap;
_rl_vi_last_key_before_insert = key;
+
+ vi_mode_changed ();
+
return (0);
}
@@ -747,6 +937,9 @@
rl_free_undo_list ();
RL_SETSTATE (RL_STATE_VICMDONCE);
+
+ vi_mode_changed ();
+
return (0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment