diff --git a/ChangeLog b/ChangeLog index 0681552f5..d2f3c6823 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,9 @@ Added a and A view mode keys that switch to next and previous viewer of current file correspondingly. Thanks to j-xella. + Added 'previewoptions' option to allow tweaking graphics preview a bit. + Thanks to Joshua Jensch (a.k.a., patroclos) and flux242. + Made :VifmCs of the plugin fail when 'termguicolors' produces a 24-bit color value. Thanks to AtomToast. @@ -51,6 +54,9 @@ Fixed presence of %q macro causing second round of macro expansion. + Fixed quickview not being redrawn after leaving File Info dialog or more + mode. + 0.11-beta to 0.11 (2020-09-24) Recommend against setting 'shellcmdflag' to "-ic" value. diff --git a/THANKS b/THANKS index e07a188c3..14573c08c 100644 --- a/THANKS +++ b/THANKS @@ -70,6 +70,7 @@ Fang (peromage) filterfalse Flaviu Tamas (flaviut) Florian Baumann (derflob) +flux242 fogine gammaray gcmt @@ -103,6 +104,7 @@ John Shea (coachshea) Jose Riha (jose1711) Joseph LP (ootput) Josh Wainwright (joshaw) +Joshua Jensch (patroclos) jsmith51 (metal.lunchbox) kalterfive kangshugang diff --git a/data/colors/Default-256.vifm b/data/colors/Default-256.vifm index 6d3a0f540..bd0df1373 100644 --- a/data/colors/Default-256.vifm +++ b/data/colors/Default-256.vifm @@ -2,7 +2,7 @@ " This is Vifm's default color scheme for terminals that support 256 colors. " -" This file last updated: 3 September, 2020 +" This file last updated: 4 December, 2020 highlight clear @@ -88,5 +88,5 @@ highlight {*.sh,*.bash,*.zsh,*.bat,*.btm,*.cmd,*.com,*.dll,*.exe,*.run,*.msu, highlight {*.patch,*.diff,*.py,*.cpp,*.hpp,*.mk,*.c,*.h,*.cpp,*.hpp,*.cc,*.hs, \*.php,*.lua,*.vim,*.vifm,*.asm,*.s,*.java,*.cxx,*.c++,*.go, \*.pl,*.pm,*.t,*.cs,*.asp,*.dart,*.js,*.rb,*.scala,*.ts,*.coffee, - \*.ml,*.mli,*.rs,*.sql,*.qml,vifmrc,vimrc,.vimrc} + \*.ml,*.mli,*.rs,*.sql,*.qml,vifmrc,vimrc,.vimrc,*.flex,*.ypp} \ cterm=none ctermfg=193 ctermbg=default diff --git a/data/man/vifm.1 b/data/man/vifm.1 index cbd0abc1b..d8a0f4aec 100644 --- a/data/man/vifm.1 +++ b/data/man/vifm.1 @@ -1,4 +1,4 @@ -.TH VIFM 1 "November 28, 2020" "vifm 0.11" +.TH VIFM 1 "December 7, 2020" "vifm 0.11" .\" --------------------------------------------------------------------------- .SH NAME .\" --------------------------------------------------------------------------- @@ -1027,7 +1027,7 @@ scroll to the beginning of the file (or N percent into file). .TP .BI v invoke an editor to edit the current file being viewed. The command for editing -is taken from the 'vicmd'/'vixcmd' option value and extended with middle line +is taken from the 'vicmd' or 'vixcmd' option value and extended with middle line number prepended by a plus sign and name of the current file. .LP All "Ctrl-W x" keys work the same was as in Normal mode. Active mode is @@ -4245,6 +4245,26 @@ scope: local .br Minimal number of characters for line number field. .TP +.BI "'previewoptions'" +type: string list +.br +default: "graphicsdelay:50000" +.br + +Tweaks how previewing is done (in quick view, miller view's column and +view mode). + + item default meaning + graphicsdelay:num 0 delay before drawing graphics (microseconds) + hardgraphicsclear unset redraw screen to get rid of graphics + +graphicsdelay is needed if terminal requires some timeout before it can +draw graphics (otherwise it gets lost). + +hardgraphicsclear seems to be necessary to get rid of sixel graphics in some +terminals, where it otherwise lingers. This can cause flicker on the screen +due to erasure followed by redrawing. +.TP .BI "'previewprg'" type: string .br diff --git a/data/vim/doc/app/vifm-app.txt b/data/vim/doc/app/vifm-app.txt index 58352091a..f0f51ebc1 100644 --- a/data/vim/doc/app/vifm-app.txt +++ b/data/vim/doc/app/vifm-app.txt @@ -1,4 +1,4 @@ -*vifm-app.txt* For Vifm version 0.11 Last change: 2020 Nov 28 +*vifm-app.txt* For Vifm version 0.11 Last change: 2020 Dec 7 Email for bugs and suggestions: @@ -907,7 +907,7 @@ i *vifm-q_i* v *vifm-q_v* invoke an editor to edit the current file being viewed. The command for - editing is taken from the |vifm-'vicmd'|/|vifm-'vixcmd'| option value and + editing is taken from the |vifm-'vicmd'| or |vifm-'vixcmd'| option value and extended with middle line number prepended by a plus sign and name of the current file. @@ -3559,6 +3559,27 @@ scope: local Minimal number of characters for line number field. + *vifm-'previewoptions'* +previewoptions +type: string list +default: "graphicsdelay:50000" + +Tweaks how previewing is done (in quick view, miller view's column and +view mode). + + item default meaning ~ + graphicsdelay:num 0 delay before drawing graphics (microseconds) + hardgraphicsclear unset redraw screen to get rid of graphics + +graphicsdelay is needed if terminal requires some timeout before it can +draw graphics (otherwise it gets lost). + +hardgraphicsclear seems to be necessary to get rid of sixel graphics in some +terminals, where it otherwise lingers. This can cause flicker on the screen +due to erasure followed by redrawing. + +Default value is used when item is missing from the option. + *vifm-'previewprg'* previewprg type: string diff --git a/data/vim/syntax/vifm.vim b/data/vim/syntax/vifm.vim index ce2aeed04..e51cdc1c5 100644 --- a/data/vim/syntax/vifm.vim +++ b/data/vim/syntax/vifm.vim @@ -1,6 +1,6 @@ " vifm syntax file " Maintainer: xaizek -" Last Change: October 6, 2020 +" Last Change: December 6, 2020 " Inspired By: Vim syntax file by Dr. Charles E. Campbell, Jr. if exists('b:current_syntax') @@ -141,13 +141,14 @@ syntax keyword vifmOption contained aproposprg autochpos caseoptions cdpath cd \ followlinks fusehome gdefault grepprg histcursor history hi hlsearch hls \ iec ignorecase ic iooptions incsearch is laststatus lines locateprg ls \ lsoptions lsview mediaprg milleroptions millerview mintimeoutlen number nu - \ numberwidth nuw previewprg quickview relativenumber rnu rulerformat ruf - \ runexec scrollbind scb scrolloff sessionoptions ssop so sort sortgroups - \ sortorder sortnumbers shell sh shellflagcmd shcf shortmess shm showtabline - \ stal sizefmt slowfs smartcase scs statusline stl suggestoptions syncregs - \ syscalls tablabel tabprefix tabscope tabstop tabsuffix timefmt timeoutlen - \ title tm trash trashdir ts tuioptions to undolevels ul vicmd viewcolumns - \ vifminfo vimhelp vixcmd wildmenu wmnu wildstyle wordchars wrap wrapscan ws + \ numberwidth nuw previewoptions previewprg quickview relativenumber rnu + \ rulerformat ruf runexec scrollbind scb scrolloff sessionoptions ssop so + \ sort sortgroups sortorder sortnumbers shell sh shellflagcmd shcf shortmess + \ shm showtabline stal sizefmt slowfs smartcase scs statusline stl + \ suggestoptions syncregs syscalls tablabel tabprefix tabscope tabstop + \ tabsuffix timefmt timeoutlen title tm trash trashdir ts tuioptions to + \ undolevels ul vicmd viewcolumns vifminfo vimhelp vixcmd wildmenu wmnu + \ wildstyle wordchars wrap wrapscan ws " Disabled boolean options syntax keyword vifmOption contained noautochpos nocf nochaselinks nodotfiles diff --git a/src/cfg/config.c b/src/cfg/config.c index d64f27c32..ef9abc3e8 100644 --- a/src/cfg/config.c +++ b/src/cfg/config.c @@ -192,6 +192,9 @@ cfg_init(void) cfg.chase_links = 0; + cfg.graphics_delay = 50000; + cfg.hard_graphics_clear = 0; + cfg.timeout_len = 1000; cfg.min_timeout_len = 150; diff --git a/src/cfg/config.h b/src/cfg/config.h index 886a0271c..7bc753f3e 100644 --- a/src/cfg/config.h +++ b/src/cfg/config.h @@ -295,6 +295,11 @@ typedef struct config_t * link expanded). */ int chase_links; + /* Delay before redrawing graphics in microseconds. */ + int graphics_delay; + /* Redraw screen to get rid of graphics. */ + int hard_graphics_clear; + int timeout_len; /* Maximum period on waiting for the input. */ int min_timeout_len; /* Minimum period on waiting for the input. */ diff --git a/src/cfg/info.c b/src/cfg/info.c index 377d3c245..26284c2bb 100644 --- a/src/cfg/info.c +++ b/src/cfg/info.c @@ -2242,6 +2242,8 @@ store_global_options(JSON_Object *root) append_dstr(options, format_str("rulerformat=%s", escape_spaces(cfg.ruler_format))); append_dstr(options, format_str("%srunexec", cfg.auto_execute ? "" : "no")); + append_dstr(options, format_str("previewoptions=%s", + escape_spaces(vle_opts_get("previewoptions", OPT_GLOBAL)))); append_dstr(options, format_str("%sscrollbind", cfg.scroll_bind ? "" : "no")); append_dstr(options, format_str("scrolloff=%d", cfg.scroll_off)); append_dstr(options, format_str("shell=%s", escape_spaces(cfg.shell))); diff --git a/src/cmd_handlers.c b/src/cmd_handlers.c index d3dbb912d..2eb1a94c0 100644 --- a/src/cmd_handlers.c +++ b/src/cmd_handlers.c @@ -30,7 +30,7 @@ #include #include #include /* NULL size_t */ -#include /* pclose() popen() snprintf() */ +#include /* snprintf() */ #include /* EXIT_SUCCESS atoi() free() realloc() */ #include /* strchr() strcmp() strcspn() strcasecmp() strcpy() strdup() strlen() strrchr() */ diff --git a/src/modes/file_info.c b/src/modes/file_info.c index e00da55cb..2a1edd439 100644 --- a/src/modes/file_info.c +++ b/src/modes/file_info.c @@ -65,7 +65,6 @@ static void cmd_ctrl_c(key_info_t key_info, keys_info_t *keys_info); static void cmd_ctrl_l(key_info_t key_info, keys_info_t *keys_info); static view_t *view; -static int was_redraw; static keys_add_info_t builtin_cmds[] = { {WK_C_c, {{&cmd_ctrl_c}, .descr = "hide file info"}}, @@ -103,8 +102,6 @@ modfinfo_enter(view_t *v) view = v; ui_setup_for_menu_like(); modfinfo_redraw(); - - was_redraw = 0; } void @@ -117,16 +114,7 @@ static void leave_file_info_mode(void) { vle_mode_set(NORMAL_MODE, VMT_PRIMARY); - - if(was_redraw) - { - update_screen(UT_FULL); - } - else - { - ui_view_title_update(curr_view); - update_all_windows(); - } + stats_redraw_later(); } void @@ -217,8 +205,6 @@ modfinfo_redraw(void) wprint(menu_win, " File Information "); ui_refresh_win(menu_win); checked_wmove(menu_win, 2, 2); - - was_redraw = 1; } /* Prints item prefixed with a label truncating the item if it's too long. diff --git a/src/modes/more.c b/src/modes/more.c index a3003d298..39ab02081 100644 --- a/src/modes/more.c +++ b/src/modes/more.c @@ -60,9 +60,6 @@ static void goto_vline(int line); static void goto_vline_below(int by); static void goto_vline_above(int by); -/* Whether UI was redrawn while this mode was active. */ -static int was_redraw; - /* Text displayed by the mode. */ static char *text; /* (first virtual line, screen width, offset in text) triples per real line. */ @@ -134,7 +131,6 @@ modmore_enter(const char txt[]) vle_mode_set(MORE_MODE, VMT_PRIMARY); modmore_redraw(); - was_redraw = 0; } void @@ -186,15 +182,7 @@ leave_more_mode(void) data = NULL; vle_mode_set(NORMAL_MODE, VMT_PRIMARY); - - if(was_redraw) - { - update_screen(UT_FULL); - } - else - { - update_all_windows(); - } + stats_redraw_later(); } void @@ -213,8 +201,6 @@ modmore_redraw(void) draw_all(get_text_beginning()); checked_wmove(menu_win, 0, 0); - - was_redraw = 1; } /* Retrieves beginning of the text that should be displayed. Returns the @@ -261,8 +247,6 @@ draw_all(const char text[]) /* Apply all changes. */ doupdate(); - - was_redraw = 1; } /* Leaves the mode. */ diff --git a/src/modes/view.c b/src/modes/view.c index 97e34fc2b..c8b81912e 100644 --- a/src/modes/view.c +++ b/src/modes/view.c @@ -1112,7 +1112,7 @@ get_view_data(modview_info_t *vi, const char file_to_view[]) { /* Wait a bit to let terminal emulator do actual refresh (at least some of * them need this). */ - usleep(50000); + usleep(cfg.graphics_delay); } const char *error; diff --git a/src/opt_handlers.c b/src/opt_handlers.c index 52a4e6a3d..49cbe72a3 100644 --- a/src/opt_handlers.c +++ b/src/opt_handlers.c @@ -92,6 +92,7 @@ static void init_lsoptions(optval_t *val); static void init_lsview(optval_t *val); static void init_milleroptions(optval_t *val); static void init_millerview(optval_t *val); +static void init_previewoptions(optval_t *val); static void init_quickview(optval_t *val); static void init_shortmess(optval_t *val); static void init_sizefmt(optval_t *val); @@ -147,6 +148,7 @@ static void mediaprg_handler(OPT_OP op, optval_t val); #endif static void mintimeoutlen_handler(OPT_OP op, optval_t val); static void scroll_line_down(view_t *view); +static void previewoptions_handler(OPT_OP op, optval_t val); static void quickview_handler(OPT_OP op, optval_t val); static void rulerformat_handler(OPT_OP op, optval_t val); static void runexec_handler(OPT_OP op, optval_t val); @@ -328,6 +330,12 @@ static const char *lsoptions_enum[][2] = { { "transposed", "fill grid by column instead of by line" }, }; +/* Possible values of 'previewoptions'. */ +static const char *previewoptions_vals[][2] = { + { "graphicsdelay:", "delay before drawing graphics" }, + { "hardgraphicsclear", "redraw screen to get rid of graphics" }, +}; + /* Possible values of 'suggestoptions'. */ static const char *suggestoptions_vals[][2] = { [BIT(SF_NORMAL)] = { "normal", "display in normal mode" }, @@ -701,6 +709,11 @@ options[] = { OPT_INT, 0, NULL, &mintimeoutlen_handler, NULL, { .ref.int_val = &cfg.min_timeout_len }, }, + { "previewoptions", "", "tweaks for how preview is done", + OPT_STRLIST, ARRAY_LEN(previewoptions_vals), previewoptions_vals, + &previewoptions_handler, NULL, + { .init = &init_previewoptions }, + }, { "quickview", "", "whether quick view is active", OPT_BOOL, 0, NULL, &quickview_handler, NULL, { .init = &init_quickview }, @@ -766,7 +779,7 @@ options[] = { OPT_STR, 0, NULL, &statusline_handler, NULL, { .ref.str_val = &cfg.status_line }, }, - { "suggestoptions", "", "when to display key suggestions", + { "suggestoptions", "", "when and how to display key suggestions", OPT_STRLIST, ARRAY_LEN(suggestoptions_vals), suggestoptions_vals, &suggestoptions_handler, NULL, { .ref.str_val = &empty }, @@ -1158,6 +1171,28 @@ init_millerview(optval_t *val) val->bool_val = curr_view->miller_view_g; } +/* Initializes 'previewoptions' option from global state. */ +static void +init_previewoptions(optval_t *val) +{ + static char buf[64]; + + size_t len = 0U; + buf[0] = '\0'; + + if(cfg.hard_graphics_clear) + { + (void)sstrappend(buf, &len, sizeof(buf), "hardgraphicsclear"); + } + if(cfg.graphics_delay != 0) + { + snprintf(buf + len, sizeof(buf) - len, "graphicsdelay:%d", + cfg.graphics_delay); + } + + val->str_val = buf; +} + /* Initializes 'quickview' option from global state. */ static void init_quickview(optval_t *val) @@ -2239,6 +2274,60 @@ scroll_line_down(view_t *view) wresize(view->win, view->window_rows, view->window_cols); } +/* Handles updates of the 'previewoptions' option. */ +static void +previewoptions_handler(OPT_OP op, optval_t val) +{ + char *new_val = strdup(val.str_val); + char *part = new_val, *state = NULL; + + int graphics_delay = 0; + int hard_graphics_clear = 0; + + while((part = split_and_get(part, ',', &state)) != NULL) + { + if(starts_with_lit(part, "graphicsdelay:")) + { + const char *const num = after_first(part, ':'); + if(!read_int(num, &graphics_delay)) + { + vle_tb_append_linef(vle_err, + "Failed to parse \"graphicsdelay\" value: %s", num); + break; + } + if(graphics_delay < 0) + { + vle_tb_append_linef(vle_err, + "\"graphicsdelay\" can't be negative, got: %s", num); + break; + } + } + else if(strcmp(part, "hardgraphicsclear") == 0) + { + hard_graphics_clear = 1; + } + else + { + break_at(part, ':'); + vle_tb_append_linef(vle_err, + "Unknown key for 'previewoptions' option: %s", part); + break; + } + } + free(new_val); + + if(part == NULL) + { + cfg.graphics_delay = graphics_delay; + cfg.hard_graphics_clear = hard_graphics_clear; + } + + /* In case of error, restore previous value, otherwise reload it anyway to + * remove any duplicates. */ + init_previewoptions(&val); + vle_opts_assign("previewoptions", val, OPT_GLOBAL); +} + /* Handles switch that controls visibility of quick view. */ static void quickview_handler(OPT_OP op, optval_t val) diff --git a/src/signals.c b/src/signals.c index 203d69924..f2c6b0348 100644 --- a/src/signals.c +++ b/src/signals.c @@ -186,7 +186,7 @@ setup_signals(void) /* Assumption: we work under shell with job control support. If it's not the * case, this code enables handling of terminal related signals the shell - * wanted us to have disabled (e.g. the app will catch Ctrl-C send to another + * wanted us to have disabled (e.g., the app will catch Ctrl-C sent to another * process). */ sigaction(SIGCHLD, &handle_signal_action, NULL); diff --git a/src/tags.c b/src/tags.c index ac101accf..a63801c86 100644 --- a/src/tags.c +++ b/src/tags.c @@ -85,6 +85,7 @@ const char *tags[] = { "vifm-'number'", "vifm-'numberwidth'", "vifm-'nuw'", + "vifm-'previewoptions'", "vifm-'previewprg'", "vifm-'quickview'", "vifm-'relativenumber'", diff --git a/src/ui/quickview.c b/src/ui/quickview.c index a4b40f752..b435dbec2 100644 --- a/src/ui/quickview.c +++ b/src/ui/quickview.c @@ -328,7 +328,7 @@ view_file(const char path[], const preview_area_t *parea, if(kind != VK_TEXTUAL) { cleanup_area(parea, curr_stats.preview.cleanup_cmd); - usleep(50000); + usleep(cfg.graphics_delay); } else { @@ -815,6 +815,12 @@ cleanup_area(const preview_area_t *parea, const char cmd[]) static void wipe_area(const preview_area_t *parea) { + if(cfg.hard_graphics_clear) + { + wclear(parea->view->win); + return; + } + /* User doesn't need to see fake filling so draw it with the color of * background. */ col_attr_t col = { .fg = parea->def_col.fg, .bg = parea->def_col.bg }; diff --git a/tests/misc/options.c b/tests/misc/options.c index f02743598..09da27856 100644 --- a/tests/misc/options.c +++ b/tests/misc/options.c @@ -726,5 +726,43 @@ TEST(sessionoptions) assert_int_equal(0, cfg.session_options); } +TEST(previewoptions) +{ + assert_success(exec_commands("set previewoptions=graphicsdelay:12345", &lwin, + CIT_COMMAND)); + assert_int_equal(12345, cfg.graphics_delay); + assert_false(cfg.hard_graphics_clear); + + assert_failure(exec_commands("set previewoptions=graphicsdelay:inf", &lwin, + CIT_COMMAND)); + assert_int_equal(12345, cfg.graphics_delay); + assert_false(cfg.hard_graphics_clear); + assert_string_equal("Failed to parse \"graphicsdelay\" value: inf", + vle_tb_get_data(vle_err)); + + assert_failure(exec_commands("set previewoptions=graphicsdelay:-12345", &lwin, + CIT_COMMAND)); + assert_int_equal(12345, cfg.graphics_delay); + assert_false(cfg.hard_graphics_clear); + assert_string_equal("\"graphicsdelay\" can't be negative, got: -12345", + vle_tb_get_data(vle_err)); + + assert_failure(exec_commands("set previewoptions=graphicsdelay:145,wtf", + &lwin, CIT_COMMAND)); + assert_int_equal(12345, cfg.graphics_delay); + assert_false(cfg.hard_graphics_clear); + assert_string_equal("Unknown key for 'previewoptions' option: wtf", + vle_tb_get_data(vle_err)); + + assert_success(exec_commands("set previewoptions=hardgraphicsclear", &lwin, + CIT_COMMAND)); + assert_int_equal(0, cfg.graphics_delay); + assert_true(cfg.hard_graphics_clear); + + assert_success(exec_commands("set previewoptions=", &lwin, CIT_COMMAND)); + assert_int_equal(0, cfg.graphics_delay); + assert_false(cfg.hard_graphics_clear); +} + /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set cinoptions+=t0 filetype=c : */ diff --git a/tests/test-data/syntax-highlight/syntax.vifm b/tests/test-data/syntax-highlight/syntax.vifm index 702a35e96..95a7cc8fb 100644 --- a/tests/test-data/syntax-highlight/syntax.vifm +++ b/tests/test-data/syntax-highlight/syntax.vifm @@ -521,6 +521,7 @@ hi OddLine " "sessionoptions" and "ssop" should be highlighted as 'option' " "tabprefix" should be highlighted as 'option' " "tabsuffix" should be highlighted as 'option' +" "previewoptions" should be highlighted as 'option' set dotfiles nodotfiles invdotfiles dotfiles! set caseoptions set sizefmt @@ -539,6 +540,7 @@ set tablabel set sessionoptions ssop set tabprefix set tabsuffix +set previewoptions " "term" should be highlighted as a function() echo term('cmd')