Repository: helix-editor/helix
File: helix-term/src/commands.rs (Rust)

Code before:
                    ch.to_uppercase().collect()
                } else if ch.is_uppercase() {
                    ch.to_lowercase().collect()
                } else {
                    vec![ch]
                }
            })
            .collect()
    });
}

fn switch_to_uppercase(cx: &mut Context) {
    switch_case_impl(cx, |string| {
        string.chunks().map(|chunk| chunk.to_uppercase()).collect()
    });
}

fn switch_to_lowercase(cx: &mut Context) {
    switch_case_impl(cx, |string| {
        string.chunks().map(|chunk| chunk.to_lowercase()).collect()
    });
}

/// Checks, if the line from line `line_num` is commented with one of the comment tokens in the language config and
/// returns the token which comments out the line.
fn has_line_comment(config: &Config, doc: &Document, line_num: usize) -> Option<String> {
    if config.continue_comments {
        let line_tokens = {
            let mut line_tokens: Vec<String> = doc
                .language_config()
                .and_then(|lc| lc.comment_tokens.as_ref())?
                .clone();
            line_tokens.sort_by(|a, b| a.len().partial_cmp(&b.len()).unwrap().reverse());
            line_tokens
        };

        let text = doc.text();
        let line = text.line(line_num);

        if let Some(pos) = line.first_non_whitespace_char() {
            let text_line = line.slice(pos..);
            return line_tokens
                .iter()
                .find(|&token| text_line.starts_with(token.as_str()))
                .cloned();
        }
    }

    None
}


Review comment (suggestion):
I think this should be moved to helix core with the other commenting logic.

There may actually already be a similar function in helix-core that can also detect block comments that you can reuse instead of writing a new function

Code after:
                } else {
                    // No change.
                    (range.from(), range.to(), None)
                }
            });

            doc.apply(&transaction, view.id);
            exit_select_mode(cx);
        }
    })
}

fn switch_case_impl<F>(cx: &mut Context, change_fn: F)
where
    F: Fn(RopeSlice) -> Tendril,
{
    let (view, doc) = current!(cx.editor);
    let selection = doc.selection(view.id);
    let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
        let text: Tendril = change_fn(range.slice(doc.text().slice(..)));

        (range.from(), range.to(), Some(text))
    });

    doc.apply(&transaction, view.id);
    exit_select_mode(cx);
}

fn switch_case(cx: &mut Context) {
    switch_case_impl(cx, |string| {
        string
            .chars()
            .flat_map(|ch| {
                if ch.is_lowercase() {
                    ch.to_uppercase().collect()
                } else if ch.is_uppercase() {
                    ch.to_lowercase().collect()
                } else {
                    vec![ch]
                }
            })
            .collect()
    });
}

fn switch_to_uppercase(cx: &mut Context) {
    switch_case_impl(cx, |string| {
        string.chunks().map(|chunk| chunk.to_uppercase()).collect()
    });
}