xref: /aosp_15_r20/external/bazelbuild-rules_python/python/private/text_util.bzl (revision 60517a1edbc8ecf509223e9af94a7adec7d736b8)
1*60517a1eSAndroid Build Coastguard Worker# Copyright 2023 The Bazel Authors. All rights reserved.
2*60517a1eSAndroid Build Coastguard Worker#
3*60517a1eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*60517a1eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*60517a1eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*60517a1eSAndroid Build Coastguard Worker#
7*60517a1eSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*60517a1eSAndroid Build Coastguard Worker#
9*60517a1eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*60517a1eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*60517a1eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*60517a1eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*60517a1eSAndroid Build Coastguard Worker# limitations under the License.
14*60517a1eSAndroid Build Coastguard Worker
15*60517a1eSAndroid Build Coastguard Worker"""Text manipulation utilities useful for repository rule writing."""
16*60517a1eSAndroid Build Coastguard Worker
17*60517a1eSAndroid Build Coastguard Workerdef _indent(text, indent = " " * 4):
18*60517a1eSAndroid Build Coastguard Worker    if "\n" not in text:
19*60517a1eSAndroid Build Coastguard Worker        return indent + text
20*60517a1eSAndroid Build Coastguard Worker
21*60517a1eSAndroid Build Coastguard Worker    return "\n".join([indent + line for line in text.splitlines()])
22*60517a1eSAndroid Build Coastguard Worker
23*60517a1eSAndroid Build Coastguard Workerdef _hanging_indent(text, indent = " " * 4):
24*60517a1eSAndroid Build Coastguard Worker    if "\n" not in text:
25*60517a1eSAndroid Build Coastguard Worker        return text
26*60517a1eSAndroid Build Coastguard Worker
27*60517a1eSAndroid Build Coastguard Worker    lines = text.splitlines()
28*60517a1eSAndroid Build Coastguard Worker    for i, line in enumerate(lines):
29*60517a1eSAndroid Build Coastguard Worker        lines[i] = (indent if i != 0 else "") + line
30*60517a1eSAndroid Build Coastguard Worker    return "\n".join(lines)
31*60517a1eSAndroid Build Coastguard Worker
32*60517a1eSAndroid Build Coastguard Workerdef _render_alias(name, actual, *, visibility = None):
33*60517a1eSAndroid Build Coastguard Worker    args = [
34*60517a1eSAndroid Build Coastguard Worker        "name = \"{}\",".format(name),
35*60517a1eSAndroid Build Coastguard Worker        "actual = {},".format(actual),
36*60517a1eSAndroid Build Coastguard Worker    ]
37*60517a1eSAndroid Build Coastguard Worker
38*60517a1eSAndroid Build Coastguard Worker    if visibility:
39*60517a1eSAndroid Build Coastguard Worker        args.append("visibility = {},".format(render.list(visibility)))
40*60517a1eSAndroid Build Coastguard Worker
41*60517a1eSAndroid Build Coastguard Worker    return "\n".join([
42*60517a1eSAndroid Build Coastguard Worker        "alias(",
43*60517a1eSAndroid Build Coastguard Worker    ] + [_indent(arg) for arg in args] + [
44*60517a1eSAndroid Build Coastguard Worker        ")",
45*60517a1eSAndroid Build Coastguard Worker    ])
46*60517a1eSAndroid Build Coastguard Worker
47*60517a1eSAndroid Build Coastguard Workerdef _render_dict(d, *, key_repr = repr, value_repr = repr):
48*60517a1eSAndroid Build Coastguard Worker    if not d:
49*60517a1eSAndroid Build Coastguard Worker        return "{}"
50*60517a1eSAndroid Build Coastguard Worker
51*60517a1eSAndroid Build Coastguard Worker    return "\n".join([
52*60517a1eSAndroid Build Coastguard Worker        "{",
53*60517a1eSAndroid Build Coastguard Worker        _indent("\n".join([
54*60517a1eSAndroid Build Coastguard Worker            "{}: {},".format(key_repr(k), value_repr(v))
55*60517a1eSAndroid Build Coastguard Worker            for k, v in d.items()
56*60517a1eSAndroid Build Coastguard Worker        ])),
57*60517a1eSAndroid Build Coastguard Worker        "}",
58*60517a1eSAndroid Build Coastguard Worker    ])
59*60517a1eSAndroid Build Coastguard Worker
60*60517a1eSAndroid Build Coastguard Workerdef _render_select(selects, *, no_match_error = None, key_repr = repr, value_repr = repr, name = "select"):
61*60517a1eSAndroid Build Coastguard Worker    dict_str = _render_dict(selects, key_repr = key_repr, value_repr = value_repr) + ","
62*60517a1eSAndroid Build Coastguard Worker
63*60517a1eSAndroid Build Coastguard Worker    if no_match_error:
64*60517a1eSAndroid Build Coastguard Worker        args = "\n".join([
65*60517a1eSAndroid Build Coastguard Worker            "",
66*60517a1eSAndroid Build Coastguard Worker            _indent(dict_str),
67*60517a1eSAndroid Build Coastguard Worker            _indent("no_match_error = {},".format(no_match_error)),
68*60517a1eSAndroid Build Coastguard Worker            "",
69*60517a1eSAndroid Build Coastguard Worker        ])
70*60517a1eSAndroid Build Coastguard Worker    else:
71*60517a1eSAndroid Build Coastguard Worker        args = "\n".join([
72*60517a1eSAndroid Build Coastguard Worker            "",
73*60517a1eSAndroid Build Coastguard Worker            _indent(dict_str),
74*60517a1eSAndroid Build Coastguard Worker            "",
75*60517a1eSAndroid Build Coastguard Worker        ])
76*60517a1eSAndroid Build Coastguard Worker
77*60517a1eSAndroid Build Coastguard Worker    return "{}({})".format(name, args)
78*60517a1eSAndroid Build Coastguard Worker
79*60517a1eSAndroid Build Coastguard Workerdef _render_list(items, *, hanging_indent = ""):
80*60517a1eSAndroid Build Coastguard Worker    """Convert a list to formatted text.
81*60517a1eSAndroid Build Coastguard Worker
82*60517a1eSAndroid Build Coastguard Worker    Args:
83*60517a1eSAndroid Build Coastguard Worker        items: list of items.
84*60517a1eSAndroid Build Coastguard Worker        hanging_indent: str, indent to apply to second and following lines of
85*60517a1eSAndroid Build Coastguard Worker            the formatted text.
86*60517a1eSAndroid Build Coastguard Worker
87*60517a1eSAndroid Build Coastguard Worker    Returns:
88*60517a1eSAndroid Build Coastguard Worker        The list pretty formatted as a string.
89*60517a1eSAndroid Build Coastguard Worker    """
90*60517a1eSAndroid Build Coastguard Worker    if not items:
91*60517a1eSAndroid Build Coastguard Worker        return "[]"
92*60517a1eSAndroid Build Coastguard Worker
93*60517a1eSAndroid Build Coastguard Worker    if len(items) == 1:
94*60517a1eSAndroid Build Coastguard Worker        return "[{}]".format(repr(items[0]))
95*60517a1eSAndroid Build Coastguard Worker
96*60517a1eSAndroid Build Coastguard Worker    text = "\n".join([
97*60517a1eSAndroid Build Coastguard Worker        "[",
98*60517a1eSAndroid Build Coastguard Worker        _indent("\n".join([
99*60517a1eSAndroid Build Coastguard Worker            "{},".format(repr(item))
100*60517a1eSAndroid Build Coastguard Worker            for item in items
101*60517a1eSAndroid Build Coastguard Worker        ])),
102*60517a1eSAndroid Build Coastguard Worker        "]",
103*60517a1eSAndroid Build Coastguard Worker    ])
104*60517a1eSAndroid Build Coastguard Worker    if hanging_indent:
105*60517a1eSAndroid Build Coastguard Worker        text = _hanging_indent(text, hanging_indent)
106*60517a1eSAndroid Build Coastguard Worker    return text
107*60517a1eSAndroid Build Coastguard Worker
108*60517a1eSAndroid Build Coastguard Workerdef _render_str(value):
109*60517a1eSAndroid Build Coastguard Worker    return repr(value)
110*60517a1eSAndroid Build Coastguard Worker
111*60517a1eSAndroid Build Coastguard Workerdef _render_tuple(items, *, value_repr = repr):
112*60517a1eSAndroid Build Coastguard Worker    if not items:
113*60517a1eSAndroid Build Coastguard Worker        return "tuple()"
114*60517a1eSAndroid Build Coastguard Worker
115*60517a1eSAndroid Build Coastguard Worker    if len(items) == 1:
116*60517a1eSAndroid Build Coastguard Worker        return "({},)".format(value_repr(items[0]))
117*60517a1eSAndroid Build Coastguard Worker
118*60517a1eSAndroid Build Coastguard Worker    return "\n".join([
119*60517a1eSAndroid Build Coastguard Worker        "(",
120*60517a1eSAndroid Build Coastguard Worker        _indent("\n".join([
121*60517a1eSAndroid Build Coastguard Worker            "{},".format(value_repr(item))
122*60517a1eSAndroid Build Coastguard Worker            for item in items
123*60517a1eSAndroid Build Coastguard Worker        ])),
124*60517a1eSAndroid Build Coastguard Worker        ")",
125*60517a1eSAndroid Build Coastguard Worker    ])
126*60517a1eSAndroid Build Coastguard Worker
127*60517a1eSAndroid Build Coastguard Workerdef _toolchain_prefix(index, name, pad_length):
128*60517a1eSAndroid Build Coastguard Worker    """Prefixes the given name with the index, padded with zeros to ensure lexicographic sorting.
129*60517a1eSAndroid Build Coastguard Worker
130*60517a1eSAndroid Build Coastguard Worker    Examples:
131*60517a1eSAndroid Build Coastguard Worker      toolchain_prefix(   2, "foo", 4) == "_0002_foo_"
132*60517a1eSAndroid Build Coastguard Worker      toolchain_prefix(2000, "foo", 4) == "_2000_foo_"
133*60517a1eSAndroid Build Coastguard Worker    """
134*60517a1eSAndroid Build Coastguard Worker    return "_{}_{}_".format(_left_pad_zero(index, pad_length), name)
135*60517a1eSAndroid Build Coastguard Worker
136*60517a1eSAndroid Build Coastguard Workerdef _left_pad_zero(index, length):
137*60517a1eSAndroid Build Coastguard Worker    if index < 0:
138*60517a1eSAndroid Build Coastguard Worker        fail("index must be non-negative")
139*60517a1eSAndroid Build Coastguard Worker    return ("0" * length + str(index))[-length:]
140*60517a1eSAndroid Build Coastguard Worker
141*60517a1eSAndroid Build Coastguard Workerrender = struct(
142*60517a1eSAndroid Build Coastguard Worker    alias = _render_alias,
143*60517a1eSAndroid Build Coastguard Worker    dict = _render_dict,
144*60517a1eSAndroid Build Coastguard Worker    hanging_indent = _hanging_indent,
145*60517a1eSAndroid Build Coastguard Worker    indent = _indent,
146*60517a1eSAndroid Build Coastguard Worker    left_pad_zero = _left_pad_zero,
147*60517a1eSAndroid Build Coastguard Worker    list = _render_list,
148*60517a1eSAndroid Build Coastguard Worker    select = _render_select,
149*60517a1eSAndroid Build Coastguard Worker    str = _render_str,
150*60517a1eSAndroid Build Coastguard Worker    toolchain_prefix = _toolchain_prefix,
151*60517a1eSAndroid Build Coastguard Worker    tuple = _render_tuple,
152*60517a1eSAndroid Build Coastguard Worker)
153