Repository: ggerganov/llama.cpp
File: common/jinja/value.cpp (C++)

Code before:
            res->val_str.mark_input_based_on(input->as_string());
            return res;
        }},
        {"safe", [](const func_args & args) -> value {
            // no-op for now
            args.ensure_vals<value_string>();
            return args.get_pos(0);
        }},
        {"tojson", tojson},
        {"indent", [](const func_args &args) -> value {
            // no support for "first" as that would require us to somehow access generation context
            args.ensure_count(2, 4);
            args.ensure_vals<value_string, value_int, value_bool, value_bool>(true, true, false, false);

            auto input = args.get_pos(0);
            auto arg0 = args.get_pos(1);

            int count = arg0->as_int();
            if (count <= 0) {
                throw raised_exception("indent must be a positive number");
            }
            std::string indented;
            for (int i = 0; i < count; i++) {
                indented.append(" ");
            }
            indented.append(input->as_string().str());
            auto res = mk_val<value_string>(indented);
            res->val_str.mark_input_based_on(input->as_string());
            return res;
        }},
        {"join", [](const func_args &) -> value {
            throw not_implemented_exception("String join builtin not implemented");
        }},
    };
    return builtins;
}


const func_builtins & value_bool_t::get_builtins() const {
    static const func_builtins builtins = {
        {"default", default_value},
        {"int", [](const func_args & args) -> value {
            args.ensure_vals<value_bool>();
            bool val = args.get_pos(0)->as_bool();
            return mk_val<value_int>(val ? 1 : 0);
        }},
        {"float", [](const func_args & args) -> value {
            args.ensure_vals<value_bool>();
            bool val = args.get_pos(0)->as_bool();
            return mk_val<value_float>(val ? 1.0 : 0.0);
        }},

Review comment (suggestion):
```suggestion
            args.ensure_count(1, 4);

            value val_input  = args.get_pos(0);
            value val_width  = args.get_kwarg_or_pos("width", 1);
            const bool first = args.get_kwarg_or_pos("first", 2)->as_bool(); // undefined == false
            const bool blank = args.get_kwarg_or_pos("blank", 3)->as_bool(); // undefined == false

            if (!is_val<value_string>(val_input)) {
                throw raised_exception("indent() first argument must be a string");
            }

            std::string indent;
            if (is_val<value_int>(val_width)) {
                indent.assign(val_width->as_int(), ' ');
            } else if (is_val<value_string>(val_width)) {
                indent = val_width->as_string().str();
            } else {
                indent = "    ";
            }
            std::string indented;
```
..now you just need to iterate through the input newlines and indent with `indent` string, first line if `first` is true and blank lines if `blank` is true.

Code after:
            auto res = mk_val<value_string>(sliced);
            res->val_str.mark_input_based_on(input->as_string());
            return res;
        }},
        {"safe", [](const func_args & args) -> value {
            // no-op for now
            args.ensure_vals<value_string>();
            return args.get_pos(0);
        }},
        {"tojson", tojson},
        {"indent", [](const func_args &args) -> value {
            args.ensure_count(1, 4);
            value val_input  = args.get_pos(0);
            value val_width  = args.get_kwarg_or_pos("width", 1);
            const bool first = args.get_kwarg_or_pos("first", 2)->as_bool(); // undefined == false
            const bool blank = args.get_kwarg_or_pos("blank", 3)->as_bool(); // undefined == false
            if (!is_val<value_string>(val_input)) {
                throw raised_exception("indent() first argument must be a string");
            }
            std::string indent;
            if (is_val<value_int>(val_width)) {
                indent.assign(val_width->as_int(), ' ');
            } else if (is_val<value_string>(val_width)) {
                indent = val_width->as_string().str();
            } else {
                indent = "    ";
            }
            std::string indented;
            std::string input = val_input->as_string().str();
            std::istringstream iss = std::istringstream(input);
            std::string line;
            while (std::getline(iss, line)) {
                if (!indented.empty()) {
                    indented.push_back('\n');
                }
                if ((indented.empty() ? first : (!line.empty() || blank))) {
                    indented += indent;
                }
                indented += line;
            }
            if (!input.empty() && input.back() == '\n') {
                indented.push_back('\n');
                if (blank) {
                    indented += indent;
                }
            }

            auto res = mk_val<value_string>(indented);
            res->val_str.mark_input_based_on(val_input->as_string());
            return res;
        }},