Exemplo n.º 1
0
/* Navigates the view to given mark if it's valid.  Returns new value for
 * save_msg flag. */
static int
navigate_to_mark(FileView *view, char m)
{
	const mark_t *const mark = get_mark_by_name(m);

	if(is_mark_valid(mark))
	{
		navigate_to_file(view, mark->directory, mark->file);
		return 0;
	}

	if(!char_is_one_of(valid_marks, m))
	{
		status_bar_message("Invalid mark name");
	}
	else if(is_empty(mark))
	{
		status_bar_message("Mark is not set");
	}
	else
	{
		status_bar_message("Mark is invalid");
	}

	fview_cursor_redraw(view);
	return 1;
}
Exemplo n.º 2
0
Arquivo: info.c Projeto: cfillion/vifm
/* Writes marks to vifminfo file.  marks is a list of length nmarks marks read
 * from vifminfo. */
static void
write_marks(FILE *const fp, const char non_conflicting_marks[],
		char *marks[], const int timestamps[], int nmarks)
{
	int active_marks[NUM_MARKS];
	const int len = init_active_marks(valid_marks, active_marks);
	int i;

	fputs("\n# Marks:\n", fp);
	for(i = 0; i < len; ++i)
	{
		const int index = active_marks[i];
		const char m = index2mark(index);
		if(!is_spec_mark(index) && char_is_one_of(non_conflicting_marks, m))
		{
			const mark_t *const mark = get_mark(index);

			fprintf(fp, "%c%c\n", LINE_TYPE_MARK, m);
			fprintf(fp, "\t%s\n", mark->directory);
			fprintf(fp, "\t%s\n", mark->file);
			fprintf(fp, "%lld\n", (long long)mark->timestamp);
		}
	}
	for(i = 0; i < nmarks; i += 3)
	{
		fprintf(fp, "%c%c\n", LINE_TYPE_MARK, marks[i][0]);
		fprintf(fp, "\t%s\n", marks[i + 1]);
		fprintf(fp, "\t%s\n", marks[i + 2]);
		fprintf(fp, "%d\n", timestamps[i/3]);
	}
}
Exemplo n.º 3
0
size_t
get_mods_len(const char *str)
{
	static const char FIXED_LENGTH_FILEMODS[] = "p~.htre";
	size_t result = 0;
	if(str[0] != ':')
	{
	}
	else if(char_is_one_of(FIXED_LENGTH_FILEMODS, str[1]))
	{
		result = 2;
	}
#ifdef _WIN32
	else if(str[1] == 'u')
	{
		result = 2;
	}
#endif
	else if(starts_with(str, ":s") || starts_with(str, ":gs"))
	{
		const char *p;
		result = (str[1] == 'g') ? 3 : 2;
		p = find_nth_chr(str, str[result], 3);
		if(p != NULL)
			result = (p - str) + 1;
		else
			result = strlen(str);
	}
	return result;
}
Exemplo n.º 4
0
/* Navigates the view to given mark if it's valid.  Returns new value for
 * save_msg flag. */
static int
navigate_to_bookmark(FileView *view, char mark)
{
	const bookmark_t *const bmark = get_bookmark(mark);

	if(is_bmark_valid(bmark))
	{
		if(change_directory(view, bmark->directory) >= 0)
		{
			load_dir_list(view, 1);
			(void)ensure_file_is_selected(view, bmark->file);
		}
	}
	else
	{
		if(!char_is_one_of(valid_bookmarks, mark))
			status_bar_message("Invalid mark name");
		else if(is_bmark_empty(bmark))
			status_bar_message("Mark is not set");
		else
			status_bar_message("Mark is invalid");

		move_to_list_pos(view, view->list_pos);
		return 1;
	}
	return 0;
}
Exemplo n.º 5
0
void
set_spec_bookmark(const char mark, const char directory[], const char file[])
{
	if(char_is_one_of(spec_bookmarks, mark))
	{
		set_mark(mark, directory, file, time(NULL), 1);
	}
}
Exemplo n.º 6
0
int
init_active_bookmarks(const char marks[], int active_bookmarks[])
{
	int i, x;

	i = 0;
	for(x = 0; x < NUM_BOOKMARKS; ++x)
	{
		if(!char_is_one_of(marks, index2mark(x)))
			continue;
		if(is_bmark_empty(&bookmarks[x]))
			continue;
		active_bookmarks[i++] = x;
	}
	return i;
}
Exemplo n.º 7
0
int
init_active_marks(const char marks[], int active_marks[])
{
	int i, x;

	i = 0;
	for(x = 0; x < NUM_MARKS; ++x)
	{
		if(!char_is_one_of(marks, index2mark(x)))
			continue;
		if(is_empty(get_mark(x)))
			continue;
		active_marks[i++] = x;
	}
	return i;
}
Exemplo n.º 8
0
Arquivo: filter.c Projeto: jubalh/vifm
/* Escapes the string for the purpose of using it in filter.  Returns new
 * string, caller should free it. */
static char *
escape_name_for_filter(const char string[])
{
	static const char *NEED_ESCAPING = "\\[](){}+*^$.?|";
	size_t len;
	char *ret, *dup;

	len = strlen(string);

	dup = ret = malloc(len*2 + 2 + 1);

	while(*string != '\0')
	{
		if(char_is_one_of(NEED_ESCAPING, *string))
		{
			*dup++ = '\\';
		}
		*dup++ = *string++;
	}
	*dup = '\0';
	return ret;
}
Exemplo n.º 9
0
/* Expands preview parameter macros specified by the key argument.  If key is
 * unknown, skips the macro.  Sets *well_formed to non-zero for valid value of
 * the key.  Reallocates the expanded string and returns result (possibly
 * NULL). */
static char *
expand_preview(char expanded[], int key, int *well_formed)
{
	FileView *view;
	char num_str[32];
	int h, w, x, y;
	int param;
	const int with_margin = (curr_stats.clear_preview == 0) && cfg.extra_padding;

	if(!char_is_one_of("hwxy", key))
	{
		*well_formed = 0;
		return expanded;
	}

	*well_formed = 1;

	view = get_preview_view(curr_view);

	getbegyx(view->win, y, x);
	getmaxyx(view->win, h, w);

	switch(key)
	{
		case 'h': param = h - 2*with_margin; break;
		case 'w': param = w - 2*with_margin; break;
		case 'x': param = x + 1*with_margin; break;
		case 'y': param = y + 1*with_margin; break;

		default:
			assert(0 && "Unhandled preview property type");
			param = 0;
			break;
	}

	snprintf(num_str, sizeof(num_str), "%d", param);

	return append_to_expanded(expanded, num_str);
}
Exemplo n.º 10
0
/* args and flags parameters can equal NULL. The string returned needs to be
 * freed in the calling function. After executing flags is one of MF_*
 * values. */
