Parse string as a DocCommand

Returns null if the string cannot be parsed. See error for the error messages produced by both the parser and the commands.

Property definitions

nitc $ CommandParser :: parse
	# Parse `string` as a DocCommand
	#
	# Returns `null` if the string cannot be parsed.
	# See `error` for the error messages produced by both the parser and the commands.
	fun parse(string: String): nullable DocCommand do
		var pos = 0
		var tmp = new FlatBuffer
		error = null

		# Parse command name
		pos = string.read_until(tmp, pos, ':', '|')
		var name = tmp.write_to_string.trim

		# Check allowed commands
		if name.is_empty then
			error = new CmdParserError("Empty command name", 0)
			return null
		end
		# If the command name contains two consecutive colons or there is no colon in the name,
		# we certainly have a wiki link to a mentity
		var is_short_link = false
		if (pos < string.length - 2 and string[pos] == ':' and string[pos + 1] == ':') or
		   pos == string.length then
			is_short_link = true
		else if pos < string.length - 1 and string[pos] == '|' then
			is_short_link = true
			pos -= 1
		else if not allowed_commands.has(name) then
			error = new CmdParserError("Unknown command name `{name}`", 0)
			return null
		end

		# Parse the argument
		tmp.clear
		pos = string.read_until(tmp, pos + 1, '|')
		var arg = tmp.write_to_string.trim
		if is_short_link and not arg.is_empty then
			arg = "{name}:{arg}"
		else if is_short_link then
			arg = name
		end

		# Parse command options
		var opts = new CmdOptions
		while pos < string.length do
			# Parse option name
			tmp.clear
			pos = string.read_until(tmp, pos + 1, ':', ',')
			var oname = tmp.write_to_string.trim
			var oval = ""
			if oname.is_empty then break
			# Parse option value
			if pos < string.length and string[pos] == ':' then
				tmp.clear
				pos = string.read_until(tmp, pos + 1, ',')
				oval = tmp.write_to_string.trim
			end
			opts[oname] = oval
		end

		# Build the command
		var command
		if is_short_link then
			command = new CmdEntityLink(model)
		else
			command = new_command(name)
		end
		if command == null then
			error = new CmdParserError("Unknown command name `{name}`", 0)
			return null
		end

		# Initialize command from string options
		var status = command.parser_init(arg, opts)
		if not status isa CmdSuccess then error = status

		return command
	end
src/doc/commands/commands_parser.nit:99,2--176,4