aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Kangas2020-10-18 15:19:09 +0200
committerStefan Kangas2020-10-18 17:25:23 +0200
commitef5a604f082f772424400f48b64e9c04edbcc766 (patch)
tree98a3987703ed2d710c22be23f057ee6de6d15a53
parent8a1441310aa151e739cfed3bd2eff3358edc8001 (diff)
downloademacs-ef5a604f082f772424400f48b64e9c04edbcc766.tar.gz
emacs-ef5a604f082f772424400f48b64e9c04edbcc766.zip
Remove C version of substitute-command-keys
* src/doc.c (Fsubstitute_command_keys_old): Remove. (syms_of_doc): Remove defsubr for Fsubstitute_command_keys_old. * src/keymap.c (describe_map, describe_map_tree) (describe_map_compare, describe_map_elt): Remove. * src/keymap.h: Remove 'describe_map_tree'. * test/lisp/help-tests.el (with-substitute-command-keys-test) (help-tests-substitute-command-keys/compare) (help-tests-substitute-command-keys/compare-all): Don't test the C version of 'substitute-command-keys' removed above.
-rw-r--r--src/doc.c303
-rw-r--r--src/keymap.c334
-rw-r--r--src/keymap.h2
-rw-r--r--test/lisp/help-tests.el37
4 files changed, 3 insertions, 673 deletions
diff --git a/src/doc.c b/src/doc.c
index 212ebe96334..f1ce266d39f 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -715,308 +715,6 @@ See variable `text-quoting-style'. */)
715 } 715 }
716} 716}
717 717
718DEFUN ("substitute-command-keys-old", Fsubstitute_command_keys_old,
719 Ssubstitute_command_keys_old, 1, 1, 0,
720 doc: /* Substitute key descriptions for command names in STRING.
721Each substring of the form \\=\\[COMMAND] is replaced by either a
722keystroke sequence that invokes COMMAND, or "M-x COMMAND" if COMMAND
723is not on any keys.
724
725Each substring of the form \\=\\{MAPVAR} is replaced by a summary of
726the value of MAPVAR as a keymap. This summary is similar to the one
727produced by `describe-bindings'. The summary ends in two newlines
728\(used by the helper function `help-make-xrefs' to find the end of the
729summary).
730
731Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR
732as the keymap for future \\=\\[COMMAND] substrings.
733
734Each grave accent \\=` is replaced by left quote, and each apostrophe \\='
735is replaced by right quote. Left and right quote characters are
736specified by `text-quoting-style'.
737
738\\=\\= quotes the following character and is discarded; thus, \\=\\=\\=\\= puts \\=\\=
739into the output, \\=\\=\\=\\[ puts \\=\\[ into the output, and \\=\\=\\=` puts \\=` into the
740output.
741
742Return the original STRING if no substitutions are made.
743Otherwise, return a new string (without any text properties). */)
744 (Lisp_Object string)
745{
746 char *buf;
747 bool changed = false;
748 bool nonquotes_changed = false;
749 unsigned char *strp;
750 char *bufp;
751 ptrdiff_t idx;
752 ptrdiff_t bsize;
753 Lisp_Object tem;
754 Lisp_Object keymap;
755 unsigned char const *start;
756 ptrdiff_t length, length_byte;
757 Lisp_Object name;
758 ptrdiff_t nchars;
759
760 if (NILP (string))
761 return Qnil;
762
763 /* If STRING contains non-ASCII unibyte data, process its
764 properly-encoded multibyte equivalent instead. This simplifies
765 the implementation and is OK since substitute-command-keys is
766 intended for use only on text strings. Keep STRING around, since
767 it will be returned if no changes occur. */
768 Lisp_Object str = Fstring_make_multibyte (string);
769
770 enum text_quoting_style quoting_style = text_quoting_style ();
771
772 nchars = 0;
773
774 /* KEYMAP is either nil (which means search all the active keymaps)
775 or a specified local map (which means search just that and the
776 global map). If non-nil, it might come from Voverriding_local_map,
777 or from a \\<mapname> construct in STRING itself.. */
778 keymap = Voverriding_local_map;
779
780 ptrdiff_t strbytes = SBYTES (str);
781 bsize = strbytes;
782
783 /* Fixed-size stack buffer. */
784 char sbuf[MAX_ALLOCA];
785
786 /* Heap-allocated buffer, if any. */
787 char *abuf;
788
789 /* Extra room for expansion due to replacing ‘\[]’ with ‘M-x ’. */
790 enum { EXTRA_ROOM = sizeof "M-x " - sizeof "\\[]" };
791
792 ptrdiff_t count = SPECPDL_INDEX ();
793
794 if (bsize <= sizeof sbuf - EXTRA_ROOM)
795 {
796 abuf = NULL;
797 buf = sbuf;
798 bsize = sizeof sbuf;
799 }
800 else
801 {
802 buf = abuf = xpalloc (NULL, &bsize, EXTRA_ROOM, STRING_BYTES_BOUND, 1);
803 record_unwind_protect_ptr (xfree, abuf);
804 }
805 bufp = buf;
806
807 strp = SDATA (str);
808 while (strp < SDATA (str) + strbytes)
809 {
810 unsigned char *close_bracket;
811
812 if (strp[0] == '\\' && strp[1] == '='
813 && strp + 2 < SDATA (str) + strbytes)
814 {
815 /* \= quotes the next character;
816 thus, to put in \[ without its special meaning, use \=\[. */
817 changed = nonquotes_changed = true;
818 strp += 2;
819 /* Fall through to copy one char. */
820 }
821 else if (strp[0] == '\\' && strp[1] == '['
822 && (close_bracket
823 = memchr (strp + 2, ']',
824 SDATA (str) + strbytes - (strp + 2))))
825 {
826 bool follow_remap = 1;
827
828 start = strp + 2;
829 length_byte = close_bracket - start;
830 idx = close_bracket + 1 - SDATA (str);
831
832 name = Fintern (make_string ((char *) start, length_byte), Qnil);
833
834 do_remap:
835 tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qnil);
836
837 if (VECTORP (tem) && ASIZE (tem) > 1
838 && EQ (AREF (tem, 0), Qremap) && SYMBOLP (AREF (tem, 1))
839 && follow_remap)
840 {
841 name = AREF (tem, 1);
842 follow_remap = 0;
843 goto do_remap;
844 }
845
846 /* Fwhere_is_internal can GC, so take relocation of string
847 contents into account. */
848 strp = SDATA (str) + idx;
849 start = strp - length_byte - 1;
850
851 if (NILP (tem)) /* but not on any keys */
852 {
853 memcpy (bufp, "M-x ", 4);
854 bufp += 4;
855 nchars += 4;
856 length = multibyte_chars_in_text (start, length_byte);
857 goto subst;
858 }
859 else
860 { /* function is on a key */
861 tem = Fkey_description (tem, Qnil);
862 goto subst_string;
863 }
864 }
865 /* \{foo} is replaced with a summary of the keymap (symbol-value foo).
866 \<foo> just sets the keymap used for \[cmd]. */
867 else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<')
868 && (close_bracket
869 = memchr (strp + 2, strp[1] == '{' ? '}' : '>',
870 SDATA (str) + strbytes - (strp + 2))))
871 {
872 {
873 bool generate_summary = strp[1] == '{';
874 /* This is for computing the SHADOWS arg for describe_map_tree. */
875 Lisp_Object active_maps = Fcurrent_active_maps (Qnil, Qnil);
876 ptrdiff_t count = SPECPDL_INDEX ();
877
878 start = strp + 2;
879 length_byte = close_bracket - start;
880 idx = close_bracket + 1 - SDATA (str);
881
882 /* Get the value of the keymap in TEM, or nil if undefined.
883 Do this while still in the user's current buffer
884 in case it is a local variable. */
885 name = Fintern (make_string ((char *) start, length_byte), Qnil);
886 tem = Fboundp (name);
887 if (! NILP (tem))
888 {
889 tem = Fsymbol_value (name);
890 if (! NILP (tem))
891 tem = get_keymap (tem, 0, 1);
892 }
893
894 /* Now switch to a temp buffer. */
895 struct buffer *oldbuf = current_buffer;
896 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
897 /* This is for an unusual case where some after-change
898 function uses 'format' or 'prin1' or something else that
899 will thrash Vprin1_to_string_buffer we are using. */
900 specbind (Qinhibit_modification_hooks, Qt);
901
902 if (NILP (tem))
903 {
904 name = Fsymbol_name (name);
905 AUTO_STRING (msg_prefix, "\nUses keymap `");
906 insert1 (Fsubstitute_command_keys_old (msg_prefix));
907 insert_from_string (name, 0, 0,
908 SCHARS (name),
909 SBYTES (name), 1);
910 AUTO_STRING (msg_suffix, "', which is not currently defined.\n");
911 insert1 (Fsubstitute_command_keys_old (msg_suffix));
912 if (!generate_summary)
913 keymap = Qnil;
914 }
915 else if (!generate_summary)
916 keymap = tem;
917 else
918 {
919 /* Get the list of active keymaps that precede this one.
920 If this one's not active, get nil. */
921 Lisp_Object earlier_maps
922 = Fcdr (Fmemq (tem, Freverse (active_maps)));
923 describe_map_tree (tem, 1, Fnreverse (earlier_maps),
924 Qnil, 0, 1, 0, 0, 1);
925 }
926 tem = Fbuffer_string ();
927 Ferase_buffer ();
928 set_buffer_internal (oldbuf);
929 unbind_to (count, Qnil);
930 }
931
932 subst_string:
933 /* Convert non-ASCII unibyte data to properly-encoded multibyte,
934 for the same reason STRING was converted to STR. */
935 tem = Fstring_make_multibyte (tem);
936 start = SDATA (tem);
937 length = SCHARS (tem);
938 length_byte = SBYTES (tem);
939 subst:
940 nonquotes_changed = true;
941 subst_quote:
942 changed = true;
943 {
944 ptrdiff_t offset = bufp - buf;
945 ptrdiff_t avail = bsize - offset;
946 ptrdiff_t need = strbytes - idx;
947 if (INT_ADD_WRAPV (need, length_byte + EXTRA_ROOM, &need))
948 string_overflow ();
949 if (avail < need)
950 {
951 abuf = xpalloc (abuf, &bsize, need - avail,
952 STRING_BYTES_BOUND, 1);
953 if (buf == sbuf)
954 {
955 record_unwind_protect_ptr (xfree, abuf);
956 memcpy (abuf, sbuf, offset);
957 }
958 else
959 set_unwind_protect_ptr (count, xfree, abuf);
960 buf = abuf;
961 bufp = buf + offset;
962 }
963 memcpy (bufp, start, length_byte);
964 bufp += length_byte;
965 nchars += length;
966
967 /* Some of the previous code can GC, so take relocation of
968 string contents into account. */
969 strp = SDATA (str) + idx;
970
971 continue;
972 }
973 }
974 else if ((strp[0] == '`' || strp[0] == '\'')
975 && quoting_style == CURVE_QUOTING_STYLE)
976 {
977 start = (unsigned char const *) (strp[0] == '`' ? uLSQM : uRSQM);
978 length = 1;
979 length_byte = sizeof uLSQM - 1;
980 idx = strp - SDATA (str) + 1;
981 goto subst_quote;
982 }
983 else if (strp[0] == '`' && quoting_style == STRAIGHT_QUOTING_STYLE)
984 {
985 *bufp++ = '\'';
986 strp++;
987 nchars++;
988 changed = true;
989 continue;
990 }
991
992 /* Copy one char. */
993 do
994 *bufp++ = *strp++;
995 while (! CHAR_HEAD_P (*strp));
996 nchars++;
997 }
998
999 if (changed) /* don't bother if nothing substituted */
1000 {
1001 tem = make_string_from_bytes (buf, nchars, bufp - buf);
1002 if (!nonquotes_changed)
1003 {
1004 /* Nothing has changed other than quoting, so copy the string’s
1005 text properties. FIXME: Text properties should survive other
1006 changes too; see bug#17052. */
1007 INTERVAL interval_copy = copy_intervals (string_intervals (string),
1008 0, SCHARS (string));
1009 if (interval_copy)
1010 {
1011 set_interval_object (interval_copy, tem);
1012 set_string_intervals (tem, interval_copy);
1013 }
1014 }
1015 }
1016 else
1017 tem = string;
1018 return unbind_to (count, tem);
1019}
1020 718
1021void 719void
1022syms_of_doc (void) 720syms_of_doc (void)
@@ -1058,5 +756,4 @@ otherwise. */);
1058 defsubr (&Sdocumentation_property); 756 defsubr (&Sdocumentation_property);
1059 defsubr (&Ssnarf_documentation); 757 defsubr (&Ssnarf_documentation);
1060 defsubr (&Sget_quoting_style); 758 defsubr (&Sget_quoting_style);
1061 defsubr (&Ssubstitute_command_keys_old);
1062} 759}
diff --git a/src/keymap.c b/src/keymap.c
index 1eded130b5d..46fa586c753 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -91,9 +91,6 @@ static Lisp_Object store_in_keymap (Lisp_Object, Lisp_Object, Lisp_Object);
91static Lisp_Object define_as_prefix (Lisp_Object, Lisp_Object); 91static Lisp_Object define_as_prefix (Lisp_Object, Lisp_Object);
92static void describe_command (Lisp_Object, Lisp_Object); 92static void describe_command (Lisp_Object, Lisp_Object);
93static void describe_translation (Lisp_Object, Lisp_Object); 93static void describe_translation (Lisp_Object, Lisp_Object);
94static void describe_map (Lisp_Object, Lisp_Object,
95 void (*) (Lisp_Object, Lisp_Object),
96 bool, Lisp_Object, Lisp_Object *, bool, bool);
97static void describe_vector (Lisp_Object, Lisp_Object, Lisp_Object, 94static void describe_vector (Lisp_Object, Lisp_Object, Lisp_Object,
98 void (*) (Lisp_Object, Lisp_Object), bool, 95 void (*) (Lisp_Object, Lisp_Object), bool,
99 Lisp_Object, Lisp_Object, bool, bool); 96 Lisp_Object, Lisp_Object, bool, bool);
@@ -2946,119 +2943,6 @@ You type Translation\n\
2946 return Qnil; 2943 return Qnil;
2947} 2944}
2948 2945
2949/* Insert a description of the key bindings in STARTMAP,
2950 followed by those of all maps reachable through STARTMAP.
2951 If PARTIAL, omit certain "uninteresting" commands
2952 (such as `undefined').
2953 If SHADOW is non-nil, it is a list of maps;
2954 don't mention keys which would be shadowed by any of them.
2955 PREFIX, if non-nil, says mention only keys that start with PREFIX.
2956 TITLE, if not 0, is a string to insert at the beginning.
2957 TITLE should not end with a colon or a newline; we supply that.
2958 If NOMENU, then omit menu-bar commands.
2959
2960 If TRANSL, the definitions are actually key translations
2961 so print strings and vectors differently.
2962
2963 If ALWAYS_TITLE, print the title even if there are no maps
2964 to look through.
2965
2966 If MENTION_SHADOW, then when something is shadowed by SHADOW,
2967 don't omit it; instead, mention it but say it is shadowed.
2968
2969 Any inserted text ends in two newlines (used by `help-make-xrefs'). */
2970
2971void
2972describe_map_tree (Lisp_Object startmap, bool partial, Lisp_Object shadow,
2973 Lisp_Object prefix, const char *title, bool nomenu,
2974 bool transl, bool always_title, bool mention_shadow)
2975{
2976 Lisp_Object maps, orig_maps, seen, sub_shadows;
2977 bool something = 0;
2978 const char *key_heading
2979 = "\
2980key binding\n\
2981--- -------\n";
2982
2983 orig_maps = maps = Faccessible_keymaps (startmap, prefix);
2984 seen = Qnil;
2985 sub_shadows = Qnil;
2986
2987 if (nomenu)
2988 {
2989 Lisp_Object list;
2990
2991 /* Delete from MAPS each element that is for the menu bar. */
2992 for (list = maps; CONSP (list); list = XCDR (list))
2993 {
2994 Lisp_Object elt, elt_prefix, tem;
2995
2996 elt = XCAR (list);
2997 elt_prefix = Fcar (elt);
2998 if (ASIZE (elt_prefix) >= 1)
2999 {
3000 tem = Faref (elt_prefix, make_fixnum (0));
3001 if (EQ (tem, Qmenu_bar))
3002 maps = Fdelq (elt, maps);
3003 }
3004 }
3005 }
3006
3007 if (!NILP (maps) || always_title)
3008 {
3009 if (title)
3010 {
3011 insert_string (title);
3012 if (!NILP (prefix))
3013 {
3014 insert_string (" Starting With ");
3015 insert1 (Fkey_description (prefix, Qnil));
3016 }
3017 insert_string (":\n");
3018 }
3019 insert_string (key_heading);
3020 something = 1;
3021 }
3022
3023 for (; CONSP (maps); maps = XCDR (maps))
3024 {
3025 register Lisp_Object elt, elt_prefix, tail;
3026
3027 elt = XCAR (maps);
3028 elt_prefix = Fcar (elt);
3029
3030 sub_shadows = Flookup_key (shadow, elt_prefix, Qt);
3031 if (FIXNATP (sub_shadows))
3032 sub_shadows = Qnil;
3033 else if (!KEYMAPP (sub_shadows)
3034 && !NILP (sub_shadows)
3035 && !(CONSP (sub_shadows)
3036 && KEYMAPP (XCAR (sub_shadows))))
3037 /* If elt_prefix is bound to something that's not a keymap,
3038 it completely shadows this map, so don't
3039 describe this map at all. */
3040 goto skip;
3041
3042 /* Maps we have already listed in this loop shadow this map. */
3043 for (tail = orig_maps; !EQ (tail, maps); tail = XCDR (tail))
3044 {
3045 Lisp_Object tem;
3046 tem = Fequal (Fcar (XCAR (tail)), elt_prefix);
3047 if (!NILP (tem))
3048 sub_shadows = Fcons (XCDR (XCAR (tail)), sub_shadows);
3049 }
3050
3051 describe_map (Fcdr (elt), elt_prefix,
3052 transl ? describe_translation : describe_command,
3053 partial, sub_shadows, &seen, nomenu, mention_shadow);
3054
3055 skip: ;
3056 }
3057
3058 if (something)
3059 insert_string ("\n");
3060}
3061
3062static int previous_description_column; 2946static int previous_description_column;
3063 2947
3064static void 2948static void
@@ -3121,224 +3005,6 @@ describe_translation (Lisp_Object definition, Lisp_Object args)
3121 insert_string ("??\n"); 3005 insert_string ("??\n");
3122} 3006}
3123 3007
3124/* describe_map puts all the usable elements of a sparse keymap
3125 into an array of `struct describe_map_elt',
3126 then sorts them by the events. */
3127
3128struct describe_map_elt
3129{
3130 Lisp_Object event;
3131 Lisp_Object definition;
3132 bool shadowed;
3133};
3134
3135/* qsort comparison function for sorting `struct describe_map_elt' by
3136 the event field. */
3137
3138static int
3139describe_map_compare (const void *aa, const void *bb)
3140{
3141 const struct describe_map_elt *a = aa, *b = bb;
3142 if (FIXNUMP (a->event) && FIXNUMP (b->event))
3143 return ((XFIXNUM (a->event) > XFIXNUM (b->event))
3144 - (XFIXNUM (a->event) < XFIXNUM (b->event)));
3145 if (!FIXNUMP (a->event) && FIXNUMP (b->event))
3146 return 1;
3147 if (FIXNUMP (a->event) && !FIXNUMP (b->event))
3148 return -1;
3149 if (SYMBOLP (a->event) && SYMBOLP (b->event))
3150 /* Sort the keystroke names in the "natural" way, with (for
3151 instance) "<f2>" coming between "<f1>" and "<f11>". */
3152 return string_version_cmp (SYMBOL_NAME (a->event), SYMBOL_NAME (b->event));
3153 return 0;
3154}
3155
3156/* Describe the contents of map MAP, assuming that this map itself is
3157 reached by the sequence of prefix keys PREFIX (a string or vector).
3158 PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */
3159
3160static void
3161describe_map (Lisp_Object map, Lisp_Object prefix,
3162 void (*elt_describer) (Lisp_Object, Lisp_Object),
3163 bool partial, Lisp_Object shadow,
3164 Lisp_Object *seen, bool nomenu, bool mention_shadow)
3165{
3166 Lisp_Object tail, definition, event;
3167 Lisp_Object tem;
3168 Lisp_Object suppress;
3169 Lisp_Object kludge;
3170 bool first = 1;
3171
3172 /* These accumulate the values from sparse keymap bindings,
3173 so we can sort them and handle them in order. */
3174 ptrdiff_t length_needed = 0;
3175 struct describe_map_elt *vect;
3176 ptrdiff_t slots_used = 0;
3177 ptrdiff_t i;
3178
3179 suppress = Qnil;
3180
3181 if (partial)
3182 suppress = intern ("suppress-keymap");
3183
3184 /* This vector gets used to present single keys to Flookup_key. Since
3185 that is done once per keymap element, we don't want to cons up a
3186 fresh vector every time. */
3187 kludge = make_nil_vector (1);
3188 definition = Qnil;
3189
3190 map = call1 (Qkeymap_canonicalize, map);
3191
3192 for (tail = map; CONSP (tail); tail = XCDR (tail))
3193 length_needed++;
3194
3195 USE_SAFE_ALLOCA;
3196 SAFE_NALLOCA (vect, 1, length_needed);
3197
3198 for (tail = map; CONSP (tail); tail = XCDR (tail))
3199 {
3200 maybe_quit ();
3201
3202 if (VECTORP (XCAR (tail))
3203 || CHAR_TABLE_P (XCAR (tail)))
3204 describe_vector (XCAR (tail),
3205 prefix, Qnil, elt_describer, partial, shadow, map,
3206 1, mention_shadow);
3207 else if (CONSP (XCAR (tail)))
3208 {
3209 bool this_shadowed = 0;
3210
3211 event = XCAR (XCAR (tail));
3212
3213 /* Ignore bindings whose "prefix" are not really valid events.
3214 (We get these in the frames and buffers menu.) */
3215 if (!(SYMBOLP (event) || FIXNUMP (event)))
3216 continue;
3217
3218 if (nomenu && EQ (event, Qmenu_bar))
3219 continue;
3220
3221 definition = get_keyelt (XCDR (XCAR (tail)), 0);
3222
3223 /* Don't show undefined commands or suppressed commands. */
3224 if (NILP (definition)) continue;
3225 if (SYMBOLP (definition) && partial)
3226 {
3227 tem = Fget (definition, suppress);
3228 if (!NILP (tem))
3229 continue;
3230 }
3231
3232 /* Don't show a command that isn't really visible
3233 because a local definition of the same key shadows it. */
3234
3235 ASET (kludge, 0, event);
3236 if (!NILP (shadow))
3237 {
3238 tem = shadow_lookup (shadow, kludge, Qt, 0);
3239 if (!NILP (tem))
3240 {
3241 /* If both bindings are keymaps, this key is a prefix key,
3242 so don't say it is shadowed. */
3243 if (KEYMAPP (definition) && KEYMAPP (tem))
3244 ;
3245 /* Avoid generating duplicate entries if the
3246 shadowed binding has the same definition. */
3247 else if (mention_shadow && !EQ (tem, definition))
3248 this_shadowed = 1;
3249 else
3250 continue;
3251 }
3252 }
3253
3254 tem = Flookup_key (map, kludge, Qt);
3255 if (!EQ (tem, definition)) continue;
3256
3257 vect[slots_used].event = event;
3258 vect[slots_used].definition = definition;
3259 vect[slots_used].shadowed = this_shadowed;
3260 slots_used++;
3261 }
3262 else if (EQ (XCAR (tail), Qkeymap))
3263 {
3264 /* The same keymap might be in the structure twice, if we're
3265 using an inherited keymap. So skip anything we've already
3266 encountered. */
3267 tem = Fassq (tail, *seen);
3268 if (CONSP (tem) && !NILP (Fequal (XCAR (tem), prefix)))
3269 break;
3270 *seen = Fcons (Fcons (tail, prefix), *seen);
3271 }
3272 }
3273
3274 /* If we found some sparse map events, sort them. */
3275
3276 qsort (vect, slots_used, sizeof (struct describe_map_elt),
3277 describe_map_compare);
3278
3279 /* Now output them in sorted order. */
3280
3281 for (i = 0; i < slots_used; i++)
3282 {
3283 Lisp_Object start, end;
3284
3285 if (first)
3286 {
3287 previous_description_column = 0;
3288 insert ("\n", 1);
3289 first = 0;
3290 }
3291
3292 ASET (kludge, 0, vect[i].event);
3293 start = vect[i].event;
3294 end = start;
3295
3296 definition = vect[i].definition;
3297
3298 /* Find consecutive chars that are identically defined. */
3299 if (FIXNUMP (vect[i].event))
3300 {
3301 while (i + 1 < slots_used
3302 && EQ (vect[i+1].event, make_fixnum (XFIXNUM (vect[i].event) + 1))
3303 && !NILP (Fequal (vect[i + 1].definition, definition))
3304 && vect[i].shadowed == vect[i + 1].shadowed)
3305 i++;
3306 end = vect[i].event;
3307 }
3308
3309 /* Now START .. END is the range to describe next. */
3310
3311 /* Insert the string to describe the event START. */
3312 insert1 (Fkey_description (kludge, prefix));
3313
3314 if (!EQ (start, end))
3315 {
3316 insert (" .. ", 4);
3317
3318 ASET (kludge, 0, end);
3319 /* Insert the string to describe the character END. */
3320 insert1 (Fkey_description (kludge, prefix));
3321 }
3322
3323 /* Print a description of the definition of this character.
3324 elt_describer will take care of spacing out far enough
3325 for alignment purposes. */
3326 (*elt_describer) (vect[i].definition, Qnil);
3327
3328 if (vect[i].shadowed)
3329 {
3330 ptrdiff_t pt = max (PT - 1, BEG);
3331
3332 SET_PT (pt);
3333 insert_string ("\n (this binding is currently shadowed)");
3334 pt = min (PT + 1, Z);
3335 SET_PT (pt);
3336 }
3337 }
3338
3339 SAFE_FREE ();
3340}
3341
3342static void 3008static void
3343describe_vector_princ (Lisp_Object elt, Lisp_Object fun) 3009describe_vector_princ (Lisp_Object elt, Lisp_Object fun)
3344{ 3010{
diff --git a/src/keymap.h b/src/keymap.h
index 3ef48fb748e..2f7df2bd955 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -36,8 +36,6 @@ extern Lisp_Object current_global_map;
36extern char *push_key_description (EMACS_INT, char *); 36extern char *push_key_description (EMACS_INT, char *);
37extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool); 37extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool);
38extern Lisp_Object get_keymap (Lisp_Object, bool, bool); 38extern Lisp_Object get_keymap (Lisp_Object, bool, bool);
39extern void describe_map_tree (Lisp_Object, bool, Lisp_Object, Lisp_Object,
40 const char *, bool, bool, bool, bool);
41extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **); 39extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **);
42extern void initial_define_key (Lisp_Object, int, const char *); 40extern void initial_define_key (Lisp_Object, int, const char *);
43extern void initial_define_lispy_key (Lisp_Object, const char *, const char *); 41extern void initial_define_lispy_key (Lisp_Object, const char *, const char *);
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
index aff5d1853a6..079b1114a81 100644
--- a/test/lisp/help-tests.el
+++ b/test/lisp/help-tests.el
@@ -58,23 +58,15 @@
58;;; substitute-command-keys 58;;; substitute-command-keys
59 59
60(defmacro with-substitute-command-keys-test (&rest body) 60(defmacro with-substitute-command-keys-test (&rest body)
61 `(cl-flet* ((should-be-same-as-c-version 61 `(cl-flet* ((test
62 ;; TODO: Remove this when old C function is removed.
63 (lambda (orig)
64 (should (equal-including-properties
65 (substitute-command-keys orig)
66 (substitute-command-keys-old orig)))))
67 (test
68 (lambda (orig result) 62 (lambda (orig result)
69 (should (equal-including-properties 63 (should (equal-including-properties
70 (substitute-command-keys orig) 64 (substitute-command-keys orig)
71 result)) 65 result))))
72 (should-be-same-as-c-version orig)))
73 (test-re 66 (test-re
74 (lambda (orig regexp) 67 (lambda (orig regexp)
75 (should (string-match (concat "^" regexp "$") 68 (should (string-match (concat "^" regexp "$")
76 (substitute-command-keys orig))) 69 (substitute-command-keys orig))))))
77 (should-be-same-as-c-version orig))))
78 ,@body)) 70 ,@body))
79 71
80(ert-deftest help-tests-substitute-command-keys/no-change () 72(ert-deftest help-tests-substitute-command-keys/no-change ()
@@ -369,29 +361,6 @@ C-b undefined
369 361
370"))))) 362")))))
371 363
372;; TODO: This is a temporary test that should be removed together with
373;; substitute-command-keys-old.
374(ert-deftest help-tests-substitute-command-keys/compare ()
375 (with-substitute-command-keys-test
376 (with-temp-buffer
377 (Info-mode)
378 (outline-minor-mode)
379 (test-re "\\{Info-mode-map}" ".*")))
380 (with-substitute-command-keys-test
381 (with-temp-buffer
382 (c-mode)
383 (outline-minor-mode)
384 (test-re "\\{c-mode-map}" ".*"))))
385
386(ert-deftest help-tests-substitute-command-keys/compare-all ()
387 (let (keymaps)
388 (mapatoms (lambda (var)
389 (when (keymapp var)
390 (push var keymaps))))
391 (dolist (keymap keymaps)
392 (with-substitute-command-keys-test
393 (test-re (concat "\\{" (symbol-name keymap) "}") ".*")))))
394
395(provide 'help-tests) 364(provide 'help-tests)
396 365
397;;; help-tests.el ends here 366;;; help-tests.el ends here