static char *
expand_macros_i(const char command[], const char args[], MacroFlags *flags,
		int for_shell, macro_filter_func filter)
{
	/* TODO: refactor this function expand_macros() */
	/* FIXME: repetitive len = strlen(expanded) could be optimized. */

	static const char MACROS_WITH_QUOTING[] = "cCfFbdDr";

	size_t cmd_len;
	char *expanded;
	size_t x;
	int len = 0;

	set_flags(flags, MF_NONE);

	cmd_len = strlen(command);

	for(x = 0; x < cmd_len; x++)
		if(command[x] == '%')
			break;

	if(x >= cmd_len)
	{
		return strdup(command);
	}

	expanded = calloc(cmd_len + 1, sizeof(char));
	strncat(expanded, command, x);
	x++;
	len = strlen(expanded);

	do
	{
		size_t y;
		char *p;

		int quotes = 0;
		if(command[x] == '"' && char_is_one_of(MACROS_WITH_QUOTING, command[x + 1]))
		{
			quotes = 1;
			++x;
		}
		switch(filter(&quotes, command[x],
					command[x] == '\0' ? '\0' : command[x + 1]))
		{
			case 'a': /* user arguments */
				if(args != NULL)
				{
					expanded = append_to_expanded(expanded, args);
					len = strlen(expanded);
				}
				break;
			case 'b': /* selected files of both dirs */
				expanded = append_selected_files(curr_view, expanded, 0, quotes,
						command + x + 1, for_shell);
				expanded = append_to_expanded(expanded, " ");
				expanded = append_selected_files(other_view, expanded, 0, quotes,
						command + x + 1, for_shell);
				len = strlen(expanded);
				break;
			case 'c': /* current dir file under the cursor */
				expanded = append_selected_files(curr_view, expanded, 1, quotes,
						command + x + 1, for_shell);
				len = strlen(expanded);
				break;
			case 'C': /* other dir file under the cursor */
				expanded = append_selected_files(other_view, expanded, 1, quotes,
						command + x + 1, for_shell);
				len = strlen(expanded);
				break;
			case 'f': /* current dir selected files */
				expanded = append_selected_files(curr_view, expanded, 0, quotes,
						command + x + 1, for_shell);
				len = strlen(expanded);
				break;
			case 'F': /* other dir selected files */
				expanded = append_selected_files(other_view, expanded, 0, quotes,
						command + x + 1, for_shell);
				len = strlen(expanded);
				break;
			case 'd': /* current directory */
				expanded = expand_directory_path(curr_view, expanded, quotes,
						command + x + 1, for_shell);
				len = strlen(expanded);
				break;
			case 'D': /* Directory of the other view. */
				expanded = expand_directory_path(other_view, expanded, quotes,
						command + x + 1, for_shell);
				len = strlen(expanded);
				break;
			case 'n': /* Forbid using of terminal multiplexer, even if active. */
				set_flags(flags, MF_NO_TERM_MUX);
				break;
			case 'm': /* Use menu. */
				set_flags(flags, MF_MENU_OUTPUT);
				break;
			case 'M': /* Use menu like with :locate and :find. */
				set_flags(flags, MF_MENU_NAV_OUTPUT);
				break;
			case 'S': /* Show command output in the status bar */
				set_flags(flags, MF_STATUSBAR_OUTPUT);
				break;
			case 's': /* Split in new screen region and execute command there. */
				set_flags(flags, MF_SPLIT);
				break;
			case 'u': /* Parse output as list of files and compose custom view. */
				set_flags(flags, MF_CUSTOMVIEW_OUTPUT);
				break;
			case 'U': /* Parse output as list of files and compose unsorted view. */
				set_flags(flags, MF_VERYCUSTOMVIEW_OUTPUT);
				break;
			case 'i': /* Ignore output. */
				set_flags(flags, MF_IGNORE);
				break;
			case 'r': /* Registers' content. */
				{
					int well_formed;
					expanded = expand_register(flist_get_dir(curr_view), expanded, quotes,
							command + x + 2, command[x + 1], &well_formed, for_shell);
					len = strlen(expanded);
					if(well_formed)
					{
						x++;
					}
				}
				break;
			case 'p': /* Preview pane properties. */
				{
					int well_formed;
					const char key = command[x + 1];
					if(key == 'c')
					{
						return expanded;
					}

					expanded = expand_preview(expanded, key, &well_formed);
					len = strlen(expanded);
					if(well_formed)
					{
						++x;
					}
				}
				break;
			case '%':
				expanded = append_to_expanded(expanded, "%");
				len = strlen(expanded);
				break;

			case '\0':
				if(char_is_one_of("pr", command[x]) && command[x + 1] != '\0')
				{
					++x;
				}
				break;
		}
		if(command[x] != '\0')
			x++;

		while(x < cmd_len)
		{
			size_t len = get_mods_len(command + x);
			if(len == 0)
			{
				break;
			}
			x += len;
		}

		y = x;

		while(x < cmd_len)
		{
			if(command[x] == '%')
				break;
			if(command[x] != '\0')
				x++;
		}

		assert(x >= y);
		assert(y <= cmd_len);

		p = realloc(expanded, len + (x - y) + 1);
		if(p == NULL)
		{
			free(expanded);
			return NULL;
		}
		expanded = p;
		strncat(expanded, command + y, x - y);
		len = strlen(expanded);

		++x;
	}
	while(x < cmd_len);

	return expanded;
}
Exemplo n.º 11
0
/* Reads contents of the filename file as an info file and updates it with the
 * state of current instance. */
