Prints the single line given. This mostly just handles indentation and ensuring line breaks are inserted as appropriate before passing it on to the formatter to print to the buffer.
(&mut self, line: &OutputDocstringLine<'_>)
| 383 | /// inserted as appropriate before passing it on to the formatter to |
| 384 | /// print to the buffer. |
| 385 | fn print_one(&mut self, line: &OutputDocstringLine<'_>) -> FormatResult<()> { |
| 386 | let trim_end = line.line.trim_end(); |
| 387 | if trim_end.is_empty() { |
| 388 | return if line.is_last { |
| 389 | // If the doc string ends with ` """`, the last line is |
| 390 | // ` `, but we don't want to insert an empty line (but close |
| 391 | // the docstring). |
| 392 | Ok(()) |
| 393 | } else { |
| 394 | empty_line().fmt(self.f) |
| 395 | }; |
| 396 | } |
| 397 | |
| 398 | let indent_offset = match self.f.options().indent_style() { |
| 399 | // Normalize all indent to spaces. |
| 400 | IndentStyle::Space => { |
| 401 | let tab_or_non_ascii_space = trim_end |
| 402 | .chars() |
| 403 | .take_while(|c| c.is_whitespace()) |
| 404 | .any(|c| c != ' '); |
| 405 | |
| 406 | if tab_or_non_ascii_space { |
| 407 | None |
| 408 | } else { |
| 409 | // It's guaranteed that the `indent` is all spaces because `tab_or_non_ascii_space` is |
| 410 | // `false` (indent contains neither tabs nor non-space whitespace). |
| 411 | let stripped_indentation_len = self.stripped_indentation.text_len(); |
| 412 | |
| 413 | // Take the string with the trailing whitespace removed, then also |
| 414 | // skip the leading whitespace. |
| 415 | Some(stripped_indentation_len) |
| 416 | } |
| 417 | } |
| 418 | IndentStyle::Tab => { |
| 419 | let line_indent = Indentation::from_str(trim_end); |
| 420 | |
| 421 | let non_ascii_whitespace = trim_end |
| 422 | .chars() |
| 423 | .take_while(|c| c.is_whitespace()) |
| 424 | .any(|c| !matches!(c, ' ' | '\t')); |
| 425 | |
| 426 | let trimmed = line_indent.trim_start(self.stripped_indentation); |
| 427 | |
| 428 | // Preserve tabs that are used for indentation, but only if the indent isn't |
| 429 | // * a mix of tabs and spaces |
| 430 | // * the `stripped_indentation` is a prefix of the line's indent |
| 431 | // * the trimmed indent isn't spaces followed by tabs because that would result in a |
| 432 | // mixed tab, spaces, tab indentation, resulting in instabilities. |
| 433 | let preserve_indent = !non_ascii_whitespace |
| 434 | && trimmed.is_some_and(|trimmed| !trimmed.is_spaces_tabs()); |
| 435 | preserve_indent.then_some(self.stripped_indentation.text_len()) |
| 436 | } |
| 437 | }; |
| 438 | |
| 439 | if let Some(indent_offset) = indent_offset { |
| 440 | // Take the string with the trailing whitespace removed, then also |
| 441 | // skip the leading whitespace. |
| 442 | if self.already_normalized { |
no test coverage detected