• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Nested Textmacros?

Status
Not open for further replies.
Level 24
Joined
Aug 1, 2013
Messages
4,657
I know this is not possible, but it almost makes me copy my JASS into another program and run all textmacros and then paste it back in the WE.

But I think this should be a standard feature.
Nested textmacros are really helpfull and there is really no reason for it not to be able to.

Is there any way to make something like this possible myself or do I just have to wait until someone updates the script and uploads a new release?
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
If you still have use for it/reference

Code:
local params = {...}

local inputPath = params[1]
local outputPath = params[2]

assert(inputPath, 'no inputPath')
assert(outputPath, 'no outputPath')

local inputFile = io.open(inputPath, 'r')

assert(inputFile, 'could not open '..inputPath)

local macrosByName = {}

local function createMacro(name)
	assert(macrosByName[name] == nil, 'macro '..tostring(name)..' doubly declared')

	local macro = {}
	
	macrosByName[name] = macro
	
	macro.args = {}
	
	function macro:addArg(arg)
		macro.args[#macro.args + 1] = arg
	end

	macro.lines = {}

	function macro:addLine(line)
		macro.lines[#macro.lines + 1] = line
	end
	
	return macro
end

local curMacro = nil
local inLines = {}

for line in inputFile:lines() do
	local name, argLine = line:match('^%s*//!%s+textmacro ([%w%d]+) takes (.+)')

	if (name ~= nil) then
		curMacro = createMacro(name)

		for arg in string.gmatch(argLine, '([%w%d]+)') do
			curMacro:addArg(arg)
		end
	else
		if (curMacro ~= nil) then
			if line:match('^%s*//! endtextmacro%s*$') then
				curMacro = nil
			else
				if (line:match('^%s*//!%s+runtextmacro%s+([%w%d]+)%((.*)%)%s*$') == nil) then
					line = line:match('^%s*//!%s*(.*)')
				end

				if (line ~= nil) then
					curMacro:addLine(line)
				end
			end
		else
			inLines[#inLines + 1] = line
		end
	end
end

inputFile:close()

local outLines = {}

local function addLineToOutput(line)
	local name, argLine = line:match('^%s*//!%s+runtextmacro%s+([%w%d]+)%((.*)%)%s*$')

	if (name ~= nil) then
	print('exec', name)
		local macro = macrosByName[name]

		assert(macro ~= nil, 'macro '..tostring(name)..' unknown')
		
		outLines[#outLines + 1] = '// textmacro run start: '..tostring(name)..'('..tostring(argLine)..')'
		
		local args = {}
		local c = 0

		local argLineEx = argLine:gsub('%\\%"', '\n')

		for arg in string.gmatch(argLineEx, '%"(.-)%"') do
			c = c + 1
			
			arg = arg:gsub('\n', '"')

			args[macro.args[c]] = arg
		end

		for i = 1, #macro.lines, 1 do
			local line = macro.lines[i]

			local pos, posEnd, arg = line:find('%$([%w%d]+)%$')

			while (pos ~= nil) do
			print('found', arg)
				if (args[arg] ~= nil) then
					line = line:sub(1, pos - 1)..args[arg]..line:sub(posEnd + 1, line:len())
					
					posEnd = posEnd + args[arg]:len() - arg:len() - 2
				end

				pos, posEnd, arg = line:find('%$([%w%d]+)%$', posEnd + 1)
			end

			addLineToOutput(line)
		end

		outLines[#outLines + 1] = '// textmacro run end: '..tostring(name)..'('..tostring(argLine)..')'
	else
		outLines[#outLines + 1] = line
	end
end

for i = 1, #inLines, 1 do
	addLineToOutput(inLines[i])
end

local outputFile = io.open(outputPath, 'w+')

assert(outputFile, 'could not open '..outputPath)

for i = 1, #outLines, 1 do
	outputFile:write(outLines[i], '\n')
end

outputFile:close()

resolves vjass textmacros
 
Level 14
Joined
Dec 12, 2012
Messages
1,007
If you still have use for it/reference

resolves vjass textmacros

Won't this also resolve textmacros in comments like

JASS:
/*
//! textmacro STUFF takes nothing
*/

?

Anyway, the problem with such tools is that you then have non-standard code that won't work for the majority of people... If its meant to be used only for oneself I think its fine, but for systems/spells etc. its quite problematic and should be well justified.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Won't this also resolve textmacros in comments like

Yes, only for simple use.

Anyway, the problem with such tools is that you then have non-standard code that won't work for the majority of people... If its meant to be used only for oneself I think its fine, but for systems/spells etc. its quite problematic and should be well justified.

Of course, and establishing standards is difficult but it would be nice if things got more modulary, which however demands a degree of basic understanding from the users. At least I do not want to be stuck with the same old restrictions eternally.

Apart from literalizing textmacros, I have already had multiple reasons to insert a compiler before jasshelper in the past. With postproc tools and the upcoming object data generation and injections, setting up a build chain becomes even more vital. Yes, it adds dependency on these technologies but it's the same when you import some essential map script systems where you do not necessarily know their entirety either. It's easier to work with a full map editor environment but then you get dictated everything and presenting such a tool is difficult for a game as complex as wc3. That's why I think it's better to increase overall knowledge, provide explicit and stackable solutions. We do need better extension points.
 
Status
Not open for further replies.
Top