<?xml version="1.0" encoding="UTF-8"?>
<xs:schema 
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns="https://klish.libcode.org/klish3"
	targetNamespace="https://klish.libcode.org/klish3">

	<xs:annotation>
		<xs:appinfo>XML schema for klish configuration files</xs:appinfo>
		<xs:documentation xml:lang="en">
		The klish utility uses XML files for configuration. This schema
		allows to validate klish XML files. To check XML files use the
		following command:
		'xmllint --schema /path/to/klish.xsd --noout *.xml'
		</xs:documentation>
		<xs:documentation xml:lang="ru">
		Утилита klish использует формат XML для своих конфигурационных
		файлов. Схема позволяет проверить конфигурационные XML файлы
		на корректность. Следующая команда выполнит проверку:
		'xmllint --schema /path/to/klish.xsd --noout *.xml'
		</xs:documentation>
	</xs:annotation>


	<xs:element name="KLISH" type="klish_t"/>
	<xs:element name="PLUGIN" type="plugin_t"/>
	<xs:element name="HOTKEY" type="hotkey_t"/>
	<xs:element name="ACTION" type="action_t"/>
	<xs:element name="ENTRY" type="entry_t"/>
	<xs:element name="VIEW" type="view_t"/> <!-- Wrapper -->
	<xs:element name="COMMAND" type="command_t"/> <!-- Wrapper -->
	<xs:element name="FILTER" type="command_t"/> <!-- Wrapper -->
	<xs:element name="COND" type="command_t"/> <!-- Wrapper -->
	<xs:element name="COMPL" type="command_t"/> <!-- Wrapper -->
	<xs:element name="HELP" type="command_t"/> <!-- Wrapper -->
	<xs:element name="PROMPT" type="command_t"/> <!-- Wrapper -->
	<xs:element name="LOG" type="command_t"/> <!-- Wrapper -->
	<xs:element name="PTYPE" type="ptype_t"/> <!-- Wrapper -->
	<xs:element name="PARAM" type="param_t"/> <!-- Wrapper -->
	<xs:element name="SWITCH" type="param_t"/> <!-- Wrapper -->
	<xs:element name="SEQ" type="param_t"/> <!-- Wrapper -->


<!--
*******************************************************
* <KLISH> is a top level container.
********************************************************
-->
	<xs:group name="klish_group_t">
		<xs:choice>
			<xs:element ref="PLUGIN" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="HOTKEY" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="ENTRY" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PTYPE" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="VIEW" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COMMAND" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="FILTER" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COND" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COMPL" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="HELP" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PROMPT" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="LOG" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PARAM" minOccurs="0" maxOccurs="unbounded"/>
		</xs:choice>
	</xs:group>

	<xs:complexType name="klish_t">
		<xs:annotation>
			<xs:documentation xml:lang="en">
			'KLISH' is the top level container.
			</xs:documentation>
			<xs:documentation xml:lang="ru">
			Тег 'KLISH' - контейнер верхнего уровня. Все остальные
			теги должны быть вложенными.
			</xs:documentation>
		</xs:annotation>
		<!--  Any order of tags and any number -->
		<xs:sequence>
			<xs:group ref="klish_group_t" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
	</xs:complexType>


<!--
*******************************************************
* <PLUGIN> is used to dynamically load plugins.
* Plugin contains symbols that can be used for ACTIONs.
*
* name - Plugin name. If "file" attribute is not specified then plugin's
*	filename is autogenerated as "kplugin-<name>.so".
*
* [id] - Internal plugin name for references. Can be the same as "name".
*
* [file] - File name to use if standard autogenerated filename (using "name"
*	field) is not appropriate.
*
* The content of PLUGIN tag can be used as a config file for this plugin.
* Parsing of this content must be implemented within plugin's init.
*
********************************************************
-->
	<xs:complexType name="plugin_t">
		<xs:annotation>
			<xs:documentation xml:lang="en">
			Load plugin with symbols (functions).
			</xs:documentation>
			<xs:documentation xml:lang="ru">
			Загружает плугин для использования определяемых в нем
			символов (функций).
			</xs:documentation>
		</xs:annotation>
		<xs:simpleContent>
			<xs:extension base="xs:string">
				<xs:attribute name="name" type="xs:string" use="required"/>
				<xs:attribute name="id" type="xs:string" use="optional"/>
				<xs:attribute name="file" type="xs:string" use="optional"/>
			</xs:extension>
		</xs:simpleContent>
	</xs:complexType>


