Detect URLs at beginning and end of buffer as well (#9212)

Ivan Žužak created

Release Notes:

- Fixed URL detection at very beginning and very end of buffer
([#9210](https://github.com/zed-industries/zed/issues/9210)).

| Before | After |
| ------ | ----- |
| ![Screenshot 2024-03-12 at 07 09
52](https://github.com/zed-industries/zed/assets/38924/5c0beb28-f63b-4455-a5cd-31cec2d9a775)
| ![Screenshot 2024-03-12 at 07 11
03](https://github.com/zed-industries/zed/assets/38924/116f76a2-21e8-4c77-ac6e-a4e3c594b09d)
|

Change summary

crates/editor/src/hover_links.rs | 57 ++++++++++++++++++++++++++++++++-
1 file changed, 55 insertions(+), 2 deletions(-)

Detailed changes

crates/editor/src/hover_links.rs 🔗

@@ -591,7 +591,8 @@ pub(crate) fn find_url(
         }
         token_start -= ch.len_utf8();
     }
-    if !found_start {
+    // Check if we didn't find the starting whitespace or if we didn't reach the start of the buffer
+    if !found_start && token_start != 0 {
         return None;
     }
 
@@ -605,7 +606,9 @@ pub(crate) fn find_url(
         }
         token_end += ch.len_utf8();
     }
-    if !found_end {
+    // Check if we didn't find the ending whitespace or if we read more or equal than LIMIT
+    // which at this point would happen only if we reached the end of buffer
+    if !found_end && (token_end - token_start >= LIMIT) {
         return None;
     }
 
@@ -1155,4 +1158,54 @@ mod tests {
             Some("https://zed.dev/channel/had-(oops)".into())
         );
     }
+
+    #[gpui::test]
+    async fn test_urls_at_beginning_of_buffer(cx: &mut gpui::TestAppContext) {
+        init_test(cx, |_| {});
+        let mut cx = EditorLspTestContext::new_rust(
+            lsp::ServerCapabilities {
+                ..Default::default()
+            },
+            cx,
+        )
+        .await;
+
+        cx.set_state(indoc! {"https://zed.dev/releases is a cool ˇwebpage."});
+
+        let screen_coord =
+            cx.pixel_position(indoc! {"https://zed.dev/relˇeases is a cool webpage."});
+
+        cx.simulate_mouse_move(screen_coord, Modifiers::command());
+        cx.assert_editor_text_highlights::<HoveredLinkState>(
+            indoc! {"«https://zed.dev/releasesˇ» is a cool webpage."},
+        );
+
+        cx.simulate_click(screen_coord, Modifiers::command());
+        assert_eq!(cx.opened_url(), Some("https://zed.dev/releases".into()));
+    }
+
+    #[gpui::test]
+    async fn test_urls_at_end_of_buffer(cx: &mut gpui::TestAppContext) {
+        init_test(cx, |_| {});
+        let mut cx = EditorLspTestContext::new_rust(
+            lsp::ServerCapabilities {
+                ..Default::default()
+            },
+            cx,
+        )
+        .await;
+
+        cx.set_state(indoc! {"A cool ˇwebpage is https://zed.dev/releases"});
+
+        let screen_coord =
+            cx.pixel_position(indoc! {"A cool webpage is https://zed.dev/releˇases"});
+
+        cx.simulate_mouse_move(screen_coord, Modifiers::command());
+        cx.assert_editor_text_highlights::<HoveredLinkState>(
+            indoc! {"A cool webpage is «https://zed.dev/releasesˇ»"},
+        );
+
+        cx.simulate_click(screen_coord, Modifiers::command());
+        assert_eq!(cx.opened_url(), Some("https://zed.dev/releases".into()));
+    }
 }