Skip to content

Latest commit

 

History

History
197 lines (176 loc) · 8.11 KB

Builtin-Lua-option-definitions.md

File metadata and controls

197 lines (176 loc) · 8.11 KB

This is the builtin Lua option definitions code as included in FA 0.11. You can find actual version of this code by running fa --print-config.

AddOptions{
    {'min_size', '-smBYTES --min-size=BYTES --SizeMore=BYTES', 'minimum filesize to process',
                    OPTION_BYTES,  function(min_size) AddFileFilter('size>='..min_size) end},
    {'max_size', '-slBYTES --max-size=BYTES --SizeLess=BYTES', 'maximum filesize to process',
                    OPTION_BYTES,  function(max_size) AddFileFilter('size<='..max_size) end},
    {'select_archive_bit', '-ao --select-archive-bit --SelectArchiveBit', "select only files with Archive bit set",
                    OPTION_BOOL, function() AddFileFilter('btest(attr,0x20)') end},
}

AddOption('include', '-nFILESPECS --include=FILESPECS', 'include only files matching FILESPECS',
OPTION_LIST,
function(filespecs)
    local filters  =  table.map (filespecs, function(filespec)  return string.format('string_match(name,%q)', wildcard2pattern(filespec))  end)
    AddFileFilter( '('..table.concat(filters,') or (')..')' )
end)

AddOption('exclude', '-xFILESPECS --exclude=FILESPECS', 'exclude FILESPECS from operation',
OPTION_LIST,
function(filespecs)
    for _,filespec in ipairs(filespecs) do
        AddFileFilter( string.format('not string_match(name,%q)', wildcard2pattern(filespec)) )
    end
end)

AddOption('filter', '-fEXPR --filter=EXPR', 'filter files by Lua expression employing vars name, type, size, time and attr',
OPTION_LIST,
function(filters)
    for _,filter in ipairs(filters) do
        if not string.match (' '..filter..' ', '[^%w_]return[^%w_]') then
            AddFileFilter(filter)
        else
            onFileFilter('function (name, type, size, time, attr); '..filter..'; end')
        end
    end
end)

AddOption('autogenerate', '-ag[FORMAT] --autogenerate=[FORMAT]', 'append to archive name string generated by strftime(FORMAT||"%Y%m%d%H%M%S")',
OPTION_STRING,
function(format)
    if format~='-' and format~='--' then
        local timestr   = os.date(format=='' and '%Y%m%d%H%M%S' or format)
        command.arcname = command.arcname .. timestr
    end
end)

AddOption('crc_only', '--crc-only --crconly', "save/check CRC, but don't store data",
OPTION_BOOL,
function()
    command.compression_groups  = {""}
    command.compression_methods = {CRC_ONLY_COMPRESSION}
end)

AddOption('large_page_mode', '-slpMODE', 'set large page mode (TRY(default), FORCE(+), DISABLE(-), MALLOC)',
OPTION_STRING,
function(mode)
    if mode==''  then mode = 'TRY' end
    if mode=='-' then mode = 'DISABLE' end
    if mode=='+' then mode = 'FORCE' end
    SetLargePageMode(mode)
end)

AddOption('prefetch', '--prefetch[PARAMS]', 'prefetching to the OS file cache (:1g:8 means read 1GB ahead using 8 threads)',
OPTION_STRING,
function(params)
    if params==''   then params = '2g:8' end
    if params=='-'  then params = '0' end
    for word in params:gmatch('([^:=/,;]+)') do
        local n = parse_num(word)
        if n then
            command.prefetch_threads = n
        else
            local size = parse_mem(word,'b')
            if size then
                command.prefetch_cache = size
            else
                return 'cannot parse "'..word..'" as number of threads or cache size'
            end
        end
    end
end)


--[[ **********************************************************************************************************************************
*** 'Method change (-mc)' option implementation****************************************************************************************
*************************************************************************************************************************************]]

