def add_ending_newline(obj): last_key = list(obj.keys())[-1] if type(obj[last_key]) == list: obj[last_key] = CommentedSeq(obj[last_key]) if hasattr(obj[last_key], "ca"): ct = CommentToken("\n\n", CommentMark(0), None) index = len(obj[last_key]) - 1 obj[last_key].ca.items[index] = [ct, None, None, None] else: ct = CommentToken("\n\n", CommentMark(0), None) obj.ca.items[last_key] = [None, None, ct, None]
def yamkix_add_eol_comment(self, comment, key=NoComment, column=None): """Custom add_eol_comment function. We need to be able to tune the number of spaces between the content and the comment for CommentedSeqs and CommentedMaps see https://stackoverflow.com/q/60915926 """ # pylint: disable=protected-access org_col = column if column is None: try: column = self._yaml_get_column(key) except AttributeError: column = 0 if comment[0] != "#": comment = "# " + comment if ( org_col != 0 ): # only do this if the specified column is not the beginning of the line if comment[0] == "#": additional_spaces = 1 if org_col is None else org_col - 1 comment = " " * additional_spaces + comment column = 0 start_mark = CommentMark(column) comment_as_list = [CommentToken(comment, start_mark, None), None] self._yaml_add_eol_comment(comment_as_list, key=key)
def replace_colorscheme(colors_path: str, config_path: str, colorscheme: str, base16_vim: bool): with open(expanduser(config_path), 'r') as config_file,\ open(expanduser(colors_path), 'r') as color_file,\ tempfile.NamedTemporaryFile(delete=False) as tmp_file: config_yaml = yaml.load(config_file) colors_yaml = yaml.load(color_file) try: # NOTE: update method doesn't read the first comment config_yaml['colors'].update(colors_yaml['colors']) except KeyError: config_yaml['colors'] = colors_yaml['colors'] new_comment_token = CommentToken( f'# COLORSCHEME: {colorscheme}\n', CommentMark(2), None, ) if has_comment_token(config_yaml['colors'].ca.comment): # removing all comments for colors in config_file while len(config_yaml['colors'].ca.comment[1]) > 0: config_yaml['colors'].ca.comment[1].pop() # adding current colorscheme name in comment config_yaml['colors'].ca.comment[1].append(new_comment_token) else: # adding current colorscheme name in comment config_yaml['colors'].ca.comment = [None, [new_comment_token]] # adding all comments for colors from colors_file if has_comment_token(colors_yaml['colors'].ca.comment): config_yaml['colors'].ca.comment[1].extend( colors_yaml['colors'].ca.comment[1]) # NOTE: not directly writing to config_file as it causes # multiple reload during write tmp_file_path = tmp_file.name yaml.dump(config_yaml, tmp_file) copyfile(tmp_file_path, expanduser(config_path)) unlink(tmp_file_path) if base16_vim: vimrc_background_path = join('~', '.vimrc_background') with open(expanduser(vimrc_background_path), 'w') as vimrc_background_file: colorscheme_no_extension = splitext(colorscheme)[0] vimrc_background_content = generate_vimrc_background( colorscheme_no_extension) vimrc_background_file.write(vimrc_background_content)
def yaml_set_start_comment(self, comment, indent=0): """overwrites any preceding comment lines on an object expects comment to be without `#` and possible have multiple lines """ from .error import CommentMark from .tokens import CommentToken pre_comments = self._yaml_get_pre_comment() if comment[-1] == '\n': comment = comment[:-1] # strip final newline if there start_mark = CommentMark(indent) for com in comment.split('\n'): pre_comments.append( CommentToken('# ' + com + '\n', start_mark, None))
def yaml_comments(text: str, stream_mark: bool = False) -> list: from ruamel.yaml.error import CommentMark, StreamMark from ruamel.yaml.tokens import CommentToken if text[-1] == "\n": text = text[:-1] if stream_mark: mark = StreamMark(name="", index=0, line=0, column=0) else: mark = CommentMark(0) return [ CommentToken(f"# {s}\n" if s else "\n", mark, None) for s in text.split("\n") ]
def set_start_comment(self, comment, indent=0): """overwrites any preceding comment lines on an object expects comment to be without `#` and possible have mutlple lines """ from ruamel.yaml.error import Mark from ruamel.yaml.tokens import CommentToken if self.ca.comment is None: pre_comments = [] self.ca.comment = [None, pre_comments] else: pre_comments = self.ca.comments[1] if comment[-1] == '\n': comment = comment[:-1] # strip final newline if there start_mark = Mark(None, None, None, indent, None, None) for com in comment.split('\n'): pre_comments.append(CommentToken('# ' + com + '\n', start_mark, None))
def yaml_set_start_comment(self, comment, indent=0): # type: (Any, Any) -> None """overwrites any preceding comment lines on an object expects comment to be without `#` and possible have multiple lines """ from .error import CommentMark from .tokens import CommentToken pre_comments = self._yaml_clear_pre_comment() # type: ignore if comment[-1] == '\n': comment = comment[:-1] # strip final newline if there start_mark = CommentMark(indent) for com in comment.split('\n'): c = com.strip() if len(c) > 0 and c[0] != '#': com = '# ' + com pre_comments.append(CommentToken(com + '\n', start_mark))
def yaml_add_eol_comment(self, comment, key=NoComment, column=None): """ there is a problem as eol comments should start with ' #' (but at the beginning of the line the space doesn't have to be before the #. The column index is for the # mark """ from .tokens import CommentToken from .error import CommentMark if column is None: column = self._yaml_get_column(key) if comment[0] != '#': comment = '# ' + comment if column is None: if comment[0] == '#': comment = ' ' + comment column = 0 start_mark = CommentMark(column) ct = [CommentToken(comment, start_mark, None), None] self._yaml_add_eol_comment(ct, key=key)
def comment_token(s, mark): # type: (Any, Any) -> Any # handle empty lines as having no comment return CommentToken(('# ' if s else "") + s + '\n', mark, None)
def replace_colorscheme( colors_path: str, config_path: str, colorscheme: str, base16_vim: bool, debug: bool, ) -> None: try: with open(expanduser(config_path), 'r') as config_file: config_yaml = yaml.load(config_file) except OSError: raise RuntimeError(f'Could not find a valid alacritty config file: {config_path}') try: with open(expanduser(colors_path), 'r') as color_file: colors_yaml = yaml.load(color_file) except OSError: raise RuntimeError(f'Could not find a valid alacritty colorscheme file: {colors_path}') try: # NOTE: update method doesn't read the first comment config_yaml['colors'].update(colors_yaml['colors']) except KeyError: config_yaml['colors'] = colors_yaml['colors'] except TypeError: if not config_yaml: config_yaml = {'colors': colors_yaml['colors']} else: raise new_comment_token = CommentToken( f'# COLORSCHEME: {colorscheme}\n', CommentMark(2), None, ) if _has_comment_token(config_yaml['colors'].ca.comment): # removing all comments for colors in config_file while len(config_yaml['colors'].ca.comment[1]) > 0: config_yaml['colors'].ca.comment[1].pop() # adding current colorscheme name in comment config_yaml['colors'].ca.comment[1].append(new_comment_token) else: # adding current colorscheme name in comment config_yaml['colors'].ca.comment = [None, [new_comment_token]] # adding all comments for colors from colors_file if _has_comment_token(colors_yaml['colors'].ca.comment): config_yaml['colors'].ca.comment[1].extend( colors_yaml['colors'].ca.comment[1] ) try: with NamedTemporaryFile(delete=False) as tmp_file: # NOTE: not directly writing to config_file as it causes # multiple reload during write tmp_file_path = tmp_file.name yaml.dump(config_yaml, tmp_file) copyfile(tmp_file_path, expanduser(config_path)) unlink(tmp_file_path) except OSError: raise RuntimeError(f'Could not modify alacritty config file: {config_path}') if debug: print(f'Applied colorscheme: {colorscheme}') if base16_vim: vimrc_background_path = join('~', '.vimrc_background') try: with open(expanduser(vimrc_background_path), 'w') as vimrc_background_file: colorscheme_no_extension = splitext(colorscheme)[0] vimrc_background_content = template_vimrc_background( colorscheme_no_extension ) vimrc_background_file.write(vimrc_background_content) except OSError: raise RuntimeError(f'Could not save file: {vimrc_background_path}') reload_neovim_sessions(vimrc_background_path)
def comment_token(s, mark): # handle empty lines as having no comment return CommentToken(('# ' if s else '') + s + '\n', mark, None)
def comment_yaml_item(data, path_to_key, data_contains_list=True): """ (EXPERIMENTAL) Comment a yaml item given its path_to_key (e.g. [foo 0 bar]), with comment preservation Inspired from https://stackoverflow.com/a/43927974 @cherrot """ if data_contains_list: path_to_key = list(map(str_or_int_map, path_to_key)) parent = data.mlget(path_to_key[:-1], list_ok=data_contains_list) if len(path_to_key) > 1 else data item_key = path_to_key[-1] deleted_item = item_key next_key = None if isinstance(parent, CommentedMap): if item_key not in parent: raise KeyError("the key \'{}\' does not exist".format(item_key)) # don't just pop the value for item_key that way you lose comments # in the original YAML, instead deepcopy and delete what is not needed block_copy = deepcopy(parent) found = False keys = [k for k in parent.keys()] for key in reversed(keys): if key == item_key: found = True else: if not found: next_key = key del block_copy[key] # now delete the key and its value, but preserve its preceding comments preceding_comments = parent.ca.items.get(item_key, [None, None, None, None])[1] if next_key is None: if parent.ca.comment is None: parent.ca.comment = [None, []] if parent.ca.comment[1] is None: parent.ca.comment[1] = [] comment_list = parent.ca.comment[1] else: comment_list = parent.ca.items.get(next_key, [None, None, None, None])[1] if comment_list is None: parent.ca.items[next_key] = [None, [], None, None] comment_list = parent.ca.items.get(next_key)[1] if preceding_comments is not None: for c in reversed(preceding_comments): comment_list.insert(0, c) del parent[item_key] elif isinstance(parent, CommentedSeq): if not is_int(item_key) or item_key >= len(parent): raise RuntimeError("the key \'{}\' is not an integer or exceeds its parent's length".format(item_key)) else: block_copy = deepcopy(parent) for i in reversed(range(len(parent))): if i != item_key: del block_copy[i] next_key = item_key preceding_comments = deepcopy(parent.ca.items.get(item_key, [None, None, None, None])[1]) parent.pop(item_key) # CommentedSet.pop(idx) automatically shifts all ca.items' indexes ! if len(parent) == 1 or next_key == len(parent): comment_list = parent.ca.end # TODO: fix this, the appended comments don't show up in some case else: comment_list = parent.ca.items.get(next_key, [None, None, None, None])[1] if comment_list is None: parent.ca.items[next_key] = [None, [], None, None] comment_list = parent.ca.items.get(next_key)[1] if preceding_comments is not None: for c in reversed(preceding_comments): comment_list.insert(0, c) else: raise RuntimeError("Couldn't reach the last item following the path_to_key " + str(path_to_key)) key_dept = len(path_to_key) - 1 if is_int(path_to_key[-1]) and key_dept > 0: key_dept = key_dept - 1 comment_list_copy = deepcopy(comment_list) del comment_list[:] start_mark = StreamMark(None, None, None, 2 * key_dept) skip = True for line in round_trip_dump(block_copy).splitlines(True): if skip: if line.strip(' ').startswith('#'): # and deleted_item not in line: continue skip = False comment_list.append(CommentToken('#' + line, start_mark, None)) comment_list.extend(comment_list_copy) return data