Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add word count for markdown files #21263

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion crates/go_to_line/src/cursor_position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub(crate) struct SelectionStats {
pub lines: usize,
pub characters: usize,
pub selections: usize,
pub words: Option<usize>,
}

pub struct CursorPosition {
Expand Down Expand Up @@ -52,6 +53,7 @@ impl CursorPosition {

editor
.update(&mut cx, |editor, cx| {
let is_markdown = is_markdown_file(editor, cx);
let buffer = editor.buffer().read(cx).snapshot(cx);
cursor_position.update(cx, |cursor_position, cx| {
cursor_position.selected_count = SelectionStats::default();
Expand All @@ -62,6 +64,21 @@ impl CursorPosition {
.text_for_range(selection.start..selection.end)
.map(|t| t.chars().count())
.sum::<usize>();

if is_markdown {
let mut words = 0;
words += buffer
.text_for_range(selection.start..selection.end)
.map(|t| t.split_whitespace().count())
.sum::<usize>();
Comment on lines +71 to +73
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my understanding, this snippet will count the exact words in the markdown file, and not the real amount of words rendered by it.
This may include the markup tags, which might be undesirable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, t.split_whitespace() will count markdown elements as words, etc and give a rough word count when markdown elements are involved. On the other hand, I don't think getting the exact word count for markdown files is feasible without some convoluted logic.

If the repo maintainers think the word count needs to be more accurate, I can modify the PR (Off the top of my head, I am thinking I just have to sanitise the text before counting the words)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some way to get the text preview that zed generates and count words in that, if that is performant enough.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting the text that ends up actually being rendered might be possible with tree-sitter queries?


if let Some(current_words) = cursor_position.selected_count.words {
cursor_position.selected_count.words =
Some(current_words + words);
} else {
cursor_position.selected_count.words = Some(words);
}
}
if last_selection
.as_ref()
.map_or(true, |last_selection| selection.id > last_selection.id)
Expand All @@ -88,6 +105,17 @@ impl CursorPosition {
.ok()
.flatten();
});

// copied from crates/markdown_preview/src/markdown_preview_view.rs
pub fn is_markdown_file<V>(editor: &Editor, cx: &mut ViewContext<V>) -> bool {
let buffer = editor.buffer().read(cx);
if let Some(buffer) = buffer.as_singleton() {
if let Some(language) = buffer.read(cx).language() {
return language.name() == "Markdown".into();
}
}
false
}
}

fn write_position(&self, text: &mut String, cx: &AppContext) {
Expand All @@ -104,19 +132,30 @@ impl CursorPosition {
lines,
characters,
selections,
words,
} = self.selected_count;
let format = LineIndicatorFormat::get(None, cx);
let is_short_format = format == &LineIndicatorFormat::Short;
let lines = (lines > 1).then_some((lines, "line"));
let selections = (selections > 1).then_some((selections, "selection"));
let characters = (characters > 0).then_some((characters, "character"));
let words = if words.is_some() {
let words = words.unwrap();
if words > 0 {
Some((words, "word"))
} else {
None
}
} else {
None
};
if (None, None, None) == (characters, selections, lines) {
// Nothing to display.
return;
}
write!(text, " (").unwrap();
let mut wrote_once = false;
for (count, name) in [selections, lines, characters].into_iter().flatten() {
for (count, name) in [selections, lines, characters, words].into_iter().flatten() {
if wrote_once {
write!(text, ", ").unwrap();
}
Expand Down
2 changes: 2 additions & 0 deletions crates/go_to_line/src/go_to_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ mod tests {
lines: 0,
characters: 0,
selections: 1,
words: None
},
workspace
.status_bar()
Expand All @@ -405,6 +406,7 @@ mod tests {
lines: 1,
characters: 3,
selections: 1,
words: None
},
workspace
.status_bar()
Expand Down
Loading