comparison lisp/subr.el @ 5664:00fd55d635fb

Sync #'truncate-string-to-width with GNU, add tests for it. lisp/ChangeLog addition: 2012-05-12 Aidan Kehoe <kehoea@parhasard.net> * subr.el: * subr.el (truncate-string-to-width): Sync with GNU's version, use its test suite in mule-tests.el. tests/ChangeLog addition: 2012-05-12 Aidan Kehoe <kehoea@parhasard.net> * automated/mule-tests.el: Test #'truncate-string-to-width, thank you Colin Walters.
author Aidan Kehoe <kehoea@parhasard.net>
date Sat, 12 May 2012 17:51:05 +0100
parents b7ae5f44b950
children 8593e614573a
comparison
equal deleted inserted replaced
5663:0df4d95bd98a 5664:00fd55d635fb
1028 "Embed OBJ (string or character) at index IDX of STRING." 1028 "Embed OBJ (string or character) at index IDX of STRING."
1029 (if (stringp obj) 1029 (if (stringp obj)
1030 (replace (the string string) obj :start1 idx) 1030 (replace (the string string) obj :start1 idx)
1031 (prog1 string (aset string idx obj)))) 1031 (prog1 string (aset string idx obj))))
1032 1032
1033 ;; From FSF 21.1; ELLIPSES is XEmacs addition. 1033 ;; XEmacs; this is in mule-util in GNU. See tests/automated/mule-tests.el for
1034 1034 ;; the tests that Colin Walters includes in that file.
1035 (defun truncate-string-to-width (str end-column &optional start-column padding 1035 (defun truncate-string-to-width (str end-column
1036 ellipses) 1036 &optional start-column padding ellipsis)
1037 "Truncate string STR to end at column END-COLUMN. 1037 "Truncate string STR to end at column END-COLUMN.
1038 The optional 3rd arg START-COLUMN, if non-nil, specifies 1038 The optional 3rd arg START-COLUMN, if non-nil, specifies the starting
1039 the starting column; that means to return the characters occupying 1039 column; that means to return the characters occupying columns
1040 columns START-COLUMN ... END-COLUMN of STR. 1040 START-COLUMN ... END-COLUMN of STR. Both END-COLUMN and START-COLUMN
1041 1041 are specified in terms of character display width in the current
1042 The optional 4th arg PADDING, if non-nil, specifies a padding character 1042 buffer; see also `char-width'.
1043 to add at the end of the result if STR doesn't reach column END-COLUMN, 1043
1044 or if END-COLUMN comes in the middle of a character in STR. 1044 The optional 4th arg PADDING, if non-nil, specifies a padding
1045 PADDING is also added at the beginning of the result 1045 character (which should have a display width of 1) to add at the end
1046 if column START-COLUMN appears in the middle of a character in STR. 1046 of the result if STR doesn't reach column END-COLUMN, or if END-COLUMN
1047 comes in the middle of a character in STR. PADDING is also added at
1048 the beginning of the result if column START-COLUMN appears in the
1049 middle of a character in STR.
1047 1050
1048 If PADDING is nil, no padding is added in these cases, so 1051 If PADDING is nil, no padding is added in these cases, so
1049 the resulting string may be narrower than END-COLUMN. 1052 the resulting string may be narrower than END-COLUMN.
1050 1053
1051 BUG: Currently assumes that the padding character is of width one. You 1054 If ELLIPSIS is non-nil, it should be a string which will replace the
1052 will get weird results if not. 1055 end of STR (including any padding) if it extends beyond END-COLUMN,
1053 1056 unless the display width of STR is equal to or less than the display
1054 If ELLIPSES is non-nil, add ellipses (specified by ELLIPSES if a string, 1057 width of ELLIPSIS. If it is non-nil and not a string, then ELLIPSIS
1055 else `...') if STR extends past END-COLUMN. The ellipses will be added in 1058 defaults to \"...\"."
1056 such a way that the total string occupies no more than END-COLUMN columns
1057 -- i.e. if the string goes past END-COLUMN, it will be truncated somewhere
1058 short of END-COLUMN so that, with the ellipses added (and padding, if the
1059 proper place to truncate the string would be in the middle of a character),
1060 the string occupies exactly END-COLUMN columns."
1061 (or start-column 1059 (or start-column
1062 (setq start-column 0)) 1060 (setq start-column 0))
1063 (let ((len (length str)) 1061 (when (and ellipsis (not (stringp ellipsis)))
1062 (setq ellipsis "..."))
1063 (let ((str-len (length str))
1064 (str-width (string-width str))
1065 (ellipsis-len (if ellipsis (length ellipsis) 0))
1066 (ellipsis-width (if ellipsis (string-width ellipsis) 0))
1064 (idx 0) 1067 (idx 0)
1065 (column 0) 1068 (column 0)
1066 (head-padding "") (tail-padding "") 1069 (head-padding "") (tail-padding "")
1067 ch last-column last-idx from-idx) 1070 ch last-column last-idx from-idx)
1068
1069 ;; find the index of START-COLUMN; bail out if end of string reached.
1070 (condition-case nil 1071 (condition-case nil
1071 (while (< column start-column) 1072 (while (< column start-column)
1072 (setq ch (aref str idx) 1073 (setq ch (aref str idx)
1073 column (+ column (char-width ch)) 1074 column (+ column (char-width ch))
1074 idx (1+ idx))) 1075 idx (1+ idx)))
1075 (args-out-of-range (setq idx len))) 1076 (args-out-of-range (setq idx str-len)))
1076 (if (< column start-column) 1077 (if (< column start-column)
1077 ;; if string ends before START-COLUMN, return either a blank string 1078 (if padding (make-string end-column padding) "")
1078 ;; or a string entirely padded. 1079 (when (and padding (> column start-column))
1079 (if padding (make-string (- end-column start-column) padding) "") 1080 (setq head-padding (make-string (- column start-column) padding)))
1080 (if (and padding (> column start-column))
1081 (setq head-padding (make-string (- column start-column) padding)))
1082 (setq from-idx idx) 1081 (setq from-idx idx)
1083 ;; If END-COLUMN is before START-COLUMN, then bail out. 1082 (when (>= end-column column)
1084 (if (< end-column column) 1083 (if (and (< end-column str-width)
1085 (setq idx from-idx ellipses "") 1084 (> str-width ellipsis-width))
1086 1085 (setq end-column (- end-column ellipsis-width))
1087 ;; handle ELLIPSES 1086 (setq ellipsis ""))
1088 (cond ((null ellipses) (setq ellipses ""))
1089 ((if (<= (string-width str) end-column)
1090 ;; string fits, no ellipses
1091 (setq ellipses "")))
1092 (t
1093 ;; else, insert default value and ...
1094 (or (stringp ellipses) (setq ellipses "..."))
1095 ;; ... take away the width of the ellipses from the
1096 ;; destination. do all computations with new, shorter
1097 ;; width. the padding computed will get us exactly up to
1098 ;; the shorted width, which is right -- it just gets added
1099 ;; to the right of the ellipses.
1100 (setq end-column (- end-column (string-width ellipses)))))
1101
1102 ;; find the index of END-COLUMN; bail out if end of string reached.
1103 (condition-case nil 1087 (condition-case nil
1104 (while (< column end-column) 1088 (while (< column end-column)
1105 (setq last-column column 1089 (setq last-column column
1106 last-idx idx 1090 last-idx idx
1107 ch (aref str idx) 1091 ch (aref str idx)
1108 column (+ column (char-width ch)) 1092 column (+ column (char-width ch))
1109 idx (1+ idx))) 1093 idx (1+ idx)))
1110 (args-out-of-range (setq idx len))) 1094 (args-out-of-range (setq idx str-len)))
1111 ;; if we went too far (stopped in middle of character), back up. 1095 (when (> column end-column)
1112 (if (> column end-column) 1096 (setq column last-column
1113 (setq column last-column idx last-idx)) 1097 idx last-idx))
1114 ;; compute remaining padding 1098 (when (and padding (< column end-column))
1115 (if (and padding (< column end-column)) 1099 (setq tail-padding (make-string (- end-column column) padding))))
1116 (setq tail-padding (make-string (- end-column column) padding)))) 1100 (concat head-padding (substring str from-idx idx)
1117 ;; get substring ... 1101 tail-padding ellipsis))))
1118 (setq str (substring str from-idx idx))
1119 ;; and construct result
1120 (if padding
1121 (concat head-padding str tail-padding ellipses)
1122 (concat str ellipses)))))
1123
1124 1102
1125 ;; alist/plist functions 1103 ;; alist/plist functions
1126 (defun plist-to-alist (plist) 1104 (defun plist-to-alist (plist)
1127 "Convert property list PLIST into the equivalent association-list form. 1105 "Convert property list PLIST into the equivalent association-list form.
1128 The alist is returned. This converts from 1106 The alist is returned. This converts from