I have written many messages already. I think, the purpose of this operator is clear. In this discussion I have come up to understanding what I would like to use.
You suggest very hard and complex solutions: <?*js*html= $str ?> <?php['html']: ?> $escape = new SplEscaper; $escape->support('e', function () { ... }); declare('filter=htmlentities'); This is not what I wanted to suggest. I have rewritten RFC a little. There is no tricks with ZEND_NAME_NOT_FQ, there is no magic constants, there is no problems with autoloading. The soultion is small, simple, and customizable. https://wiki.php.net/rfc/escaping_operator There are 3 functions: callable|null set_escape_handler(callable $handler) bool restore_escape_handler() escape_handler_call(mixed $string, mixed $context) They work similar to set_error_handler() / restore_error_handler(). Operator is compiled into the following AST: echo escape_handler_call(first_argument, second_argument); Function escape_handler_call() just pass given arguments into user-defined handler. Second argument is not required. If the handler is not set, it throws an exception. There is no default handler for any context, to prevent 'built-in' wrong work of <?* $str ?> constructions in non-HTML contexts like CSV. This is not hard to create a handler once. Default context can be set in it as default value for second argument. set_escape_handler(function($str, $context = 'html') { ... }); What is under discussion: Starting sign. Last one is more comfortable to type. <?* $a, $b ?> <?: $a, $b ?> Separator sign. Maybe it should differ from standard <?= $a, $b ?> syntax to prevent mistakes like <?= $a, 'html' ?> instead of <?* $a, 'html' ?>. '|' won't give error, but looks more similar to escaping in template engines. <?* $a , $b ?> <?* $a | $b ?> <?* $a |> $b ?> <?: $a : $b ?> If to wrap functions in a class or namespace (fully qualified), to not clutter up a global namespace: set_escape_handler() restore_escape_handler() escape_handler_call() PHPEscaper::setEscapeHandler() PHPEscaper::restoreEscapeHandler() PHPEscaper::escapeHandlerCall() And also any names in source code or details of implementation, without changing main algorithm. What is not under discussion: Built-in contexts. Because escape_handler_call() is not an escaper itself, but just a helper to call user-defined escaper, it should not handle any contexts. This allows to prevent 'built-in' wrong work of <?* $str ?> constructions in non-HTML contexts like CSV. Multiple arguments. <?* $a, 'js', 'html' ?> I think, it is enough that second argument can be of any type, e.g. an array. Complicated syntax like <?*html*js= $str ?>. If we allow custom handlers, then we need runtime processing, so the example above cannot be compiled into <?= htmlspecialchars(json_encode($str)) ?> directly, and it will something like <?= escape_handler_call(escape_handler_call($str, 'html'), 'js') ?> I.e. we anyway need to pass context as a second argument, so why not allow user to do it. If someone wants more complex solution or built-in template engine, he can create another RFC and suggest his own implementation.