patch 8.2.4820: not simple programmatic way to find a specific mapping

Problem:    Not simple programmatic way to find a specific mapping.
Solution:   Add getmappings(). (Ernie Rael, closes #10273)
diff --git a/src/map.c b/src/map.c
index f3ff007..38f5282 100644
--- a/src/map.c
+++ b/src/map.c
@@ -2274,6 +2274,42 @@
     return NULL;
 }
 
+/*
+ * Fill in the empty dictionary with items as defined by maparg builtin.
+ */
+    static void
+mapblock2dict(
+	mapblock_T  *mp,
+	dict_T	    *dict,
+	char_u	    *lhsrawalt,	    // may be NULL
+	int	    buffer_local)   // false if not buffer local mapping
+{
+    char_u	    *lhs = str2special_save(mp->m_keys, TRUE);
+    char_u	    *mapmode = map_mode_to_chars(mp->m_mode);
+
+    dict_add_string(dict, "lhs", lhs);
+    vim_free(lhs);
+    dict_add_string(dict, "lhsraw", mp->m_keys);
+    if (lhsrawalt)
+	// Also add the value for the simplified entry.
+	dict_add_string(dict, "lhsrawalt", lhsrawalt);
+    dict_add_string(dict, "rhs", mp->m_orig_str);
+    dict_add_number(dict, "noremap", mp->m_noremap ? 1L : 0L);
+    dict_add_number(dict, "script", mp->m_noremap == REMAP_SCRIPT
+		    ? 1L : 0L);
+    dict_add_number(dict, "expr", mp->m_expr ? 1L : 0L);
+    dict_add_number(dict, "silent", mp->m_silent ? 1L : 0L);
+    dict_add_number(dict, "sid", (long)mp->m_script_ctx.sc_sid);
+    dict_add_number(dict, "scriptversion",
+		    (long)mp->m_script_ctx.sc_version);
+    dict_add_number(dict, "lnum", (long)mp->m_script_ctx.sc_lnum);
+    dict_add_number(dict, "buffer", (long)buffer_local);
+    dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L);
+    dict_add_string(dict, "mode", mapmode);
+
+    vim_free(mapmode);
+}
+
     static void
 get_maparg(typval_T *argvars, typval_T *rettv, int exact)
 {
@@ -2346,40 +2382,67 @@
 
     }
     else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL)
-    {
-	// Return a dictionary.
-	char_u	    *lhs = str2special_save(mp->m_keys, TRUE);
-	char_u	    *mapmode = map_mode_to_chars(mp->m_mode);
-	dict_T	    *dict = rettv->vval.v_dict;
-
-	dict_add_string(dict, "lhs", lhs);
-	vim_free(lhs);
-	dict_add_string(dict, "lhsraw", mp->m_keys);
-	if (did_simplify)
-	    // Also add the value for the simplified entry.
-	    dict_add_string(dict, "lhsrawalt", mp_simplified->m_keys);
-	dict_add_string(dict, "rhs", mp->m_orig_str);
-	dict_add_number(dict, "noremap", mp->m_noremap ? 1L : 0L);
-	dict_add_number(dict, "script", mp->m_noremap == REMAP_SCRIPT
-								    ? 1L : 0L);
-	dict_add_number(dict, "expr", mp->m_expr ? 1L : 0L);
-	dict_add_number(dict, "silent", mp->m_silent ? 1L : 0L);
-	dict_add_number(dict, "sid", (long)mp->m_script_ctx.sc_sid);
-	dict_add_number(dict, "scriptversion",
-					    (long)mp->m_script_ctx.sc_version);
-	dict_add_number(dict, "lnum", (long)mp->m_script_ctx.sc_lnum);
-	dict_add_number(dict, "buffer", (long)buffer_local);
-	dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L);
-	dict_add_string(dict, "mode", mapmode);
-
-	vim_free(mapmode);
-    }
+	mapblock2dict(mp, rettv->vval.v_dict,
+		    did_simplify ? mp_simplified->m_keys : NULL, buffer_local);
 
     vim_free(keys_buf);
     vim_free(alt_keys_buf);
 }
 
 /*
+ * "getmappings()" function
+ */
+    void
+f_getmappings(typval_T *argvars UNUSED, typval_T *rettv)
+{
+    dict_T	*d;
+    mapblock_T	*mp;
+    int		buffer_local;
+    char_u	*keys_buf;
+    int		did_simplify;
+    int		hash;
+    char_u	*lhs;
+    const int	flags = REPTERM_FROM_PART | REPTERM_DO_LT;
+
+    if (rettv_list_alloc(rettv) != OK)
+	return;
+
+    validate_maphash();
+
+    // Do it twice: once for global maps and once for local maps.
+    for (buffer_local = 0; buffer_local <= 1; ++buffer_local)
+    {
+	for (hash = 0; hash < 256; ++hash)
+	{
+	    if (buffer_local)
+		mp = curbuf->b_maphash[hash];
+	    else
+		mp = maphash[hash];
+	    for (; mp; mp = mp->m_next)
+	    {
+		if (mp->m_simplified)
+		    continue;
+		if ((d = dict_alloc()) == NULL)
+		    return;
+		if (list_append_dict(rettv->vval.v_list, d) == FAIL)
+		    return;
+
+		keys_buf = NULL;
+		did_simplify = FALSE;
+
+		lhs = str2special_save(mp->m_keys, TRUE);
+		(void)replace_termcodes(lhs, &keys_buf, flags, &did_simplify);
+		vim_free(lhs);
+
+		mapblock2dict(mp, d,
+				 did_simplify ? keys_buf : NULL, buffer_local);
+		vim_free(keys_buf);
+	    }
+	}
+    }
+}
+
+/*
  * "maparg()" function
  */
     void