Модуль:Ustring

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
Документация

Этот модуль предоставляет класс для работы со строками в кодировке Юникод так же просто, как с обычными строками. Он используется в других модулях, не в функции #invoke.

Пример использования

[править код]
local u = require('Module:Ustring')
local s = u.new('Хорошо живёт на свете %s!')
print(s:format('Винни-Пух')) --результат: Хорошо живёт на свете Винни-Пух!
print(s:format('Винни-Пух'):len()) --результат: 32

Конструктор new

[править код]
 local s = u.new( str )

Создаёт объект строки, идентичной строке str, но с другим набором методов.

Содержит исходную строку типа string.

Содержит конструктор, который применяется к строкам в результатах других функций. По умолчанию это конструктор new.

Обзор методов

[править код]

Наследуются все методы из стандартной библиотеки ustring, при этом к каждой строке в результатах применяется self.new. Метод gmatch переопределён так, что применяет конструктор ко всем результатам итератора; метод gcodepoint не переопределён и итерирует по точкам Unicode, которые возвращаются в цикл как значения типа string (если надо применять конструктор, используйте s:gmatch(".")).

Перегруженные операторы

[править код]

Конкатенация ..

[править код]

Объекты могут складываться между собой и с обычными строками, результат всегда объект.

Сравнение

[править код]

Сравнивать можно только объекты между собой. Для сравнения применяется функция u.strcmp, где u — объект, возвращённый require. Если переопределить эту функцию в этом объекте, все объекты ustring будут сравниваться иначе.

Индексация

[править код]

Вызов объекта с числовым ключом возвращает символ с данным номером (типа string):

print( (u.new('Привет!'))[7] ) -- результат: "!"

Ограничения

[править код]

Пока что метаметод __len не поддерживается Lua, поэтому вместо оператора #s надо писать s:len().

local function strcmp(a , b)--скопирована из Module:String, дабы не импортировать всё из-за неё
    local s1c = mw.ustring.gcodepoint( a );
    local s2c = mw.ustring.gcodepoint( b );
    while true do
        local c1 = s1c();
        local c2 = s2c();
        if c1 == nil then
            if c2 == nil then
                return 0
            else
                return -1
            end
        else
            if c2 ~= nil then
                if c1 ~= c2 then
                  return c1 < c2 and -1 or 1
              end
            else
                return 1
            end
        end
    end
    return 0
end

local M;

local mt={
    __index = function(self,key)
        if type(key)=='string' then
            return function(...)
                local args = {...}
                args[1] = rawget(self,'string')
                if key=='gmatch' then
                    local f = mw.ustring.gmatch(unpack(args));
                    return function(static,var)
                        local ret={f(static,var)}
                        for k,v in pairs(ret) do
                            if type(v)=='string' then
                                ret[k]=self.new(v)
                            end
                        end
                        return unpack(ret)
                    end
                else
                    args = {mw.ustring[key](unpack(args))}
                    for k,v in pairs(args) do
                        if type(v)=='string' then
                            args[k]=self.new(v)
                        end
                    end
                    return unpack(args)
                end
            end
        elseif type(key)=='number' then
            return mw.ustring.sub(rawget(self,'string'),key,key)
        else
            return nil
        end
    end;
    __concat = function(a,b) return (a.new or b.new)(tostring(a)..tostring(b)) end;-- плоховато, но обычно работает
    __tostring = function(self) return rawget(self,'string') end;
    -- Операторы сравнения, увы, работают только с двумя объектами одного класса
    -- Операцию сравнения можно перегрузить!
    __lt = function(a,b) return ({[-1]=true;[0]=false;[1]=false})[M.strcmp(tostring(a),tostring(b))] end;
    __le = function(a,b) return ({[-1]=true,[0]=true,[1]=false})[M.strcmp(tostring(a),tostring(b))] end;
    __eq = function(a,b) return ({[-1]=false,[0]=true,[1]=false})[M.strcmp(tostring(a),tostring(b))] end;
    __len = function(self) return self:len() end -- пока не работает в движке Lua
}

M = {
    strcmp = strcmp,
    new = function(s)
        local self={new=M.new,string=s}
        setmetatable(self,mt)
        return self
    end
}

return M