def get_popup_actions(view): data = build_comment_data(view, view.size()) comment_message = "" if not data[0] and not data[1]: comment_message = '<p style="font-size: 10px; color: #FFBF00; margin: 0 0 10px 0; padding: 0">ⓘ You must select/install proper syntax in order to add ignore comments.</p>' return """ <div style="display: block; padding: 20px 25px 0"> {} {} {} </div> """.format( comment_message, get_popup_action("line", "Ignore for line", bool(comment_message)), get_popup_action("file", "Ignore for file", bool(comment_message)), )
def insert_new_line_with_comment(view, edit, point, type, id, target): data = build_comment_data(view, target.begin()) indent = re.findall(r"^\s*", view.substr(view.full_line(point)))[0] if data[0]: snip = "{0}{1}{2}".format(indent, data[0][0][0], get_ignore_text(type, id)) elif data[1]: snip = "{0}{1} {2} {3}".format( indent, data[1][0][0], get_ignore_text(type, id), data[1][0][1] ) view.insert(edit, target.begin(), snip) view.sel().clear() view.sel().add( view.find( "<please specify a reason of ignoring this>", target.begin(), sublime.IGNORECASE, ) ) update_highlighted_region(view, point, with_new_line=True)
def run(self, edit, width=0, keep_selection=False): # use the narrowest ruler from the view if no width specified, or default to 72 if no rulers are enabled width = width or next(iter(self.view.settings().get('rulers', [])), 72) # determine the indentation style used in the view use_spaces = self.view.settings().get('translate_tabs_to_spaces', False) tab_size = self.view.settings().get('tab_size', 4) one_level = ' ' * tab_size if use_spaces else '\t' # make sure the entire line is selected for each selection region # - `remove_line_comment` needs the region to be at the start of the line # - `dedent` needs it in order to see what indentation all lines have in common # but first, ensure we follow the Principal of Least Surprise by not expanding the selection to lines where only column 0 is selected # - related reading: https://forum.sublimetext.com/t/next-line-is-included-when-sorting-a-multi-line-selection/30580 self.view.run_command('deselect_trailing_newlines') if any(sel for sel in self.view.sel() if not sel.empty()): self.view.run_command('expand_selection', {'to': 'line'}) else: self.view.run_command('expand_selection_to_paragraph') new_sel = list() sel_comment_data = list() # loop through the selections in reverse order so that the selection positions don't move when the selected text changes size for sel in reversed(self.view.sel()): # if the selection contains any single line comments, toggle the comments off # so the comment tokens won't get wrapped into the middle of the line - we'll reapply them later # note the selector doesn't just use `comment.line punctuation.definition.comment`, because C# line documentation comments are scoped as `comment.block.documentation.cs punctuation.definition.comment.documentation.cs` comment_punctuation = list( find_regions_matching_selector( self.view, sel, 'comment punctuation.definition.comment - punctuation.definition.comment.begin - punctuation.definition.comment.end' )) sel_comment_data.append( self.view.substr(comment_punctuation[0]) + ' ' if any(comment_punctuation) else None) for punctuation in reversed(comment_punctuation): # also remove any space after the comment line punctuation, else the `indentation_level` API can return the wrong result... if self.view.substr(punctuation.end()) == ' ': punctuation = punctuation.cover( sublime.Region(punctuation.end(), punctuation.end() + len(' '))) self.view.erase(edit, punctuation) # loop through the selections in reverse order so that the selection positions don't move when the selected text changes size for sel, line_comment in zip(reversed(self.view.sel()), sel_comment_data): # determine how much indentation is at the first selected line indentation_level = self.view.indentation_level(sel.begin()) indentation = one_level * indentation_level if line_comment: # if line comments were removed earlier comment_data = build_comment_data(self.view, sel.begin()) # find the line comment that corresponds to the comment punctuation used, and check if indentation is disabled for it or not disable_indent = next( (data[1] for data in comment_data if isinstance(data, tuple) and data[0].strip() == line_comment), False) # apply the line comment token as part of the indentation so the text wrapper will re-comment the text for us if disable_indent: # if the line comment token has DISABLE_INDENT set indentation = line_comment + indentation # apply the indentation after the line comment token else: indentation += line_comment # apply the indentation before the line comment token # create a text wrapper that will keep the existing indentation level wrapper = textwrap.TextWrapper( drop_whitespace=True, width=width - ( 0 if use_spaces else (tab_size - 1) * indentation_level ), # if hard tab characters are used, then we need to pretend the max width is smaller, because here Python counts a tab as a single char. Easier to just not use tabs, people! initial_indent=indentation, subsequent_indent=indentation, expand_tabs=False, replace_whitespace=True, ) # unindent the selected text, before then reformatting said text to fill the available (column) space # do it on a paragraph by paragraph basis so we don't lose blank line gaps text = '' for paragraph in textwrap.dedent( self.view.substr(sel)).split('\n\n'): if text != '': text += '\n\n' text += wrapper.fill(paragraph) # replace the selected text with the re-wrapped text self.view.replace(edit, sel, text + '\n') # resize the selection to match the new wrapped text size - or move it to the end of the wrapped text end_pos = sel.begin() + len(text) start_pos = sel.begin() if keep_selection else end_pos new_sel.append(sublime.Region(start_pos, end_pos)) self.view.sel().clear() self.view.sel().add_all(new_sel)
def _determine_comment_style(self): # I'm not exactly sure why this function needs a point. It seems to # return the same value regardless of location for the stuff I've # tried. (self._lc, self._bc) = comment.build_comment_data(self.view, 0)
def run(self, edit, width=0): # use the narrowest ruler from the view if no width specified, or default to 72 if no rulers are enabled width = width or next(iter(self.view.settings().get('rulers', [])), 72) # determine the indentation style used in the view use_spaces = self.view.settings().get('translate_tabs_to_spaces', False) tab_size = self.view.settings().get('tab_size', 4) one_level = ' ' * tab_size if use_spaces else '\t' # make sure the entire line is selected for each selection region # - `remove_line_comment` needs the region to be at the start of the line # - `dedent` needs it in order to see what indentation all lines have in common # but first, ensure we follow the Principal of Least Surprise by not expanding the selection to lines where only column 0 is selected # - related reading: https://forum.sublimetext.com/t/next-line-is-included-when-sorting-a-multi-line-selection/30580 self.view.run_command('deselect_trailing_newlines') self.view.run_command('expand_selection', { 'to': 'line' }) new_sel = list() sel_comment_data = list() # loop through the selections in reverse order so that the selection positions don't move when the selected text changes size for sel in reversed(self.view.sel()): # if the selection contains any single line comments, toggle the comments off # so the comment tokens won't get wrapped into the middle of the line - we'll reapply them later comment_data = build_comment_data(self.view, sel.begin()) sel_comment_data.append(comment_data if ToggleCommentCommand.remove_line_comment(None, self.view, edit, comment_data, sel) else None) # loop through the selections in reverse order so that the selection positions don't move when the selected text changes size for sel, comment_data in zip(reversed(self.view.sel()), sel_comment_data): # determine how much indentation is at the first selected line indentation_level = self.view.indentation_level(sel.begin()) indentation = one_level * indentation_level if comment_data: # if line comments were removed earlier line_comments, block_comments = comment_data # apply the line comment token as part of the indentation so the text wrapper will re-comment the text for us if any(line_comments): # if there is at least one line comment token defined line_comment = line_comments[0] # if there are multiple such line comment tokens we will use the first one if line_comment[1]: # if the line comment token has DISABLE_INDENT set indentation = line_comment[0] + indentation # apply the indentation after the line comment token else: indentation += line_comment[0] # apply the indentation before the line comment token # create a text wrapper that will keep the existing indentation level wrapper = textwrap.TextWrapper( drop_whitespace=True, width=width - (0 if use_spaces else (tab_size - 1) * indentation_level), # if hard tab characters are used, then we need to pretend the max width is smaller, because here Python counts a tab as a single char. Easier to just not use tabs, people! initial_indent=indentation, subsequent_indent=indentation, expand_tabs=False, replace_whitespace=True, ) # unindent the selected text, before then reformatting said text to fill the available (column) space # do it on a paragraph by paragraph basis so we don't lose blank line gaps text = '' for paragraph in textwrap.dedent(self.view.substr(sel)).split('\n\n'): if text != '': text += '\n\n' text += wrapper.fill(paragraph) # replace the selected text with the re-wrapped text self.view.replace(edit, sel, text + '\n') # resize the selection to match the new wrapped text size new_sel.append(sublime.Region(sel.begin(), sel.begin() + len(text))) self.view.sel().clear() self.view.sel().add_all(new_sel)