static void
update_info_file(const char filename[])
{
	/* TODO: refactor this function update_info_file() */

	FILE *fp;
	char ** list;
	int nlist = -1;
	char **ft = NULL, **fx = NULL , **fv = NULL, **cmds = NULL, **marks = NULL;
	char **lh = NULL, **rh = NULL, **cmdh = NULL, **srch = NULL, **regs = NULL;
	int *lhp = NULL, *rhp = NULL;
	size_t nlhp = 0, nrhp = 0;
	char **prompt = NULL, **trash = NULL;
	int nft = 0, nfx = 0, nfv = 0, ncmds = 0, nmarks = 0, nlh = 0, nrh = 0;
	int ncmdh = 0, nsrch = 0, nregs = 0, nprompt = 0, ntrash = 0;
	int i;

	if(cfg.vifm_info == 0)
		return;

	list = list_udf();
	while(list[++nlist] != NULL);

	if((fp = fopen(filename, "r")) != NULL)
	{
		char *line = NULL, *line2 = NULL, *line3 = NULL;
		while((line = read_vifminfo_line(fp, line)) != NULL)
		{
			const char type = line[0];
			const char *const line_val = line + 1;

			if(type == LINE_TYPE_COMMENT || type == '\0')
				continue;

			if(type == LINE_TYPE_FILETYPE)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					assoc_record_t prog;
					if(get_default_program_for_file(line_val, &prog))
					{
						free_assoc_record(&prog);
						continue;
					}
					nft = add_to_string_array(&ft, nft, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_XFILETYPE)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					assoc_record_t x_prog;
					if(get_default_program_for_file(line_val, &x_prog))
					{
						assoc_record_t console_prog;
						if(get_default_program_for_file(line_val, &console_prog))
						{
							if(strcmp(x_prog.command, console_prog.command) == 0)
							{
								free_assoc_record(&console_prog);
								free_assoc_record(&x_prog);
								continue;
							}
						}
						free_assoc_record(&x_prog);
					}
					nfx = add_to_string_array(&fx, nfx, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_FILEVIEWER)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if(get_viewer_for_file(line_val) != NULL)
						continue;
					nfv = add_to_string_array(&fv, nfv, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_COMMAND)
			{
				if(line_val[0] == '\0')
					continue;
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					const char *p = line_val;
					for(i = 0; i < nlist; i += 2)
					{
						int cmp = strcmp(list[i], p);
						if(cmp < 0)
							continue;
						if(cmp == 0)
							p = NULL;
						break;
					}
					if(p == NULL)
						continue;
					ncmds = add_to_string_array(&cmds, ncmds, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_LWIN_HIST)
			{
				if(line_val[0] == '\0')
					continue;
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					int pos;

					if(lwin.history_pos + nlh/2 == cfg.history_len - 1)
						continue;
					if(is_in_view_history(&lwin, line_val))
						continue;

					pos = read_possible_possible_pos(fp);
					nlh = add_to_string_array(&lh, nlh, 2, line_val, line2);
					if(nlh/2 > nlhp)
					{
						nlhp = add_to_int_array(&lhp, nlhp, pos);
						nlhp = MIN(nlh/2, nlhp);
					}
				}
			}
			else if(type == LINE_TYPE_RWIN_HIST)
			{
				if(line_val[0] == '\0')
					continue;
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					int pos;

					if(rwin.history_pos + nrh/2 == cfg.history_len - 1)
						continue;
					if(is_in_view_history(&rwin, line_val))
						continue;

					pos = read_possible_possible_pos(fp);
					nrh = add_to_string_array(&rh, nrh, 2, line_val, line2);
					if(nrh/2 > nrhp)
					{
						nrhp = add_to_int_array(&rhp, nrhp, pos);
						nrhp = MIN(nrh/2, nrhp);
					}
				}
			}
			else if(type == LINE_TYPE_BOOKMARK)
			{
				const char mark = line_val[0];
				if(line_val[1] != '\0')
				{
					LOG_ERROR_MSG("Expected end of line, but got: %s", line_val + 1);
				}
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if((line3 = read_vifminfo_line(fp, line3)) != NULL)
					{
						const char mark_str[] = { mark, '\0' };
						if(!char_is_one_of(valid_bookmarks, mark))
							continue;
						if(!is_bookmark_empty(mark2index(mark)))
							continue;
						nmarks = add_to_string_array(&marks, nmarks, 3, mark_str, line2,
								line3);
					}
				}
			}
			else if(type == LINE_TYPE_TRASH)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if(!path_exists_at(cfg.trash_dir, line_val))
						continue;
					if(is_in_trash(line_val))
						continue;
					ntrash = add_to_string_array(&trash, ntrash, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_CMDLINE_HIST)
			{
				if(cfg.cmd_history_num >= 0 && is_in_string_array(cfg.cmd_history,
						cfg.cmd_history_num + 1, line_val))
					continue;
				ncmdh = add_to_string_array(&cmdh, ncmdh, 1, line_val);
			}
			else if(type == LINE_TYPE_SEARCH_HIST)
			{
				if(cfg.search_history_num >= 0 && is_in_string_array(cfg.search_history,
						cfg.search_history_num + 1, line_val))
					continue;
				nsrch = add_to_string_array(&srch, nsrch, 1, line_val);
			}
			else if(type == LINE_TYPE_PROMPT_HIST)
			{
				if(cfg.prompt_history_num >= 0 && is_in_string_array(cfg.prompt_history,
						cfg.prompt_history_num + 1, line_val))
					continue;
				nprompt = add_to_string_array(&prompt, nprompt, 1, line_val);
			}
			else if(type == LINE_TYPE_REG)
			{
				if(register_exists(line_val[0]))
					continue;
				nregs = add_to_string_array(&regs, nregs, 1, line);
			}
		}
		free(line);
		free(line2);
		free(line3);
		fclose(fp);
	}

	if((fp = fopen(filename, "w")) == NULL)
	{
		return;
	}

	fprintf(fp, "# You can edit this file by hand, but it's recommended not to do that.\n");

	if(cfg.vifm_info & VIFMINFO_OPTIONS)
	{
		fputs("\n# Options:\n", fp);
		fprintf(fp, "=aproposprg=%s\n", escape_spaces(cfg.apropos_prg));
		fprintf(fp, "=%sautochpos\n", cfg.auto_ch_pos ? "" : "no");
		fprintf(fp, "=columns=%d\n", cfg.columns);
		fprintf(fp, "=%sconfirm\n", cfg.confirm ? "" : "no");
		fprintf(fp, "=cpoptions=%s%s%s\n",
				cfg.filter_inverted_by_default ? "f" : "",
				cfg.selection_is_primary ? "s" : "",
				cfg.tab_switches_pane ? "t" : "");
		fprintf(fp, "=%sfastrun\n", cfg.fast_run ? "" : "no");
		fprintf(fp, "=findprg=%s\n", escape_spaces(cfg.find_prg));
		fprintf(fp, "=%sfollowlinks\n", cfg.follow_links ? "" : "no");
		fprintf(fp, "=fusehome=%s\n", escape_spaces(cfg.fuse_home));
		fprintf(fp, "=%sgdefault\n", cfg.gdefault ? "" : "no");
		fprintf(fp, "=grepprg=%s\n", escape_spaces(cfg.grep_prg));
		fprintf(fp, "=history=%d\n", cfg.history_len);
		fprintf(fp, "=%shlsearch\n", cfg.hl_search ? "" : "no");
		fprintf(fp, "=%siec\n", cfg.use_iec_prefixes ? "" : "no");
		fprintf(fp, "=%signorecase\n", cfg.ignore_case ? "" : "no");
		fprintf(fp, "=%sincsearch\n", cfg.inc_search ? "" : "no");
		fprintf(fp, "=%slaststatus\n", cfg.last_status ? "" : "no");
		fprintf(fp, "=lines=%d\n", cfg.lines);
		fprintf(fp, "=locateprg=%s\n", escape_spaces(cfg.locate_prg));
		fprintf(fp, "=rulerformat=%s\n", escape_spaces(cfg.ruler_format));
		fprintf(fp, "=%srunexec\n", cfg.auto_execute ? "" : "no");
		fprintf(fp, "=%sscrollbind\n", cfg.scroll_bind ? "" : "no");
		fprintf(fp, "=scrolloff=%d\n", cfg.scroll_off);
		fprintf(fp, "=shell=%s\n", escape_spaces(cfg.shell));
		fprintf(fp, "=shortmess=%s\n", cfg.trunc_normal_sb_msgs ? "T" : "");
#ifndef _WIN32
		fprintf(fp, "=slowfs=%s\n", escape_spaces(cfg.slow_fs_list));
#endif
		fprintf(fp, "=%ssmartcase\n", cfg.smart_case ? "" : "no");
		fprintf(fp, "=%ssortnumbers\n", cfg.sort_numbers ? "" : "no");
		fprintf(fp, "=statusline=%s\n", escape_spaces(cfg.status_line));
		fprintf(fp, "=tabstop=%d\n", cfg.tab_stop);
		fprintf(fp, "=timefmt=%s\n", escape_spaces(cfg.time_format + 1));
		fprintf(fp, "=timeoutlen=%d\n", cfg.timeout_len);
		fprintf(fp, "=%strash\n", cfg.use_trash ? "" : "no");
		fprintf(fp, "=undolevels=%d\n", cfg.undo_levels);
		fprintf(fp, "=vicmd=%s%s\n", escape_spaces(cfg.vi_command),
				cfg.vi_cmd_bg ? " &" : "");
		fprintf(fp, "=vixcmd=%s%s\n", escape_spaces(cfg.vi_x_command),
				cfg.vi_cmd_bg ? " &" : "");
		fprintf(fp, "=%swrapscan\n", cfg.wrap_scan ? "" : "no");
		fprintf(fp, "=[viewcolumns=%s\n", escape_spaces(lwin.view_columns));
		fprintf(fp, "=]viewcolumns=%s\n", escape_spaces(rwin.view_columns));
		fprintf(fp, "=[%slsview\n", lwin.ls_view ? "" : "no");
		fprintf(fp, "=]%slsview\n", rwin.ls_view ? "" : "no");

		fprintf(fp, "%s", "=dotdirs=");
		if(cfg.dot_dirs & DD_ROOT_PARENT)
			fprintf(fp, "%s", "rootparent,");
		if(cfg.dot_dirs & DD_NONROOT_PARENT)
			fprintf(fp, "%s", "nonrootparent,");
		fprintf(fp, "\n");

		fprintf(fp, "=classify=%s\n", escape_spaces(classify_to_str()));

		fprintf(fp, "=vifminfo=options");
		if(cfg.vifm_info & VIFMINFO_FILETYPES)
			fprintf(fp, ",filetypes");
		if(cfg.vifm_info & VIFMINFO_COMMANDS)
			fprintf(fp, ",commands");
		if(cfg.vifm_info & VIFMINFO_BOOKMARKS)
			fprintf(fp, ",bookmarks");
		if(cfg.vifm_info & VIFMINFO_TUI)
			fprintf(fp, ",tui");
		if(cfg.vifm_info & VIFMINFO_DHISTORY)
			fprintf(fp, ",dhistory");
		if(cfg.vifm_info & VIFMINFO_STATE)
			fprintf(fp, ",state");
		if(cfg.vifm_info & VIFMINFO_CS)
			fprintf(fp, ",cs");
		if(cfg.vifm_info & VIFMINFO_SAVEDIRS)
			fprintf(fp, ",savedirs");
		if(cfg.vifm_info & VIFMINFO_CHISTORY)
			fprintf(fp, ",chistory");
		if(cfg.vifm_info & VIFMINFO_SHISTORY)
			fprintf(fp, ",shistory");
		if(cfg.vifm_info & VIFMINFO_PHISTORY)
			fprintf(fp, ",phistory");
		if(cfg.vifm_info & VIFMINFO_DIRSTACK)
			fprintf(fp, ",dirstack");
		if(cfg.vifm_info & VIFMINFO_REGISTERS)
			fprintf(fp, ",registers");
		fprintf(fp, "\n");

		fprintf(fp, "=%svimhelp\n", cfg.use_vim_help ? "" : "no");
		fprintf(fp, "=%swildmenu\n", cfg.wild_menu ? "" : "no");
		fprintf(fp, "=%swrap\n", cfg.wrap_quick_view ? "" : "no");
	}

	if(cfg.vifm_info & VIFMINFO_FILETYPES)
	{
		fputs("\n# Filetypes:\n", fp);
		for(i = 0; i < filetypes.count; i++)
		{
			int j;
			assoc_t ft_assoc = filetypes.list[i];
			for(j = 0; j < ft_assoc.records.count; j++)
			{
				assoc_record_t ft_record = ft_assoc.records.list[j];
				/* The type check is to prevent builtin fake associations to be written
				 * into vifminfo file */
				if(ft_record.command[0] != '\0' && ft_record.type != ART_BUILTIN)
				{
					fprintf(fp, ".%s\n\t{%s}%s\n", ft_assoc.pattern,
							ft_record.description, ft_record.command);
				}
			}
		}
		for(i = 0; i < nft; i += 2)
			fprintf(fp, ".%s\n\t%s\n", ft[i], ft[i + 1]);

		fputs("\n# X Filetypes:\n", fp);
		for(i = 0; i < xfiletypes.count; i++)
		{
			int j;
			assoc_t xft_assoc = xfiletypes.list[i];
			for(j = 0; j < xft_assoc.records.count; j++)
			{
				assoc_record_t xft_record = xft_assoc.records.list[j];
				if(xft_record.command[0] != '\0')
				{
					fprintf(fp, "x%s\n\t{%s}%s\n", xft_assoc.pattern,
							xft_record.description, xft_record.command);
				}
			}
		}
		for(i = 0; i < nfx; i += 2)
			fprintf(fp, ".%s\n\t%s\n", fx[i], fx[i + 1]);

		fputs("\n# Fileviewers:\n", fp);
		for(i = 0; i < fileviewers.count; i++)
		{
			int j;
			assoc_t fv_assoc = fileviewers.list[i];
			for(j = 0; j < fv_assoc.records.count; j++)
			{
				assoc_record_t fv_record = fileviewers.list[i].records.list[j];
				if(fv_record.command[0] != '\0')
				{
					fprintf(fp, ",%s\n\t%s\n", fv_assoc.pattern, fv_record.command);
				}
			}
		}
		for(i = 0; i < nfv; i += 2)
			fprintf(fp, ",%s\n\t%s\n", fv[i], fv[i + 1]);
	}

	if(cfg.vifm_info & VIFMINFO_COMMANDS)
	{
		fputs("\n# Commands:\n", fp);
		for(i = 0; list[i] != NULL; i += 2)
			fprintf(fp, "!%s\n\t%s\n", list[i], list[i + 1]);
		for(i = 0; i < ncmds; i += 2)
			fprintf(fp, "!%s\n\t%s\n", cmds[i], cmds[i + 1]);
	}

	if(cfg.vifm_info & VIFMINFO_BOOKMARKS)
	{
		int len = init_active_bookmarks(valid_bookmarks);

		fputs("\n# Bookmarks:\n", fp);
		for(i = 0; i < len; i++)
		{
			int j = active_bookmarks[i];
			if(is_spec_bookmark(j))
				continue;
			fprintf(fp, "'%c\n\t%s\n\t", index2mark(j), bookmarks[j].directory);
			fprintf(fp, "%s\n", bookmarks[j].file);
		}
		for(i = 0; i < nmarks; i += 3)
			fprintf(fp, "'%c\n\t%s\n\t%s\n", marks[i][0], marks[i + 1], marks[i + 2]);
	}

	if(cfg.vifm_info & VIFMINFO_TUI)
	{
		fputs("\n# TUI:\n", fp);
		fprintf(fp, "a%c\n", (curr_view == &rwin) ? 'r' : 'l');
		fprintf(fp, "q%d\n", curr_stats.view);
		fprintf(fp, "v%d\n", curr_stats.number_of_windows);
		fprintf(fp, "o%c\n", (curr_stats.split == VSPLIT) ? 'v' : 'h');
		fprintf(fp, "m%d\n", curr_stats.splitter_pos);

		put_sort_info(fp, 'l', &lwin);
		put_sort_info(fp, 'r', &rwin);
	}

	if((cfg.vifm_info & VIFMINFO_DHISTORY) && cfg.history_len > 0)
	{
		save_view_history(&lwin, NULL, NULL, -1);
		fputs("\n# Left window history (oldest to newest):\n", fp);
		for(i = 0; i < nlh; i += 2)
			fprintf(fp, "d%s\n\t%s\n%d\n", lh[i], lh[i + 1], lhp[i/2]);
		for(i = 0; i <= lwin.history_pos; i++)
			fprintf(fp, "d%s\n\t%s\n%d\n", lwin.history[i].dir, lwin.history[i].file,
					lwin.history[i].rel_pos);
		if(cfg.vifm_info & VIFMINFO_SAVEDIRS)
			fprintf(fp, "d\n");

		save_view_history(&rwin, NULL, NULL, -1);
		fputs("\n# Right window history (oldest to newest):\n", fp);
		for(i = 0; i < nrh; i += 2)
			fprintf(fp, "D%s\n\t%s\n%d\n", rh[i], rh[i + 1], rhp[i/2]);
		for(i = 0; i <= rwin.history_pos; i++)
			fprintf(fp, "D%s\n\t%s\n%d\n", rwin.history[i].dir, rwin.history[i].file,
					rwin.history[i].rel_pos);
		if(cfg.vifm_info & VIFMINFO_SAVEDIRS)
			fprintf(fp, "D\n");
	}

	if(cfg.vifm_info & VIFMINFO_CHISTORY)
	{
		fputs("\n# Command line history (oldest to newest):\n", fp);
		for(i = 0; i < MIN(ncmdh, cfg.history_len - cfg.cmd_history_num); i++)
			fprintf(fp, ":%s\n", cmdh[i]);
		for(i = cfg.cmd_history_num; i >= 0; i--)
			fprintf(fp, ":%s\n", cfg.cmd_history[i]);
	}

	if(cfg.vifm_info & VIFMINFO_SHISTORY)
	{
		fputs("\n# Search history (oldest to newest):\n", fp);
		for(i = 0; i < nsrch; i++)
			fprintf(fp, "/%s\n", srch[i]);
		for(i = cfg.search_history_num; i >= 0; i--)
			fprintf(fp, "/%s\n", cfg.search_history[i]);
	}

	if(cfg.vifm_info & VIFMINFO_PHISTORY)
	{
		fputs("\n# Prompt history (oldest to newest):\n", fp);
		for(i = 0; i < nprompt; i++)
			fprintf(fp, "p%s\n", prompt[i]);
		for(i = cfg.prompt_history_num; i >= 0; i--)
			fprintf(fp, "p%s\n", cfg.prompt_history[i]);
	}

	if(cfg.vifm_info & VIFMINFO_REGISTERS)
	{
		fputs("\n# Registers:\n", fp);
		for(i = 0; i < nregs; i++)
			fprintf(fp, "%s\n", regs[i]);
		for(i = 0; valid_registers[i] != '\0'; i++)
		{
			int j;
			registers_t *reg = find_register(valid_registers[i]);
			if(reg == NULL)
				continue;
			for(j = 0; j < reg->num_files; j++)
			{
				if(reg->files[j] == NULL)
					continue;
				fprintf(fp, "\"%c%s\n", reg->name, reg->files[j]);
			}
		}
	}

	if(cfg.vifm_info & VIFMINFO_DIRSTACK)
	{
		fputs("\n# Directory stack (oldest to newest):\n", fp);
		for(i = 0; i < stack_top; i++)
		{
			fprintf(fp, "S%s\n\t%s\n", stack[i].lpane_dir, stack[i].lpane_file);
			fprintf(fp, "S%s\n\t%s\n", stack[i].rpane_dir, stack[i].rpane_file);
		}
	}

	fputs("\n# Trash content:\n", fp);
	for(i = 0; i < nentries; i++)
		fprintf(fp, "t%s\n\t%s\n", trash_list[i].trash_name, trash_list[i].path);
	for(i = 0; i < ntrash; i += 2)
		fprintf(fp, "t%s\n\t%s\n", trash[i], trash[i + 1]);

	if(cfg.vifm_info & VIFMINFO_STATE)
	{
		fputs("\n# State:\n", fp);
		fprintf(fp, "f%s\n", lwin.filename_filter);
		fprintf(fp, "i%d\n", lwin.invert);
		fprintf(fp, "[.%d\n", lwin.hide_dot);
		fprintf(fp, "F%s\n", rwin.filename_filter);
		fprintf(fp, "I%d\n", rwin.invert);
		fprintf(fp, "].%d\n", rwin.hide_dot);
		fprintf(fp, "s%d\n", cfg.use_screen);
	}

	if(cfg.vifm_info & VIFMINFO_CS)
	{
		fputs("\n# Color scheme:\n", fp);
		fprintf(fp, "c%s\n", cfg.cs.name);
	}

	fclose(fp);

	free_string_array(ft, nft);
	free_string_array(fv, nfv);
	free_string_array(fx, nfx);
	free_string_array(cmds, ncmds);
	free_string_array(marks, nmarks);
	free_string_array(list, nlist);
	free_string_array(lh, nlh);
	free_string_array(rh, nrh);
	free(lhp);
	free(rhp);
	free_string_array(cmdh, ncmdh);
	free_string_array(srch, nsrch);
	free_string_array(regs, nregs);
	free_string_array(prompt, nprompt);
	free_string_array(trash, ntrash);
}
Exemplo n.º 12
0
int
let_variable(const char *cmd)
{
	char name[VAR_NAME_MAX + 1];
	char *p;
	int append = 0;
	var_t res_var;
	char *str_var;
	ParsingErrors parsing_error;

	assert(initialized);

	/* currently we support only environment variables */
	if(*cmd != '$')
	{
		text_buffer_add("Incorrect variable type");
		return -1;
	}
	cmd++;

	/* copy variable name */
	p = name;
	while(*cmd != '\0' && char_is_one_of(ENV_VAR_NAME_CHARS, *cmd) &&
			*cmd != '.' && *cmd != '=' && p - name < sizeof(name) - 1)
	{
		if(*cmd != '_' && !isalnum(*cmd))
		{
			text_buffer_add("Incorrect variable name");
			return -1;
		}
		*p++ = *cmd++;
	}
	/* test for empty variable name */
	if(p == name)
	{
		text_buffer_addf("%s: %s", "Unsupported variable name", "empty name");
		return -1;
	}
	*p = '\0';

	cmd = skip_whitespace(cmd);

	/* check for dot and skip it */
	if(*cmd == '.')
	{
		append = 1;
		cmd++;
	}

	/* check for equal sign and skip it */
	if(*cmd != '=')
	{
		text_buffer_addf("%s: %s", "Incorrect :let statement", "'=' expected");
		return -1;
	}

	parsing_error = parse(cmd + 1, &res_var);
	if(parsing_error != PE_NO_ERROR)
	{
		report_parsing_error(parsing_error);
		return -1;
	}

	if(get_last_position() != NULL && *get_last_position() != '\0')
	{
		text_buffer_addf("%s: %s", "Incorrect :let statement",
				"trailing characters");
		return -1;
	}

	/* update environment variable */
	str_var = var_to_string(res_var);
	if(append)
		append_envvar(name, str_var);
	else
		set_envvar(name, str_var);
	free(str_var);

	var_free(res_var);

	return 0;
}
Exemplo n.º 13
0
int
unlet_variables(const char *cmd)
{
	int error = 0;
	assert(initialized);

	while(*cmd != '\0')
	{
		envvar_t *record;

		char name[VAR_NAME_MAX + 1];
		char *p;
		int envvar = 1;

		/* check if its environment variable */
		if(*cmd != '$')
			envvar = 0;
		else
			cmd++;

		/* copy variable name */
		p = name;
		while(*cmd != '\0' && char_is_one_of(ENV_VAR_NAME_CHARS, *cmd) &&
				p - name < sizeof(name) - 1)
			*p++ = *cmd++;
		*p = '\0';

		if(*cmd != '\0' && !isspace(*cmd))
		{
			text_buffer_add("Trailing characters");
			error++;
			break;
		}

		cmd = skip_whitespace(cmd);

		/* currently we support only environment variables */
		if(!envvar)
		{
			text_buffer_addf("%s: %s", "Unsupported variable type", name);

			cmd = skip_non_whitespace(cmd);
			error++;
			continue;
		}

		/* test for empty variable name */
		if(name[0] == '\0')
		{
			text_buffer_addf("%s: %s", "Unsupported variable name", "empty name");
			error++;
			continue;
		}

		record = find_record(name);
		if(record == NULL || record->removed)
		{
			text_buffer_addf("%s: %s", "No such variable", name);
			error++;
			continue;
		}

		if(record->from_parent)
			record->removed = 1;
		else
			free_record(record);
		env_remove(name);
	}

	return error;
}
Exemplo n.º 14
0
Arquivo: info.c Projeto: cfillion/vifm
/* Reads contents of the filename file as an info file and updates it with the
 * state of current instance. */
