Python. Хромая реализация require. (
Выкладываю на общий суд небольшую наработку в виде скрипта для реализации функции require(…). Для работы скрипта необходимо создать с ним в одной директории папку scr. Туда положить war3map.lua с использованием функции require.
Требования:
  • все модули должны находится в поддиректориях src
  • первая строка модуля должна содержать локальную таблицу модуля ( local module_name = {} )
  • все функции и переменные модулей должны быть полями этой таблицы.
Запуск concate.py
На выходе получаем файл war3map.lua в папке build, готовый к запаковке в архив. Подготавливалось для рабочего места в jetBrain (как оказалось в vscode отвратительная поддержка lua). В дальнейшем планируется добавить в автозаполнение common.j . Стоит ли выкладывать после доработки?
Переформатированный common.j -> common.lua, blizzard.j -> blizzard.lua. В дальнейшем будет использоваться для автозаполнения в jetBrain
» concate.py

import os
from shutil import copyfile

import preparse
import parse

argc = len(sys.argv)
if argc < 4:
    build_path = 'build/'
else:
    build_path = sys.argv[3]

if argc < 3:
    src_path = 'src/'
else: 
    src_path = sys.argv[2]

if argc < 2:
    main_path = 'src/'
else:
    main_path = sys.argv[1]
    
#print(main_path + '\n' + src_path + '\n' + build_path)

included_list = []
if os.path.isfile(build_path + 'war3map.lua'):
    os.remove(build_path + 'war3map.lua')

copyfile(main_path + 'war3map.lua', build_path + 'war3map.lua')

preparse.preParseSrc(src_path)
preparse.fixRequires(build_path, src_path, build_path)
lines = parse.parseFile(build_path + 'war3map.lua')

if os.path.isfile(build_path + 'war3map.lua'):
    os.remove(build_path + 'war3map.lua')
result = open(build_path + 'war3map.lua', 'w')
result.writelines(lines)
result.close()


#input("Press Enter to continue...")

» prepares.py
import os
import utils as u

def preParseSrc(path, build_path = 'build/'):
    for name in os.listdir(path):
        full_path = path +  name
        if os.path.isfile(full_path):
            if full_path != path + 'war3map.lua':
                parseFile(full_path, build_path)
        else:
            preParseSrc(full_path + '/', build_path)

def parseFile(path, build_path = 'build/'):
    print('Preparsing ' + path + '...')
    f = open(path)
    old_name = u.getModuleName(path)
    new_name = u.path2Name(path)
    lines = f.readlines()

    res_path = build_path + path[path.find('/') + 1:path.rfind('/') + 1] + new_name + '.lua'
    if os.path.isfile(res_path):
        os.remove(res_path)

    if not os.path.exists(res_path[:res_path.rfind('/') + 1]):
        os.makedirs(res_path[:res_path.rfind('/') + 1])

    b_file = open(res_path, 'w')
    lines[0] = 'local ' + new_name + ' = {}\n'
    lines.remove(lines[len(lines) - 1])
    for line in lines:
        b_file.write(line.replace(old_name + '.', new_name + '.'))

def fixRequires(path, src_path = 'src/', build_path = 'build/'):
    for name in os.listdir(path):
        full_path = path + name
        if os.path.isfile(full_path):
            fixRequire(full_path, src_path, build_path)
        else:
            fixRequires(full_path + '/', src_path, build_path)

def fixRequire(path, src_path, build_path):
    print('Fixing requires ' + path + '...')
    f = open(path, 'r')
    lines = f.readlines()
    f.close()

    res = []
    for line in lines:
        if line.replace(' ', '').find('=require(') > -1:
            module = line[line.find('(\'') + 2: line.find('\')')]
            module_path = src_path + u.getRelativeModulePath(line)
            new_name = u.path2Name(module_path)
            new_path = build_path + module_path[module_path.find('/') + 1:module_path.rfind('/') + 1] + new_name + '.lua'
            new_module = u.path2Module(new_path[new_path.find('/') + 1:])
            line = line.replace(module, new_module)
        res.append(line)

    os.remove(path)
    f = open(path, 'w')
    f.writelines(res)
    f.close()
» parse.py
import os
import utils as u

def parseFile(path, build_path = 'build/'):
    print('Parsing ' + path + '...')
    f = open(path, 'r')
    cur_dir = path[:path.rfind('/') + 1]
    lines = f.readlines()
    f.close()
    res = []
    for line in lines:
        l = line.replace(' ', '')
        pos = l.find('=require(')
        if pos > 0:
            module_path = cur_dir + u.getRelativeModulePath(line)
            print(module_path)
            module_lines = parseFile(module_path)
            for l in module_lines:
                res.append(l)
            res.append(line[:line.find('=')] + ' = ' + getModuleName(module_path) + '\n')
        else:
            res.append(line)
    return res

def getModuleName(path):
    m_file = open(path)
    first_line = m_file.readline()
    m_file.close()

    start = first_line.find('local ') + 5
    l = first_line.replace(' ', '')
    end = l.find('={}')

    return l[start:end]

def listRequires(path, cur_dir):
    f = open(path)
    lines = f.readlines()
    res = []
    for line in lines:
        line = line.replace(' ', '')
        pos = line.find('=require(')
        if pos > 0:
            res.append(cur_dir + line[line.find('(\''):line.find('\')')])
    f.close()
    return res
» utils.py
def getModuleName(path):
    m_file = open(path)
    first_line = m_file.readline()
    m_file.close()

    start = first_line.find('local ') + 5
    l = first_line.replace(' ', '')
    end = l.find('={}')

    return l[start:end]

def path2Name(path):
    return path[path.find('/') + 1:].replace('/', '_')[:-4]

def path2Module(path):
    return path.replace('/', '.')[:-4]

def getRelativeModulePath(line):
    module = line[line.find('(\'') + 2:line.find('\')')]
    return module.replace('.', '/') + '.lua'

def getBuiltFilePath(src_path, build_path = 'build/'):
    return build_path + src_path[src_path.find('/') + 1:]

Лучший ответ:
питон всегда хорош, особенно в случае варкрафта, где ваш код может вдохновить юного падавана изучать языки программирования. Я вот вообще не лезу совмещать вар3 и ЯП, потому что это не для меня. Молодцом, стоит выкладывать, когда хромота кода пропадет)


Views: 248

BrEd Pitt #1 - 2 years ago 2
Голосов: +2 / -0

питон всегда хорош, особенно в случае варкрафта, где ваш код может вдохновить юного падавана изучать языки программирования. Я вот вообще не лезу совмещать вар3 и ЯП, потому что это не для меня. Молодцом, стоит выкладывать, когда хромота кода пропадет)