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