I don't know of a way to do it without any commands at all, but in my own work, I created a single command as a gateway to scripts. Its code is here:
<command name="Dungeons_DoScriptCmd">
<pattern>DoScript #text1# #text2#;DoScript #text1#</pattern>
<script>
<![CDATA[
// text = object.attribute parameters
// text2 = parameter string (param1,param2,...)
source = Split(text1, ".")
object = StringListItem(source, 0)
attribute = StringListItem(source, 1)
if (not IsDefined("text2")) {
text2 = ""
}
args = Split(text2, ",")
params = NewDictionary()
argnum = 1
foreach (arg, args) {
dictionary add(params, "arg"+argnum, arg)
argnum = argnum + 1
}
//msg("object = " + object + ", attribute = " + attribute + ", params = " + params)
do (GetObject(object), attribute, params)
]]>
</script>
</command>
You could use this as is or make your own variant. It doesn't allow direct inline script, but it does allow a script to be called on an object. You specify the object and script attribute to be called as "object.script". You an also pass an additional string, which is a comma-separated list of arguments (e.g. "foo,bar,3,5"), and they appear to the script as variables arg1, arg2, etc.
Your example would then be:
By the way, do you have {command:DoScript player.sethairlength long:long} or {command:DoScript player.sethairlength short:short} hair?
where you'd have a script attribute on the player like to handle setting the hair length:
<sethairlength type="script">
this.hairlength = arg1
</sethairlength>
Hope that helps.