static void
update_info_file(const char filename[])
{
	/* TODO: refactor this function update_info_file() */

	FILE *fp;
	char **cmds_list;
	int ncmds_list = -1;
	char **ft = NULL, **fx = NULL, **fv = NULL, **cmds = NULL, **marks = NULL;
	char **lh = NULL, **rh = NULL, **cmdh = NULL, **srch = NULL, **regs = NULL;
	int *lhp = NULL, *rhp = NULL, *bt = NULL, *bmt = NULL;
	char **prompt = NULL, **filter = NULL, **trash = NULL;
	char **bmarks = NULL;
	int nft = 0, nfx = 0, nfv = 0, ncmds = 0, nmarks = 0, nlh = 0, nrh = 0;
	int ncmdh = 0, nsrch = 0, nregs = 0, nprompt = 0, nfilter = 0, ntrash = 0;
	int nbmarks = 0;
	char **dir_stack = NULL;
	int ndir_stack = 0;
	char *non_conflicting_marks;

	if(cfg.vifm_info == 0)
		return;

	cmds_list = list_udf();
	while(cmds_list[++ncmds_list] != NULL);

	non_conflicting_marks = strdup(valid_marks);

	if((fp = os_fopen(filename, "r")) != NULL)
	{
		size_t nlhp = 0UL, nrhp = 0UL, nbt = 0UL, nbmt = 0UL;
		char *line = NULL, *line2 = NULL, *line3 = NULL, *line4 = NULL;
		while((line = read_vifminfo_line(fp, line)) != NULL)
		{
			const char type = line[0];
			const char *const line_val = line + 1;

			if(type == LINE_TYPE_COMMENT || type == '\0')
				continue;

			if(type == LINE_TYPE_FILETYPE)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if(!ft_assoc_exists(&filetypes, line_val, line2))
					{
						nft = add_to_string_array(&ft, nft, 2, line_val, line2);
					}
				}
			}
			else if(type == LINE_TYPE_XFILETYPE)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if(!ft_assoc_exists(&xfiletypes, line_val, line2))
					{
						nfx = add_to_string_array(&fx, nfx, 2, line_val, line2);
					}
				}
			}
			else if(type == LINE_TYPE_FILEVIEWER)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if(!ft_assoc_exists(&fileviewers, line_val, line2))
					{
						nfv = add_to_string_array(&fv, nfv, 2, line_val, line2);
					}
				}
			}
			else if(type == LINE_TYPE_COMMAND)
			{
				if(line_val[0] == '\0')
					continue;
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					int i;
					const char *p = line_val;
					for(i = 0; i < ncmds_list; i += 2)
					{
						int cmp = strcmp(cmds_list[i], p);
						if(cmp < 0)
							continue;
						if(cmp == 0)
							p = NULL;
						break;
					}
					if(p == NULL)
						continue;
					ncmds = add_to_string_array(&cmds, ncmds, 2, line_val, line2);
				}
			}
			else if(type == LINE_TYPE_LWIN_HIST || type == LINE_TYPE_RWIN_HIST)
			{
				if(line_val[0] == '\0')
					continue;
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					const int pos = read_optional_number(fp);

					if(type == LINE_TYPE_LWIN_HIST)
					{
						process_hist_entry(&lwin, line_val, line2, pos, &lh, &nlh, &lhp,
								&nlhp);
					}
					else
					{
						process_hist_entry(&rwin, line_val, line2, pos, &rh, &nrh, &rhp,
								&nrhp);
					}
				}
			}
			else if(type == LINE_TYPE_MARK)
			{
				const char mark = line_val[0];
				if(line_val[1] != '\0')
				{
					LOG_ERROR_MSG("Expected end of line, but got: %s", line_val + 1);
				}
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if((line3 = read_vifminfo_line(fp, line3)) != NULL)
					{
						const int timestamp = read_optional_number(fp);
						const char mark_str[] = { mark, '\0' };

						if(!char_is_one_of(valid_marks, mark))
						{
							continue;
						}

						if(is_mark_older(mark, timestamp))
						{
							char *const pos = strchr(non_conflicting_marks, mark);
							if(pos != NULL)
							{
								nmarks = add_to_string_array(&marks, nmarks, 3, mark_str, line2,
										line3);
								nbt = add_to_int_array(&bt, nbt, timestamp);

								*pos = '\xff';
							}
						}
					}
				}
			}
			else if(type == LINE_TYPE_BOOKMARK)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if((line3 = read_vifminfo_line(fp, line3)) != NULL)
					{
						long timestamp;
						if(read_number(line3, &timestamp) &&
								bmark_is_older(line_val, timestamp))
						{
							nbmarks = add_to_string_array(&bmarks, nbmarks, 2, line_val,
									line2);
							nbmt = add_to_int_array(&bmt, nbmt, timestamp);
						}
					}
				}
			}
			else if(type == LINE_TYPE_TRASH)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					char *const trash_name = convert_old_trash_path(line_val);
					if(exists_in_trash(trash_name) && !is_in_trash(trash_name))
					{
						ntrash = add_to_string_array(&trash, ntrash, 2, trash_name, line2);
					}
					free(trash_name);
				}
			}
			else if(type == LINE_TYPE_CMDLINE_HIST)
			{
				if(!hist_contains(&cfg.cmd_hist, line_val))
				{
					ncmdh = add_to_string_array(&cmdh, ncmdh, 1, line_val);
				}
			}
			else if(type == LINE_TYPE_SEARCH_HIST)
			{
				if(!hist_contains(&cfg.search_hist, line_val))
				{
					nsrch = add_to_string_array(&srch, nsrch, 1, line_val);
				}
			}
			else if(type == LINE_TYPE_PROMPT_HIST)
			{
				if(!hist_contains(&cfg.prompt_hist, line_val))
				{
					nprompt = add_to_string_array(&prompt, nprompt, 1, line_val);
				}
			}
			else if(type == LINE_TYPE_FILTER_HIST)
			{
				if(!hist_contains(&cfg.filter_hist, line_val))
				{
					nfilter = add_to_string_array(&filter, nfilter, 1, line_val);
				}
			}
			else if(type == LINE_TYPE_DIR_STACK)
			{
				if((line2 = read_vifminfo_line(fp, line2)) != NULL)
				{
					if((line3 = read_vifminfo_line(fp, line3)) != NULL)
					{
						if((line4 = read_vifminfo_line(fp, line4)) != NULL)
						{
							ndir_stack = add_to_string_array(&dir_stack, ndir_stack, 4,
									line_val, line2, line3 + 1, line4);
						}
					}
				}
			}
			else if(type == LINE_TYPE_REG)
			{
				if(regs_exists(line_val[0]))
				{
					continue;
				}
				nregs = add_to_string_array(&regs, nregs, 1, line);
			}
		}
		free(line);
		free(line2);
		free(line3);
		free(line4);
		fclose(fp);
	}

	if((fp = os_fopen(filename, "w")) != NULL)
	{
		fprintf(fp, "# You can edit this file by hand, but it's recommended not to "
				"do that.\n");

		if(cfg.vifm_info & VIFMINFO_OPTIONS)
		{
			write_options(fp);
		}

		if(cfg.vifm_info & VIFMINFO_FILETYPES)
		{
			write_assocs(fp, "Filetypes", LINE_TYPE_FILETYPE, &filetypes, nft, ft);
			write_assocs(fp, "X Filetypes", LINE_TYPE_XFILETYPE, &xfiletypes, nfx,
					fx);
			write_assocs(fp, "Fileviewers", LINE_TYPE_FILEVIEWER, &fileviewers, nfv,
					fv);
		}

		if(cfg.vifm_info & VIFMINFO_COMMANDS)
		{
			write_commands(fp, cmds_list, cmds, ncmds);
		}

		if(cfg.vifm_info & VIFMINFO_MARKS)
		{
			write_marks(fp, non_conflicting_marks, marks, bt, nmarks);
		}

		if(cfg.vifm_info & VIFMINFO_BOOKMARKS)
		{
			write_bmarks(fp, bmarks, bmt, nbmarks);
		}

		if(cfg.vifm_info & VIFMINFO_TUI)
		{
			write_tui_state(fp);
		}

		if((cfg.vifm_info & VIFMINFO_DHISTORY) && cfg.history_len > 0)
		{
			write_view_history(fp, &lwin, "Left", LINE_TYPE_LWIN_HIST, nlh, lh, lhp);
			write_view_history(fp, &rwin, "Right", LINE_TYPE_RWIN_HIST, nrh, rh, rhp);
		}

		if(cfg.vifm_info & VIFMINFO_CHISTORY)
		{
			write_history(fp, "Command line", LINE_TYPE_CMDLINE_HIST,
					MIN(ncmdh, cfg.history_len - cfg.cmd_hist.pos), cmdh, &cfg.cmd_hist);
		}

		if(cfg.vifm_info & VIFMINFO_SHISTORY)
		{
			write_history(fp, "Search", LINE_TYPE_SEARCH_HIST, nsrch, srch,
					&cfg.search_hist);
		}

		if(cfg.vifm_info & VIFMINFO_PHISTORY)
		{
			write_history(fp, "Prompt", LINE_TYPE_PROMPT_HIST, nprompt, prompt,
					&cfg.prompt_hist);
		}

		if(cfg.vifm_info & VIFMINFO_FHISTORY)
		{
			write_history(fp, "Local filter", LINE_TYPE_FILTER_HIST, nfilter, filter,
					&cfg.filter_hist);
		}

		if(cfg.vifm_info & VIFMINFO_REGISTERS)
		{
			write_registers(fp, regs, nregs);
		}

		if(cfg.vifm_info & VIFMINFO_DIRSTACK)
		{
			write_dir_stack(fp, dir_stack, ndir_stack);
		}

		write_trash(fp, trash, ntrash);

		if(cfg.vifm_info & VIFMINFO_STATE)
		{
			write_general_state(fp);
		}

		if(cfg.vifm_info & VIFMINFO_CS)
		{
			fputs("\n# Color scheme:\n", fp);
			fprintf(fp, "c%s\n", cfg.cs.name);
		}

		fclose(fp);
	}

	free_string_array(ft, nft);
	free_string_array(fv, nfv);
	free_string_array(fx, nfx);
	free_string_array(cmds, ncmds);
	free_string_array(marks, nmarks);
	free_string_array(cmds_list, ncmds_list);
	free_string_array(lh, nlh);
	free_string_array(rh, nrh);
	free(lhp);
	free(rhp);
	free(bt);
	free(bmt);
	free_string_array(cmdh, ncmdh);
	free_string_array(srch, nsrch);
	free_string_array(regs, nregs);
	free_string_array(prompt, nprompt);
	free_string_array(filter, nfilter);
	free_string_array(trash, ntrash);
	free_string_array(bmarks, nbmarks);
	free_string_array(dir_stack, ndir_stack);
	free(non_conflicting_marks);
}
Exemplo n.º 15
0
/* Expands macros in the *format string advancing the pointer as it goes.  The
 * opt represents conditional expression state, should be zero for non-recursive
 * calls.  Returns newly allocated string, which should be freed by the
 * caller. */