<!--
*******************************************************
* <HOTKEY> is used to define hotkey actions
*
* key - Hot-key
*
* cmd - Text string defines command to execute on pressing hot-key. It's like
*	a common user CLI input. This string will be interpreted by CLI engine.
*
********************************************************
-->
	<xs:complexType name="hotkey_t">
		<xs:attribute name="key" type="xs:string" use="required"/>
		<xs:attribute name="cmd" type="xs:string" use="required"/>
	</xs:complexType>


<!--
********************************************************
* <ACTION> specifies the action to be taken for
* a command.
*
* In addition the optional 'sym' attribute can specify
* the name of an internal command which will be invoked
* to handle script.
*
* [sym="<symbol>"] - specify the name of an internally registered
*	function (symbol). The content of the ACTION tag is
*	taken as the arguments to this function. Plugins can define
*	these symbols. The "<symbol>" can be defined as "sym@plugin" i.e.
*	parental plugin can be defined explicitly.
*
* [lock="<name>"] - Named lock. It will use special lockfile while
*	action execution.
*
* [interrupt="true/false"] - The boolean field that specify that action can be
*	be interrupted by Ctrl^C. Default is false.
*
* [in="true/false/tty"] - Does ACTION need input. The "tty" means action can use
*	terminal. Default is "false".
*
* [out="true/false/tty"] - How does ACTION use output. The "tty" means action
*	generate output for terminal. Default is "true".
*
* [exec_on="fail/success/always/never"] - ACTION's execution depends on
*	return code of previous elements of ACTION chain. If the
*	condition is not met then ACTION will not be executed. The "always"
*	value means that ACTION will be always executed and chain return
*	code will be ignored. Default is "success".
*
* [update_retcode="true/false"] - The chain return value can be updated
*	by current ACTION's return code or ACTION's return code can be ignored.
*	Default is "true".
*
* [permanent="true/false"] - The klish can be invoked with dry-run option. In
*	this case all ACTIONs will be not actually executed but will always
*	return success. But some actions like navigation is necessary to be
*	executed in any case. Permanent flag will inform engine to always
*	execute ACTION.
*
* [sync="true/false"] - Common behaviour is to fork() process before ACTION
*	execution. But ACTION may be executed in-place (without fork()) if sync
*	flag is set to true. It's not recommended to use sync ACTIONs widely.
*	It's usefull for small fast functions only.
*
********************************************************
-->

	<xs:simpleType name="action_cond_t">
		<xs:restriction base="xs:string">
			<xs:enumeration value="fail"/>
			<xs:enumeration value="success"/>
			<xs:enumeration value="always"/>
			<xs:enumeration value="never"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:simpleType name="action_io_t">
		<xs:restriction base="xs:string">
			<xs:enumeration value="false"/>
			<xs:enumeration value="true"/>
			<xs:enumeration value="tty"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:complexType name="action_t">
		<xs:simpleContent>
			<xs:extension base="xs:string">
				<xs:attribute name="sym" type="xs:string" use="optional"/>
				<xs:attribute name="lock" type="xs:string" use="optional"/>
				<xs:attribute name="interrupt" type="xs:boolean" use="optional" default="false"/>
				<xs:attribute name="in" type="action_io_t" use="optional" default="false"/>
				<xs:attribute name="out" type="action_io_t" use="optional" default="true"/>
				<xs:attribute name="exec_on" type="action_cond_t" use="optional" default="success"/>
				<xs:attribute name="update_retcode" type="xs:boolean" use="optional" default="true"/>
				<xs:attribute name="permanent" type="xs:boolean" use="optional" default="false"/>
				<xs:attribute name="sync" type="xs:boolean" use="optional" default="false"/>
			</xs:extension>
		</xs:simpleContent>
	</xs:complexType>


