www.smarty.net/docs/en/language.function.function.... например
Но вообще надо понимать, что в реальной жизни шаблоны не такие красивые и причесанные как в специально нарисованных примерах.
И рекурсивный вывод никогда не будет выглядеть конфеткой.
Еще один вариант - дерево всегда можно развернуть в линейный массив, и выводить в цикле вместо рекурсии.
Я одно время заморочился таким. В итоге код подготовки распух, а код шаблона уменьшился. Но я бы не сказал, что он стал сильно красивее:
<? foreach ($TREE as $row): ?>
<? if($row['li']=="open"): ?><ul><?endif?>
<? if($row['li']=="close"): ?></ul><?endif?>
<? if($row['id']!=0): ?>
<? if($id==$row['id']): ?>
<li><?=$row['title']?></li>
<? else: ?>
<li><a href="?id=<?=$row['id']?>"><?=$row['title']?></a></li>
<? endif ?>
<? endif ?>
<? endforeach ?>
</ul>