static LineWithAttrs
parse_view_macros(view_t *view, const char **format, const char macros[],
		int opt)
{
	const dir_entry_t *const curr = get_current_entry(view);
	LineWithAttrs result = { .line = strdup(""), .attrs = strdup("") };
	char c;
	int nexpansions = 0;
	int has_expander = 0;

	if(curr == NULL)
	{
		return result;
	}

	while((c = **format) != '\0')
	{
		size_t width = 0;
		int left_align = 0;
		char buf[PATH_MAX + 1];
		const char *const next = ++*format;
		int skip, ok;

		if(c != '%' ||
				(!char_is_one_of(macros, *next) && !isdigit(*next) &&
				 (*next != '=' || has_expander)))
		{
			if(strappendch(&result.line, &result.line_len, c) != 0)
			{
				break;
			}
			continue;
		}

		if(*next == '=')
		{
			(void)sync_attrs(&result, 0);

			if(strappend(&result.line, &result.line_len, "%=") != 0 ||
					strappendch(&result.attrs, &result.attrs_len, '=') != 0)
			{
				break;
			}
			++*format;
			has_expander = 1;
			continue;
		}

		if(*next == '-')
		{
			left_align = 1;
			++*format;
		}

		while(isdigit(**format))
		{
			width = width*10 + *(*format)++ - '0';
		}
		c = *(*format)++;

		skip = 0;
		ok = 1;
		buf[0] = '\0';
		switch(c)
		{
			case 'a':
				friendly_size_notation(get_free_space(curr_view->curr_dir), sizeof(buf),
						buf);
				break;
			case 't':
				format_entry_name(curr, NF_FULL, sizeof(buf), buf);
				break;
			case 'T':
				if(curr->type == FT_LINK)
				{
					char full_path[PATH_MAX + 1];
					char link_path[PATH_MAX + 1];  //add by sim1
					get_full_path_of(curr, sizeof(full_path), full_path);
					//mod by sim1 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
					if(get_link_target(full_path, link_path, sizeof(link_path)) != 0)
					{
						copy_str(buf, sizeof(buf), "Failed to resolve link");
					}
					else
					{
						snprintf(buf, sizeof(buf), " -> %s", link_path);
					}
					//mod by sim1 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
				}
				break;
			case 'f':
				get_short_path_of(view, curr, NF_FULL, 0, sizeof(buf), buf);
				break;
			case 'A':
#ifndef _WIN32
				get_perm_string(buf, sizeof(buf), curr->mode);
#else
				copy_str(buf, sizeof(buf), attr_str_long(curr->attrs));
#endif
				break;
			case 'u':
				get_uid_string(curr, 0, sizeof(buf), buf);
				break;
			case 'g':
				get_gid_string(curr, 0, sizeof(buf), buf);
				break;
			case 's':
				friendly_size_notation(fentry_get_size(view, curr), sizeof(buf), buf);
				break;
			//add by sim1 ************************************************
			case 'r':
				{
					char path[PATH_MAX] = {0};
					get_full_path_at(view, view->list_pos, sizeof(path), path);
					(void)get_rating_string(buf, sizeof(buf), path);
				}
				break;
			case 'n':
				{
					int nitems = !fentry_is_dir(curr) ? 0 : (int)fentry_get_nitems(view, curr);
					snprintf(buf, sizeof(buf), "%d", nitems);
				}
				break;
			//add by sim1 ************************************************
			case 'E':
				{
					uint64_t size = 0U;

					typedef int (*iter_f)(view_t *view, dir_entry_t **entry);
					/* No current element for visual mode, since it can contain truly
					 * empty selection when cursor is on ../ directory. */
					iter_f iter = vle_mode_is(VISUAL_MODE) ? &iter_selected_entries
					                                       : &iter_selection_or_current;

					dir_entry_t *entry = NULL;
					while(iter(view, &entry))
					{
						size += fentry_get_size(view, entry);
					}

					friendly_size_notation(size, sizeof(buf), buf);
				}
				break;
			case 'd':
				{
					struct tm *tm_ptr = localtime(&curr->mtime);
					strftime(buf, sizeof(buf), cfg.time_format, tm_ptr);
				}
				break;
			case '-':
			case 'x':
				skip = expand_num(buf, sizeof(buf), view->filtered);
				break;
			case 'l':
				skip = expand_num(buf, sizeof(buf), view->list_pos + 1);
				break;
			case 'L':
				skip = expand_num(buf, sizeof(buf), view->list_rows + view->filtered);
				break;
			case 'S':
				skip = expand_num(buf, sizeof(buf), view->list_rows);
				break;
			case '%':
				copy_str(buf, sizeof(buf), "%");
				break;
			case 'z':
				copy_str(buf, sizeof(buf), get_tip());
				break;
			case 'D':
				if(curr_stats.number_of_windows == 1)
				{
					view_t *const other = (view == curr_view) ? other_view : curr_view;
					//mod by sim1
					//copy_str(buf, sizeof(buf), replace_home_part(other->curr_dir));
					snprintf(buf, sizeof(buf), " ‖ %s", replace_home_part(other->curr_dir));
				}
				break;
			case '[':
				{
					LineWithAttrs opt = parse_view_macros(view, format, macros, 1);
					copy_str(buf, sizeof(buf), opt.line);
					free(opt.line);

					char *attrs = opt.attrs;
					if(sync_attrs(&result, 0) && opt.attrs_len > 0U)
					{
						if(*attrs != ' ')
						{
							result.attrs[result.attrs_len - 1U] = *attrs;
						}
						++attrs;
					}
					strappend(&result.attrs, &result.attrs_len, attrs);
					free(opt.attrs);
					break;
				}
			case ']':
				if(opt)
				{
					if(nexpansions == 0)
					{
						replace_string(&result.line, "");
						replace_string(&result.attrs, "");
						result.line_len = 0U;
						result.attrs_len = 0U;
					}
					if(sync_attrs(&result, 0))
					{
						result.attrs[--result.attrs_len] = '\0';
					}
					return result;
				}

				LOG_INFO_MSG("Unmatched %%]");
				ok = 0;
				break;
			case '{':
				{
					/* Try to find matching closing bracket
					 * TODO: implement the way to escape it, so that the expr may contain
					 * closing brackets */
					const char *e = strchr(*format, '}');
					char *expr = NULL, *resstr = NULL;
					var_t res = var_false();
					ParsingErrors parsing_error;

					/* If there's no matching closing bracket, just add the opening one
					 * literally */
					if(e == NULL)
					{
						ok = 0;
						break;
					}

					/* Create a NULL-terminated copy of the given expr.
					 * TODO: we could temporarily use buf for that, to avoid extra
					 * allocation, but explicitly named variable reads better. */
					expr = calloc(e - (*format) + 1 /* NUL-term */, 1);
					memcpy(expr, *format, e - (*format));

					/* Try to parse expr, and convert the res to string if succeed. */
					parsing_error = parse(expr, 0, &res);
					if(parsing_error == PE_NO_ERROR)
					{
						resstr = var_to_str(res);
					}

					if(resstr != NULL)
					{
						copy_str(buf, sizeof(buf), resstr);
					}
					else
					{
						copy_str(buf, sizeof(buf), "<Invalid expr>");
					}

					var_free(res);
					free(resstr);
					free(expr);

					*format = e + 1 /* closing bracket */;
				}
				break;
			case '*':
				if(width > 9)
				{
					snprintf(buf, sizeof(buf), "%%%d*", (int)width);
					width = 0;
					break;
				}
				(void)sync_attrs(&result, 1);
				result.attrs[result.attrs_len - 1] = '0' + width;
				width = 0;
				break;

			default:
				LOG_INFO_MSG("Unexpected %%-sequence: %%%c", c);
				ok = 0;
				break;
		}

		if(char_is_one_of("tTAugsEd", c) && fentry_is_fake(curr))
		{
			buf[0] = '\0';
		}

		if(!ok)
		{
			*format = next;
			if(strappendch(&result.line, &result.line_len, '%') != 0)
			{
				break;
			}
			continue;
		}

		check_expanded_str(buf, skip, &nexpansions);
		stralign(buf, width, ' ', left_align);

		if(strappend(&result.line, &result.line_len, buf) != 0)
		{
			break;
		}
	}

	/* Unmatched %[. */
	if(opt)
	{
		(void)strprepend(&result.line, &result.line_len, "%[");
	}

	if(sync_attrs(&result, 0))
	{
		result.attrs[--result.attrs_len] = '\0';
	}
	return result;
}

