=== modified file 'doc/lispintro/emacs-lisp-intro.texi' --- doc/lispintro/emacs-lisp-intro.texi 2014-06-10 02:20:31 +0000 +++ doc/lispintro/emacs-lisp-intro.texi 2014-06-27 14:49:59 +0000 @@ -4457,7 +4457,9 @@ @itemx string-equal The @code{string-lessp} function tests whether its first argument is smaller than the second argument. A shorter, alternative name for the -same function (a @code{defalias}) is @code{string<}. +same function (a @code{defalias}) is @code{string<}. If the optional +third argument is non-nil, strings are compared ignoring case +differences. The arguments to @code{string-lessp} must be strings or symbols; the ordering is lexicographic, so case is significant. The print names of @@ -4469,7 +4471,9 @@ @code{string-equal} provides the corresponding test for equality. Its shorter, alternative name is @code{string=}. There are no string test -functions that correspond to @var{>}, @code{>=}, or @code{<=}. +functions that correspond to @var{>}, @code{>=}, or @code{<=}. This +function accepts an optional third argument with the same meaning as +in @code{stirng-lessp}. @item message Print a message in the echo area. The first argument is a string that === modified file 'doc/lispref/strings.texi' --- doc/lispref/strings.texi 2014-04-24 15:11:04 +0000 +++ doc/lispref/strings.texi 2014-06-27 14:43:36 +0000 @@ -415,25 +415,27 @@ @end example @end defun address@hidden string= string1 string2 address@hidden string-equal string1 string2 &optional ignore-case This function returns @code{t} if the characters of the two strings match exactly. Symbols are also allowed as arguments, in which case -the symbol names are used. Case is always significant, regardless of address@hidden +the symbol names are used. If the optional argument @var{ignore-case} +is address@hidden, characters are matched ignoring case differences. This function is equivalent to @code{equal} for comparing two strings (@pxref{Equality Predicates}). In particular, the text properties of the two strings are ignored; use @code{equal-including-properties} if you need to distinguish between strings that differ only in their text properties. However, unlike @code{equal}, if either argument is not a -string or symbol, @code{string=} signals an error. +string or symbol, @code{string-equal} signals an error. @example -(string= "abc" "abc") +(string-equal "abc" "abc") @result{} t -(string= "abc" "ABC") +(string-equal "abc" "ABC") @result{} nil -(string= "ab" "ABC") +(string-equal "abc" "ABC" t) + @result{} t +(string-equal "ab" "ABC") @result{} nil @end example @@ -454,13 +456,12 @@ Representations}. @end defun address@hidden string-equal string1 string2 address@hidden is another name for @code{string=}. address@hidden string= string1 string2 address@hidden is another name for @code{string-equal}. @end defun @cindex lexical comparison address@hidden string< string1 string2 address@hidden (findex string< causes problems for permuted index!!) address@hidden string-lessp string1 string2 &optional ignore-case This function compares two strings a character at a time. It scans both the strings at the same time to find the first pair of corresponding characters that do not match. If the lesser character of these two is @@ -468,6 +469,8 @@ function returns @code{t}. If the lesser character is the one from @var{string2}, then @var{string1} is greater, and this function returns @code{nil}. If the two strings match entirely, the value is @code{nil}. +If the optional argument @var{ignore-case} is address@hidden, characters +are compared ignoring case differences. Pairs of characters are compared according to their character codes. Keep in mind that lower case letters have higher numeric values in the @@ -479,11 +482,11 @@ @example @group -(string< "abc" "abd") +(string-lessp "abc" "abd") @result{} t -(string< "abd" "abc") +(string-lessp "abd" "abc") @result{} nil -(string< "123" "abc") +(string-lessp "123" "abc") @result{} t @end group @end example @@ -495,15 +498,15 @@ @example @group -(string< "" "abc") - @result{} t -(string< "ab" "abc") - @result{} t -(string< "abc" "") - @result{} nil -(string< "abc" "ab") - @result{} nil -(string< "" "") +(string-lessp "" "abc") + @result{} t +(string-lessp "ab" "abc") + @result{} t +(string-lessp "abc" "") + @result{} nil +(string-lessp "abc" "ab") + @result{} nil +(string-lessp "" "") @result{} nil @end group @end example @@ -512,8 +515,8 @@ are used. @end defun address@hidden string-lessp string1 string2 address@hidden is another name for @code{string<}. address@hidden string< string1 string2 address@hidden<} is another name for @code{string-lessp}. @end defun @defun string-prefix-p string1 string2 &optional ignore-case === modified file 'src/buffer.c' --- src/buffer.c 2014-06-23 04:11:29 +0000 +++ src/buffer.c 2014-06-27 14:33:07 +0000 @@ -435,7 +435,7 @@ return general; } -/* Like Fassoc, but use Fstring_equal to compare +/* Like Fassoc, but use string_equal to compare (which ignores text properties), and don't ever QUIT. */ @@ -447,7 +447,7 @@ { register Lisp_Object elt, tem; elt = XCAR (tail); - tem = Fstring_equal (Fcar (elt), key); + tem = string_equal (Fcar (elt), key); if (!NILP (tem)) return elt; } @@ -493,7 +493,7 @@ FOR_EACH_LIVE_BUFFER (tail, buf) { if (!STRINGP (BVAR (XBUFFER (buf), filename))) continue; - if (!NILP (Fstring_equal (BVAR (XBUFFER (buf), filename), filename))) + if (!NILP (string_equal (BVAR (XBUFFER (buf), filename), filename))) return buf; } return Qnil; @@ -507,7 +507,7 @@ FOR_EACH_LIVE_BUFFER (tail, buf) { if (!STRINGP (BVAR (XBUFFER (buf), file_truename))) continue; - if (!NILP (Fstring_equal (BVAR (XBUFFER (buf), file_truename), filename))) + if (!NILP (string_equal (BVAR (XBUFFER (buf), file_truename), filename))) return buf; } return Qnil; @@ -1076,7 +1076,7 @@ CHECK_STRING (name); - tem = Fstring_equal (name, ignore); + tem = string_equal (name, ignore); if (!NILP (tem)) return name; tem = Fget_buffer (name); @@ -1101,7 +1101,7 @@ { gentemp = concat2 (tem2, make_formatted_string (number, "<%"pD"d>", ++count)); - tem = Fstring_equal (gentemp, ignore); + tem = string_equal (gentemp, ignore); if (!NILP (tem)) return gentemp; tem = Fget_buffer (gentemp); === modified file 'src/bytecode.c' --- src/bytecode.c 2014-05-27 23:48:35 +0000 +++ src/bytecode.c 2014-06-27 14:33:07 +0000 @@ -1787,7 +1787,7 @@ Lisp_Object v1; BEFORE_POTENTIAL_GC (); v1 = POP; - TOP = Fstring_equal (TOP, v1); + TOP = string_equal (TOP, v1); AFTER_POTENTIAL_GC (); NEXT; } @@ -1797,7 +1797,7 @@ Lisp_Object v1; BEFORE_POTENTIAL_GC (); v1 = POP; - TOP = Fstring_lessp (TOP, v1); + TOP = string_lessp (TOP, v1); AFTER_POTENTIAL_GC (); NEXT; } === modified file 'src/dbusbind.c' --- src/dbusbind.c 2014-05-20 08:25:18 +0000 +++ src/dbusbind.c 2014-06-27 14:33:07 +0000 @@ -283,7 +283,7 @@ dbus_address_entries_free (entries); \ /* Canonicalize session bus address. */ \ if ((session_bus_address != NULL) \ - && (!NILP (Fstring_equal \ + && (!NILP (string_equal \ (bus, build_string (session_bus_address))))) \ bus = QCdbus_session_bus; \ } \ === modified file 'src/dired.c' --- src/dired.c 2014-04-16 19:43:46 +0000 +++ src/dired.c 2014-06-27 14:33:07 +0000 @@ -996,9 +996,8 @@ Comparison is in lexicographic order and case is significant. */) (Lisp_Object f1, Lisp_Object f2) { - return Fstring_lessp (Fcar (f1), Fcar (f2)); + return string_lessp (Fcar (f1), Fcar (f2)); } - DEFUN ("system-users", Fsystem_users, Ssystem_users, 0, 0, 0, doc: /* Return a list of user names currently registered in the system. === modified file 'src/editfns.c' --- src/editfns.c 2014-06-23 04:11:29 +0000 +++ src/editfns.c 2014-06-27 14:33:07 +0000 @@ -137,7 +137,7 @@ /* If the user name claimed in the environment vars differs from the real uid, use the claimed name to find the full name. */ - tem = Fstring_equal (Vuser_login_name, Vuser_real_login_name); + tem = string_equal (Vuser_login_name, Vuser_real_login_name); if (! NILP (tem)) tem = Vuser_login_name; else === modified file 'src/fileio.c' --- src/fileio.c 2014-06-23 04:11:29 +0000 +++ src/fileio.c 2014-06-27 14:33:07 +0000 @@ -2301,7 +2301,7 @@ #ifdef DOS_NT /* If the file names are identical but for the case, don't attempt to move directory to itself. */ - && (NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))) + && (NILP (Fstring_equal (file, newname, Qt))) #endif ) { @@ -2328,7 +2328,7 @@ /* If the file names are identical but for the case, don't ask for confirmation: they simply want to change the letter-case of the file name. */ - if (NILP (Fstring_equal (Fdowncase (file), Fdowncase (newname)))) + if (NILP (Fstring_equal (file, newname, Qt))) #endif if (NILP (ok_if_already_exists) || INTEGERP (ok_if_already_exists)) @@ -4544,8 +4544,8 @@ } if (auto_saving - && NILP (Fstring_equal (BVAR (current_buffer, filename), - BVAR (current_buffer, auto_save_file_name)))) + && NILP (string_equal (BVAR (current_buffer, filename), + BVAR (current_buffer, auto_save_file_name)))) { val = Qutf_8_emacs; eol_parent = Qunix; @@ -5023,8 +5023,8 @@ else if (quietly) { if (auto_saving - && ! NILP (Fstring_equal (BVAR (current_buffer, filename), - BVAR (current_buffer, auto_save_file_name)))) + && ! NILP (string_equal (BVAR (current_buffer, filename), + BVAR (current_buffer, auto_save_file_name)))) SAVE_MODIFF = MODIFF; return Qnil; === modified file 'src/fns.c' --- src/fns.c 2014-06-26 07:13:13 +0000 +++ src/fns.c 2014-06-27 14:33:07 +0000 @@ -204,11 +204,43 @@ return make_number (SBYTES (string)); } -DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0, +/* Similar to strcasecmp but for Lisp strings. */ + +static int +string_compare (Lisp_Object s1, Lisp_Object s2, Lisp_Object ignore_case) +{ + ptrdiff_t i1 = 0, i1_byte = 0, i2 = 0, i2_byte = 0; + + while (i1 < SCHARS (s1) && i2 < SCHARS (s2)) + { + int c1, c2; + + FETCH_STRING_CHAR_ADVANCE (c1, s1, i1, i1_byte); + FETCH_STRING_CHAR_ADVANCE (c2, s2, i2, i2_byte); + + if (! NILP (ignore_case)) + { + c1 = XINT (Fdowncase (make_number (c1))); + c2 = XINT (Fdowncase (make_number (c2))); + } + + if (c1 != c2) + return c1 < c2 ? -1 : 1; + } + + if (i1 < SCHARS (s2)) + return -1; + else if (i2 < SCHARS (s1)) + return 1; + return 0; +} + +DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 3, 0, doc: /* Return t if two strings have identical contents. -Case is significant, but text properties are ignored. -Symbols are also allowed; their print names are used instead. */) - (register Lisp_Object s1, Lisp_Object s2) +If IGNORE-CASE is non-nil, characters are converted to lower-case +before comparing them. Text properties are ignored. Symbols are +also allowed; their print names are used instead. */) + (Lisp_Object s1, Lisp_Object s2, Lisp_Object ignore_case) { if (SYMBOLP (s1)) s1 = SYMBOL_NAME (s1); @@ -217,11 +249,11 @@ CHECK_STRING (s1); CHECK_STRING (s2); - if (SCHARS (s1) != SCHARS (s2) - || SBYTES (s1) != SBYTES (s2) - || memcmp (SDATA (s1), SDATA (s2), SBYTES (s1))) - return Qnil; - return Qt; + if (NILP (ignore_case)) + return (SCHARS (s1) != SCHARS (s2) + || SBYTES (s1) != SBYTES (s2) + || memcmp (SDATA (s1), SDATA (s2), SBYTES (s1))) ? Qnil : Qt; + return string_compare (s1, s2, ignore_case) == 0 ? Qt : Qnil; } DEFUN ("compare-strings", Fcompare_strings, Scompare_strings, 6, 7, 0, @@ -300,15 +332,12 @@ return Qt; } -DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, +DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 3, 0, doc: /* Return t if first arg string is less than second in lexicographic order. -Case is significant. -Symbols are also allowed; their print names are used instead. */) - (register Lisp_Object s1, Lisp_Object s2) +If IGNORE-CASE is non-nil, characters are converted to lower-case before +comparing them. Symbols are also allowed; their print names are used instead. */) + (Lisp_Object s1, Lisp_Object s2, Lisp_Object ignore_case) { - register ptrdiff_t end; - register ptrdiff_t i1, i1_byte, i2, i2_byte; - if (SYMBOLP (s1)) s1 = SYMBOL_NAME (s1); if (SYMBOLP (s2)) @@ -316,27 +345,9 @@ CHECK_STRING (s1); CHECK_STRING (s2); - i1 = i1_byte = i2 = i2_byte = 0; - - end = SCHARS (s1); - if (end > SCHARS (s2)) - end = SCHARS (s2); - - while (i1 < end) - { - /* When we find a mismatch, we must compare the - characters, not just the bytes. */ - int c1, c2; - - FETCH_STRING_CHAR_ADVANCE (c1, s1, i1, i1_byte); - FETCH_STRING_CHAR_ADVANCE (c2, s2, i2, i2_byte); - - if (c1 != c2) - return c1 < c2 ? Qt : Qnil; - } - return i1 < SCHARS (s2) ? Qt : Qnil; + return string_compare (s1, s2, ignore_case) < 0 ? Qt : Qnil; } - + static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args, enum Lisp_Type target_type, bool last_special); === modified file 'src/font.c' --- src/font.c 2014-06-21 19:45:59 +0000 +++ src/font.c 2014-06-27 14:33:07 +0000 @@ -717,7 +717,7 @@ Lisp_Object prev = Qnil; while (CONSP (extra) - && NILP (Fstring_lessp (prop, XCAR (XCAR (extra))))) + && NILP (string_lessp (prop, XCAR (XCAR (extra))))) prev = extra, extra = XCDR (extra); if (NILP (prev)) === modified file 'src/frame.c' --- src/frame.c 2014-06-17 16:09:19 +0000 +++ src/frame.c 2014-06-27 14:33:07 +0000 @@ -2050,7 +2050,7 @@ CHECK_STRING (name); /* Don't change the name if it's already NAME. */ - if (! NILP (Fstring_equal (name, f->name))) + if (! NILP (string_equal (name, f->name))) return; /* Don't allow the user to set the frame name to F, so it === modified file 'src/ftfont.c' --- src/ftfont.c 2014-06-17 16:09:19 +0000 +++ src/ftfont.c 2014-06-27 14:33:07 +0000 @@ -1119,8 +1119,8 @@ if (! NILP (AREF (spec, FONT_FAMILY_INDEX)) && NILP (assq_no_quit (AREF (spec, FONT_FAMILY_INDEX), ftfont_generic_family_list)) - && NILP (Fstring_equal (AREF (spec, FONT_FAMILY_INDEX), - AREF (entity, FONT_FAMILY_INDEX)))) + && NILP (string_equal (AREF (spec, FONT_FAMILY_INDEX), + AREF (entity, FONT_FAMILY_INDEX)))) entity = Qnil; } } === modified file 'src/keymap.c' --- src/keymap.c 2014-06-12 14:55:48 +0000 +++ src/keymap.c 2014-06-27 14:33:07 +0000 @@ -3199,8 +3199,8 @@ if (INTEGERP (a->event) && !INTEGERP (b->event)) return -1; if (SYMBOLP (a->event) && SYMBOLP (b->event)) - return (!NILP (Fstring_lessp (a->event, b->event)) ? -1 - : !NILP (Fstring_lessp (b->event, a->event)) ? 1 + return (!NILP (string_lessp (a->event, b->event)) ? -1 + : !NILP (string_lessp (b->event, a->event)) ? 1 : 0); return 0; } === modified file 'src/lisp.h' --- src/lisp.h 2014-06-25 12:11:08 +0000 +++ src/lisp.h 2014-06-27 14:33:07 +0000 @@ -3482,6 +3482,18 @@ extern Lisp_Object string_make_unibyte (Lisp_Object); extern void syms_of_fns (void); +INLINE Lisp_Object +string_equal (Lisp_Object s1, Lisp_Object s2) +{ + return Fstring_equal (s1, s2, Qnil); +} + +INLINE Lisp_Object +string_lessp (Lisp_Object s1, Lisp_Object s2) +{ + return Fstring_lessp (s1, s2, Qnil); +} + /* Defined in floatfns.c. */ extern void syms_of_floatfns (void); extern Lisp_Object fmod_float (Lisp_Object x, Lisp_Object y); === modified file 'src/nsfns.m' --- src/nsfns.m 2014-06-01 08:23:18 +0000 +++ src/nsfns.m 2014-06-27 14:33:07 +0000 @@ -180,7 +180,7 @@ CHECK_STRING (name); for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) - if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name))) + if (!NILP (string_equal (XCAR (dpyinfo->name_list_element), name))) return dpyinfo; error ("Emacs for Nextstep does not yet support multi-display"); @@ -390,7 +390,7 @@ /* see if it's changed */ if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && EQ (string_equal (oldval, arg), Qt)) return; } else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil)) @@ -482,7 +482,7 @@ CHECK_STRING (name); /* Don't change the name if it's already NAME. */ - if (! NILP (Fstring_equal (name, f->name))) + if (! NILP (string_equal (name, f->name))) return; fset_name (f, name); === modified file 'src/search.c' --- src/search.c 2014-06-23 04:11:29 +0000 +++ src/search.c 2014-06-27 14:33:07 +0000 @@ -227,7 +227,7 @@ goto compile_it; if (SCHARS (cp->regexp) == SCHARS (pattern) && STRING_MULTIBYTE (cp->regexp) == STRING_MULTIBYTE (pattern) - && !NILP (Fstring_equal (cp->regexp, pattern)) + && !NILP (string_equal (cp->regexp, pattern)) && EQ (cp->buf.translate, (! NILP (translate) ? translate : make_number (0))) && cp->posix == posix && (EQ (cp->syntax_table, Qt) === modified file 'src/w32fns.c' --- src/w32fns.c 2014-06-22 23:12:17 +0000 +++ src/w32fns.c 2014-06-27 14:33:07 +0000 @@ -1543,7 +1543,7 @@ return; if (STRINGP (arg) && STRINGP (oldval) - && EQ (Fstring_equal (oldval, arg), Qt)) + && EQ (string_equal (oldval, arg), Qt)) return; if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval)) @@ -1566,7 +1566,7 @@ { if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && EQ (string_equal (oldval, arg), Qt)) return; } else if (!NILP (arg) || NILP (oldval)) @@ -1774,7 +1774,7 @@ CHECK_STRING (name); /* Don't change the name if it's already NAME. */ - if (! NILP (Fstring_equal (name, f->name))) + if (! NILP (string_equal (name, f->name))) return; fset_name (f, name); @@ -5200,7 +5200,7 @@ CHECK_STRING (name); for (dpyinfo = &one_w32_display_info; dpyinfo; dpyinfo = dpyinfo->next) - if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name))) + if (!NILP (string_equal (XCAR (dpyinfo->name_list_element), name))) return dpyinfo; /* Use this general default value to start with. */ === modified file 'src/w32menu.c' --- src/w32menu.c 2014-06-04 04:58:31 +0000 +++ src/w32menu.c 2014-06-27 14:33:07 +0000 @@ -1060,9 +1060,9 @@ return 0; name = XCAR (name); - if (!NILP (Fstring_equal (name, yes))) + if (!NILP (string_equal (name, yes))) other = no; - else if (!NILP (Fstring_equal (name, no))) + else if (!NILP (string_equal (name, no))) other = yes; else return 0; @@ -1075,7 +1075,7 @@ if (!CONSP (name)) return 0; name = XCAR (name); - if (NILP (Fstring_equal (name, other))) + if (NILP (string_equal (name, other))) return 0; /* Check there are no more options. */ @@ -1181,7 +1181,7 @@ value = Qnil; } - if (!NILP (Fstring_equal (name, lispy_answer))) + if (!NILP (string_equal (name, lispy_answer))) { return value; } === modified file 'src/xfaces.c' --- src/xfaces.c 2014-06-10 03:32:36 +0000 +++ src/xfaces.c 2014-06-27 14:33:07 +0000 @@ -976,7 +976,7 @@ lookup STD_COLOR separately. If it's impossible to lookup a standard color, we just give up and use TTY_COLOR. */ if ((!STRINGP (XCAR (color_desc)) - || NILP (Fstring_equal (color, XCAR (color_desc)))) + || NILP (string_equal (color, XCAR (color_desc)))) && !NILP (Ffboundp (Qtty_color_standard_values))) { /* Look up STD_COLOR separately. */ === modified file 'src/xfns.c' --- src/xfns.c 2014-06-22 05:00:14 +0000 +++ src/xfns.c 2014-06-27 14:33:07 +0000 @@ -895,7 +895,7 @@ if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && EQ (string_equal (oldval, arg), Qt)) return; } else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil)) @@ -927,7 +927,7 @@ if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && EQ (string_equal (oldval, arg), Qt)) return; } else if (!NILP (arg) || NILP (oldval)) @@ -1442,7 +1442,7 @@ CHECK_STRING (name); /* Don't change the name if it's already NAME. */ - if (! NILP (Fstring_equal (name, f->name))) + if (! NILP (string_equal (name, f->name))) return; fset_name (f, name); @@ -4343,7 +4343,7 @@ CHECK_STRING (name); for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) - if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name))) + if (!NILP (string_equal (XCAR (dpyinfo->name_list_element), name))) return dpyinfo; /* Use this general default value to start with. */ === modified file 'test/automated/fns-tests.el' --- test/automated/fns-tests.el 2014-06-25 10:36:51 +0000 +++ test/automated/fns-tests.el 2014-06-27 15:15:23 +0000 @@ -100,3 +100,38 @@ (should (compare-strings "こんにちはコンニチハ" nil nil "こんにちはコンニチハ" nil nil)) (should (= (compare-strings "んにちはコンニチハこ" nil nil "こんにちはコンニチハ" nil nil) 1)) (should (= (compare-strings "こんにちはコンニチハ" nil nil "んにちはコンニチハこ" nil nil) -1))) + +(ert-deftest fns-test-string-equal () + (should-error (string-equal)) + (should-error (string-equal 1 2)) + (should-error (string-equal '[1 2 3 4] "1 2 3 4")) + (should-error (string-equal "aaa" "bbb" "ccc" "ddd")) + (should (string-equal "foo" 'foo)) + (should (string-equal "BAR" 'bar t)) + (should (string-equal "aaa" "aaa")) + (should-not (string-equal "aaa" "aaaa")) + (should-not (string-equal "aaaa" "aaa")) + (should-not (string-equal "aaa" "aab")) + (should-not (string-equal "aab" "aaa")) + (should (string-equal "AAA" "aaa" t)) + (should (string-equal "bbb" "BBB" t)) + (should-not (string-equal (make-string 10 1234) (make-string 11 1234))) + (should (string-equal "ӒӒӒ" "ӒӒӒ")) + (should-not (string-equal "ӓӓӓ" "ӒӒӒ")) + (should (string-equal "ӓӓӓ" "ӒӒӒ" t))) + +(ert-deftest fns-test-string-lessp () + (should-error (string-lessp)) + (should-error (string-lessp 1 2)) + (should-error (string-lessp '[1 2 3 4] "1 2 3 4")) + (should-error (string-lessp "aaa" "bbb" "ccc" "ddd")) + (should (string-lessp "" "a")) + (should-not (string-lessp "" "")) + (should (string-lessp "aaa" "bbb")) + (should (string-lessp "aaa" "aab")) + (should (string-lessp "aaa" "aaaa")) + (should-not (string-lessp "ddd" "ddd")) + (should-not (string-lessp "ddd" "ccc")) + (should (string-lessp (make-string 4 1111) (make-string 4 1112))) + (should (string-lessp "ӒӒӒ" "ӓӓӓ")) + (should-not (string-lessp "ӒӒӒ" "ӓӓӓ" t)))