History

msg: allow to truncate the message to terminal width

Kacper Michajłow committed 2 years ago

Commit bf025cd1 parent 95f00469 files · +106 −15Browse files

Unified · Split

9 files
  1. DOCS/interface-changes/term-clip-cc.txt +1 −0
  2. DOCS/man/input.rst +5 −0
  3. common/msg.c +33 −4
  4. common/msg.h +2 −0
  5. misc/codepoint_width.c +27 −9
  6. misc/codepoint_width.h +4 −1
  7. player/command.c +8 −0
  8. sub/osd_libass.c +4 −0
  9. test/codepoint_width.c +22 −1
DOCS/interface-changes/term-clip-cc.txt+1−0
@@ -0,0 +1 @@
1add `term-clip-cc`
DOCS/man/input.rst+5−0
@@ -3377,6 +3377,11 @@ Property list · 3376 unmodified lines
3377 See ``--cursor-autohide``. Setting this to a new value will always update3377 See ``--cursor-autohide``. Setting this to a new value will always update
3378 the cursor, and reset the internal timer.3378 the cursor, and reset the internal timer.
3379 3379
3380``term-clip-cc``
3381 Inserts the symbol to force line truncation to the current terminal width.
3382 This can be used for ``show-text`` and other OSD messages. It must be the
3383 first character in the line. It takes effect until the end of the line.
3384
3380``osd-sym-cc``3385``osd-sym-cc``
3381 Inserts the current OSD symbol as opaque OSD control code (cc). This makes3386 Inserts the current OSD symbol as opaque OSD control code (cc). This makes
3382 sense only with the ``show-text`` command or options which set OSD messages.3387 sense only with the ``show-text`` command or options which set OSD messages.
common/msg.c+33−4
@@ -374,7 +374,7 @@ static bool test_terminal_level(struct mp_log *log, int lev) · 373 unmodified lines
374}374}
375 375
376static void append_terminal_line(struct mp_log *log, int lev,376static void append_terminal_line(struct mp_log *log, int lev,
377 bstr text, bstr *term_msg, int *line_w)377 bstr text, bstr *term_msg, int *line_w, int term_w)
378{378{
379 struct mp_log_root *root = log->root;379 struct mp_log_root *root = log->root;
380 380
@@ -394,8 +394,35 @@ static void append_terminal_line(struct mp_log *log, int lev, · 13 unmodified lines
394 }394 }
395 395
396 bstr_xappend(root, term_msg, text);396 bstr_xappend(root, term_msg, text);
397
398 const unsigned char *cut_pos = NULL;
399 int width = term_disp_width(bstr_splice(*term_msg, start, term_msg->len),
400 term_w - 3, &cut_pos);
401 if (cut_pos) {
402 int new_len = cut_pos - term_msg->start;
403 bstr rem = {(unsigned char *)cut_pos, term_msg->len - new_len};
404 term_msg->len = new_len;
405
406 bstr_xappend(root, term_msg, bstr0("..."));
407
408 while (rem.len) {
409 if (bstr_eatstart0(&rem, "\033[")) {
410 bstr_xappend(root, term_msg, bstr0("\033["));
411
412 while (rem.len && !((*rem.start >= '@' && *rem.start <= '~') || *rem.start == 'm')) {
413 bstr_xappend(root, term_msg, bstr_splice(rem, 0, 1));
414 rem = bstr_cut(rem, 1);
415 }
416 bstr_xappend(root, term_msg, bstr_splice(rem, 0, 1));
417 }
418 rem = bstr_cut(rem, 1);
419 }
420
421 bstr_xappend(root, term_msg, bstr0("\n"));
422 width += 3;
423 }
397 *line_w = root->isatty[term_msg_fileno(root, lev)]424 *line_w = root->isatty[term_msg_fileno(root, lev)]
398 ? term_disp_width(bstr_splice(*term_msg, start, term_msg->len)) : 0;425 ? width : 0;
399}426}
400 427
401static struct mp_log_buffer_entry *log_buffer_read(struct mp_log_buffer *buffer)428static struct mp_log_buffer_entry *log_buffer_read(struct mp_log_buffer *buffer)
@@ -496,7 +523,8 @@ static void write_term_msg(struct mp_log *log, int lev, bstr text, bstr *out) · 94 unmodified lines
496 523
497 if (print_term) {524 if (print_term) {
498 int line_w;525 int line_w;
499 append_terminal_line(log, lev, line, &root->term_msg_tmp, &line_w);526 append_terminal_line(log, lev, line, &root->term_msg_tmp, &line_w,
527 bstr_eatstart0(&line, TERM_MSG_0) ? term_w : INT_MAX);
500 term_msg_lines += (!line_w || !term_w)528 term_msg_lines += (!line_w || !term_w)
501 ? 1 : (line_w + term_w - 1) / term_w;529 ? 1 : (line_w + term_w - 1) / term_w;
502 }530 }
@@ -506,7 +534,8 @@ static void write_term_msg(struct mp_log *log, int lev, bstr text, bstr *out) · 3 unmodified lines
506 if (lev == MSGL_STATUS) {534 if (lev == MSGL_STATUS) {
507 int line_w = 0;535 int line_w = 0;
508 if (str.len && print_term)536 if (str.len && print_term)
509 append_terminal_line(log, lev, str, &root->term_msg_tmp, &line_w);537 append_terminal_line(log, lev, str, &root->term_msg_tmp, &line_w,
538 bstr_eatstart0(&str, TERM_MSG_0) ? term_w : INT_MAX);
510 term_msg_lines += !term_w ? (str.len ? 1 : 0)539 term_msg_lines += !term_w ? (str.len ? 1 : 0)
511 : (line_w + term_w - 1) / term_w;540 : (line_w + term_w - 1) / term_w;
512 } else if (str.len) {541 } else if (str.len) {
common/msg.h+2−0
@@ -25,6 +25,8 @@ · 24 unmodified lines
25 25
26#include "osdep/compiler.h"26#include "osdep/compiler.h"
27 27
28#define TERM_MSG_0 "\xFC"
29
28struct mp_log;30struct mp_log;
29 31
30// A mp_log instance that never outputs anything.32// A mp_log instance that never outputs anything.
misc/codepoint_width.c+27−9
@@ -662,20 +662,26 @@ static int ucdToCharacterWidth(const int val) · 661 unmodified lines
662 * License along with mpv. If not, see <http://www.gnu.org/licenses/>.662 * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
663 */663 */
664 664
665int term_disp_width(bstr str)665#include "common/common.h"
666
667int term_disp_width(bstr str, int max_width, const unsigned char **cut_pos)
666{668{
667 static const int ambiguous_width = 1;669 static const int ambiguous_width = 1;
668 670
669 int width = 0;671 int width = 0;
670 672
673 const unsigned char *prev_pos = str.start;
671 while (str.len) {674 while (str.len) {
675 int current_width = 0;
676
672 if (bstr_eatstart0(&str, "\033[")) {677 if (bstr_eatstart0(&str, "\033[")) {
673 while (str.len && !((*str.start >= '@' && *str.start <= '~') || *str.start == 'm'))678 while (str.len && !((*str.start >= '@' && *str.start <= '~') || *str.start == 'm'))
674 str = bstr_cut(str, 1);679 str = bstr_cut(str, 1);
675 str = bstr_cut(str, 1);680 str = bstr_cut(str, 1);
676 continue;681 goto next;
677 }682 }
678 683
684 prev_pos = str.start;
679 int cp = bstr_decode_utf8(str, &str);685 int cp = bstr_decode_utf8(str, &str);
680 686
681 // Stop processing on any invalid input687 // Stop processing on any invalid input
@@ -684,18 +690,17 @@ int term_disp_width(bstr str) · 2 unmodified lines
684 690
685 if (cp == '\r') {691 if (cp == '\r') {
686 width = 0;692 width = 0;
687 continue;693 goto next;
688 }694 }
689 695
690 if (cp < 0x20)696 if (cp < 0x20)
691 continue;697 goto next;
692 698
693 if (cp <= 0x7E) {699 if (cp <= 0x7E) {
694 width++;700 current_width = 1;
695 continue;701 goto next;
696 }702 }
697 703
698 int grapheme_width = 0;
699 int state = 0;704 int state = 0;
700 705
701 while (true) {706 while (true) {
@@ -711,7 +716,7 @@ int term_disp_width(bstr str) · 9 unmodified lines
711 if (cp == 0xFE0F)716 if (cp == 0xFE0F)
712 w = 2;717 w = 2;
713 718
714 grapheme_width += w;719 current_width += w;
715 720
716 if (!str.len)721 if (!str.len)
717 break;722 break;
@@ -730,7 +735,20 @@ int term_disp_width(bstr str) · 12 unmodified lines
730 735
731 str = cluster_end;736 str = cluster_end;
732 }737 }
733 width += grapheme_width > 2 ? 2 : grapheme_width;738
739next:
740 current_width = MPMIN(current_width, 2);
741 if (width + current_width > max_width) {
742 assert(prev_pos < str.start + str.len);
743 *cut_pos = prev_pos;
744 break;
745 }
746 width += current_width;
747 if (width == max_width) {
748 if (str.len)
749 *cut_pos = str.start;
750 break;
751 }
734 }752 }
735 753
736 return width;754 return width;
misc/codepoint_width.h+4−1
@@ -6,6 +6,9 @@ · 5 unmodified lines
6 * @brief Determines the number of columns required to display a given string.6 * @brief Determines the number of columns required to display a given string.
7 *7 *
8 * @param str Sequence of UTF-8 chars8 * @param str Sequence of UTF-8 chars
9 * @param max_width Maximum allowed width of string
10 * @param cut_pos If max_width is exceeded, this will be initialized to last
11 * full printable character before width limit.
9 * @return int width of the string12 * @return int width of the string
10 */13 */
11int term_disp_width(bstr str);14int term_disp_width(bstr str, int max_width, const unsigned char **cut_pos);
player/command.c+8−0
@@ -2926,6 +2926,12 @@ static int mp_property_osd_ass(void *ctx, struct m_property *prop, · 2925 unmodified lines
2926 return m_property_read_sub(props, action, arg);2926 return m_property_read_sub(props, action, arg);
2927}2927}
2928 2928
2929static int mp_property_term_clip(void *ctx, struct m_property *prop,
2930 int action, void *arg)
2931{
2932 return m_property_strdup_ro(action, arg, TERM_MSG_0);
2933}
2934
2929static int mp_property_term_size(void *ctx, struct m_property *prop,2935static int mp_property_term_size(void *ctx, struct m_property *prop,
2930 int action, void *arg)2936 int action, void *arg)
2931{2937{
@@ -4159,6 +4165,8 @@ static const struct m_property mp_properties_base[] = { · 1227 unmodified lines
4159 {"osd-sym-cc", mp_property_osd_sym},4165 {"osd-sym-cc", mp_property_osd_sym},
4160 {"osd-ass-cc", mp_property_osd_ass},4166 {"osd-ass-cc", mp_property_osd_ass},
4161 4167
4168 {"term-clip-cc", mp_property_term_clip},
4169
4162 {"mouse-pos", mp_property_mouse_pos},4170 {"mouse-pos", mp_property_mouse_pos},
4163 {"touch-pos", mp_property_touch_pos},4171 {"touch-pos", mp_property_touch_pos},
4164 4172
sub/osd_libass.c+4−0
@@ -207,6 +207,10 @@ void osd_mangle_ass(bstr *dst, const char *in, bool replace_newlines) · 206 unmodified lines
207 in += 1;207 in += 1;
208 continue;208 continue;
209 }209 }
210 if (*in == TERM_MSG_0[0]) {
211 in += 1;
212 continue;
213 }
210 if (escape_ass && *in == '{')214 if (escape_ass && *in == '{')
211 bstr_xappend(NULL, dst, bstr0("\\"));215 bstr_xappend(NULL, dst, bstr0("\\"));
212 // Replace newlines with \N for escape-ass. This is necessary to apply216 // Replace newlines with \N for escape-ass. This is necessary to apply
test/codepoint_width.c+22−1
@@ -17,9 +17,11 @@ · 16 unmodified lines
17 17
18#include "test_utils.h"18#include "test_utils.h"
19 19
20#include <limits.h>
21
20#include "misc/codepoint_width.h"22#include "misc/codepoint_width.h"
21 23
22#define W(s) term_disp_width((bstr)bstr0_lit(s))24#define W(s) term_disp_width((bstr)bstr0_lit(s), INT_MAX, &(const unsigned char *){NULL})
23 25
24int main(void) {26int main(void) {
25 assert_int_equal(W("A"), 1); // Single ASCII character27 assert_int_equal(W("A"), 1); // Single ASCII character
@@ -64,4 +66,23 @@ int main(void) { · 38 unmodified lines
64 66
65 // ASCII characters with carriage return67 // ASCII characters with carriage return
66 assert_int_equal(W("ABC\rDEF"), 3);68 assert_int_equal(W("ABC\rDEF"), 3);
69
70 bstr str = bstr0("ABCDEF");
71 const unsigned char *cut_pos;
72
73 cut_pos = NULL;
74 assert_int_equal(term_disp_width(str, 3, &cut_pos), 3);
75 assert_int_equal(cut_pos - str.start, 3);
76
77 cut_pos = NULL;
78 assert_int_equal(term_disp_width(str, -2, &cut_pos), 0);
79 assert_int_equal(cut_pos - str.start, 0);
80
81 cut_pos = NULL;
82 assert_int_equal(term_disp_width(str, str.len, &cut_pos), 6);
83 if (cut_pos) {
84 printf("%s:%d: cut_pos != NULL\n", __FILE__, __LINE__);
85 fflush(stdout);
86 abort();
87 }
67}88}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t