patch 8.2.4633: Visual range does not work before command modifiers

Problem:    Visual range does not work before command modifiers.
Solution:   Move Visual range to after command modifiers.
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 5e7cb83..9b3504f 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -2782,13 +2782,25 @@
 	cmdmod_T    *cmod,
 	int	    skip_only)
 {
+    char_u  *cmd_start;
     char_u  *p;
     int	    starts_with_colon = FALSE;
     int	    vim9script = in_vim9script();
+    int	    has_visual_range = FALSE;
 
     CLEAR_POINTER(cmod);
     cmod->cmod_flags = sticky_cmdmod_flags;
 
+    if (STRNCMP(eap->cmd, "'<,'>", 5) == 0)
+    {
+	// The automatically inserted Visual area range is skipped, so that
+	// typing ":cmdmod cmd" in Visual mode works without having to move the
+	// range to after the modififiers.
+	eap->cmd += 5;
+	cmd_start = eap->cmd;
+	has_visual_range = TRUE;
+    }
+
     // Repeat until no more command modifiers are found.
     for (;;)
     {
@@ -2849,12 +2861,11 @@
 	{
 	    char_u *s, *n;
 
-	    for (s = p; ASCII_ISALPHA(*s); ++s)
+	    for (s = eap->cmd; ASCII_ISALPHA(*s); ++s)
 		;
 	    n = skipwhite(s);
-	    if (vim_strchr((char_u *)".=", *n) != NULL
-		    || *s == '['
-		    || (*n != NUL && n[1] == '='))
+	    if (*n == '.' || *n == '=' || (*n != NUL && n[1] == '=')
+		    || *s == '[')
 		break;
 	}
 
@@ -3081,6 +3092,17 @@
 	break;
     }
 
+    if (has_visual_range && eap->cmd > cmd_start)
+    {
+	// Move the '<,'> range to after the modifiers and insert a colon.
+	// Since the modifiers have been parsed put the colon on top of the
+	// space: "'<,'>mod cmd" -> "mod:'<,'>cmd
+	// Put eap->cmd after the colon.
+	mch_memmove(cmd_start - 5, cmd_start, eap->cmd - cmd_start);
+	eap->cmd -= 5;
+	mch_memmove(eap->cmd - 1, ":'<,'>", 6);
+    }
+
     return OK;
 }