/* Makes sure that result->attrs has at least as many elements as result->line
 * contains characters + extra_width.  Returns non-zero if result->attrs has
 * extra characters compared to result->line. */
static int
sync_attrs(LineWithAttrs *result, int extra_width)
{
	const size_t nchars = utf8_strsw(result->line) + extra_width;
	if(result->attrs_len < nchars)
	{
		char *const new_attrs = format_str("%s%*s", result->attrs,
				(int)(nchars - result->attrs_len), "");
		free(result->attrs);
		result->attrs = new_attrs;
		result->attrs_len = nchars;
	}
	return (result->attrs_len > nchars);
}

/* Prints number into the buffer.  Returns non-zero if numeric value is
 * "empty" (zero). */
static int
expand_num(char buf[], size_t buf_len, int val)
{
	snprintf(buf, buf_len, "%d", val);
	return (val == 0);
}
Exemplo n.º 16
0
int
is_spec_mark(const int x)
{
	return char_is_one_of(spec_marks, index2mark(x));
}
Exemplo n.º 17
0
int
is_spec_bookmark(const int x)
{
	const char mark = index2mark(x);
	return char_is_one_of(spec_bookmarks, mark);
}
Exemplo n.º 18
0
/* Expands macros in the *format string advancing the pointer as it goes.  The
 * opt represents conditional expression state, should be zero for non-recursive
 * calls.  Returns newly allocated string, which should be freed by the
 * caller. */
