Support relative line number on wrapped lines (#39268)
**Problem:** Current relative line numbering creates a mismatch with vim-style navigation when soft wrap is enabled. Users must mentally calculate whether target lines are wrapped segments or logical lines, making `<n>j/k` navigation unreliable and cognitively demanding. **How things work today:** - Real line navigation (`j/k` moves by logical lines): Requires determining if visible lines are wrapped segments before jumping. Can't jump to wrapped lines directly. - Display line navigation (`j/k` moves by display rows): Line numbers don't correspond to actual row distances for multi-line jumps. **Proposed solution:** Count and number each display line (including wrapped segments) for relative numbering. This creates direct visual-to-navigational correspondence where the relative number shown always matches the `<n>j/k` distance needed. **Benefits:** - Eliminates mental overhead of distinguishing wrapped vs. logical lines - Makes relative line numbers consistently actionable regardless of wrap state - Preserves intuitive "what you see is what you navigate" principle - Maintains vim workflow efficiency in narrow window scenarios Also explained an discussed in https://github.com/zed-industries/zed/discussions/25733. Release Notes: Release Notes: - Added support for counting wrapped lines as relative lines and for displaying line numbers for wrapped segments. Changes `relative_line_numbers` from a boolean to an enum: `enabled`, `disabled`, or `wrapped`. --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
co-authored by
Conrad Irwin
parent
1c4923e1c8
commit
d5e297147f
@@ -129,3 +129,9 @@ pub(crate) mod m_2025_10_17 {
|
||||
|
||||
pub(crate) use settings::make_file_finder_include_ignored_an_enum;
|
||||
}
|
||||
|
||||
pub(crate) mod m_2025_10_21 {
|
||||
mod settings;
|
||||
|
||||
pub(crate) use settings::make_relative_line_numbers_an_enum;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
use anyhow::Result;
|
||||
use serde_json::Value;
|
||||
|
||||
pub fn make_relative_line_numbers_an_enum(value: &mut Value) -> Result<()> {
|
||||
let Some(relative_line_numbers) = value.get_mut("relative_line_numbers") else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
*relative_line_numbers = match relative_line_numbers {
|
||||
Value::Bool(true) => Value::String("enabled".to_string()),
|
||||
Value::Bool(false) => Value::String("disabled".to_string()),
|
||||
_ => anyhow::bail!("Expected relative_line_numbers to be a boolean"),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
@@ -214,6 +214,7 @@ pub fn migrate_settings(text: &str) -> Result<Option<String>> {
|
||||
),
|
||||
MigrationType::Json(migrations::m_2025_10_16::restore_code_actions_on_format),
|
||||
MigrationType::Json(migrations::m_2025_10_17::make_file_finder_include_ignored_an_enum),
|
||||
MigrationType::Json(migrations::m_2025_10_21::make_relative_line_numbers_an_enum),
|
||||
];
|
||||
run_migrations(text, migrations)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user