AddOption('method_change', '-mcDIRECTIVE', 'modify compressor: [$group1,$group2][:]-$group,-algo,+algo,algo1/algo2',
-- Parsing function
function(param)
    local action

    --mcd-: replace rar-compatible abbreviated directives with longer explicit ones
    local rarAbbrevs = {d="-delta", e="-exe", l="-lzp", r="-rep", z="-dict", a="-$wav", c="-$bmp", t="-$text"}
    param = rarAbbrevs[param:match('^(%a)%-$')] or param

    -- Split param into list of groups and operation to perform on these groups
    local groups,operation = param:match('^:?($.-)([:+-].+)$')
    if not groups then
        groups = ''
        operation = param
    end

    --mc:lzma/lzma:max:512mb
    local old_compressor,new_compressor = operation:match('^:?(.+)/([^$].*)$')
    if old_compressor   then action = function(env) env.replace_compressor(groups,old_compressor,DecodeMethod(new_compressor)) end  else
    --mc+precomp+xtor
    local new_compressor = operation:match('^:?%+(.+)$') or operation:match('^:?(.+)%+$')
    if new_compressor   then action = function(env) env.add_compressor(groups,DecodeMethod(new_compressor)) end  else
    --mc-$wav,$bmp
    local old_groups = operation:match('^:?%-($.+)$') or operation:match('^:?($.+)%-$')
    if old_groups and (groups=='')  then action = function(env) env.remove_groups(old_groups) end  else
    --mc-rep,lzp
    local old_compressor = operation:match('^:?%-(.+)$') or operation:match('^:?(.+)%-$')
    if old_compressor   then action = function(env) env.remove_compressor(groups,old_compressor) end  else
    --unrecognized
    return 'Bad option format'
    end end end end

    optvalue.method_change = optvalue.method_change or {}
    table.insert (optvalue.method_change, action)
end,

-- Post-processing function
function()
    local cgroups, cmethods = command.compression_groups, command.compression_methods
    cgroups[1] = '$default'

    -- Filter cmethods[i] through f if cgroup[i] is in the `groups` list or the list is empty
    local function filter_methods (groups, f)
        for i,group in ipairs(cgroups) do
            if groups==""  or  group:in_list(groups) then
                cmethods[i] = f(cmethods[i],group)
            end
        end
    end

    -- Filter through the f each compressor in the `groups`
    local function filter_compressors (groups, f)
        filter_methods (groups, function (method)
            local cm = {}
            for old_compressor in string.gmatch(method, "[^+]+") do
                local name = string.match (old_compressor..':', '^([^:]*):')
                local new_compressor = f(name,old_compressor)
                if new_compressor ~= "" then
                    table.insert(cm, new_compressor or old_compressor)
                end
            end
            return table.concat(cm,'+')
        end)
    end

    local env = {}
    function env.add_compressor(groups,compressor)
        filter_methods (groups, function(method)  return compressor..'+'..method; end)
    end
    function env.replace_compressor(groups,old_names,new_compressor)
        filter_compressors (groups, function(name)  if name:in_list(old_names) then return new_compressor end end)
    end
    function env.remove_compressor(groups,names)
        --mc-grzip removes groups like $bmp=mm+grzip where "grzip" is the last compressor in the chain
        filter_methods (groups, function(method,group)
            local compressors = split_method(method)
            if #compressors>0  and  group~='$default' then
                local last_compressor_name = get_compressor_name(compressors[#compressors])
                if last_compressor_name:in_list(names) then
                    compressors = {}
                end
            end
            return join_method(compressors)
        end)
        --mc-grzip also removes grzip from middle of compression chain
        filter_compressors (groups, function(name)  if name:in_list(names) then return "" end end)
    end
    function env.remove_groups(groups)
        filter_methods (groups, function() return "" end)
    end

    -- Modify the compressor by executing code built at the parsing stage
    for _,directive in ipairs(optvalue.method_change or {}) do
        directive(env)
    end

    -- Remove groups whose compression method became empty
    local g,m = {},{}
    cgroups[1] = ''
    for i,method in ipairs(cmethods) do
        if method > "" then
            table.insert (g, cgroups[i])
            table.insert (m, cmethods[i])
        end
    end
    command.compression_groups, command.compression_methods = g,m
end)