static char *
parse_view_macros(FileView *view, const char **format, const char macros[],
		int opt)
{
	const dir_entry_t *const entry = &view->dir_entry[view->list_pos];
	char *result = strdup("");
	size_t len = 0;
	char c;
	int nexpansions = 0;

	while((c = **format) != '\0')
	{
		size_t width = 0;
		int left_align = 0;
		char buf[PATH_MAX];
		const char *const next = ++*format;
		int skip, ok;

		if(c != '%' || (!char_is_one_of(macros, *next) && !isdigit(*next)))
		{
			if(strappendch(&result, &len, c) != 0)
			{
				break;
			}
			continue;
		}

		if(*next == '-')
		{
			left_align = 1;
			++*format;
		}

		while(isdigit(**format))
		{
			width = width*10 + *(*format)++ - '0';
		}
		c = *(*format)++;

		skip = 0;
		ok = 1;
		switch(c)
		{
			case 't':
				format_entry_name(entry, sizeof(buf), buf);
				break;
			case 'A':
#ifndef _WIN32
				get_perm_string(buf, sizeof(buf), entry->mode);
#else
				snprintf(buf, sizeof(buf), "%s", attr_str_long(entry->attrs));
#endif
				break;
			case 'u':
				get_uid_string(entry, 0, sizeof(buf), buf);
				break;
			case 'g':
				get_gid_string(entry, 0, sizeof(buf), buf);
				break;
			case 's':
				friendly_size_notation(entry->size, sizeof(buf), buf);
				break;
			case 'E':
				{
					uint64_t size = 0;
					if(view->selected_files > 0)
					{
						int i;
						for(i = 0; i < view->list_rows; i++)
						{
							if(view->dir_entry[i].selected)
							{
								size += get_file_size_by_entry(view, i);
							}
						}
					}
					/* Make exception for VISUAL_MODE, since it can contain empty
					 * selection when cursor is on ../ directory. */
					else if(!vle_mode_is(VISUAL_MODE))
					{
						size = get_file_size_by_entry(view, view->list_pos);
					}
					friendly_size_notation(size, sizeof(buf), buf);
				}
				break;
			case 'd':
				{
					struct tm *tm_ptr = localtime(&entry->mtime);
					strftime(buf, sizeof(buf), cfg.time_format, tm_ptr);
				}
				break;
			case '-':
				skip = expand_num(buf, sizeof(buf), view->filtered);
				break;
			case 'l':
				skip = expand_num(buf, sizeof(buf), view->list_pos + 1);
				break;
			case 'L':
				skip = expand_num(buf, sizeof(buf), view->list_rows + view->filtered);
				break;
			case 'S':
				skip = expand_num(buf, sizeof(buf), view->list_rows);
				break;
			case '%':
				snprintf(buf, sizeof(buf), "%%");
				break;
			case '[':
				{
					char *const opt_str = parse_view_macros(view, format, macros, 1);
					copy_str(buf, sizeof(buf), opt_str);
					free(opt_str);
					break;
				}
			case ']':
				if(opt)
				{
					if(nexpansions == 0)
					{
						replace_string(&result, "");
					}
					return result;
				}
				else
				{
					LOG_INFO_MSG("Unmatched %]", c);
					ok = 0;
				}
				break;

			default:
				LOG_INFO_MSG("Unexpected %%-sequence: %%%c", c);
				ok = 0;
				break;
		}

		if(!ok)
		{
			*format = next;
			if(strappendch(&result, &len, '%') != 0)
			{
				break;
			}
			continue;
		}

		check_expanded_str(buf, skip, &nexpansions);
		stralign(buf, width, ' ', left_align);

		if(strappend(&result, &len, buf) != 0)
		{
			break;
		}
	}

	/* Unmatched %[. */
	if(opt)
	{
		(void)strprepend(&result, &len, "%[");
	}

	return result;
}
Exemplo n.º 19
0
/* Processes one :set statement.  Returns zero on success. */
static int
process_option(const char arg[])
{
	char option[OPTION_NAME_MAX + 1];
	int err;
	const char *p;
	opt_t *opt;

	p = skip_alphas(arg);

	snprintf(option, p - arg + 1, "%s", arg);

	if(strcmp(option, "all") == 0)
	{
		print_options();
		return 0;
	}

	opt = get_option(option);
	if(opt == NULL)
	{
		text_buffer_addf("%s: %s", "Unknown option", arg);
		return 1;
	}

	err = 0;
	if(*p == '\0')
	{
		opt_t *o = find_option(option);
		if(o != NULL)
		{
			if(o->type == OPT_BOOL)
				err = set_on(opt);
			else
				err = set_print(o);
		}
		else if(strncmp(option, "no", 2) == 0)
		{
			err = set_off(opt);
		}
		else if(strncmp(option, "inv", 3) == 0)
		{
			err = set_inv(opt);
		}
	}
	else if(char_is_one_of(ENDING_CHARS, *p))
	{
		if(*(p + 1) != '\0')
		{
			text_buffer_addf("%s: %s", "Trailing characters", arg);
			return 1;
		}
		if(*p == '!')
			err = set_inv(opt);
		else if(*p == '?')
			err = set_print(opt);
		else
			err = set_reset(opt);
	}
	else if(strncmp(p, "+=", 2) == 0)
	{
		err = set_add(opt, p + 2);
	}
	else if(strncmp(p, "-=", 2) == 0)
	{
		err = set_remove(opt, p + 2);
	}
	else if(*p == '=' || *p == ':')
	{
		err = set_set(opt, p + 1);
	}
	else
	{
		text_buffer_addf("%s: %s", "Trailing characters", arg);
	}

	if(err)
	{
		text_buffer_addf("%s: %s", "Invalid argument", arg);
	}
	return err;
}
Exemplo n.º 20
0
/* Checks whether given mark corresponds to bookmark that can be set by a user.
 * Returns non-zero if so, otherwise zero is returned. */
static int
is_user_bookmark(const char mark)
{
	return char_is_one_of(valid_bookmarks, mark)
	    && !char_is_one_of(spec_bookmarks, mark);
}