<!--
*******************************************************
* <ENTRY> This tag is used to define wide class of elements.
*
* name - A text name for entry.
*
* [help] - A text string which describes the purpose of the entry.
*
* [container="true/false"] - If entry is container. Container entry can't
*	have parsable argument i.e. only container's children can be considered
*	as a candidates to be a appropriate instance for parsed argument.
*	For example VIEW is a container. It just structurizes commands but
*	are not commands itself. Another example of container is a SWITCH.
*	It describes parsing of child elements but has no special keyword
*	while user typing.
*
* [mode] - Entry mode. It can be "sequence", "switch", "empty". Default is
*	"sequence".
*
* [purpose] - Purpose of entry. It can be "common", "ptype", "prompt", "cond",
*	"completion", "help". Default is "common". Another "purposes" are
*	processed in a special ways.
*
* [min="<num>"] - Min number of entry occurence while user input parsing.
*	Default is 1.
*
* [max="<num>"] - Max number of entry occurence while user input parsing.
*	Default is 1.
*
* [ref="<reference>"] - Entry can reference another entry.
*
* [value="<val>"] - defines the user's value for subcommand. If this option
*	is defined the entered parameter will be compared to this
*	value instead the "name" field. If this field is defined
*	the mode of PARAM will be forced to "subcommand". The
*	feature is implemented to support subcommands with the
*	same names.
*
* [restore="true/false"] - Restore (or not) hierarchy level of executed
*	entry. Default is "false".
*
* [order="true/false"] - If order="true" then user can't enter previously declared
*	optional parameters after current validated parameter.
*	The allowed values is "true" or "false". It's false by default.
*
* [filter="true/false"] - Developer can define 'filter' command to filter stdout
*	of piped ("|") commands. Filter can't contain 'sync' ACTIONs. It will be
*	always fork()-ed. Only filters can be on the right hand to pipe "|".
*	Consider filters as a special type of commands.
*
********************************************************
-->
	<xs:simpleType name="entry_mode_t">
		<xs:restriction base="xs:string">
			<xs:enumeration value="sequence"/>
			<xs:enumeration value="switch"/>
			<xs:enumeration value="empty"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:simpleType name="entry_purpose_t">
		<xs:restriction base="xs:string">
			<xs:enumeration value="common"/>
			<xs:enumeration value="ptype"/>
			<xs:enumeration value="prompt"/>
			<xs:enumeration value="cond"/>
			<xs:enumeration value="completion"/>
			<xs:enumeration value="help"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:simpleType name="entry_filter_t">
		<xs:restriction base="xs:string">
			<xs:enumeration value="true"/>
			<xs:enumeration value="false"/>
			<xs:enumeration value="dual"/>
		</xs:restriction>
	</xs:simpleType>

	<xs:group name="entry_group_t">
		<xs:choice>
			<xs:element ref="HOTKEY" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="ACTION" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="ENTRY" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PTYPE" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="VIEW" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COMMAND" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="FILTER" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PARAM" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COND" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COMPL" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="HELP" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PROMPT" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="LOG" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="SWITCH" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="SEQ" minOccurs="0" maxOccurs="unbounded"/>
		</xs:choice>
	</xs:group>

	<xs:complexType name="entry_t">
		<!--  Any order of tags and any number -->
		<xs:sequence>
			<xs:group ref="entry_group_t" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="name" type="xs:string" use="required"/>
		<xs:attribute name="help" type="xs:string" use="optional"/>
		<xs:attribute name="container" type="xs:boolean" use="optional" default="false"/>
		<xs:attribute name="mode" type="entry_mode_t" use="optional" default="switch"/>
		<xs:attribute name="purpose" type="entry_purpose_t" use="optional" default="common"/>
		<xs:attribute name="min" type="xs:string" use="optional" default="1"/>
		<xs:attribute name="max" type="xs:string" use="optional" default="1"/>
		<xs:attribute name="ref" type="xs:string" use="optional"/>
		<xs:attribute name="value" type="xs:string" use="optional"/>
		<xs:attribute name="restore" type="xs:boolean" use="optional" default="false"/>
		<xs:attribute name="order" type="xs:boolean" use="optional" default="false"/>
		<xs:attribute name="filter" type="entry_filter_t" use="optional" default="false"/>
	</xs:complexType>


