Ejemplo n.º 1
0
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]
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
 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))
Ejemplo n.º 5
0
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")
    ]
Ejemplo n.º 6
0
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))
Ejemplo n.º 7
0
    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))
Ejemplo n.º 8
0
 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)
Ejemplo n.º 9
0
 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)
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
 def comment_token(s, mark):
     # handle empty lines as having no comment
     return CommentToken(('# ' if s else '') + s + '\n', mark, None)
Ejemplo n.º 12
0
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