<commit_before>"""
If you select multiple lines in a Python file and type '#', then all selected
lines are commented out.

A different character is used in other programming languages. This can be
configured with comment_char in filetypes.toml.
"""

import functools
import tkinter
from typing import Optional

from porcupine import get_tab_manager, menubar, tabs, utils


def comment_or_uncomment(tab: tabs.FileTab, event: 'Optional[tkinter.Event[tkinter.Text]]') -> utils.BreakOrNone:
    comment_char = tab.settings.get('comment_char', Optional[str])
    if event is not None and event.char != comment_char:
        return None

    try:
        start_index, end_index = map(str, tab.textwidget.tag_ranges('sel'))
    except ValueError:
        # nothing selected, add '#' normally
        return None

    start = int(start_index.split('.')[0])
    end = int(end_index.split('.')[0])
    if end_index.split('.')[1] != '0':
        # something's selected on the end line, let's (un)comment it too
        end += 1

    gonna_uncomment = all(
        tab.textwidget.get('%d.0' % lineno, '%d.1' % lineno) == comment_char
        for lineno in range(start, end))

    # TODO: use change_batch
    for lineno in range(start, end):
        if gonna_uncomment:
            tab.textwidget.delete('%d.0' % lineno, '%d.1' % lineno)
        else:
            tab.textwidget.insert('%d.0' % lineno, comment_char)

    # select everything on the (un)commented lines
    tab.textwidget.tag_remove('sel', '1.0', 'end')
    tab.textwidget.tag_add('sel', '%d.0' % start, '%d.0' % end)
    return 'break'


def comment_or_uncomment_in_current_tab() -> None:
    tab = get_tab_manager().select()
    assert isinstance(tab, tabs.FileTab)
    comment_or_uncomment(tab, None)

<commit_msg>use change_batch in comment_block plugin (fixes #183)<commit_after>"""
If you select multiple lines in a Python file and type '#', then all selected
lines are commented out.

A different character is used in other programming languages. This can be
configured with comment_char in filetypes.toml.
"""

import functools
import tkinter
from typing import Optional

from porcupine import get_tab_manager, menubar, tabs, textwidget, utils


def comment_or_uncomment(tab: tabs.FileTab, event: 'Optional[tkinter.Event[tkinter.Text]]') -> utils.BreakOrNone:
    comment_char = tab.settings.get('comment_char', Optional[str])
    if event is not None and event.char != comment_char:
        return None

    try:
        start_index, end_index = map(str, tab.textwidget.tag_ranges('sel'))
    except ValueError:
        # nothing selected, add '#' normally
        return None

    start = int(start_index.split('.')[0])
    end = int(end_index.split('.')[0])
    if end_index.split('.')[1] != '0':
        # something's selected on the end line, let's (un)comment it too
        end += 1

    gonna_uncomment = all(
        tab.textwidget.get('%d.0' % lineno, '%d.1' % lineno) == comment_char
        for lineno in range(start, end))

    with textwidget.change_batch(tab.textwidget):
        for lineno in range(start, end):
            if gonna_uncomment:
                tab.textwidget.delete('%d.0' % lineno, '%d.1' % lineno)
            else:
                tab.textwidget.insert('%d.0' % lineno, comment_char)

    # select everything on the (un)commented lines
    tab.textwidget.tag_remove('sel', '1.0', 'end')
    tab.textwidget.tag_add('sel', '%d.0' % start, '%d.0' % end)
    return 'break'


def comment_or_uncomment_in_current_tab() -> None:
    tab = get_tab_manager().select()
    assert isinstance(tab, tabs.FileTab)
    comment_or_uncomment(tab, None)


{'fraction_non_alphanumeric': 0.12462173314993122, 'fraction_numerical': 0.008528198074277854, 'mean_word_length': 3.2877358490566038, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '954123', 'n_tokens_mistral': 1192, 'n_tokens_neox': 1153, 'n_words': 322}