예제 #1
0
파일: display.c 프로젝트: JakeSc/tig
bool
open_external_viewer(const char *argv[], const char *dir, bool confirm, bool refresh, const char *notice)
{
    bool ok;

    def_prog_mode();           /* save current tty modes */
    endwin();                  /* restore original tty modes */
    ok = io_run_fg(argv, dir);
    if (confirm || !ok) {
        if (!ok && *notice)
            fprintf(stderr, "%s", notice);
        fprintf(stderr, "Press Enter to continue");
        getc(opt_tty);
    }
    reset_prog_mode();
    if (watch_update(WATCH_EVENT_AFTER_EXTERNAL) && refresh) {
        struct view *view;
        int i;

        foreach_displayed_view (view, i) {
            if (watch_dirty(&view->watch))
                refresh_view(view);
        }
    }
    redraw_display(TRUE);
    return ok;
}
예제 #2
0
파일: xxx.c 프로젝트: lexuszhi1990/hen
static int view_driver(struct view *view, int key)
{
	switch (key) 
    {
	case REQ_MOVE_DOWN:
	case REQ_MOVE_UP:
		if (view)
			navigate_view(view, key);
		break;
	case REQ_VIEW_CLOSE:
        quit(0);
        break;
    case REQ_OPEN_VIM:
        report("Shelling out...");
        def_prog_mode();           /* save current tty modes */
        endwin();                  /* end curses mode temporarily */
        system(vim_cmd);           /* run shell */
        report("returned");        /* prepare return message */
        reset_prog_mode();         /* return to the previous tty modes */
        break;
    case REQ_VIEW_MAIN: 
        open_view(view);
        break;
    case REQ_SCREEN_RESIZE:
        resize_display();
        redraw_display(TRUE);
        break;

	default:
		return TRUE;
	}

	return TRUE;
}
예제 #3
0
파일: display.c 프로젝트: noscripter/tig
bool
open_external_viewer(const char *argv[], const char *dir, bool silent, bool confirm, bool refresh, const char *notice)
{
	bool ok;

	if (silent) {
		ok = io_run_bg(argv, dir);

	} else {
		endwin();                  /* restore original tty modes */
		ok = io_run_fg(argv, dir);
		if (confirm || !ok) {
			if (!ok && *notice)
				fprintf(stderr, "%s", notice);
			if (!is_script_executing()) {
				fprintf(stderr, "Press Enter to continue");
				getc(opt_tty);
			}
		}
	}

	if (watch_update(WATCH_EVENT_AFTER_COMMAND) && refresh) {
		struct view *view;
		int i;

		foreach_displayed_view (view, i) {
			if (watch_dirty(&view->watch))
				refresh_view(view);
		}
	}
	redraw_display(true);
	return ok;
}
예제 #4
0
파일: display.c 프로젝트: phschoen/tig
bool
open_external_viewer(const char *argv[], const char *dir, bool silent, bool confirm, bool echo, bool refresh, const char *notice)
{
	bool ok;

	if (echo) {
		char buf[SIZEOF_STR] = "";

		io_run_buf(argv, buf, sizeof(buf), dir, false);
		if (*buf) {
			report("%s", buf);
			return true;
		} else {
			report("No output");
			return false;
		}
	} else if (silent || is_script_executing()) {
		ok = io_run_bg(argv, dir);

	} else {
		clear();
		refresh();
		endwin();                  /* restore original tty modes */
		ok = io_run_fg(argv, dir);
		if (confirm || !ok) {
			if (!ok && *notice)
				fprintf(stderr, "%s", notice);
			fprintf(stderr, "Press Enter to continue");
			getc(opt_tty);
			fseek(opt_tty, 0, SEEK_END);
		}
		set_terminal_modes();
	}

	if (watch_update(WATCH_EVENT_AFTER_COMMAND) && refresh) {
		struct view *view;
		int i;

		foreach_displayed_view (view, i) {
			if (watch_dirty(&view->watch))
				refresh_view(view);
		}
	}
	redraw_display(true);
	return ok;
}
예제 #5
0
파일: display.c 프로젝트: zhez/tig
bool
open_external_viewer(const char *argv[], const char *dir, bool confirm, const char *notice)
{
	bool ok;

	def_prog_mode();           /* save current tty modes */
	endwin();                  /* restore original tty modes */
	ok = io_run_fg(argv, dir);
	if (confirm) {
		if (!ok && *notice)
			fprintf(stderr, "%s", notice);
		fprintf(stderr, "Press Enter to continue");
		getc(opt_tty);
	}
	reset_prog_mode();
	redraw_display(TRUE);
	return ok;
}
예제 #6
0
파일: prompt.c 프로젝트: gonzus/tig
static void
prompt_update_display(enum view_flag flags)
{
	struct view *view;
	int i;

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

	foreach_displayed_view(view, i) {
		if (view_has_flags(view, flags) && view_can_refresh(view))
			reload_view(view);
		else
			redraw_view(view);
	}
}
예제 #7
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;
}
예제 #8
0
파일: display.c 프로젝트: zhez/tig
int
get_input(int prompt_position)
{
	struct view *view;
	int i, key, cursor_y, cursor_x;

	if (prompt_position)
		input_mode = TRUE;

	while (TRUE) {
		bool loading = FALSE;

		foreach_view (view, i) {
			update_view(view);
			if (view_is_displayed(view) && view->has_scrolled &&
			    use_scroll_redrawwin)
				redrawwin(view->win);
			view->has_scrolled = FALSE;
			if (view->pipe)
				loading = TRUE;
		}

		/* Update the cursor position. */
		if (prompt_position) {
			getbegyx(status_win, cursor_y, cursor_x);
			cursor_x = prompt_position;
		} else {
			view = display[current_view];
			getbegyx(view->win, cursor_y, cursor_x);
			cursor_x = view->width - 1;
			cursor_y += view->pos.lineno - view->pos.offset;
		}
		setsyx(cursor_y, cursor_x);

		/* Refresh, accept single keystroke of input */
		doupdate();
		nodelay(status_win, loading);
		key = wgetch(status_win);

		/* wgetch() with nodelay() enabled returns ERR when
		 * there's no input. */
		if (key == ERR) {

		} else if (key == KEY_RESIZE) {
			int height, width;

			getmaxyx(stdscr, height, width);

			wresize(status_win, 1, width);
			mvwin(status_win, height - 1, 0);
			wnoutrefresh(status_win);
			resize_display();
			redraw_display(TRUE);

		} else {
			input_mode = FALSE;
			if (key == erasechar())
				key = KEY_BACKSPACE;
			return key;
		}
	}
예제 #9
0
파일: clc.c 프로젝트: elanthis/clc
int main (int argc, char** argv) {
	const char* default_port = "23";
	struct sigaction sa;
	int i;

	/* process command line args */
	for (i = 1; i < argc; ++i) {
		/* help */
		if (strcmp(argv[i], "-h") == 0) {
			printf(
				"CLC %s by Sean Middleditch <*****@*****.**>\n"
				"This program has been released into the PUBLIC DOMAIN.\n\n"
				"Usage:\n"
				"  clc [-h] <host> [<port>]\n\n"
				"Options:\n"
				"  -h   display help\n", CLC_VERSION
			);
			return 0;
		}

		/* other unknown option */
		if (argv[i][0] == '-') {
			fprintf(stderr, "Unknown option %s.\nUse -h to see available options.\n", argv[i]);
			exit(1);
		}

		/* if host is unset, this is the host */
		if (host == NULL) {
			host = argv[i];
		/* otherwise, it's a port */
		} else {
			port = argv[i];
		}
	}

	/* ensure we have a host */
	if (host == NULL) {
		fprintf(stderr, "No host was given.\nUse -h to see command format.\n");
		exit(1);
	}

	/* set default port if none was given */
	if (port == NULL)
		port = default_port;

	/* cleanup on any failure */
	atexit(cleanup);

	/* set terminal defaults */
	memset(&terminal, 0, sizeof(struct TERMINAL));
	terminal.state = TERM_ASCII;
	terminal.flags = TERM_FLAGS_DEFAULT;
	terminal.color = TERM_COLOR_DEFAULT;

	/* initial telnet handler */
	telnet = telnet_init(telnet_telopts, telnet_event, 0, 0);

	/* connect to server */
	sock = do_connect(host, port);
	if (sock == -1) {
		fprintf(stderr, "Failed to connect to %s:%s\n", host, port);
		exit(1);
	}
	printf("Connected to %s:%s\n", host, port);

	/* set initial banner */
	snprintf(banner, sizeof(banner), "CLC - %s:%s (connected)", host, port);

	/* configure curses */
	initscr();
	start_color();
	nonl();
	cbreak();
	noecho();

	win_main = newwin(LINES-2, COLS, 0, 0);
	win_banner = newwin(1, COLS, LINES-2, 0);
	win_input = newwin(1, COLS, LINES-1, 0);

	idlok(win_main, TRUE);
	scrollok(win_main, TRUE);

	nodelay(win_input, FALSE);
	keypad(win_input, TRUE);

	use_default_colors();

	init_pair(COLOR_RED, COLOR_RED, -1);
	init_pair(COLOR_BLUE, COLOR_BLUE, -1);
	init_pair(COLOR_GREEN, COLOR_GREEN, -1);
	init_pair(COLOR_CYAN, COLOR_CYAN, -1);
	init_pair(COLOR_MAGENTA, COLOR_MAGENTA, -1);
	init_pair(COLOR_YELLOW, COLOR_YELLOW, -1);
	init_pair(COLOR_WHITE, COLOR_WHITE, -1);

	init_pair(TERM_COLOR_DEFAULT, -1, -1);
	wbkgd(win_main, COLOR_PAIR(TERM_COLOR_DEFAULT));
	wclear(win_main);
	init_pair(10, COLOR_WHITE, COLOR_BLUE);
	wbkgd(win_banner, COLOR_PAIR(10));
	wclear(win_banner);
	init_pair(11, -1, -1);
	wbkgd(win_input, COLOR_PAIR(11));
	wclear(win_input);

	redraw_display();

	/* set signal handlers */
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = handle_signal;
	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGWINCH, &sa, NULL);

	/* initial edit buffer */
	memset(&editbuf, 0, sizeof(struct EDITBUF));

	/* setup poll info */
	struct pollfd fds[2];
	fds[0].fd = 1;
	fds[0].events = POLLIN;
	fds[1].fd = sock;
	fds[1].events = POLLIN;

	/* main loop */
	while (running) {
		/* poll sockets */
		if (poll(fds, 2, -1) == -1) {
			if (errno != EAGAIN && errno != EINTR) {
				endwin();
				fprintf(stderr, "poll() failed: %s\n", strerror(errno));
				return 1;
			}
		}

		/* resize event? */
		if (have_sigwinch) {
			have_sigwinch = 0;
			redraw_display();
		}

		/* escape? */
		if (have_sigint) {
			exit(0);
		}

		/* input? */
		if (fds[0].revents & POLLIN) {
			int key = wgetch(win_input);
			if (key != ERR)
				on_key(key);
		}

		/* process input data */
		if (fds[1].revents & POLLIN) {
			char buffer[2048];
			int ret = recv(sock, buffer, sizeof(buffer), 0);
			if (ret == -1) {
				if (errno != EAGAIN && errno != EINTR) {
					endwin();
					fprintf(stderr, "recv() failed: %s\n", strerror(errno));
					return 1;
				}
			} else if (ret == 0) {
				running = 0;
			} else {
				recv_bytes += ret;
				telnet_recv(telnet, buffer, ret);
			}
		}

		/* flush output */
		paint_banner();
		wnoutrefresh(win_main);
		wnoutrefresh(win_banner);
		wnoutrefresh(win_input);
		doupdate();
	}

	/* final display, pause */
	sock = -1;
	autobanner = 1;
	paint_banner();
	wnoutrefresh(win_banner);
	doupdate();
	wgetch(win_input);

	/* clean up */
	endwin();
	printf("Disconnected.\n");

	/* free memory (so Valgrind leak detection is useful) */
	telnet_free(telnet);

	return 0;
}
예제 #10
0
파일: tig.c 프로젝트: 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;
}
예제 #11
0
파일: prompt.c 프로젝트: 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;
}
예제 #12
0
파일: display.c 프로젝트: Yair-Karmy/tig
int
get_input(int prompt_position, struct key_input *input, bool modifiers)
{
	struct view *view;
	int i, key, cursor_y, cursor_x;

	if (prompt_position)
		input_mode = TRUE;

	memset(input, 0, sizeof(*input));

	while (TRUE) {
		bool loading = FALSE;

		foreach_view (view, i) {
			update_view(view);
			if (view_is_displayed(view) && view->has_scrolled &&
			    use_scroll_redrawwin)
				redrawwin(view->win);
			view->has_scrolled = FALSE;
			if (view->pipe)
				loading = TRUE;
		}

		/* Update the cursor position. */
		if (prompt_position) {
			getbegyx(status_win, cursor_y, cursor_x);
			cursor_x = prompt_position;
		} else {
			view = display[current_view];
			getbegyx(view->win, cursor_y, cursor_x);
			cursor_x = view->width - 1;
			cursor_y += view->pos.lineno - view->pos.offset;
		}
		setsyx(cursor_y, cursor_x);

		/* Refresh, accept single keystroke of input */
		doupdate();
		nodelay(status_win, loading);
		key = wgetch(status_win);

		/* wgetch() with nodelay() enabled returns ERR when
		 * there's no input. */
		if (key == ERR) {

		} else if (key == KEY_ESC && modifiers) {
			input->modifiers.escape = 1;

		} else if (key == KEY_RESIZE) {
			int height, width;

			getmaxyx(stdscr, height, width);

			wresize(status_win, 1, width);
			mvwin(status_win, height - 1, 0);
			wnoutrefresh(status_win);
			resize_display();
			redraw_display(TRUE);

		} else {
			int pos, key_length;

			input_mode = FALSE;
			if (key == erasechar())
				key = KEY_BACKSPACE;

			/*
			 * Ctrl-<key> values are represented using a 0x1F
			 * bitmask on the key value. To 'unmap' we assume that:
			 *
			 * - Ctrl-Z is handled by Ncurses.
			 * - Ctrl-m is the same as Return/Enter.
			 * - Ctrl-i is the same as Tab.
			 *
			 * For all other key values in the range the Ctrl flag
			 * is set and the key value is updated to the proper
			 * ASCII value.
			 */
			if (KEY_CTL('a') <= key && key <= KEY_CTL('x') && key != KEY_RETURN && key != KEY_TAB) {
				input->modifiers.control = 1;
				key = key | 0x40;
			}

			if ((key >= KEY_MIN && key < KEY_MAX) || key < 0x1F) { // || key == ' ') {
				input->data.key = key;
				return input->data.key;
			}

			input->modifiers.multibytes = 1;
			input->data.bytes[0] = key;

			key_length = utf8_char_length(input->data.bytes);
			for (pos = 1; pos < key_length && pos < sizeof(input->data.bytes) - 1; pos++) {
				input->data.bytes[pos] = wgetch(status_win);
			}

			return OK;
		}
	}
예제 #13
0
파일: prompt.c 프로젝트: 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 {
예제 #14
0
파일: tig.c 프로젝트: fourks/tig
static enum request
run_prompt_command(struct view *view, char *cmd)
{
	enum request request;

	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, 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 (strlen(cmd) == 1) {
		struct key_input input = { { cmd[0] } };

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

	} else if (cmd[0] == '/' || cmd[0] == '?') {
		const char *search = cmd + 1;

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

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

	} else if (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 {
		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();
				resize_display();
				redraw_display(TRUE);
			}
		}
		return request;
	}
	return REQ_NONE;
}