Денис
Мне только один способ приходит в голову:
a = "Тестовая строка"
if #a ~= utf8.len(a) then
print("UTF8")
else
print("Not utf8")
end
mva
Snusmumriken
Денис
Snusmumriken
Он самый, и у него куча применений.
Денис
Я пытался им воспользоваться, но он на латинице показывает истину
Snusmumriken
А чем латиница не utf8?
Денис
она однобайтовая)))
Snusmumriken
Она всё ещё входит в диапазон utf8.
Денис
чаще всего
Денис
Она всё ещё входит в диапазон utf8.
теоретически - да))) но если мы говорим про работу библиотеки string, то там латиница проходит в любом виде, а вот мультибайтовые истории - уже нет
Денис
В любом случае, спасибо за методы!
Snusmumriken
Практически — если видишь что строка содержит чисто utf8-символы — используй функции по работе с utf8. Если содержит что-то ещё — забей на это дело и посылай такую строку нафиг.
Snusmumriken
Ещё проще: поддерживай только utf8, а что не utf8 конверть в utf8 и поддерживай. Не конвертится? Нафиг.
Денис
Денис
Ещё проще: поддерживай только utf8, а что не utf8 конверть в utf8 и поддерживай. Не конвертится? Нафиг.
-- The multibyte strings cannot be processed by the Lua String library correctly.
function utils.exposeUTF8Chars(utfString)
local result = {}
for _, character in utf8.codes(utfString) do
table.insert(result, utf8.char(character))
end
return result
end
function utils.truncateSmart(stringShouldbeTruncated, truncateLength)
local truncatedString = stringShouldbeTruncated
-- We will not work with string as usual cuz REAPER may provide us the multibyte UTF8 strings.
-- But Lua provides us the raw UTF8 processing, so we will attempt to solve this trouble like that.
if utf8.len(stringShouldbeTruncated) > truncateLength then
truncatedString = nil
local strTable = utils.exposeUTF8Chars(stringShouldbeTruncated)
local lastChunkLeft = 0
for i = truncateLength, 1, -1 do
local char = utf8.codepoint(strTable[i])
-- The char code is more comfort for checking
if char == 32 or char == 45 or char == 95 then
lastChunkLeft = i
break
end
end
local lastChunkRight = 0
for i = truncateLength+1, #strTable do
local char = utf8.codepoint(strTable[i])
if char == 32 or char == 45 or char == 95 then
lastChunkRight = i
break
end
end
if lastChunkLeft > 0 and lastChunkRight > 0 then
truncatedString = table.concat(strTable, "", 1, lastChunkLeft-1)
if (lastChunkRight-truncateLength) > (truncateLength-lastChunkLeft) then
truncatedString = truncatedString..table.concat(strTable, "", lastChunkLeft, lastChunkRight-1)
end
truncatedString = truncatedString.."..."
elseif lastChunkLeft == 0 and lastChunkRight > 0 then
truncatedString = table.concat(strTable, "", 1, lastChunkRight-1).."..."
elseif lastChunkLeft > 0 and lastChunkRight == 0 then
truncatedString = table.concat(strTable, "", 1, lastChunkLeft-1).."..."
elseif lastChunkLeft == 0 and lastChunkRight == 0 then
if (#strTable-truncateLength) < truncateLength then
truncatedString = table.concat(strTable, "").."..."
end
end
if not truncatedString then
truncatedString = table.concat(strTable, "", 1, truncateLength).."..."
end
end
return truncatedString
end
Snusmumriken
Ой мама )
Денис
Snusmumriken
Так, а что делает эта функция?
Триммит строки с utf8? Типа string.sub?
Денис
Поэтому хотел сделать так, что если строка однобайтовая, то мы ее будем препарировать стандартно, если нет- через такие костыли
Денис
Так, а что делает эта функция?
Триммит строки с utf8? Типа string.sub?
Первая функция - разбирает строку на массив символов. Вторая - усекает строку по-умному: смотрит на чанк, куда указывает усечение, проверяет середина ли это слова, и если да, то как ему лучше это усечь: полностью убрать это слово (если чанк от разделителя до усечения меньше, чем чанк после усечения до разделителя) или оставить полностью (если наоборот).
Snusmumriken
Вообще, выглядит как повод декомпозировать на набор функций. И примерно заменяется на:
function truncate(str, len)
local offset = utf8.offset(str, 1, -len)
return str:sub(1, offset - 1)
end
Snusmumriken
Может быть чутка медленней на чистой латинице, но пофигу.
Денис
Денис
то есть, если например подать строку типа "Spire_X64_V1.1.13", а вторым параметром передать 3, то функция вернет "Spire..."
Snusmumriken
Так, а чем X64 отличается от V1 принципиально?
Snusmumriken
Просто в таком случае можно например обрезать всё после символа:
function truncate(str, len)
-- cleaning
if str:find([-_ ]) then
str = str:match("(.-)[-_ ]")
end
local offset = utf8.offset(str, 1, -len)
return str:sub(1, offset - 1)
end
Snusmumriken
Поправил
Snusmumriken
Ты использовал коды для сверки вместо конкретных символов - и _, сделал регулярку.
Snusmumriken
Если хочешь цепляться за последний фильтрующийся символ, то вместо .- в регулярке будет .*
Snusmumriken
А теперь в чём преимущества подобного подхода: регулярки конечно довольно медленные, но эти — быстрые, в процессе не создаётся никаких таблиц, а все операции поиска и сравнения происходят на сишной стороне, то есть в процессе не генерируется тонна строк.
Snusmumriken
Ну и просто короче и лучше читается. Если ты нормально воспринимаешь регулярные выражения. Они всё таки сильно визуальные.
Денис
Так, а чем X64 отличается от V1 принципиально?
Эта функция используется при идентификации объекта, там помимо этого еще много информации собирается, а в последствие отправляется на синтез речи. То есть, если пользователь решает, что он в идентификации хочет слышать не больше трех символов, то мы ему это даем. В данном случае "Spire_X64_V1.1.13" - это имя объекта.
Snusmumriken
О, кстати целевое назначение отличное
Денис
Т.е., сумарно конечная строка может выглядеть как "Violet Red opened folder Spire... volume 0 dB, 1 of 11."
Денис
Надо попробовать подкинуть такие регулярки...
Денис
А что, в Lua Patterns работает минус?
Денис
Я видел в доке только +, * и ?
Денис
Snusmumriken
Обычно в выражениях его нужно экранировать, но внутри квадратных скобок все символы сырые, и не надо экранировать ничего кроме тех же квадратных скобок.
Денис
Snusmumriken
Опа, кто ето тут у нас?
Александр
Такой вопрос кстати: а есть что-то типо обрезанного луа, чисто для хранения данных ? Ну в духе того, чтобы использовать луашные таблицы, типы данных, строки и комментарии, но чтобы без ВМ, без функций и пр. ? Понятно, что можно просто не использовать этого в луа или перегружать переменную _ENV, _G, но хотелось бы прям по жёсткому изолировать данные от среды исполнения
Snusmumriken
Не думаю. Чем тебе чистая луа мешает? Она мелкая ))
Snusmumriken
Вообще как бы для этого делали SOL
Hello, World! 🎄
Hello, World! 🎄
Snusmumriken
Да юзеру скорее всего выдать описание.
Но достаточно дёрнуть луа вм без openlibs, и будет чистейшая луа без стандартной либы.
Ivan
Опа, кто ето тут у нас?
Это вы про меня? Да так, программист-системщик, захотелось вот с луа поиграться, посмотреть на возможности, может что интересного сделать
Snusmumriken
Да я как раз тыкаю тебя по D чату.
Ivan
Ivan
Igor
Александр
Мне вообще среду исполнения убрать хочется, полностью, т.е. хочется по сути использовать луа вместо xml, json, но чтобы даже в теории никогда не нужно было думать о вопросе безопасности и/или том, что например внутри такого файла есть бесконечный цикл
Igor
но эта фигнюшка вместе с LuaJIT идёт
Igor
для компиляции последнего используется
Igor
там многих библиотек нет, да и функций внутри имеющихся тоже
Snusmumriken
Snusmumriken
Или зарегай что тебе нужно. Или очисть _G полностью. Или сделай любую фигню.
Александр
Snusmumriken
Хмммм, тогда уже ужасно, придётся проверить на наличие кейвордов вроде function/while/for и т.д, причём именно кейвордов в идеале.
Александр
Snusmumriken
Насколько пользовательский код тут будет гоняться? Ты хочешь выдавать свой сервер с луа-конфигами юзерам? Или юзеры сами смогут разворачивать?
Snusmumriken
Если первое — наверное проще таки json, если второе — вообще наплевать.
Александр
Тут больше перестраховка и хотелка сделать такие порции данных совместимыми с луа
Snusmumriken
Есть ещё очень смешной вариант, перед запуском пользовательского кода, после каждого элемента цикла, ретурна или ещё чего-нибудь принудительно влепить coroutine.yield(), после чего дёргать обёрнутую в корутину функцию пока таймаут не вылезет. Заодно не будет мешать другому. И как бы весь основной функционал сохраняется, и даже если там что-то бесконечное — ваще пофигу.
Александр
Snusmumriken
Но прикольно и компромиссно ))
Lucky
https://redis.io/
jon
Всем привет, подскажите, как без боли работать с проектом на луа из нескольких файлов? Я что-то себя конченным ощущаю. Есть какой-то хитрый способ определить путь к желаемому файлу луа? Я играюсь уже часа 3, не могу прописать никак путь
Igor
jon
я ковыряясь в исходниках нашёл такую штуку как package.path, чтоб было проще. Но проблема в том, что адресация к файлам идёт не относительно конкретного файла
Igor
Допустим, есть у тебя папка myproject в ней есть файл main.lua и папка megascripts, в которой лежит файл test.lua. Чтобы получить к нему доступ из main.lua ты должен сделать require('megascripts.test')
jon
с этим понятно, а что делать вот в такой ситуации.
Вот как я понимаю путь к подключаемому модулю идёт относительно скрипта - точки входа. Но что тогда делать, когда есть проект, в этом проекте есть ещё тесты на луа, соответственно путь от запускаемого скрипта вечно плавает
jon
или я чего не понимаю?
Snusmumriken
Нет, относительно исполняемого файла (exe/elf).
Snusmumriken
Для путей к скрипту я дал кусок кода, просто вставь его в начало.
jon