<!--
*******************************************************
* <PTYPE> is used to define the syntax for a parameter type.
*
* See ENTRY tag for attributes description.
*
********************************************************
-->

	<xs:group name="ptype_group_t">
		<xs:choice>
			<xs:element ref="ACTION" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="ENTRY" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COND" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COMPL" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="HELP" minOccurs="0" maxOccurs="unbounded"/>
		</xs:choice>
	</xs:group>

	<xs:complexType name="ptype_t">
		<xs:sequence>
			<xs:group ref="ptype_group_t" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="name" type="xs:string" use="optional"/>
		<xs:attribute name="help" type="xs:string" use="optional"/>
		<xs:attribute name="ref" type="xs:string" use="optional"/>
		<xs:attribute name="value" type="xs:string" use="optional"/>
	</xs:complexType>


<!--
*******************************************************
* <VIEW> defines the contents of a specific CLI view.
*
* See ENTRY tag for attributes description.
*
********************************************************
-->

	<xs:group name="view_group_t">
		<xs:choice>
			<xs:element ref="HOTKEY" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="ENTRY" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PTYPE" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="VIEW" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COMMAND" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="FILTER" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PARAM" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COND" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COMPL" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="HELP" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PROMPT" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="LOG" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="SWITCH" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="SEQ" minOccurs="0" maxOccurs="unbounded"/>
		</xs:choice>
	</xs:group>

	<xs:complexType name="view_t">
		<xs:sequence>
			<xs:group ref="view_group_t" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="name" type="xs:string" use="required"/>
		<xs:attribute name="help" type="xs:string" use="optional"/>
		<xs:attribute name="ref" type="xs:string" use="optional"/>
	</xs:complexType>


<!--
*******************************************************
* <PARAM> This tag is used to define a parameter for a command.
*
* See ENTRY tag for attributes description.
*
********************************************************
-->
	<xs:group name="param_group_t">
		<xs:choice>
			<xs:element ref="ACTION" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="ENTRY" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PTYPE" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="VIEW" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COMMAND" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="FILTER" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="PARAM" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COND" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="COMPL" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="HELP" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="LOG" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="SWITCH" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="SEQ" minOccurs="0" maxOccurs="unbounded"/>
		</xs:choice>
	</xs:group>

	<xs:complexType name="param_t">
		<!--  Any order of tags and any number -->
		<xs:sequence>
			<xs:group ref="param_group_t" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="name" type="xs:string" use="required"/>
		<xs:attribute name="help" type="xs:string" use="optional"/>
		<xs:attribute name="ptype" type="xs:string" use="optional"/>
		<xs:attribute name="mode" type="entry_mode_t" use="optional" default="sequence"/>
		<xs:attribute name="min" type="xs:string" use="optional" default="1"/>
		<xs:attribute name="max" type="xs:string" use="optional" default="1"/>
		<xs:attribute name="ref" type="xs:string" use="optional"/>
		<xs:attribute name="value" type="xs:string" use="optional"/>
		<xs:attribute name="order" type="xs:boolean" use="optional" default="false"/>
	</xs:complexType>


<!--
*******************************************************
* <COMMAND> is used to define a command within the CLI.
*
* See ENTRY tag for attributes description.
*
********************************************************
-->
	<xs:complexType name="command_t">
		<!--  Any order of tags and any number -->
		<xs:sequence>
			<xs:group ref="entry_group_t" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="name" type="xs:string" use="optional"/>
		<xs:attribute name="help" type="xs:string" use="optional"/>
		<xs:attribute name="mode" type="entry_mode_t" use="optional" default="sequence"/>
		<xs:attribute name="min" type="xs:string" use="optional" default="1"/>
		<xs:attribute name="max" type="xs:string" use="optional" default="1"/>
		<xs:attribute name="ref" type="xs:string" use="optional"/>
		<xs:attribute name="value" type="xs:string" use="optional"/>
		<xs:attribute name="restore" type="xs:boolean" use="optional" default="false"/>
		<xs:attribute name="filter" type="entry_filter_t" use="optional" default="false"/>
	</xs:complexType>

</xs:schema>