Example #1
0
File: prompt.c Project: gonzus/tig
bool
prompt_menu(const char *prompt, const struct menu_item *items, int *selected)
{
	enum input_status status = INPUT_OK;
	struct key key;
	int size = 0;

	while (items[size].text)
		size++;

	assert(size > 0);

	while (status == INPUT_OK) {
		const struct menu_item *item = &items[*selected];
		char hotkey[] = { '[', (char) item->hotkey, ']', ' ', 0 };
		int i;

		update_status("%s (%d of %d) %s%s", prompt, *selected + 1, size,
			      item->hotkey ? hotkey : "", item->text);

		switch (get_input(COLS - 1, &key, FALSE)) {
		case KEY_RETURN:
		case KEY_ENTER:
		case '\n':
			status = INPUT_STOP;
			break;

		case KEY_LEFT:
		case KEY_UP:
			*selected = *selected - 1;
			if (*selected < 0)
				*selected = size - 1;
			break;

		case KEY_RIGHT:
		case KEY_DOWN:
			*selected = (*selected + 1) % size;
			break;

		case KEY_ESC:
			status = INPUT_CANCEL;
			break;

		default:
			for (i = 0; items[i].text; i++)
				if (items[i].hotkey == key.data.bytes[0]) {
					*selected = i;
					status = INPUT_STOP;
					break;
				}
		}
	}

	report_clear();

	return status != INPUT_CANCEL;
}
Example #2
0
rc_t report_destroy( p_report self )
{
    rc_t rc;
    if ( self != NULL )
    {
        rc = report_clear( self );
        free( self );
    }
    else
        rc = RC( rcExe, rcNoTarg, rcConstructing, rcSelf, rcNull );
    return rc;
}
Example #3
0
File: refs.c Project: bbolli/tig
static enum request
refs_request(struct view *view, enum request request, struct line *line)
{
	struct reference *reference = line->data;

	switch (request) {
	case REQ_REFRESH:
		load_refs(TRUE);
		refresh_view(view);
		return REQ_NONE;

	case REQ_ENTER:
	{
		const struct ref *ref = reference->ref;
		const char *all_references_argv[] = {
			GIT_MAIN_LOG_CUSTOM(encoding_arg, commit_order_arg(), "",
				refs_is_all(reference) ? "--all" : ref->name, "")
		};

		open_argv(view, &main_view, all_references_argv, NULL, OPEN_SPLIT);
		return REQ_NONE;
	}
	case REQ_JUMP_COMMIT:
	{
		int lineno;

		for (lineno = 0; lineno < view->lines; lineno++) {
			struct reference *reference = view->line[lineno].data;

			if (!strncasecmp(reference->ref->id, view->env->search, strlen(view->env->search))) {
				select_view_line(view, lineno);
				report_clear();
				return REQ_NONE;
			}
		}
	}
	default:
		return request;
	}
}
Example #4
0
static bool
view_driver(struct view *view, enum request request)
{
	int i;

	if (request == REQ_NONE)
		return true;

	if (request >= REQ_RUN_REQUESTS) {
		request = open_run_request(view, request);

		// exit quickly rather than going through view_request and back
		if (request == REQ_QUIT)
			return false;
	}

	request = view_request(view, request);
	if (request == REQ_NONE)
		return true;

	switch (request) {
	case REQ_MOVE_UP:
	case REQ_MOVE_DOWN:
	case REQ_MOVE_PAGE_UP:
	case REQ_MOVE_PAGE_DOWN:
	case REQ_MOVE_HALF_PAGE_UP:
	case REQ_MOVE_HALF_PAGE_DOWN:
	case REQ_MOVE_FIRST_LINE:
	case REQ_MOVE_LAST_LINE:
		move_view(view, request);
		break;

	case REQ_SCROLL_FIRST_COL:
	case REQ_SCROLL_LEFT:
	case REQ_SCROLL_RIGHT:
	case REQ_SCROLL_LINE_DOWN:
	case REQ_SCROLL_LINE_UP:
	case REQ_SCROLL_PAGE_DOWN:
	case REQ_SCROLL_PAGE_UP:
	case REQ_SCROLL_WHEEL_DOWN:
	case REQ_SCROLL_WHEEL_UP:
		scroll_view(view, request);
		break;

	case REQ_VIEW_GREP:
		open_grep_view(view);
		break;

	case REQ_VIEW_MAIN:
		open_main_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_DIFF:
		open_diff_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_LOG:
		open_log_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_TREE:
		open_tree_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_HELP:
		open_help_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_REFS:
		open_refs_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_BLAME:
		open_blame_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_BLOB:
		open_blob_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_STATUS:
		open_status_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_STAGE:
		open_stage_view(view, NULL, 0, OPEN_DEFAULT);
		break;
	case REQ_VIEW_PAGER:
		open_pager_view(view, OPEN_DEFAULT);
		break;
	case REQ_VIEW_STASH:
		open_stash_view(view, OPEN_DEFAULT);
		break;

	case REQ_NEXT:
	case REQ_PREVIOUS:
		if (view->parent) {
			int line;

			view = view->parent;
			line = view->pos.lineno;
			view_request(view, request);
			move_view(view, request);
			if (view_is_displayed(view))
				update_view_title(view);
			if (line != view->pos.lineno)
				view_request(view, REQ_ENTER);
		} else {
			move_view(view, request);
		}
		break;

	case REQ_VIEW_NEXT:
	{
		int nviews = displayed_views();
		int next_view = nviews ? (current_view + 1) % nviews : current_view;

		if (next_view == current_view) {
			report("Only one view is displayed");
			break;
		}

		current_view = next_view;
		/* Blur out the title of the previous view. */
		update_view_title(view);
		report_clear();
		break;
	}
	case REQ_REFRESH:
		report("Refreshing is not supported by the %s view", view->name);
		break;

	case REQ_PARENT:
		report("Moving to parent is not supported by the %s view", view->name);
		break;

	case REQ_BACK:
		report("Going back is not supported by the %s view", view->name);
		break;

	case REQ_MAXIMIZE:
		if (displayed_views() == 2)
			maximize_view(view, true);
		break;

	case REQ_OPTIONS:
		toggle_option(view);
		break;

	case REQ_SEARCH:
	case REQ_SEARCH_BACK:
		search_view(view, request);
		break;

	case REQ_FIND_NEXT:
	case REQ_FIND_PREV:
		find_next(view, request);
		break;

	case REQ_MOVE_NEXT_MERGE:
	case REQ_MOVE_PREV_MERGE:
		report("Moving between merge commits is not supported by the %s view", view->name);
		break;

	case REQ_STOP_LOADING:
		foreach_view(view, i) {
			if (view->pipe)
				report("Stopped loading the %s view", view->name),
			end_update(view, true);
		}
		break;

	case REQ_SHOW_VERSION:
		report("tig-%s (built %s)", TIG_VERSION, __DATE__);
		return true;

	case REQ_SCREEN_REDRAW:
		redraw_display(true);
		break;

	case REQ_EDIT:
		report("Nothing to edit");
		break;

	case REQ_ENTER:
		report("Nothing to enter");
		break;

	case REQ_VIEW_CLOSE:
		/* XXX: Mark closed views by letting view->prev point to the
		 * view itself. Parents to closed view should never be
		 * followed. */
		if (view->prev && view->prev != view) {
			maximize_view(view->prev, true);
			view->prev = view;
			watch_unregister(&view->watch);
			view->parent = NULL;
			break;
		}
		/* Fall-through */
	case REQ_QUIT:
		return false;

	default:
		report("Unknown key, press %s for help",
		       get_view_key(view, REQ_VIEW_HELP));
		return true;
	}

	return true;
}
Example #5
0
File: tig.c Project: lcd047/tig
static enum request
run_prompt_command(struct view *view, char *cmd)
{
	enum request request;

	if (cmd && string_isnumber(cmd)) {
		int lineno = view->pos.lineno + 1;

		if (parse_int(&lineno, cmd, 1, view->lines + 1) == SUCCESS) {
			select_view_line(view, lineno - 1);
			report_clear();
		} else {
			report("Unable to parse '%s' as a line number", cmd);
		}
	} else if (cmd && iscommit(cmd)) {
		string_ncopy(view->env->search, cmd, strlen(cmd));

		request = view_request(view, REQ_JUMP_COMMIT);
		if (request == REQ_JUMP_COMMIT) {
			report("Jumping to commits is not supported by the '%s' view", view->name);
		}

	} else if (cmd && strlen(cmd) == 1) {
		struct key_input input = { { cmd[0] } };

		return get_keybinding(&view->ops->keymap, &input);

	} else if (cmd && cmd[0] == '!') {
		struct view *next = VIEW(REQ_VIEW_PAGER);
		const char *argv[SIZEOF_ARG];
		int argc = 0;

		cmd++;
		/* When running random commands, initially show the
		 * command in the title. However, it maybe later be
		 * overwritten if a commit line is selected. */
		string_ncopy(next->ref, cmd, strlen(cmd));

		if (!argv_from_string(argv, &argc, cmd)) {
			report("Too many arguments");
		} else if (!argv_format(view->env, &next->argv, argv, FALSE, TRUE)) {
			report("Argument formatting failed");
		} else {
			next->dir = NULL;
			open_view(view, REQ_VIEW_PAGER, OPEN_PREPARED);
		}

	} else if (cmd) {
		request = get_request(cmd);
		if (request != REQ_UNKNOWN)
			return request;

		char *args = strchr(cmd, ' ');
		if (args) {
			*args++ = 0;
			if (set_option(cmd, args) == SUCCESS) {
				request = !view->unrefreshable ? REQ_REFRESH : REQ_SCREEN_REDRAW;
				if (!strcmp(cmd, "color"))
					init_colors();
			}
		}
		return request;
	}
	return REQ_NONE;
}
Example #6
0
File: tig.c Project: lcd047/tig
static int
view_driver(struct view *view, enum request request)
{
	int i;

	if (request == REQ_NONE)
		return TRUE;

	if (request >= REQ_RUN_REQUESTS) {
		request = open_run_request(view, request);

		// exit quickly rather than going through view_request and back
		if (request == REQ_QUIT)
			return FALSE;
	}

	request = view_request(view, request);
	if (request == REQ_NONE)
		return TRUE;

	switch (request) {
	case REQ_MOVE_UP:
	case REQ_MOVE_DOWN:
	case REQ_MOVE_PAGE_UP:
	case REQ_MOVE_PAGE_DOWN:
	case REQ_MOVE_FIRST_LINE:
	case REQ_MOVE_LAST_LINE:
		move_view(view, request);
		break;

	case REQ_SCROLL_FIRST_COL:
	case REQ_SCROLL_LEFT:
	case REQ_SCROLL_RIGHT:
	case REQ_SCROLL_LINE_DOWN:
	case REQ_SCROLL_LINE_UP:
	case REQ_SCROLL_PAGE_DOWN:
	case REQ_SCROLL_PAGE_UP:
	case REQ_SCROLL_WHEEL_DOWN:
	case REQ_SCROLL_WHEEL_UP:
		scroll_view(view, request);
		break;

	case REQ_VIEW_GREP:
		open_grep_view(view);
		break;

	case REQ_VIEW_MAIN:
	case REQ_VIEW_DIFF:
	case REQ_VIEW_LOG:
	case REQ_VIEW_TREE:
	case REQ_VIEW_HELP:
	case REQ_VIEW_BRANCH:
	case REQ_VIEW_BLAME:
	case REQ_VIEW_BLOB:
	case REQ_VIEW_STATUS:
	case REQ_VIEW_STAGE:
	case REQ_VIEW_PAGER:
	case REQ_VIEW_STASH:
		open_view(view, request, OPEN_DEFAULT);
		break;

	case REQ_NEXT:
	case REQ_PREVIOUS:
		if (view->parent) {
			int line;

			view = view->parent;
			line = view->pos.lineno;
			view_request(view, request);
			move_view(view, request);
			if (view_is_displayed(view))
				update_view_title(view);
			if (line != view->pos.lineno)
				view_request(view, REQ_ENTER);
		} else {
			move_view(view, request);
		}
		break;

	case REQ_VIEW_NEXT:
	{
		int nviews = displayed_views();
		int next_view = (current_view + 1) % nviews;

		if (next_view == current_view) {
			report("Only one view is displayed");
			break;
		}

		current_view = next_view;
		/* Blur out the title of the previous view. */
		update_view_title(view);
		report_clear();
		break;
	}
	case REQ_REFRESH:
		report("Refreshing is not supported by the %s view", view->name);
		break;

	case REQ_PARENT:
		report("Moving to parent is not supported by the the %s view", view->name);
		break;

	case REQ_BACK:
		report("Going back is not supported for by %s view", view->name);
		break;

	case REQ_MAXIMIZE:
		if (displayed_views() == 2)
			maximize_view(view, TRUE);
		break;

	case REQ_OPTIONS:
	case REQ_TOGGLE_LINENO:
	case REQ_TOGGLE_DATE:
	case REQ_TOGGLE_AUTHOR:
	case REQ_TOGGLE_FILENAME:
	case REQ_TOGGLE_GRAPHIC:
	case REQ_TOGGLE_REV_GRAPH:
	case REQ_TOGGLE_REFS:
	case REQ_TOGGLE_CHANGES:
	case REQ_TOGGLE_IGNORE_SPACE:
	case REQ_TOGGLE_ID:
	case REQ_TOGGLE_FILES:
	case REQ_TOGGLE_TITLE_OVERFLOW:
	case REQ_TOGGLE_FILE_SIZE:
	case REQ_TOGGLE_UNTRACKED_DIRS:
	case REQ_TOGGLE_VERTICAL_SPLIT:
		{
			char action[SIZEOF_STR] = "";
			enum view_flag flags = toggle_option(view, request, action);
	
			if (flags == VIEW_FLAG_RESET_DISPLAY) {
				resize_display();
				redraw_display(TRUE);
			} else {
				foreach_displayed_view(view, i) {
					if (view_has_flags(view, flags) && !view->unrefreshable)
						reload_view(view);
					else
						redraw_view(view);
				}
			}

			if (*action)
				report("%s", action);
		}
		break;

	case REQ_TOGGLE_SORT_FIELD:
	case REQ_TOGGLE_SORT_ORDER:
		report("Sorting is not yet supported for the %s view", view->name);
		break;

	case REQ_DIFF_CONTEXT_UP:
	case REQ_DIFF_CONTEXT_DOWN:
		report("Changing the diff context is not yet supported for the %s view", view->name);
		break;

	case REQ_SEARCH:
	case REQ_SEARCH_BACK:
		search_view(view, request);
		break;

	case REQ_FIND_NEXT:
	case REQ_FIND_PREV:
		find_next(view, request);
		break;

	case REQ_STOP_LOADING:
		foreach_view(view, i) {
			if (view->pipe)
				report("Stopped loading the %s view", view->name),
			end_update(view, TRUE);
		}
		break;

	case REQ_SHOW_VERSION:
		report("tig-%s (built %s)", TIG_VERSION, __DATE__);
		return TRUE;

	case REQ_SCREEN_REDRAW:
		redraw_display(TRUE);
		break;

	case REQ_EDIT:
		report("Nothing to edit");
		break;

	case REQ_ENTER:
		report("Nothing to enter");
		break;

	case REQ_VIEW_CLOSE:
		/* XXX: Mark closed views by letting view->prev point to the
		 * view itself. Parents to closed view should never be
		 * followed. */
		if (view->prev && view->prev != view) {
			maximize_view(view->prev, TRUE);
			view->prev = view;
			break;
		}
		/* Fall-through */
	case REQ_QUIT:
		return FALSE;

	default:
		report("Unknown key, press %s for help",
		       get_view_key(view, REQ_VIEW_HELP));
		return TRUE;
	}

	return TRUE;
}
Example #7
0
File: prompt.c Project: gonzus/tig
enum request
run_prompt_command(struct view *view, const char *argv[])
{
	enum request request;
	const char *cmd = argv[0];
	size_t cmdlen = cmd ? strlen(cmd) : 0;

	if (!cmd)
		return REQ_NONE;

	if (string_isnumber(cmd)) {
		int lineno = view->pos.lineno + 1;

		if (parse_int(&lineno, cmd, 0, view->lines + 1) == SUCCESS) {
			if (!lineno)
				lineno = 1;
			select_view_line(view, lineno - 1);
			report_clear();
		} else {
			report("Unable to parse '%s' as a line number", cmd);
		}
	} else if (iscommit(cmd)) {
		int lineno;

		if (!(view->ops->column_bits & view_column_bit(ID))) {
			report("Jumping to commits is not supported by the %s view", view->name);
			return REQ_NONE;
		}

		for (lineno = 0; lineno < view->lines; lineno++) {
			struct view_column_data column_data = {};
			struct line *line = &view->line[lineno];

			if (view->ops->get_column_data(view, line, &column_data) &&
			    column_data.id &&
			    !strncasecmp(column_data.id, cmd, cmdlen)) {
				string_ncopy(view->env->search, cmd, cmdlen);
				select_view_line(view, lineno);
				report_clear();
				return REQ_NONE;
			}
		}

		report("Unable to find commit '%s'", view->env->search);
		return REQ_NONE;

	} else if (cmdlen > 1 && (cmd[0] == '/' || cmd[0] == '?')) {
		char search[SIZEOF_STR];

		if (!argv_to_string(argv, search, sizeof(search), " ")) {
			report("Failed to copy search string");
			return REQ_NONE;
		}

		if (!strcmp(search + 1, view->env->search))
			return cmd[0] == '/' ? REQ_FIND_NEXT : REQ_FIND_PREV;

		string_ncopy(view->env->search, search + 1, strlen(search + 1));
		return cmd[0] == '/' ? REQ_SEARCH : REQ_SEARCH_BACK;

	} else if (cmdlen > 1 && cmd[0] == '!') {
		struct view *next = &pager_view;
		bool copied;

		/* Trim the leading '!'. */
		argv[0] = cmd + 1;
		copied = argv_format(view->env, &next->argv, argv, FALSE, TRUE);
		argv[0] = cmd;

		if (!copied) {
			report("Argument formatting failed");
		} else {
			/* When running random commands, initially show the
			 * command in the title. However, it maybe later be
			 * overwritten if a commit line is selected. */
			argv_to_string(next->argv, next->ref, sizeof(next->ref), " ");

			next->dir = NULL;
			open_pager_view(view, OPEN_PREPARED | OPEN_WITH_STDERR);
		}

	} else if (!strcmp(cmd, "save-display")) {
		const char *path = argv[1] ? argv[1] : "tig-display.txt";

		if (!save_display(path))
			report("Failed to save screen to %s", path);
		else
			report("Saved screen to %s", path);

	} else if (!strcmp(cmd, "exec")) {
		struct run_request req = { view->keymap, {}, argv + 1 };
		enum status_code code = parse_run_request_flags(&req.flags, argv + 1);

		if (code != SUCCESS) {
			report("Failed to execute command: %s", get_status_message(code));
		} else {
			return exec_run_request(view, &req);
		}

	} else if (!strcmp(cmd, "toggle")) {
		enum view_flag flags = VIEW_NO_FLAGS;
		enum status_code code = prompt_toggle(view, argv, &flags);
		const char *action = get_status_message(code);

		if (code != SUCCESS) {
			report("%s", action);
			return REQ_NONE;
		}

		prompt_update_display(flags);

		if (*action)
			report("%s", action);

	} else if (!strcmp(cmd, "script")) {
		if (is_script_executing()) {
			report("Scripts cannot be run from scripts");
		} else if (!open_script(argv[1])) {
			report("Failed to open %s", argv[1]);
		}

	} else {
		struct key key = {};
		enum status_code code;
		enum view_flag flags = VIEW_NO_FLAGS;

		/* Try :<key> */
		key.modifiers.multibytes = 1;
		string_ncopy(key.data.bytes, cmd, cmdlen);
		request = get_keybinding(view->keymap, &key, 1);
		if (request != REQ_NONE)
			return request;

		/* Try :<command> */
		request = get_request(cmd);
		if (request != REQ_UNKNOWN)
			return request;

		code = set_option(argv[0], argv_size(argv + 1), &argv[1]);
		if (code != SUCCESS) {
			report("%s", get_status_message(code));
			return REQ_NONE;
		}

		if (!strcmp(cmd, "set")) {
			struct prompt_toggle *toggle;

			toggle = find_prompt_toggle(option_toggles, ARRAY_SIZE(option_toggles),
						    "", argv[1], strlen(argv[1]));

			if (toggle)
				flags = toggle->flags;
		}

		if (flags) {
			prompt_update_display(flags);

		} else {
			request = view_can_refresh(view) ? REQ_REFRESH : REQ_SCREEN_REDRAW;
			if (!strcmp(cmd, "color"))
				init_colors();
			resize_display();
			redraw_display(TRUE);
		}

	}
	return REQ_NONE;
}
Example #8
0
File: prompt.c Project: gonzus/tig
static char *
prompt_input(const char *prompt, struct input *input)
{
	enum input_status status = INPUT_OK;
	unsigned char chars_length[SIZEOF_STR];
	struct key key;
	size_t promptlen = strlen(prompt);
	int pos = 0, chars = 0;

	input->buf[pos] = 0;

	while (status == INPUT_OK || status == INPUT_SKIP) {

		update_status("%s%.*s", prompt, pos, input->buf);

		if (get_input(pos + promptlen, &key, FALSE) == OK) {
			int len = strlen(key.data.bytes);

			if (pos + len >= sizeof(input->buf)) {
				report("Input string too long");
				return NULL;
			}

			string_ncopy_do(input->buf + pos, sizeof(input->buf) - pos, key.data.bytes, len);
			pos += len;
			chars_length[chars++] = len;
			status = input->handler(input, &key);
			if (status != INPUT_OK) {
				pos -= len;
				chars--;
			} else {
				int changed_pos = strlen(input->buf);

				if (changed_pos != pos) {
					pos = changed_pos;
					chars_length[chars - 1] = changed_pos - (pos - len);
				}
			}
		} else {
			status = input->handler(input, &key);
			if (status == INPUT_DELETE) {
				int len = chars_length[--chars];

				pos -= len;
				status = INPUT_OK;
			} else {
				int changed_pos = strlen(input->buf);

				if (changed_pos != pos) {
					pos = changed_pos;
					chars_length[chars++] = changed_pos - pos;
				}
			}
		}
		input->buf[pos] = 0;
	}

	report_clear();

	if (status == INPUT_CANCEL)
		return NULL;

	input->buf[pos++] = 0;

	return input->buf;
}
Example #9
0
File: prompt.c Project: bbolli/tig
enum request
run_prompt_command(struct view *view, const char *argv[])
{
	enum request request;
	const char *cmd = argv[0];
	size_t cmdlen = cmd ? strlen(cmd) : 0;

	if (!cmd)
		return REQ_NONE;

	if (string_isnumber(cmd)) {
		int lineno = view->pos.lineno + 1;

		if (parse_int(&lineno, cmd, 1, view->lines + 1) == SUCCESS) {
			select_view_line(view, lineno - 1);
			report_clear();
		} else {
			report("Unable to parse '%s' as a line number", cmd);
		}
	} else if (iscommit(cmd)) {
		string_ncopy(view->env->search, cmd, cmdlen);
		return REQ_JUMP_COMMIT;

	} else if (cmdlen > 1 && (cmd[0] == '/' || cmd[0] == '?')) {
		char search[SIZEOF_STR];

		if (!argv_to_string(argv, search, sizeof(search), " ")) {
			report("Failed to copy search string");
			return REQ_NONE;
		}

		if (!strcmp(search + 1, view->env->search))
			return cmd[0] == '/' ? REQ_FIND_NEXT : REQ_FIND_PREV;

		string_ncopy(view->env->search, search + 1, strlen(search + 1));
		return cmd[0] == '/' ? REQ_SEARCH : REQ_SEARCH_BACK;

	} else if (cmdlen > 1 && cmd[0] == '!') {
		struct view *next = &pager_view;
		bool copied;

		/* Trim the leading '!'. */
		argv[0] = cmd + 1;
		copied = argv_format(view->env, &next->argv, argv, FALSE, TRUE);
		argv[0] = cmd;

		if (!copied) {
			report("Argument formatting failed");
		} else {
			/* When running random commands, initially show the
			 * command in the title. However, it maybe later be
			 * overwritten if a commit line is selected. */
			argv_to_string(next->argv, next->ref, sizeof(next->ref), " ");

			next->dir = NULL;
			open_pager_view(view, OPEN_PREPARED | OPEN_WITH_STDERR);
		}

	} else if (!strcmp(cmd, "toggle")) {
		char action[SIZEOF_STR] = "";
		enum view_flag flags = prompt_toggle(view, argv, action);
		int i;

		if (flags & VIEW_RESET_DISPLAY) {
			resize_display();
			redraw_display(TRUE);
		}

		foreach_displayed_view(view, i) {
			if (view_has_flags(view, flags) && !view->unrefreshable)
				reload_view(view);
			else
				redraw_view(view);
		}

		if (*action)
			report("%s", action);

	} else {
Example #10
0
File: prompt.c Project: bbolli/tig
static char *
prompt_input(const char *prompt, input_handler handler, void *data)
{
	enum input_status status = INPUT_OK;
	static char buf[SIZEOF_STR];
	unsigned char chars_length[SIZEOF_STR];
	struct key_input input;
	size_t promptlen = strlen(prompt);
	int pos = 0, chars = 0;

	buf[pos] = 0;

	while (status == INPUT_OK || status == INPUT_SKIP) {
		update_status("%s%.*s", prompt, pos, buf);

		switch (get_input(pos + promptlen, &input, FALSE)) {
		case KEY_RETURN:
		case KEY_ENTER:
		case '\n':
			status = pos ? INPUT_STOP : INPUT_CANCEL;
			break;

		case KEY_BACKSPACE:
			if (pos > 0) {
				int len = chars_length[--chars];

				pos -= len;
				buf[pos] = 0;
			} else {
				status = INPUT_CANCEL;
			}
			break;

		case KEY_ESC:
			status = INPUT_CANCEL;
			break;

		default:
			if (pos >= sizeof(buf)) {
				report("Input string too long");
				return NULL;
			}

			status = handler(data, buf, &input);
			if (status == INPUT_OK) {
				int len = strlen(input.data.bytes);

				string_ncopy_do(buf + pos, sizeof(buf) - pos, input.data.bytes, len);
				pos += len;
				chars_length[chars++] = len;
			}
		}
	}

	report_clear();

	if (status == INPUT_CANCEL)
		return NULL;

	buf[pos++] = 0;

	return buf;
}