@@ -1238,24 +1238,61 @@ impl Document {
12381238 }
12391239
12401240 pub fn text_format(&self, mut viewport_width: u16, theme: Option<&Theme>) -> TextFormat {
1241− if let Some(max_line_len) = self
1241+ let config = self.config.load();
1242+ let text_width = self
12421243 .language_config()
1243− .and_then(|config| config.max_line_length)
1244− {
1245− viewport_width = viewport_width.min(max_line_len as u16)
1244+ .and_then(|config| config.text_width)
1245+ .unwrap_or(config.text_width);
1246+ let soft_wrap_at_text_width = self
1247+ .language_config()
1248+ .and_then(|config| {
1249+ config
1250+ .soft_wrap
1251+ .as_ref()
1252+ .and_then(|soft_wrap| soft_wrap.wrap_at_text_width)
1253+ })
1254+ .or(config.soft_wrap.wrap_at_text_width)
1255+ .unwrap_or(false);
1256+ if soft_wrap_at_text_width {
1257+ // We increase max_line_len by 1 because softwrap considers the newline character
1258+ // as part of the line length while the "typical" expectation is that this is not the case.
1259+ // In particular other commands like :reflow do not count the line terminator.
1260+ // This is technically inconsistent for the last line as that line never has a line terminator
1261+ // but having the last visual line exceed the width by 1 seems like a rare edge case.
1262+ viewport_width = viewport_width.min(text_width as u16 + 1)
12461263 }
12471264 let config = self.config.load();
1248− let soft_wrap = &config.soft_wrap;
1265+ let editor_soft_wrap = &config.soft_wrap;
1266+ let language_soft_wrap = self
1267+ .language
1268+ .as_ref()
1269+ .and_then(|config| config.soft_wrap.as_ref());
1270+ let enable_soft_wrap = language_soft_wrap
1271+ .and_then(|soft_wrap| soft_wrap.enable)
1272+ .or(editor_soft_wrap.enable)
1273+ .unwrap_or(false);
1274+ let max_wrap = language_soft_wrap
1275+ .and_then(|soft_wrap| soft_wrap.max_wrap)
1276+ .or(config.soft_wrap.max_wrap)
1277+ .unwrap_or(20);
1278+ let max_indent_retain = language_soft_wrap
1279+ .and_then(|soft_wrap| soft_wrap.max_indent_retain)
1280+ .or(editor_soft_wrap.max_indent_retain)
1281+ .unwrap_or(40);
1282+ let wrap_indicator = language_soft_wrap
1283+ .and_then(|soft_wrap| soft_wrap.wrap_indicator.clone())
1284+ .or_else(|| config.soft_wrap.wrap_indicator.clone())
1285+ .unwrap_or_else(|| "↪ ".into());
12491286 let tab_width = self.tab_width() as u16;
12501287 TextFormat {
1251− soft_wrap: soft_wrap.enable && viewport_width > 10,
1288+ soft_wrap: enable_soft_wrap && viewport_width > 10,
12521289 tab_width,
1253− max_wrap: soft_wrap.max_wrap.min(viewport_width / 4),
1254− max_indent_retain: soft_wrap.max_indent_retain.min(viewport_width * 2 / 5),
1290+ max_wrap: max_wrap.min(viewport_width / 4),
1291+ max_indent_retain: max_indent_retain.min(viewport_width * 2 / 5),
12551292 // avoid spinning forever when the window manager
12561293 // sets the size to something tiny
12571294 viewport_width,
1258− wrap_indicator: soft_wrap.wrap_indicator.clone().into_boxed_str(),
1295+ wrap_indicator: wrap_indicator.into_boxed_str(),
12591296 wrap_indicator_highlight: theme
12601297 .and_then(|theme| theme.find_scope_index("ui.virtual.wrap"))
12611298 .map(Highlight),