docs_preprocessor: Ensure keybind is found for actions with arguments (#27224)

Finn Evers and Marshall Bowers created

Tried fixing a keybind in
https://github.com/zed-industries/zed/pull/27217 just to find out it
[still doesnt render
afterwards](https://zed.dev/docs/extensions/languages#language-metadata)
😅 This PR is a quick follow-up to fix this issue.

Issue here is (as seen in the code comment) that the
`editor::ToggleComments` command has additional arguments which caused
the match to fail. However, simply adding the missing arguments does not
work, since the regex only matches the first closing brace and fails to
match multiple closing braces. I decided against changing the matching
since it additionally looked confusing and unintuitive to use.

To not be too intrusive with this change, I just decided to add some
processing for the action string (the `KeymapAction` is not exported
from the settings and the `Value` it holds is also private). The
processing basically reverts the conversion done in `keymap_file.rs`
https://github.com/zed-industries/zed/blob/4b5df2189b9d6d2ed183cfbced7e502884cd3d48/crates/settings/src/keymap_file.rs#L102-L115
and extracts just the action name. It changes nothing for existing
keybinds and fixes the aforementioned issue.

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>

Change summary

crates/docs_preprocessor/src/main.rs | 32 +++++++++++++++++++++++++++++
1 file changed, 31 insertions(+), 1 deletion(-)

Detailed changes

crates/docs_preprocessor/src/main.rs 🔗

@@ -125,7 +125,7 @@ fn find_binding(os: &str, action: &str) -> Option<String> {
     // Find the binding in reverse order, as the last binding takes precedence.
     keymap.sections().rev().find_map(|section| {
         section.bindings().rev().find_map(|(keystroke, a)| {
-            if a.to_string() == action {
+            if name_for_action(a.to_string()) == action {
                 Some(keystroke.to_string())
             } else {
                 None
@@ -134,6 +134,36 @@ fn find_binding(os: &str, action: &str) -> Option<String> {
     })
 }
 
+/// Removes any configurable options from the stringified action if existing,
+/// ensuring that only the actual action name is returned. If the action consists
+/// only of a string and nothing else, the string is returned as-is.
+///
+/// Example:
+///
+/// This will return the action name unmodified.
+///
+/// ```
+/// let action_as_str = "assistant::Assist";
+/// let action_name = name_for_action(action_as_str);
+/// assert_eq!(action_name, "assistant::Assist");
+/// ```
+///
+/// This will return the action name with any trailing options removed.
+///
+///
+/// ```
+/// let action_as_str = "\"editor::ToggleComments\", {\"advance_downwards\":false}";
+/// let action_name = name_for_action(action_as_str);
+/// assert_eq!(action_name, "editor::ToggleComments");
+/// ```
+fn name_for_action(action_as_str: String) -> String {
+    action_as_str
+        .split(",")
+        .next()
+        .map(|name| name.trim_matches('"').to_string())
+        .unwrap_or(action_as_str)
+}
+
 fn load_keymap(asset_path: &str) -> Result<KeymapFile> {
     let content = util::asset_str::<settings::SettingsAssets>(asset_path);
     KeymapFile::parse(content.as_ref())