diff --git a/Cargo.lock b/Cargo.lock index 352415b1730c5c240d46e02051e7da10eb2724a1..dd0ff583c7fd2373dc24c0d28252b9e3a0e13f89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9277,7 +9277,7 @@ dependencies = [ [[package]] name = "libwebrtc" version = "0.3.10" -source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6" +source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4" dependencies = [ "cxx", "jni", @@ -9357,7 +9357,7 @@ checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "livekit" version = "0.7.8" -source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6" +source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4" dependencies = [ "chrono", "futures-util", @@ -9380,7 +9380,7 @@ dependencies = [ [[package]] name = "livekit-api" version = "0.4.2" -source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6" +source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4" dependencies = [ "futures-util", "http 0.2.12", @@ -9404,7 +9404,7 @@ dependencies = [ [[package]] name = "livekit-protocol" version = "0.3.9" -source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6" +source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4" dependencies = [ "futures-util", "livekit-runtime", @@ -9421,7 +9421,7 @@ dependencies = [ [[package]] name = "livekit-runtime" version = "0.4.0" -source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6" +source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4" dependencies = [ "tokio", "tokio-stream", @@ -16931,8 +16931,7 @@ dependencies = [ [[package]] name = "tree-sitter-python" version = "0.23.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d065aaa27f3aaceaf60c1f0e0ac09e1cb9eb8ed28e7bcdaa52129cffc7f4b04" +source = "git+https://github.com/zed-industries/tree-sitter-python?rev=218fcbf3fda3d029225f3dec005cb497d111b35e#218fcbf3fda3d029225f3dec005cb497d111b35e" dependencies = [ "cc", "tree-sitter-language", @@ -18348,7 +18347,7 @@ dependencies = [ [[package]] name = "webrtc-sys" version = "0.3.7" -source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6" +source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4" dependencies = [ "cc", "cxx", @@ -18361,7 +18360,7 @@ dependencies = [ [[package]] name = "webrtc-sys-build" version = "0.3.6" -source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6" +source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4" dependencies = [ "fs2", "regex", diff --git a/Cargo.toml b/Cargo.toml index ccc70fcb94cf23b45f876802b7dd9211ec0b189c..f8f5c2a6d017cb8591d1a1f6426b70e7226188f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -598,7 +598,7 @@ tree-sitter-html = "0.23" tree-sitter-jsdoc = "0.23" tree-sitter-json = "0.24" tree-sitter-md = { git = "https://github.com/tree-sitter-grammars/tree-sitter-markdown", rev = "9a23c1a96c0513d8fc6520972beedd419a973539" } -tree-sitter-python = "0.23" +tree-sitter-python = { git = "https://github.com/zed-industries/tree-sitter-python", rev = "218fcbf3fda3d029225f3dec005cb497d111b35e" } tree-sitter-regex = "0.24" tree-sitter-ruby = "0.23" tree-sitter-rust = "0.24" diff --git a/crates/editor/src/actions.rs b/crates/editor/src/actions.rs index ff6263dfa71184ded4e7697dd6132aa12138063d..697bd6ef3760c32e2f02456f101e1f3ddc1b15f8 100644 --- a/crates/editor/src/actions.rs +++ b/crates/editor/src/actions.rs @@ -388,7 +388,6 @@ actions!( RestartLanguageServer, RevealInFileManager, ReverseLines, - RevertFile, ReloadFile, Rewrap, RunFlycheck, diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 3671653e16b0c6452e4c57b9108768b6376b87bf..5b9a2ef773f6deb5ef2f26e573125021445cbcfd 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -21771,9 +21771,9 @@ async fn test_tab_in_leading_whitespace_auto_indents_for_python(cx: &mut TestApp cx.set_state(indoc! {" def main(): ˇ try: - ˇ fetch() + ˇ fetch() ˇ except ValueError: - ˇ handle_error() + ˇ handle_error() ˇ else: ˇ match value: ˇ case _: @@ -21901,74 +21901,101 @@ async fn test_outdent_after_input_for_python(cx: &mut TestAppContext) { finally:ˇ "}); - // TODO: test `except` auto outdents when typed inside `try` block right after for block - // cx.set_state(indoc! {" - // def main(): - // try: - // for i in range(n): - // pass - // ˇ - // "}); - // cx.update_editor(|editor, window, cx| { - // editor.handle_input("except:", window, cx); - // }); - // cx.assert_editor_state(indoc! {" - // def main(): - // try: - // for i in range(n): - // pass - // except:ˇ - // "}); - - // TODO: test `else` auto outdents when typed inside `except` block right after for block - // cx.set_state(indoc! {" - // def main(): - // try: - // i = 2 - // except: - // for i in range(n): - // pass - // ˇ - // "}); - // cx.update_editor(|editor, window, cx| { - // editor.handle_input("else:", window, cx); - // }); - // cx.assert_editor_state(indoc! {" - // def main(): - // try: - // i = 2 - // except: - // for i in range(n): - // pass - // else:ˇ - // "}); - - // TODO: test `finally` auto outdents when typed inside `else` block right after for block - // cx.set_state(indoc! {" - // def main(): - // try: - // i = 2 - // except: - // j = 2 - // else: - // for i in range(n): - // pass - // ˇ - // "}); - // cx.update_editor(|editor, window, cx| { - // editor.handle_input("finally:", window, cx); - // }); - // cx.assert_editor_state(indoc! {" - // def main(): - // try: - // i = 2 - // except: - // j = 2 - // else: - // for i in range(n): - // pass - // finally:ˇ - // "}); + // test `else` does not outdents when typed inside `except` block right after for block + cx.set_state(indoc! {" + def main(): + try: + i = 2 + except: + for i in range(n): + pass + ˇ + "}); + cx.update_editor(|editor, window, cx| { + editor.handle_input("else:", window, cx); + }); + cx.assert_editor_state(indoc! {" + def main(): + try: + i = 2 + except: + for i in range(n): + pass + else:ˇ + "}); + + // test `finally` auto outdents when typed inside `else` block right after for block + cx.set_state(indoc! {" + def main(): + try: + i = 2 + except: + j = 2 + else: + for i in range(n): + pass + ˇ + "}); + cx.update_editor(|editor, window, cx| { + editor.handle_input("finally:", window, cx); + }); + cx.assert_editor_state(indoc! {" + def main(): + try: + i = 2 + except: + j = 2 + else: + for i in range(n): + pass + finally:ˇ + "}); + + // test `except` outdents to inner "try" block + cx.set_state(indoc! {" + def main(): + try: + i = 2 + if i == 2: + try: + i = 3 + ˇ + "}); + cx.update_editor(|editor, window, cx| { + editor.handle_input("except:", window, cx); + }); + cx.assert_editor_state(indoc! {" + def main(): + try: + i = 2 + if i == 2: + try: + i = 3 + except:ˇ + "}); + + // test `except` outdents to outer "try" block + cx.set_state(indoc! {" + def main(): + try: + i = 2 + if i == 2: + try: + i = 3 + ˇ + "}); + cx.update_editor(|editor, window, cx| { + editor.handle_input("except:", window, cx); + }); + cx.assert_editor_state(indoc! {" + def main(): + try: + i = 2 + if i == 2: + try: + i = 3 + except:ˇ + "}); // test `else` stays at correct indent when typed after `for` block cx.set_state(indoc! {" diff --git a/crates/gpui/src/action.rs b/crates/gpui/src/action.rs index bfb37efd9a45e7e69781634a54c686548272b404..24fbd70b63d87f564301153073c5ebe7b7fdaa32 100644 --- a/crates/gpui/src/action.rs +++ b/crates/gpui/src/action.rs @@ -48,6 +48,8 @@ macro_rules! actions { /// actions!(editor, [MoveUp, MoveDown, MoveLeft, MoveRight, Newline]); /// ``` /// +/// Registering the actions with the same name will result in a panic during `App` creation. +/// /// # Derive Macro /// /// More complex data types can also be actions, by using the derive macro for `Action`: @@ -280,14 +282,27 @@ impl ActionRegistry { } fn insert_action(&mut self, action: MacroActionData) { + let name = action.name; + if self.by_name.contains_key(name) { + panic!( + "Action with name `{name}` already registered \ + (might be registered in `#[action(deprecated_aliases = [...])]`." + ); + } self.by_name.insert( - action.name, + name, ActionData { build: action.build, json_schema: action.json_schema, }, ); for &alias in action.deprecated_aliases { + if self.by_name.contains_key(alias) { + panic!( + "Action with name `{alias}` already registered. \ + `{alias}` is specified in `#[action(deprecated_aliases = [...])]` for action `{name}`." + ); + } self.by_name.insert( alias, ActionData { @@ -295,14 +310,13 @@ impl ActionRegistry { json_schema: action.json_schema, }, ); - self.deprecated_aliases.insert(alias, action.name); + self.deprecated_aliases.insert(alias, name); self.all_names.push(alias); } - self.names_by_type_id.insert(action.type_id, action.name); - self.all_names.push(action.name); + self.names_by_type_id.insert(action.type_id, name); + self.all_names.push(name); if let Some(deprecation_msg) = action.deprecation_message { - self.deprecation_messages - .insert(action.name, deprecation_msg); + self.deprecation_messages.insert(name, deprecation_msg); } } diff --git a/crates/gpui/src/keymap/context.rs b/crates/gpui/src/keymap/context.rs index 1221aa1224bcd9a541dd6461016b601939a15b28..eaad06098218275ab37c9078c358cab019e90761 100644 --- a/crates/gpui/src/keymap/context.rs +++ b/crates/gpui/src/keymap/context.rs @@ -432,7 +432,7 @@ mod tests { actions!( test_only, [ - A, B, C, D, E, F, G, // Don't wrap, test the trailing comma + H, I, J, K, L, M, N, // Don't wrap, test the trailing comma ] ); } diff --git a/crates/gpui/src/platform/linux/wayland/window.rs b/crates/gpui/src/platform/linux/wayland/window.rs index 4507101eede0b6a66087768b26754a9f3eace934..9d602130d4c545213175b2bbbd088ec5f9062c1c 100644 --- a/crates/gpui/src/platform/linux/wayland/window.rs +++ b/crates/gpui/src/platform/linux/wayland/window.rs @@ -699,12 +699,14 @@ impl WaylandWindowStatePtr { } } if let PlatformInput::KeyDown(event) = input { - if let Some(key_char) = &event.keystroke.key_char { - let mut state = self.state.borrow_mut(); - if let Some(mut input_handler) = state.input_handler.take() { - drop(state); - input_handler.replace_text_in_range(None, key_char); - self.state.borrow_mut().input_handler = Some(input_handler); + if event.keystroke.modifiers.is_subset_of(&Modifiers::shift()) { + if let Some(key_char) = &event.keystroke.key_char { + let mut state = self.state.borrow_mut(); + if let Some(mut input_handler) = state.input_handler.take() { + drop(state); + input_handler.replace_text_in_range(None, key_char); + self.state.borrow_mut().input_handler = Some(input_handler); + } } } } diff --git a/crates/gpui/src/platform/linux/x11/window.rs b/crates/gpui/src/platform/linux/x11/window.rs index 673c04a3e5edfcdbb4efd508bffd50b0c50891c5..248911a5b97d08d2ceaf48db22c215480ea68db0 100644 --- a/crates/gpui/src/platform/linux/x11/window.rs +++ b/crates/gpui/src/platform/linux/x11/window.rs @@ -982,14 +982,17 @@ impl X11WindowStatePtr { } } if let PlatformInput::KeyDown(event) = input { - let mut state = self.state.borrow_mut(); - if let Some(mut input_handler) = state.input_handler.take() { - if let Some(key_char) = &event.keystroke.key_char { - drop(state); - input_handler.replace_text_in_range(None, key_char); - state = self.state.borrow_mut(); + // only allow shift modifier when inserting text + if event.keystroke.modifiers.is_subset_of(&Modifiers::shift()) { + let mut state = self.state.borrow_mut(); + if let Some(mut input_handler) = state.input_handler.take() { + if let Some(key_char) = &event.keystroke.key_char { + drop(state); + input_handler.replace_text_in_range(None, key_char); + state = self.state.borrow_mut(); + } + state.input_handler = Some(input_handler); } - state.input_handler = Some(input_handler); } } } diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 90a899f79d42f33f91044f025bc22383c2f3881d..ae0184b22a97acfb2adf1080a352479fca2ab82e 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -2913,7 +2913,12 @@ impl BufferSnapshot { ) -> Option> + '_> { let config = &self.language.as_ref()?.config; let prev_non_blank_row = self.prev_non_blank_row(row_range.start); - let significant_indentation = config.significant_indentation; + + #[derive(Debug, Clone)] + struct StartPosition { + start: Point, + suffix: SharedString, + } // Find the suggested indentation ranges based on the syntax tree. let start = Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0); @@ -2929,13 +2934,13 @@ impl BufferSnapshot { .collect::>(); let mut indent_ranges = Vec::>::new(); + let mut start_positions = Vec::::new(); let mut outdent_positions = Vec::::new(); while let Some(mat) = matches.peek() { let mut start: Option = None; let mut end: Option = None; - let mut outdent: Option = None; - let config = &indent_configs[mat.grammar_index]; + let config = indent_configs[mat.grammar_index]; for capture in mat.captures { if capture.index == config.indent_capture_ix { start.get_or_insert(Point::from_ts_point(capture.node.start_position())); @@ -2945,21 +2950,18 @@ impl BufferSnapshot { } else if Some(capture.index) == config.end_capture_ix { end = Some(Point::from_ts_point(capture.node.start_position())); } else if Some(capture.index) == config.outdent_capture_ix { - let point = Point::from_ts_point(capture.node.start_position()); - outdent.get_or_insert(point); - outdent_positions.push(point); + outdent_positions.push(Point::from_ts_point(capture.node.start_position())); + } else if let Some(suffix) = config.suffixed_start_captures.get(&capture.index) { + start_positions.push(StartPosition { + start: Point::from_ts_point(capture.node.start_position()), + suffix: suffix.clone(), + }); } } matches.advance(); - // in case of significant indentation expand end to outdent position - let end = if significant_indentation { - outdent.or(end) - } else { - end - }; if let Some((start, end)) = start.zip(end) { - if start.row == end.row && (!significant_indentation || start.column < end.column) { + if start.row == end.row { continue; } let range = start..end; @@ -2997,24 +2999,26 @@ impl BufferSnapshot { matches.advance(); } - // we don't use outdent positions to truncate in case of significant indentation - // rather we use them to expand (handled above) - if !significant_indentation { - outdent_positions.sort(); - for outdent_position in outdent_positions { - // find the innermost indent range containing this outdent_position - // set its end to the outdent position - if let Some(range_to_truncate) = indent_ranges - .iter_mut() - .filter(|indent_range| indent_range.contains(&outdent_position)) - .next_back() - { - range_to_truncate.end = outdent_position; - } + outdent_positions.sort(); + for outdent_position in outdent_positions { + // find the innermost indent range containing this outdent_position + // set its end to the outdent position + if let Some(range_to_truncate) = indent_ranges + .iter_mut() + .filter(|indent_range| indent_range.contains(&outdent_position)) + .next_back() + { + range_to_truncate.end = outdent_position; } } + start_positions.sort_by_key(|b| b.start); + // Find the suggested indentation increases and decreased based on regexes. + let mut regex_outdent_map = HashMap::default(); + let mut last_seen_suffix: HashMap> = HashMap::default(); + let mut start_positions_iter = start_positions.iter().peekable(); + let mut indent_change_rows = Vec::<(u32, Ordering)>::new(); self.for_each_line( Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0) @@ -3034,6 +3038,33 @@ impl BufferSnapshot { { indent_change_rows.push((row + 1, Ordering::Greater)); } + while let Some(pos) = start_positions_iter.peek() { + if pos.start.row < row { + let pos = start_positions_iter.next().unwrap(); + last_seen_suffix + .entry(pos.suffix.to_string()) + .or_default() + .push(pos.start); + } else { + break; + } + } + for rule in &config.decrease_indent_patterns { + if rule.pattern.as_ref().map_or(false, |r| r.is_match(line)) { + let row_start_column = self.indent_size_for_line(row).len; + let basis_row = rule + .valid_after + .iter() + .filter_map(|valid_suffix| last_seen_suffix.get(valid_suffix)) + .flatten() + .filter(|start_point| start_point.column <= row_start_column) + .max_by_key(|start_point| start_point.row); + if let Some(outdent_to_row) = basis_row { + regex_outdent_map.insert(row, outdent_to_row.row); + } + break; + } + } }, ); @@ -3043,6 +3074,7 @@ impl BufferSnapshot { } else { row_range.start.saturating_sub(1) }; + let mut prev_row_start = Point::new(prev_row, self.indent_size_for_line(prev_row).len); Some(row_range.map(move |row| { let row_start = Point::new(row, self.indent_size_for_line(row).len); @@ -3080,17 +3112,17 @@ impl BufferSnapshot { if range.start.row == prev_row && range.end > row_start { indent_from_prev_row = true; } - if significant_indentation && self.is_line_blank(row) && range.start.row == prev_row - { - indent_from_prev_row = true; - } - if !significant_indentation || !self.is_line_blank(row) { - if range.end > prev_row_start && range.end <= row_start { - outdent_to_row = outdent_to_row.min(range.start.row); - } + if range.end > prev_row_start && range.end <= row_start { + outdent_to_row = outdent_to_row.min(range.start.row); } } + if let Some(basis_row) = regex_outdent_map.get(&row) { + indent_from_prev_row = false; + outdent_to_row = *basis_row; + from_regex = true; + } + let within_error = error_ranges .iter() .any(|e| e.start.row < row && e.end > row_start); diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index f564b54ed52e028a8a19f13616bc42364ff4d4a4..f77afc76d2ffae034e2f0d3d3d4d2507c919b518 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -696,10 +696,6 @@ pub struct LanguageConfig { #[serde(default)] #[schemars(schema_with = "bracket_pair_config_json_schema")] pub brackets: BracketPairConfig, - /// If set to true, indicates the language uses significant whitespace/indentation - /// for syntax structure (like Python) rather than brackets/braces for code blocks. - #[serde(default)] - pub significant_indentation: bool, /// If set to true, auto indentation uses last non empty line to determine /// the indentation level for a new line. #[serde(default = "auto_indent_using_last_non_empty_line_default")] @@ -717,6 +713,12 @@ pub struct LanguageConfig { #[serde(default, deserialize_with = "deserialize_regex")] #[schemars(schema_with = "regex_json_schema")] pub decrease_indent_pattern: Option, + /// A list of rules for decreasing indentation. Each rule pairs a regex with a set of valid + /// "block-starting" tokens. When a line matches a pattern, its indentation is aligned with + /// the most recent line that began with a corresponding token. This enables context-aware + /// outdenting, like aligning an `else` with its `if`. + #[serde(default)] + pub decrease_indent_patterns: Vec, /// A list of characters that trigger the automatic insertion of a closing /// bracket when they immediately precede the point where an opening /// bracket is inserted. @@ -776,6 +778,15 @@ pub struct LanguageConfig { pub documentation: Option, } +#[derive(Clone, Debug, Deserialize, Default, JsonSchema)] +pub struct DecreaseIndentConfig { + #[serde(default, deserialize_with = "deserialize_regex")] + #[schemars(schema_with = "regex_json_schema")] + pub pattern: Option, + #[serde(default)] + pub valid_after: Vec, +} + #[derive(Clone, Debug, Serialize, Deserialize, Default, JsonSchema)] pub struct LanguageMatcher { /// Given a list of `LanguageConfig`'s, the language of a file can be determined based on the path extension matching any of the `path_suffixes`. @@ -899,6 +910,7 @@ impl Default for LanguageConfig { auto_indent_on_paste: None, increase_indent_pattern: Default::default(), decrease_indent_pattern: Default::default(), + decrease_indent_patterns: Default::default(), autoclose_before: Default::default(), line_comments: Default::default(), block_comment: Default::default(), @@ -914,7 +926,6 @@ impl Default for LanguageConfig { jsx_tag_auto_close: None, completion_query_characters: Default::default(), debuggers: Default::default(), - significant_indentation: Default::default(), documentation: None, } } @@ -1092,6 +1103,7 @@ struct IndentConfig { start_capture_ix: Option, end_capture_ix: Option, outdent_capture_ix: Option, + suffixed_start_captures: HashMap, } pub struct OutlineConfig { @@ -1522,6 +1534,14 @@ impl Language { ("outdent", &mut outdent_capture_ix), ], ); + + let mut suffixed_start_captures = HashMap::default(); + for (ix, name) in query.capture_names().iter().enumerate() { + if let Some(suffix) = name.strip_prefix("start.") { + suffixed_start_captures.insert(ix as u32, suffix.to_owned().into()); + } + } + if let Some(indent_capture_ix) = indent_capture_ix { grammar.indents_config = Some(IndentConfig { query, @@ -1529,6 +1549,7 @@ impl Language { start_capture_ix, end_capture_ix, outdent_capture_ix, + suffixed_start_captures, }); } Ok(self) diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index 03b1b749c1b81bddcef37c5ebc202618d1def01a..dc6996d3999a0d6bd366f8d444b19e046e0150a8 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -1395,7 +1395,7 @@ mod tests { // dedent "else" on the line after a closing paren append(&mut buffer, "\n else:\n", cx); - assert_eq!(buffer.text(), "if a:\n b(\n )\nelse:\n"); + assert_eq!(buffer.text(), "if a:\n b(\n )\nelse:\n "); buffer }); diff --git a/crates/languages/src/python/config.toml b/crates/languages/src/python/config.toml index f878cb396654923815754ec18a327255a36af558..6d83d3f3dec6ba44e87e1d361fb5e61198767874 100644 --- a/crates/languages/src/python/config.toml +++ b/crates/languages/src/python/config.toml @@ -28,6 +28,11 @@ brackets = [ auto_indent_using_last_non_empty_line = false debuggers = ["Debugpy"] -significant_indentation = true -increase_indent_pattern = "^\\s*(try)\\b.*:" -decrease_indent_pattern = "^\\s*(else|elif|except|finally)\\b.*:" +increase_indent_pattern = "^[^#].*:\\s*$" +decrease_indent_patterns = [ + { pattern = "^\\s*elif\\b.*:", valid_after = ["if", "elif"] }, + { pattern = "^\\s*else\\b.*:", valid_after = ["if", "elif", "for", "while", "except"] }, + { pattern = "^\\s*except\\b.*:", valid_after = ["try", "except"] }, + { pattern = "^\\s*finally\\b.*:", valid_after = ["try", "except", "else"] }, + { pattern = "^\\s*case\\b.*:", valid_after = ["match", "case"] } +] diff --git a/crates/languages/src/python/indents.scm b/crates/languages/src/python/indents.scm index f306d814350091994af4ab322432045a4adf35c7..617aa706d3177c368f334c409989a27d09655b1e 100644 --- a/crates/languages/src/python/indents.scm +++ b/crates/languages/src/python/indents.scm @@ -1,72 +1,17 @@ -(_ "(" ")" @end) @indent (_ "[" "]" @end) @indent (_ "{" "}" @end) @indent +(_ "(" ")" @end) @indent -(function_definition - ":" @start - body: (block) @indent -) - -(if_statement - ":" @start - consequence: (block) @indent - alternative: (_)? @outdent -) - -(else_clause - ":" @start - body: (block) @indent -) - -(elif_clause - ":" @start - consequence: (block) @indent -) - -(for_statement - ":" @start - body: (block) @indent -) - -(with_statement - ":" @start - body: (block) @indent -) - -(while_statement - ":" @start - body: (block) @indent -) - -(match_statement - ":" @start - body: (block) @indent -) - -(class_definition - ":" @start - body: (block) @indent -) - -(case_clause - ":" @start - consequence: (block) @indent -) - -(try_statement - ":" @start - body: (block) @indent - (except_clause)? @outdent - (else_clause)? @outdent - (finally_clause)? @outdent -) - -(except_clause - ":" @start - (block) @indent -) - -(finally_clause - ":" @start - (block) @indent -) +(function_definition) @start.def +(class_definition) @start.class +(if_statement) @start.if +(for_statement) @start.for +(while_statement) @start.while +(with_statement) @start.with +(match_statement) @start.match +(try_statement) @start.try +(elif_clause) @start.elif +(else_clause) @start.else +(except_clause) @start.except +(finally_clause) @start.finally +(case_pattern) @start.case diff --git a/crates/livekit_client/Cargo.toml b/crates/livekit_client/Cargo.toml index 2762d61f8919711637bf7971d1e59b9bfa9b8845..b4518d6c166ba1c3de027874bfdc5ea8caef0245 100644 --- a/crates/livekit_client/Cargo.toml +++ b/crates/livekit_client/Cargo.toml @@ -40,8 +40,8 @@ util.workspace = true workspace-hack.workspace = true [target.'cfg(not(any(all(target_os = "windows", target_env = "gnu"), target_os = "freebsd")))'.dependencies] -libwebrtc = { rev = "80bb8f4c9112789f7c24cc98d8423010977806a6", git = "https://github.com/zed-industries/livekit-rust-sdks" } -livekit = { rev = "80bb8f4c9112789f7c24cc98d8423010977806a6", git = "https://github.com/zed-industries/livekit-rust-sdks", features = [ +libwebrtc = { rev = "d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4", git = "https://github.com/zed-industries/livekit-rust-sdks" } +livekit = { rev = "d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4", git = "https://github.com/zed-industries/livekit-rust-sdks", features = [ "__rustls-tls" ] } diff --git a/crates/vim/src/helix.rs b/crates/vim/src/helix.rs index 8c1ab3297e28a7f3b910ba673cdcfc240506d5c4..425280d58bd50ae73a39362bd635f28f1630eb44 100644 --- a/crates/vim/src/helix.rs +++ b/crates/vim/src/helix.rs @@ -3,14 +3,12 @@ use gpui::{Action, actions}; use gpui::{Context, Window}; use language::{CharClassifier, CharKind}; -use crate::motion::MotionKind; use crate::{Vim, motion::Motion, state::Mode}; -actions!(vim, [HelixNormalAfter, HelixDelete]); +actions!(vim, [HelixNormalAfter]); pub fn register(editor: &mut Editor, cx: &mut Context) { Vim::action(editor, cx, Vim::helix_normal_after); - Vim::action(editor, cx, Vim::helix_delete); } impl Vim { @@ -292,27 +290,6 @@ impl Vim { _ => self.helix_move_and_collapse(motion, times, window, cx), } } - - pub fn helix_delete(&mut self, _: &HelixDelete, window: &mut Window, cx: &mut Context) { - self.store_visual_marks(window, cx); - self.update_editor(window, cx, |vim, editor, window, cx| { - // Fixup selections so they have helix's semantics. - // Specifically: - // - Make sure that each cursor acts as a 1 character wide selection - editor.transact(window, cx, |editor, window, cx| { - editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| { - s.move_with(|map, selection| { - if selection.is_empty() && !selection.reversed { - selection.end = movement::right(map, selection.end); - } - }); - }); - }); - - vim.copy_selections_content(editor, MotionKind::Exclusive, window, cx); - editor.insert("", window, cx); - }); - } } #[cfg(test)] diff --git a/docs/src/languages/python.md b/docs/src/languages/python.md index 2848884316f7336467fd5fec09b42cbf7ba4e49e..05f1491ca73b2adccb04aeca412a2bef9702e22a 100644 --- a/docs/src/languages/python.md +++ b/docs/src/languages/python.md @@ -2,7 +2,7 @@ Python support is available natively in Zed. -- Tree-sitter: [tree-sitter-python](https://github.com/tree-sitter/tree-sitter-python) +- Tree-sitter: [tree-sitter-python](https://github.com/zed-industries/tree-sitter-python) - Language Servers: - [microsoft/pyright](https://github.com/microsoft/pyright) - [python-lsp/python-lsp-server](https://github.com/python-lsp/python-lsp-server) (PyLSP)