class EL_TEMPLATE

(source code)

Client examples: CLUSTER_TREE_ECF_LINESCONDITION_ECF_LINECUSTOM_ECF_LINESDUPLICITY_OS_COMMANDGROUPED_ECF_LINESLIBRARIES_ECF_LINESNAME_LOCATION_ECF_LINENAME_VALUE_ECF_LINEOLD_NAME_NEW_NAME_ECF_LINEOPTION_ECF_LINESPLATFORM_CONDITION_ECF_LINESPLATFORM_FILE_RULE_ECF_LINESPYXIS_ECF_CONSTANTSRENAMING_MAP_ECF_LINESSUB_CLUSTERS_ECF_LINESSYSTEM_ECF_LINESTEMPLATE_TEST_SETWEB_LOG_ENTRY_TEST_SETWRITEABLE_LIBRARIES_ECF_LINES

description

Basic string template to substitute variables names with possible forms:

$a_1 OR ${a_1}

and composed of characters in ranges

'a' .. 'z'
'A' .. 'Z'
'0' .. '9'
'_'

For a literal dollar sign use % to escape it, for example: "USD 100 %$"

notes

An alternative to this class is EL_SUBSTITUTION_TEMPLATE found in libary text-process.ecf.

EL_SUBSTITUTION_TEMPLATE*
   EL_STRING_8_TEMPLATE
   EL_STRING_32_TEMPLATE
   EL_ZSTRING_TEMPLATE

Template classes EL_STRING_32_TEMPLATE and EL_ZSTRING_TEMPLATE permit variable names with characters outside the Latin-1 set.

note
	description: "[
		Basic string template to substitute variables names with possible forms:
		
			$a_1 OR ${a_1}
			
		and composed of characters in ranges
			
			'a' .. 'z'
			'A' .. 'Z'
			'0' .. '9'
			'_'
			
		For a literal dollar sign use % to escape it, for example: "USD 100 %$"
	]"
	notes: "See end of class"

	author: "Finnian Reilly"
	copyright: "Copyright (c) 2001-2022 Finnian Reilly"
	contact: "finnian at eiffel hyphen loop dot com"

	license: "MIT license (See: en.wikipedia.org/wiki/MIT_License)"
	date: "2025-04-16 17:53:03 GMT (Wednesday 16th April 2025)"
	revision: "26"

class
	EL_TEMPLATE [S -> STRING_GENERAL create make, make_empty end]

inherit
	EL_TEMPLATE_LIST [S, READABLE_STRING_8]
		rename
			Iterable as Iterable_
		end

create
	make

convert
	make ({S})

feature {NONE} -- Initialization

	make (a_template: READABLE_STRING_GENERAL)
		local
			iterable: EL_ITERABLE_SPLIT_FACTORY_ROUTINES; template: S
			i, length, variable_count, offset, item_count: INTEGER
			previous_end_character: CHARACTER_32
		do
			template := new_string (a_template)
			variable_count := a_template.occurrences ('$')
			create place_holder_table.make (variable_count)
			make_list (variable_count * 2)
			across iterable.new_split_on_character (template, '$') as list loop
				offset := list.item_lower
				if attached {S} list.item as item then
					item_count := item.count
					if list.cursor_index = 1 or else previous_end_character = '%%' then
						if previous_end_character = '%%' then
							last.put_code ({EL_ASCII}.Dollar, last.count)
						end
						if item_count > 0 then
							extend (item.twin)
						end
					else
						length := 0
						from i := 1 until i > item_count loop
							inspect item [i]
								when 'a'.. 'z', 'A'.. 'Z', '0' .. '9', '_', '{' then
									length := length + 1
									i := i + 1
								when '}' then
									length := length + 1
									i := item_count + 1
							else
								i := item_count + 1
							end
						end
						put_substitution (template.substring (offset - 1, offset + length - 1))
						if length < item_count then
							extend (item.substring (length + 1, item_count))
						end
					end
					if item_count > 0 then
						previous_end_character := item [item_count]
					else
						previous_end_character := '%U'
					end
				end
			end
		end

feature -- Access

	name_list: EL_ARRAYED_LIST [READABLE_STRING_8]
		-- variable name list
		do
			Result := place_holder_table.key_list
		end

feature -- Status query

	has (name: READABLE_STRING_8): BOOLEAN
		do
			Result := place_holder_table.has (name)
		end

feature {NONE} -- Implementation

	field_key (name: READABLE_STRING_8): READABLE_STRING_8
		do
			Result := name
		end

	found_item (name: READABLE_STRING_8): detachable S
		do
			if place_holder_table.has_key (name) then
				Result := place_holder_table.found_item
			end
		end

	key (str: READABLE_STRING_8): READABLE_STRING_8
		do
			Result := str
		end

	put_substitution (variable: S)
		require
			latin_1_characters: variable.is_valid_as_string_8
		local
			place_holder: S; name: STRING_8
		do
			name := variable.to_string_8
			if name.same_type (variable) then
				name := name.twin
			end
			if name [2] = '{' then
			-- canonical form: ${var}
				name.remove_head (2); name.remove_tail (1)
			else
				name.remove_head (1)
			end
			if place_holder_table.has_key (name) then
			-- same `place_holder' can appear repeatedly in `Current' list
				place_holder := place_holder_table.found_item
			else
				place_holder := variable
				place_holder_table.extend (place_holder, name)
			end
			extend (place_holder)
		end

feature {EL_REFLECTION_HANDLER} -- Internal attributes

	place_holder_table: EL_STRING_8_TABLE [S];
		-- variable name list

note
	notes: "[
		An alternative to this class is ${EL_SUBSTITUTION_TEMPLATE} found in libary
		[./library/text-process.html text-process.ecf].

			EL_SUBSTITUTION_TEMPLATE*
				${EL_STRING_8_TEMPLATE}
				${EL_STRING_32_TEMPLATE}
				${EL_ZSTRING_TEMPLATE}
				
		Template classes ${EL_STRING_32_TEMPLATE} and ${EL_ZSTRING_TEMPLATE} permit variable
		names with characters outside the Latin-1 set.
	]"

end