From a254ac87f7bf9327d704e1630eabe2cd19057e17 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Sat, 15 Oct 2016 01:47:43 -0400 Subject: [PATCH 1/4] Created libraries from commonly used functions. Moved official/debug-helpers.lua into lib/dtutils/debug.lua. Created a logging library to provide various levels of logging. Documented all libraries and functions. Created tools to extract documentation in text, man page, and pdf formats. --- lib/dtutils.lua | 457 +++++++++++++++ .../de_DE/LC_MESSAGES/dtutils.processor.po | 23 + lib/dtutils/debug.lua | 219 ++++++++ lib/dtutils/extensions.lua | 185 +++++++ lib/dtutils/file.lua | 523 ++++++++++++++++++ lib/dtutils/processor.lua | 266 +++++++++ lib/libLog.lua | 378 +++++++++++++ official/debug-helpers.lua | 93 ---- tools/get_lib_manpages.lua | 63 +++ tools/get_libdoc.lua | 46 ++ 10 files changed, 2160 insertions(+), 93 deletions(-) create mode 100644 lib/dtutils.lua create mode 100644 lib/dtutils/de_DE/LC_MESSAGES/dtutils.processor.po create mode 100644 lib/dtutils/debug.lua create mode 100644 lib/dtutils/extensions.lua create mode 100644 lib/dtutils/file.lua create mode 100644 lib/dtutils/processor.lua create mode 100644 lib/libLog.lua delete mode 100644 official/debug-helpers.lua create mode 100644 tools/get_lib_manpages.lua create mode 100644 tools/get_libdoc.lua diff --git a/lib/dtutils.lua b/lib/dtutils.lua new file mode 100644 index 0000000..db2be0a --- /dev/null +++ b/lib/dtutils.lua @@ -0,0 +1,457 @@ +--[[ + + dtutils.lua - common darktable lua functions + + Copyright (C) 2016 Bill Ferguson . + Copyright (C) 2016 Tobias Jakobs + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +]] + +local dtutils = {} + +dtutils.libdoc = { + Sections = {"Name", "Synopsis", "Description", "See_Also", "License"}, + Name = [[dtutils - A Darktable lua utilities library]], + Synopsis = [[local du = require "lib/dtutils"]], + Description = [[dtutils provides a common library of functions used to build + lua scripts. There are also sublibraries that provide more functions.]], + See_Also = [[dtutils.debug(3), dtutils.extensionts(3), dtutils.file(3), dtutils.processor(3)]], + License = [[This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .]], + functions = {} +} + +local dt = require "darktable" + +local log = require "lib/libLog" + +dt.configuration.check_version(...,{3,0,0}) + +--[[ + NAME + split - split a string on a specified separator + + SYNOPSIS + local du = require "lib/dtutils" + + local result = du.split(str, pat) + str - string - the string to split + pat - string - the pattern to split on + + DESCRIPTION + split separates a string into a table of strings. The strings are separated at each + occurrence of the supplied pattern. + + RETURN VALUE + result - a table of strings on success, or an empty table on error + + EXAMPLE + split("/a/long/path/name/to/a/file.txt", "/") would return a table like + {"a", "long", "path", "name", "to", "a", "file.txt"} + +]] + +dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value", "Example"}, + Name = [[split - split a string on a specified separator]], + Synopsis = [[local du = require "lib/dtutils" + + local result = du.split(str, pat) + str - string - the string to split + pat - string - the pattern to split on]], + Description = [[split separates a string into a table of strings. The strings are separated at each + occurrence of the supplied pattern.]], + Return_Value = [[result - a table of strings on success, or an empty table on error]], + Example = [[split("/a/long/path/name/to/a/file.txt", "/") would return a table like + {"a", "long", "path", "name", "to", "a", "file.txt"}]], +} + +-- Thanks to http://lua-users.org/wiki/SplitJoin +function dtutils.split(str, pat) + local t = {} -- NOTE: use {n = 0} in Lua-5.0 + local fpat = "(.-)" .. pat + local last_end = 1 + local s, e, cap = str:find(fpat, 1) + while s do + if s ~= 1 or cap ~= "" then + table.insert(t,cap) + end + last_end = e+1 + s, e, cap = str:find(fpat, last_end) + end + if last_end <= #str then + cap = str:sub(last_end) + table.insert(t, cap) + end + return t +end + +--[[ + NAME + join - join a table of strings with a specified separator + + SYNOPSIS + local du = require "lib/dtutils" + + local result = du.join(tabl, pat) + tabl - a table of strings + pat - a separator + + DESCRIPTION + join assembles a table of strings into a string with the specified pattern + in between each string + + RETURN VALUE + result - the joined string on success, or an empty string on failure + + EXAMPLE + join({"a", "long", "path", "name", "to", "a", "file.txt"}, " ") would return the string + "a long path name to a file.txt" + +]] + +dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value", "Example"}, + Name = [[join - join a table of strings with a specified separator]], + Synopsis = [[local du = require "lib/dtutils" + + local result = du.join(tabl, pat) + tabl - a table of strings + pat - a separator]], + Description = [[join assembles a table of strings into a string with the specified pattern + in between each string]], + Return_Value = [[result - the joined string on success, or an empty string on failure]], + Example = [[join({"a", "long", "path", "name", "to", "a", "file.txt"}, " ") would return the string + "a long path name to a file.txt"]], +} + +-- Thanks to http://lua-users.org/wiki/SplitJoin +function dtutils.join(tabl, pat) + returnstr = "" + for i,str in pairs(tabl) do + returnstr = returnstr .. str .. pat + end + return string.sub(returnstr, 1, -(pat:len() + 1)) +end + +--[[ + NAME + prequire - a protected lua require + + SYNOPSIS + local du = require "lib/dtutils" + + local result = du.prequire(req_name) + req_name - the filename of the lua code to load without the ".lua" filetype + + DESCRIPTION + prequire is a protected require that can survive an error in the code being loaded without + bringing down the calling routine. + + RETURN VALUE + result - the code or true on success, otherwise an error message + + EXAMPLE + prequire("lib/dtutils.file") which would load lib/dtutils/file.lua + +]] + +dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value", "Example"}, + Name = [[prequire - a protected lua require]], + Synopsis = [[local du = require "lib/dtutils" + + local result = du.prequire(req_name) + req_name - the filename of the lua code to load without the ".lua" filetype]], + Description = [[prequire is a protected require that can survive an error in the code being loaded without + bringing down the calling routine.]], + Return_Value = [[result - the code or true on success, otherwise an error message]], + Example = [[prequire("lib/dtutils.file") which would load lib/dtutils/file.lua]], +} + +function dtutils.prequire(req_name) + local status, lib = pcall(require, req_name) + if status then + log.msg(log.info, "Loaded " .. req_name) + else + log.msg(log.info, "Error loading " .. req_name) + end + return lib +end + +--[[ + NAME + push - push a value on a stack + + SYNOPSIS + local du = require "lib/dtutils" + + du.push(stack, value) + stack - table - a table being used as the stack + value - any type - the value to be put on the stack + + DESCRIPTION + Push a value on a stack + + RETURN VALUE + none + +]] + +dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[push - push a value on a stack]], + Synopsis = [[local du = require "lib/dtutils" + + du.push(stack, value) + stack - table - a table being used as the stack + value - any type - the value to be put on the stack]], + Description = [[Push a value on a stack]], + Return_Value = [[none]], +} + +dtutils.push = table.insert + +--[[ + NAME + pop - pop a value from a stack + + SYNOPSIS + local du = require "lib/dtutils" + + local result = du.pop(stack) + stack - table - a table being used as a stack + + DESCRIPTION + Remove the last value pushed on the stack and return it + + RETURN VALUE + result = nil if stack isn't a table or the stack is empty, otherwise the value removed from the stack + +]] + +dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[pop - pop a value from a stack]], + Synopsis = [[local du = require "lib/dtutils" + + local result = du.pop(stack) + stack - table - a table being used as a stack]], + Description = [[Remove the last value pushed on the stack and return it]], + Return_Value = [[result = nil if stack isn't a table or the stack is empty, otherwise the value removed from the stack]], +} + +dtutils.pop = table.remove + +--[[ + NAME + update_combobox_choices - change the list of choices in a combobox + + SYNOPSIS + local du = require "lib/dtutils" + + du.update_combobox_choices(combobox_widget, choice_table) + combobox_widget - lua_combobox - a combobox widget + choice_table - table - a table of strings for the combobox choices + + DESCRIPTION + Set the combobox choices to the supplied list. Remove any extra choices from the end + + RETURN VALUE + none + +]] + +dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[update_combobox_choices - change the list of choices in a combobox]], + Synopsis = [[local du = require "lib/dtutils" + + du.update_combobox_choices(combobox_widget, choice_table) + combobox_widget - lua_combobox - a combobox widget + choice_table - table - a table of strings for the combobox choices]], + Description = [[Set the combobox choices to the supplied list. Remove any extra choices from the end]], + Return_Value = [[none]], +} + +function dtutils.update_combobox_choices(combobox, choice_table) + local items = #combobox + local choices = #choice_table + for i, name in ipairs(choice_table) do + log.msg(log.debug, "Setting choice " .. i .. " to " .. name) + combobox[i] = name + end + if choices < items then + for j = items, choices + 1, -1 do + log.msg(log.debug, "Removing choice " .. j) + combobox[j] = nil + end + end + combobox.value = 1 +end + +--[[ + NAME + spairs - an iterator that provides sorted pairs from a table + + SYNOPSIS + local du = require "lib/dtutils" + + for key, value in du.spairs(t, order) do + t - table - table of key, value pairs + order - function - an optional function to sort the pairs + if none is supplied, table.sort() is used + + DESCIRPTION + spairs is an iterator that returns key, value pairs from a table in sorted + order. The sorting order is the result of table.sort() if no function is + supplied, otherwise sorting is done as specified in the function. + + EXAMPLE + HighScore = { Robin = 8, Jon = 10, Max = 11 } + + -- basic usage, just sort by the keys + for k,v in spairs(HighScore) do + print(k,v) + end + --> Jon 10 + --> Max 11 + --> Robin 8 + + -- this uses an custom sorting function ordering by score descending + for k,v in spairs(HighScore, function(t,a,b) return t[b] < t[a] end) do + print(k,v) + end + --> Max 11 + --> Jon 10 + --> Robin 8 + + REFERENCE + Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua + +]] + +dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Example", "Reference"}, + Name = [[spairs - an iterator that provides sorted pairs from a table]], + Synopsis = [[local du = require "lib/dtutils" + + for key, value in du.spairs(t, order) do + t - table - table of key, value pairs + order - function - an optional function to sort the pairs + if none is supplied, table.sort() is used]], + Description = [[spairs is an iterator that returns key, value pairs from a table in sorted + order. The sorting order is the result of table.sort() if no function is + supplied, otherwise sorting is done as specified in the function.]], + Example = [[HighScore = { Robin = 8, Jon = 10, Max = 11 } + + -- basic usage, just sort by the keys + for k,v in spairs(HighScore) do + print(k,v) + end + --> Jon 10 + --> Max 11 + --> Robin 8 + + -- this uses an custom sorting function ordering by score descending + for k,v in spairs(HighScore, function(t,a,b) return t[b] < t[a] end) do + print(k,v) + end + --> Max 11 + --> Jon 10 + --> Robin 8]], + Reference = [[Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua]], +} + +-- Sort a table +function dtutils.spairs(_table, order) -- Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua + -- collect the keys + local keys = {} + for _key in pairs(_table) do keys[#keys + 1] = _key end + + -- if order function given, sort by it by passing the table and keys a, b, + -- otherwise just sort the keys + if order then + table.sort(keys, function(a,b) return order(_table, a, b) end) + else + table.sort(keys) + end + + -- return the iterator function + local i = 0 + return function() + i = i + 1 + if keys[i] then + return keys[i], _table[keys[i]] + end + end +end + +--[[ + + NAME + urlencode - encode a string in a websage manner + + SYNOPOIS + local du = require "lib/dtutils" + + local result = du.urlencode(str) + str - string - the string that needs to be made websafe + + DESCRIPTION + urlencode converts a string into a websafe version suitable for + use in a web browser. + + RETURN_VALUE + result - string - a websafe string + + REFERENCE + https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/ + +]] + +dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value", "Reference"}, + Name = [[urlencode - encode a string in a websage manner]], + Synopsis = [[local du = require "lib/dtutils" + + local result = du.urlencode(str) + str - string - the string that needs to be made websafe]], + Description = [[urlencode converts a string into a websafe version suitable for + use in a web browser.]], + Return_Value = [[result - string - a websafe string]], + Reference = [[https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/]], +} + +function dtutils.urlencode(str) + if (str) then + str = string.gsub (str, "\n", "\r\n") + str = string.gsub (str, "([^%w ])", function () return string.format ("%%%02X", string.byte()) end) + str = string.gsub (str, " ", "+") + end + return str +end + +return dtutils diff --git a/lib/dtutils/de_DE/LC_MESSAGES/dtutils.processor.po b/lib/dtutils/de_DE/LC_MESSAGES/dtutils.processor.po new file mode 100644 index 0000000..ba35c0d --- /dev/null +++ b/lib/dtutils/de_DE/LC_MESSAGES/dtutils.processor.po @@ -0,0 +1,23 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-10-01 00:36-0400\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: dtutils.processor.lua:42 +#, lua-format +msgid "Export Image %i/%i" +msgstr "Exportiere Bild %i/%i" diff --git a/lib/dtutils/debug.lua b/lib/dtutils/debug.lua new file mode 100644 index 0000000..767d86f --- /dev/null +++ b/lib/dtutils/debug.lua @@ -0,0 +1,219 @@ +--[[ +This file is part of darktable, +copyright (c) 2014 Jérémy Rosen + +darktable is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +darktable is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with darktable. If not, see . +]] +--[[ +DEBUG HELPERS +A collection of helper functions to help debugging lua scripts. + +require it as + +dhelpers = require "official/debug-helpers" + +Each function is documented in its own header + + +]] + + +local dt = require "darktable" +local io = require "io" +local table = require "table" +require "darktable.debug" +local log = require "lib/libLog" +local M = {} -- The actual content of the module + +M.libdoc = { + Sections = {"Name", "Synopsis", "Description", "License"}, + Name = [[dtutils.debug - debugging helpers used in developing darktable lua scripts]], + Synopsis = [[local dd = require "lib/dtutils.debug"]], + Description = [[dtutils.debug provides an interface to the darktable debugging routines.]], + License = [[This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .]], + functions = {} +} + +--[[ + NAME + tracepoint - print out a tracepoint and dump the arguments + + SYNOPSIS + local dd = require "lib/dtutils.debug" + + local result = tracepoint(name, ...) + name - string - the name of the tracepoint to print out + ... - arguments - variables to dump the contents of + + DESCRIPTION + tracepoint prints its name and dumps its parameters using + dt.debug + + RETURN VALUE + result - ... - the supplied argument list + +]] + +M.libdoc.functions[#M.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[tracepoint - print out a tracepoint and dump the arguments]], + Synopsis = [[local dd = require "lib/dtutils.debug" + + local result = tracepoint(name, ...) + name - string - the name of the tracepoint to print out + ... - arguments - variables to dump the contents of]], + Description = [[tracepoint prints its name and dumps its parameters using + dt.debug]], + Return_Value = [[result - ... - the supplied argument list]], +} + +function M.tracepoint(name,...) + log.always(4, "***** "..name.." ****") + params = {...} + print(dt.debug.dump(params,"parameters")) + return ...; +end + + + +--[[ + NAME + new_tracepoint - create a function returning a tracepoint + + SYNOPSIS + local dd = require "lib/dtutils.debug" + + local result = new_tracepoint(name, ...) + name - string - the name of the tracepoint to print out + ... - arguments - variables to dump the contents of + + + DESCRIPTION + A function that returns a tracepoint function with the given name + This is mainly used to debug callbacks. + + RETURN VALUE + result - function - a function that returns the result of a tracepoint + + EXAMPLE + register_event(event, dd.new_tracepoint("hit callback")) + + will print the following each time the callback is called + + **** hit callback **** + + +]] + +M.libdoc.functions[#M.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value", "Example"}, + Name = [[new_tracepoint - create a function returning a tracepoint]], + Synopsis = [[local dd = require "lib/dtutils.debug" + + local result = new_tracepoint(name, ...) + name - string - the name of the tracepoint to print out + ... - arguments - variables to dump the contents of]], + Description = [[A function that returns a tracepoint function with the given name + This is mainly used to debug callbacks.]], + Return_Value = [[result - function - a function that returns the result of a tracepoint]], + Example = [[register_event(event, dd.new_tracepoint("hit callback")) + + will print the following each time the callback is called + + **** hit callback **** + ]], +} + +function M.new_tracepoint(name) + return function(...) return M.tracepoint(name,...) end +end + + +--[[ + NAME + dprint - pass a variable to dt.debug.dump and print the results to stdout + + SYNOPSIS + local dd = require "lib/dtutils.debug" + + dd.dprint(var) + var - variable - any variable that you want to see the contents of + + DESCRIPTION + Wrapper around debug.dump, will directly print to stdout, + same calling convention + +]] + +M.libdoc.functions[#M.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description"}, + Name = [[dprint - pass a variable to dt.debug.dump and print the results to stdout]], + Synopsis = [[local dd = require "lib/dtutils.debug" + + dd.dprint(var) + var - variable - any variable that you want to see the contents of]], + Description = [[Wrapper around debug.dump, will directly print to stdout, + same calling convention]], +} + +function M.dprint(...) + log.always(4, dt.debug.dump(...)) +end + +--[[ + NAME + terse_dump - set dt.debug.known to shorten all image dumps to a single line + + SYNOPSIS + local dd = require "lib/dtutils.debug" + + dd.terse_dump() + + DESCRIPTION + terse_dump sets dt.debug.known to shorten all images to a single line. + If you don't need to debug the content of images, this will avoid them flooding your logs +]] + +M.libdoc.functions[#M.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description"}, + Name = [[terse_dump - set dt.debug.known to shorten all image dumps to a single line]], + Synopsis = [[local dd = require "lib/dtutils.debug" + + dd.terse_dump()]], + Description = [[terse_dump sets dt.debug.known to shorten all images to a single line. + If you don't need to debug the content of images, this will avoid them flooding your logs]], +} + +function M.terse_dump() + for _,v in ipairs(dt.database) do + dt.debug.known[v] = tostring(v) + end +end + + + +return M +-- vim: shiftwidth=2 expandtab tabstop=2 cindent +-- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on; diff --git a/lib/dtutils/extensions.lua b/lib/dtutils/extensions.lua new file mode 100644 index 0000000..ca37152 --- /dev/null +++ b/lib/dtutils/extensions.lua @@ -0,0 +1,185 @@ +--[[ + + NAME + dtutils/extensions.lua - a library of extenstions to the lua libraries + + SYNOPSIS + require "lib/dtutils.extensions" + + DESCRIPTION + This library contains extensions to the lua libraries. + +]] + +local dtutils_extensions = {} +dtutils_extensions.libdoc = { + Sections = {"Name", "Synopsis", "Description", "License"}, + Name = "dtutils.extensions - a library of extenstions to the lua libraries", + Synopsis = [[require "lib/dtutils.extensions"]], + Description = [[This library contains extensions to the lua libraries.]], + License = [[This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .]], + functions = {} +} + +--[[ + + NAME + string.strip_accents - strip accents from characters + + SYNOPSIS + require "lib/dtutils.extensions" + + result = string.strip_accents(str) + str - string - the string with characters that need accents removed + + DESCRIPTION + strip_accents removes accents from accented characters returning the + unaccented character. + + RETURN VALUE + result - string - the string containing unaccented characters + +]] + +dtutils_extensions.libdoc.functions[#dtutils_extensions.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[string.strip_accents - strip accents from characters]], + Synopsis = [[require "lib/dtutils.extensions" + + result = string.strip_accents(str) + str - string - the string with characters that need accents removed]], + Description = [[strip_accents removes accents from accented characters returning the + unaccented character.]], + Return_Value = [[result - string - the string containing unaccented characters]], +} + +-- Strip accents from a string +-- Copied from https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/ +function string.strip_accents( str ) + local tableAccents = {} + tableAccents["à"] = "a" + tableAccents["á"] = "a" + tableAccents["â"] = "a" + tableAccents["ã"] = "a" + tableAccents["ä"] = "a" + tableAccents["ç"] = "c" + tableAccents["è"] = "e" + tableAccents["é"] = "e" + tableAccents["ê"] = "e" + tableAccents["ë"] = "e" + tableAccents["ì"] = "i" + tableAccents["í"] = "i" + tableAccents["î"] = "i" + tableAccents["ï"] = "i" + tableAccents["ñ"] = "n" + tableAccents["ò"] = "o" + tableAccents["ó"] = "o" + tableAccents["ô"] = "o" + tableAccents["õ"] = "o" + tableAccents["ö"] = "o" + tableAccents["ù"] = "u" + tableAccents["ú"] = "u" + tableAccents["û"] = "u" + tableAccents["ü"] = "u" + tableAccents["ý"] = "y" + tableAccents["ÿ"] = "y" + tableAccents["À"] = "A" + tableAccents["Á"] = "A" + tableAccents["Â"] = "A" + tableAccents["Ã"] = "A" + tableAccents["Ä"] = "A" + tableAccents["Ç"] = "C" + tableAccents["È"] = "E" + tableAccents["É"] = "E" + tableAccents["Ê"] = "E" + tableAccents["Ë"] = "E" + tableAccents["Ì"] = "I" + tableAccents["Í"] = "I" + tableAccents["Î"] = "I" + tableAccents["Ï"] = "I" + tableAccents["Ñ"] = "N" + tableAccents["Ò"] = "O" + tableAccents["Ó"] = "O" + tableAccents["Ô"] = "O" + tableAccents["Õ"] = "O" + tableAccents["Ö"] = "O" + tableAccents["Ù"] = "U" + tableAccents["Ú"] = "U" + tableAccents["Û"] = "U" + tableAccents["Ü"] = "U" + tableAccents["Ý"] = "Y" + + local normalizedString = "" + + for strChar in string.gmatch(str, "([%z\1-\127\194-\244][\128-\191]*)") do + if tableAccents[strChar] ~= nil then + normalizedString = normalizedString..tableAccents[strChar] + else + normalizedString = normalizedString..strChar + end + end + + return normalizedString + +end + +--[[ + + NAME + string.escape_xml_characters - escape characters for xml documents + + SYNOPSIS + require "lib/dtutils.extensions" + + result = string.escape_xml_characters(str) + str - string - the string that needs escaped + + DESCRIPTION + escape_xml_characters provides the escape sequences for + "&", '"', "'", "<", and ">" with the corresponding "&", + """, "'", "<", and ">". + + RETURNN VALUE + result - string - the string containing escapes for the xml characters + +]] + +dtutils_extensions.libdoc.functions[#dtutils_extensions.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = "string.escape_xml_characters - escape characters for xml documents", + Synopsis = [[ require "lib/dtutils.extensions" + + result = string.escape_xml_characters(str) + str - string - the string that needs escaped]], + Description = [[escape_xml_characters provides the escape sequences for + "&", '"', "'", "<", and ">" with the corresponding "&", + """, "'", "<", and ">".]], + Return_Value = [[result - string - the string containing escapes for the xml characters]], +} + +-- Escape XML characters +-- Keep & first, otherwise it will double escape other characters +-- https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents +function string.escape_xml_characters( str ) + + str = string.gsub(str,"&", "&") + str = string.gsub(str,"\"", """) + str = string.gsub(str,"'", "'") + str = string.gsub(str,"<", "<") + str = string.gsub(str,">", ">") + + return str +end + +return dtutils_extensions diff --git a/lib/dtutils/file.lua b/lib/dtutils/file.lua new file mode 100644 index 0000000..ebeba68 --- /dev/null +++ b/lib/dtutils/file.lua @@ -0,0 +1,523 @@ +--[[ + + dtutils/file.lua - common darktable lua file functions + + Copyright (C) 2016 Bill Ferguson . + Copyright (C) 2016 Tobias Jakobs + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +]] + +local dtutils_file = {} +dtutils_file.libdoc = { + Sections = {"Name", "Synopsis", "Description", "License"}, + Name = [[dtutils.file - common darktable lua file functions]], + Synopsis = [[local df = require "lib/dtutils.file"]], + Description = [[dtutils.file provides common file manipulation functions used in + constructing Darktable lua scripts]], + License = [[This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .]], + functions = {} +} + +local dt = require "darktable" + +local log = require "lib/libLog" + +local gettext = dt.gettext + +dt.configuration.check_version(...,{3,0,0}) + +-- Tell gettext where to find the .mo file translating messages for a particular domain +gettext.bindtextdomain("dtutils.file",dt.configuration.config_dir.."/lua/locale/") + +local function _(msgid) + return gettext.dgettext("dtutils.file", msgid) +end + +--[[ + NAME + check_if_bin_exists - check if an executable is in the path + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.check_if_bin_exists(bin) + bin - string - the binary to check for + + DESCRIPTION + check_if_bin_exists checks to see if the specified binary executable is + in the path. + + RETURN VALUE + result - boolean - true if the executable was found, false if not + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[check_if_bin_exists - check if an executable is in the path]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.check_if_bin_exists(bin) + bin - string - the binary to check for]], + Description = [[check_if_bin_exists checks to see if the specified binary executable is + in the path.]], + Return_Value = [[result - boolean - true if the executable was found, false if not]], +} + +function dtutils_file.check_if_bin_exists(bin) + local result = os.execute("which " .. bin) + if not result then + result = false + end + return result +end + +--[[ + NAME + split_filepath - split a filepath into parts + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.split_filepath(filepath) + filepath - string - path and filename + + DESCRIPTION + split_filepath splits a filepath into the path, filename, basename and filetype and puts + that in a table + + RETURN VALUE + result - table - a table containing the path, filename, basename, and filetype + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[split_filepath - split a filepath into parts]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.split_filepath(filepath) + filepath - string - path and filename]], + Description = [[split_filepath splits a filepath into the path, filename, basename and filetype and puts + that in a table]], + Return_Value = [[result - table - a table containing the path, filename, basename, and filetype]], +} + +function dtutils_file.split_filepath(str) + local result = {} + -- Thank you Tobias Jakobs for the awesome regular expression, which I tweaked a little + result["path"], result["filename"], result["basename"], result["filetype"] = string.match(str, "(.-)(([^\\/]-)%.?([^%.\\/]*))$") + return result +end + +--[[ + NAME + get_path - get the path from a file path + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.get_path(filepath) + filepath - string - path and filename + + DESCRIPTION + get_path strips the filename and filetype from a path and returns the path + + RETURN VALUE + result - string - the path + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[get_path - get the path from a file path]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.get_path(filepath) + filepath - string - path and filename]], + Description = [[get_path strips the filename and filetype from a path and returns the path]], + Return_Value = [[result - string - the path]], +} + +function dtutils_file.get_path(str) + local parts = dtutils_file.split_filepath(str) + return parts["path"] +end + +--[[ + NAME + get_filename - get the filename and extension from a file path + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.get_filename(filepath) + filepath - string - path and filename + + DESCRIPTION + get_filename strips the path from a filepath and returns the filename + + RETURN VALUE + result - string - the file name and type + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[get_filename - get the filename and extension from a file path]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.get_filename(filepath) + filepath - string - path and filename]], + Description = [[get_filename strips the path from a filepath and returns the filename]], + Return_Value = [[result - string - the file name and type]], +} + +function dtutils_file.get_filename(str) + local parts = dtutils_file.split_filepath(str) + return parts["filename"] +end + +--[[ + NAME + get_basename - get the filename without the path or extension + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.get_basename(filepath) + filepath - string - path and filename + + DESCRIPTION + get_basename returns the name of the file without the path or filetype + + RETURN VALUE + result - string - the basename of the file + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[get_basename - get the filename without the path or extension]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.get_basename(filepath) + filepath - string - path and filename]], + Description = [[get_basename returns the name of the file without the path or filetype]], + Return_Value = [[result - string - the basename of the file]], +} + +function dtutils_file.get_basename(str) + local parts = dtutils_file.split_filepath(str) + return parts["basename"] +end + +--[[ + NAME + get_filetype - get the filetype from a filename + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.get_filetype(filepath) + filepath - string - path and filename + + DESCRIPTION + get_filetype returns the filetype from the supplied filepath + + RETURN VALUE + result - string - the filetype + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[get_filetype - get the filetype from a filename]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.get_filetype(filepath) + filepath - string - path and filename]], + Description = [[get_filetype returns the filetype from the supplied filepath]], + Return_Value = [[result - string - the filetype]], +} + +function dtutils_file.get_filetype(str) + local parts = dtutils_file.split_filepath(str) + return parts["filetype"] +end + +--[[ + NAME + check_if_file_exists - check if a file or path exist + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.check_if_file_exists(filepath) + filepath - string - a file or path to check + + DESCRIPTION + check_if_file_exists checks to see if a file or path exists + + RETURN VALUE + result - boolean - true if the file or path exists, false if it doesn't + +]] + +-- Thanks Tobias Jakobs for the idea +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[check_if_file_exists - check if a file or path exist]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.check_if_file_exists(filepath) + filepath - string - a file or path to check]], + Description = [[check_if_file_exists checks to see if a file or path exists]], + Return_Value = [[result - boolean - true if the file or path exists, false if it doesn't]], +} + +function dtutils_file.check_if_file_exists(filepath) + local result = os.execute("test -e " .. filepath) + if not result then + result = false + end + return result +end + +--[[ + NAME + chop_filetype - remove a filetype from a filename + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.chop_filetype(path) + path - string - a filename with or without a path + + DESCRIPTION + chop_filetype removes the filetype from the filename + + RETURN VALUE + result - string - the path and filename without the filetype + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[chop_filetype - remove a filetype from a filename]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.chop_filetype(path) + path - string - a filename with or without a path]], + Description = [[chop_filetype removes the filetype from the filename]], + Return_Value = [[result - string - the path and filename without the filetype]], +} + +function dtutils_file.chop_filetype(path) + local length = dtutils_file.get_filetype(path):len() + 2 + return string.sub(path, 1, -length) +end + +--[[ + NAME + file_copy - copy a file to another name/location + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.file_copy(fromFile, toFile) + fromFile - string - name of file to copy from + toFile - string - name of file to copy to + + DESCRIPTION + copy a file using a succession of methods from operating system + to a pure lua solution + + RETURN VALUE + result - boolean - nil on error, true on success + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[file_copy - copy a file to another name/location]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.file_copy(fromFile, toFile) + fromFile - string - name of file to copy from + toFile - string - name of file to copy to]], + Description = [[copy a file using a succession of methods from operating system + to a pure lua solution]], + Return_Value = [[result - boolean - nil on error, true on success]], +} + +function dtutils_file.file_copy(fromFile, toFile) + local result = nil + -- if cp exists, use it + if dtutils_file.check_if_bin_exists("cp") then + result = os.execute("cp '" .. fromFile .. "' '" .. toFile .. "'") + end + -- if cp was not present, or if cp failed, then a pure lua solution + if not result then + local fileIn, err = io.open(fromFile, 'rb') + if fileIn then + local fileOut, errr = io.open(toFile, 'w') + if fileOut then + local content = fileIn:read(4096) + while content do + fileOut:write(content) + content = fileIn:read(4096) + end + result = true + fileIn:close() + fileOut:close() + else + log.msg(log.error, errr) + end + else + log.msg(log.error, err) + end + end + return result +end + +--[[ + NAME + file_move - move a file from one directory to another + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.file_move(fromFile, toFile) + fromFile - string - name of the original file + toFile - string - the new file location and name + + DESCRIPTION + Move a file from one place to another. Try a succession of methods from + builtin to operating system to a pure lua solution. + + RETURN VALUE + result - boolean - nil on error, some value on success + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[file_move - move a file from one directory to another]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.file_move(fromFile, toFile) + fromFile - string - name of the original file + toFile - string - the new file location and name]], + Description = [[Move a file from one place to another. Try a succession of methods from + builtin to operating system to a pure lua solution.]], + Return_Value = [[result - boolean - nil on error, some value on success]], +} + +function dtutils_file.file_move(fromFile, toFile) + local success = os.rename(fromFile, toFile) + if not success then + -- an error occurred, so let's try using the operating system function + if dtutils_file.check_if_bin_exists("mv") then + success = os.execute("mv '" .. fromFile .. "' '" .. toFile .. "'") + end + -- if the mv didn't exist or succeed, then... + if not success then + -- pure lua solution + success = dtutils_file.file_copy(fromFile, toFile) + if success then + os.remove(fromFile) + else + log.msg(log.error, "Unable to move " .. fromFile .. " to " .. toFile .. ". Leaving " .. fromFile .. " in place.") + end + end + end + return success -- nil on error, some value if success +end + +--[[ + NAME + filename_increment - add a two digit increment to a filename + + SYNOPSIS + local df = require "lib/dtutils.file" + + local result = df.filename_increment(filepath) + filepath - string - filename to increment + + DESCRIPTION + filename_increment solves the problem of filename confllict by adding an + increment to the filename. If the supplied filename has no increment then + "01" is added to the basename. If the filename already has an increment, then + 1 is added to it and the filename returned. + + RETURN VALUE + result - string - the incremented filename + +]] + +dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[filename_increment - add a two digit increment to a filename]], + Synopsis = [[local df = require "lib/dtutils.file" + + local result = df.filename_increment(filepath) + filepath - string - filename to increment]], + Description = [[filename_increment solves the problem of filename confllict by adding an + increment to the filename. If the supplied filename has no increment then + "01" is added to the basename. If the filename already has an increment, then + 1 is added to it and the filename returned.]], + Return_Value = [[result - string - the incremented filename]], +} + +function dtutils_file.filename_increment(filepath) + + -- break up the filepath into parts + local path = dtutils_file.get_path(filepath) + local basename = dtutils_file.get_basename(filepath) + local filetype = dtutils_file.get_filetype(filepath) + + -- check to see if we've incremented before + local increment = string.match(basename, "_(%d-)$") + + if increment then + -- we do 2 digit increments so make sure we didn't grab part of the filename + if string.len(increment) > 2 then + -- we got the filename so set the increment to 01 + increment = "01" + else + increment = string.format("%02d", tonumber(increment) + 1) + basename = string.gsub(basename, "_(%d-)$", "") + end + else + increment = "01" + end + local incremented_filepath = path .. basename .. "_" .. increment .. "." .. filetype + + return incremented_filepath +end + +return dtutils_file diff --git a/lib/dtutils/processor.lua b/lib/dtutils/processor.lua new file mode 100644 index 0000000..b79e0b9 --- /dev/null +++ b/lib/dtutils/processor.lua @@ -0,0 +1,266 @@ +--[[ + This file is part of darktable, + copyright (c) 2016 Bill Ferguson + + darktable is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + darktable is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with darktable. If not, see . +]] + +local dtutils_processor = {} + +dtutils_processor.libdoc = { + Sections = {"Name", "Synopsis", "Description", "License"}, + Name = [[dtutils.processor - Darktable lua functions for building processor scripts]], + Synopsis = [[local dp = require "lib/dtutils.processor"]], + Description = [[dtutils.processor provides common functions used for building scripts + that send images out to an external process, process them, and return the result (i.e. processors).]], + License = [[This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .]], + functions = {} +} + +local dt = require "darktable" +local dtutils = require "lib/dtutils" +local df = require "lib/dtutils.file" +local log = require "lib/libLog" + +local gettext = dt.gettext + +dt.configuration.check_version(...,{3,0,0}) + +-- Tell gettext where to find the .mo file translating messages for a particular domain +-- This should be $HOME/.config/darktable/lua/locale/ +gettext.bindtextdomain("dtutils",dt.configuration.config_dir.."/lua/locale/") + +local function _(msgid) + return gettext.dgettext("dtutils.processor", msgid) +end + +--[[ + NAME + exporter_status - show the status while exporting images + + SYNOPSIS + local dp = require "lib/dtutils.processor" + + local result = dp.exporter_status(storage, image, format, filename, number, total, high_quality, extra_data) + storage - dt_imageio_module_storage_t - the storage that the status is being shown for + image - dt_lua_image_t - the current image + format - dt_imageio_module_format_t - the format of the export image + filename - string - the filename being exported to + number - integer - the number of this image in the sequence + total - integer - the total number of images being exported + high_quality - boolean + extra_data - extra data from the storage + + DESCRIPTION + exporter_status runs prior to each image being exported and prints out a status that lets the user + know how many images, out of the total, have been exported + + RETURN VALUE + none + +]] + +dtutils_processor.libdoc.functions[#dtutils_processor.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[exporter_status - show the status while exporting images]], + Synopsis = [[local dp = require "lib/dtutils.processor" + + local result = dp.exporter_status(storage, image, format, filename, number, total, high_quality, extra_data) + storage - dt_imageio_module_storage_t - the storage that the status is being shown for + image - dt_lua_image_t - the current image + format - dt_imageio_module_format_t - the format of the export image + filename - string - the filename being exported to + number - integer - the number of this image in the sequence + total - integer - the total number of images being exported + high_quality - boolean + extra_data - extra data from the storage]], + Description = [[exporter_status runs prior to each image being exported and prints out a status that lets the user + know how many images, out of the total, have been exported]], + Return_Value = [[none]], +} + +function dtutils_processor.exporter_status(storage, image, format, filename, + number, total, high_quality, extra_data) + dt.print(string.format(_("Export Image %i/%i"), number, total)) +end + +--[[ + NAME + extract_image_list - assemble the exported image filenames from an image_table into a string + + SYNOPSIS + local dp = require "lib/dtutils.processor" + + result = dp.extract_image_list(image_table) + image_table - table - a table of images such as supplied by the exporter or by libPlugin.build_image_table + + DESCRIPTION + extract_image_list concatenates the exported image names into a space separated string suitable for + passing as an argument to a processor. Each filename is bracketed with single quotes to protect against + spaces and special characters in the filepath + + RETURN VALUE + result - string - the assembled image list on success, or an empty image list on error + +]] + +dtutils_processor.libdoc.functions[#dtutils_processor.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[extract_image_list - assemble the exported image filenames from an image_table into a string]], + Synopsis = [[local dp = require "lib/dtutils.processor" + + result = dp.extract_image_list(image_table) + image_table - table - a table of images such as supplied by the exporter or by libPlugin.build_image_table]], + Description = [[extract_image_list concatenates the exported image names into a space separated string suitable for + passing as an argument to a processor. Each filename is bracketed with single quotes to protect against + spaces and special characters in the filepath]], + Return_Value = [[result - string - the assembled image list on success, or an empty image list on error]], +} + +function dtutils_processor.extract_image_list(image_table) + local img_list = "" + for _,exp_img in pairs(image_table) do + img_list = img_list .. " " .. "'" .. exp_img .. "'" + end + return img_list +end + +--[[ + NAME + extract_collection_path - extract the collection path from an image table + + SYNOPSIS + local dp = require "lib/dtutils.processor" + + local result = dp.extract_collection_path(image_table) + image_table - table - a table of images such as supplied by the exporter or by libPlugin.build_image_table + + DESCRIPTION + extract_collection_path looks at the first image in the image_table and returns the path + + RETURN VALUE + result - string - the collection path on success, or nil if there was an error + + LIMITATIONS + The collection path is determined from the first image. If the table consists of images from different + collections, then only the first collection is used. + +]] + +dtutils_processor.libdoc.functions[#dtutils_processor.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value", "Limitations"}, + Name = [[extract_collection_path - extract the collection path from an image table]], + Synopsis = [[local dp = require "lib/dtutils.processor" + + local result = dp.extract_collection_path(image_table) + image_table - table - a table of images such as supplied by the exporter or by libPlugin.build_image_table]], + Description = [[extract_collection_path looks at the first image in the image_table and returns the path]], + Return_Value = [[result - string - the collection path on success, or nil if there was an error]], + Limitations = [[The collection path is determined from the first image. If the table consists of images from different + collections, then only the first collection is used.]], +} + +function dtutils_processor.extract_collection_path(image_table) + collection_path = nil + for i,_ in pairs(image_table) do + collection_path = i.path + break + end + return collection_path +end + +--[[ + NAME + make_output_filename- make an output filename from an image list + + SYNOPSIS + local dp = require "lib/dtutils.processor" + + local result = dtutils.make_output_filename(img_list) + img_list - string - a space separated list of filenames + + DESCRIPTION + make_output_filename takes a string of filenames, breaks them apart, then + combines them in a way that makes some sense. This is useful in routines + that do panoramas, hdr, or focus stacks. The returned filename is a representation + of the files used to construct the image. If there are 3 or fewer images, then the file + basenames are concatenated with a separator. If there is more than 3 images, the first and + last file basenames are concatenated with a separator. + + RETURN VALUE + result - string - the constructed filename on success, nil on error + +]] + +dtutils_processor.libdoc.functions[#dtutils_processor.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[make_output_filename- make an output filename from an image list]], + Synopsis = [[local dp = require "lib/dtutils.processor" + + local result = dtutils.make_output_filename(img_list) + img_list - string - a space separated list of filenames]], + Description = [[make_output_filename takes a string of filenames, breaks them apart, then + combines them in a way that makes some sense. This is useful in routines + that do panoramas, hdr, or focus stacks. The returned filename is a representation + of the files used to construct the image. If there are 3 or fewer images, then the file + basenames are concatenated with a separator. If there is more than 3 images, the first and + last file basenames are concatenated with a separator.]], + Return_Value = [[result - string - the constructed filename on success, nil on error]], +} + +function dtutils_processor.make_output_filename(img_list) + local images = {} + local cnt = 1 + local max_distinct_names = 3 + local name_separator = "-" + local outputFileName = nil + log.msg(log.debug, "img_list is ", img_list) + + local result = dtutils.split(img_list, " ") + table.sort(result) + for _,img in pairs(result) do + images[cnt] = df.get_basename(img) + cnt = cnt + 1 + end + + cnt = cnt - 1 + + if cnt > 1 then + if cnt > max_distinct_names then + -- take the first and last + outputFileName = images[1] .. name_separator .. images[cnt] + else + -- join them + outputFileName = dtutils.join(images, name_separator) + end + else + -- return the single name + outputFileName = images[cnt] + end + + return outputFileName +end + +return dtutils_processor diff --git a/lib/libLog.lua b/lib/libLog.lua new file mode 100644 index 0000000..052a9da --- /dev/null +++ b/lib/libLog.lua @@ -0,0 +1,378 @@ +--[[ + + libLog.lua - darktable lua logging library + + Copyright (C) 2016 Bill Ferguson . + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +]] + +local libLog = {} +libLog.libdoc = { + Sections = {"Name", "Synopsis", "Description", "License", "Copyright"}, + Name = "libLog - darktable lua logging library", + Synopsis = [[local log = require "lib/libLog"]], + Description = [[libLog provides a multi-level logging solution for use with + the darktable lua scripts.]], + License = [[This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .]], + Copyright = "Copyright (C) 2016 Bill Ferguson .", + functions = {} +} + +local dt = require "darktable" + +-- set the default log levels + +libLog.debug = {"DEBUG:", false} +libLog.info = {"INFO:", false} +libLog.warn = {"WARN:", false} +libLog.error = {"ERROR:", true} +libLog.success = {"SUCCESS:", true} + +libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = "caller - get the name of the calling routine", + Synopsis = [[local log = require "lib/libLog" + +result = log.caller(level) + level - number - the number of stack levels to go down to retrieve the caller routine information]], + Description = "caller gets the name of the calling routine and returns it", + Return_Value = [[result - string - the name and line number of the calling function or 'callback: ' if the attempt to get the + caller returns nil]], +} + +--[[ + NAME + caller - get the name of the calling routine + + SYNOPSIS + local log = require "lib/libLog" + + local result = log.caller(level) + level - number - the number of stack levels to go down to retrieve the caller routine information + + DESCRIPTION + caller gets the name of the calling routine and returns it + + RETURN VALUE + result - string - the name of the calling function and line number or 'callback: ' if the attempt to get the + caller returns nil + + +]] + +function libLog.caller(level) + local name = debug.getinfo(level).name + local lineno = nil + local source = nil + if name then + lineno = debug.getinfo(level).currentline + -- returns the path to the file prefixed with @ + source = debug.getinfo(level).source + -- we just need the filename, so grab it from the string + -- Thanks, Tobias Jakobs :-) + source = string.match(source, "@.-([^\\/]-%.?[^%.\\/]*)$") + return name .. ": " .. source .. ": " .. lineno .. ":" + else + return "callback:" + end +end + +libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Limitations"}, + Name = "msg - print a log message", + Synopsis = [[local log = require "lib/libLog" + + log.msg(level, ...) + level - table - the type of message, one of: + libLog.debug - debugging messages + libLog.info - informational messages + libLog.warn - warning messages + libLog.error - error messages + libLog.success - success messages + ... - string(s) - the message to print, which could be a comma separated set of strings]], + Description = [[msg checks the level to see if it is enabled, then prints the level type and message if it is. + debug messages print straight to the console, info and warn messages to dt.print_error() and error + and success to dt.print()]], + Limitations = [[If you use libLog.msg in a callback, the name of the calling routine can't be determined. A solution + is to include some means of reference such as the name of the callback as an argument, i.e. + + libLog.msg(libLog.debug, "libPlugin.format_combobox:", "value is " .. self.value) + + which would result in + + DEBUG: callback: libPlugin.format_combobox: value is JPEG]], +} + +--[[ + NAME + msg - print a log message + + SYNOPSIS + local log = require "lib/libLog" + + log.msg(level, ...) + level - table - the type of message, one of: + libLog.debug - debugging messages + libLog.info - informational messages + libLog.warn - warning messages + libLog.error - error messages + libLog.success - success messages + ... - string(s) - the message to print, which could be a comma separated set of strings + + DESCRIPTION + msg checks the level to see if it is enabled, then prints the level type and message if it is. + debug messages print straight to the console, info and warn messages to dt.print_error() and error + and success to dt.print() + + RETURN VALUE + none + + LIMITATIONS + If you use libLog.msg in a callback, the name of the calling routine can't be determined. A solution + is to include some means of reference such as the name of the callback as an argument, i.e. + + libLog.msg(libLog.debug, "libPlugin.format_combobox:", "value is " .. self.value) + + which would result in + + DEBUG: callback: libPlugin.format_combobox: value is JPEG + +]] + +function libLog.msg(level, ...) + local message = {...} + if level[2] == true then + libLog.print(level[1], libLog.caller(3), unpack(message)) + end +end + +libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value", "Reference"}, + Name = "print - print the supplied arguments", + Synopsis = [[local log = require "lib/libLog" + + log.print(...) + ... - arguments to be printed that are converted with tostring()]], + Description = [[print loops through the arguments converting each to a string then writing + them to stdout. Spaces are put between each argument on output.]], + Return_Value = "none", + Reference = "http://stackoverflow.com/questions/7148678/lua-print-on-the-same-line", +} + +--[[ + NAME + libLog.print - print the supplied arguments + + SYNOPSIS + local log = require "lib/libLog" + + log.print(...) + ... - arguments to be printed that are converted with tostring() + + DESCRIPTION + print loops through the arguments converting each to a string then writing + them to stdout. Spaces are put between each argument on output. + + RETURN VALUE + none + + REFERENCE + http://stackoverflow.com/questions/7148678/lua-print-on-the-same-line + +]] + +function libLog.print(...) + local write = io.write + local n = select("#",...) + for i = 1,n do + local v = tostring(select(i,...)) + write(v) + if i~=n then + write(' ') + end + end + write('\n') +end + +libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[set_level - set the logging level]], + Synopsis = [[local log = require "lib/libLog" + + log.set_level(level) + level - string - a string specifying the level, one of: "debug", "info", "warn", "error", "success"]], + Description = [[set_level sets the logging level to the level specified. Every level above the specified level + is also enabled, therefore specifying "debug" would turn on all levels and specifying "success" + would turn all levels off except libLog.success.]], + Return_Value = "none", +} + +--[[ + NAME + set_level - set the logging level + + SYNOPSIS + local log = require "lib/libLog" + + log.set_level(level) + level - string - a string specifying the level, one of: "debug", "info", "warn", "error", "success" + + DESCRIPTION + set_level sets the logging level to the level specified. Every level above the specified level + is also enabled, therefore specifying "debug" would turn on all levels and specifying "success" + would turn all levels off except libLog.success. + + RETURN VALUE + none + +]] + +function libLog.set_level(level) + level = level:lower() + if string.match(level, "debug") then + -- turn everything on + libLog.debug[2] = true + libLog.info[2] = true + libLog.warn[2] = true + libLog.error[2] = true + libLog.success[2] = true + elseif string.match(level, "info") then + -- turn off debug and everything else on + libLog.debug[2] = false + libLog.info[2] = true + libLog.warn[2] = true + libLog.error[2] = true + libLog.success[2] = true + elseif string.match(level, "warn") then + -- turn off debug and info and everything else on + libLog.debug[2] = false + libLog.info[2] = false + libLog.warn[2] = true + libLog.error[2] = true + libLog.success[2] = true + elseif string.match(level, "error") or string.match("reset") then + -- everything off except error and success + libLog.debug[2] = false + libLog.info[2] = false + libLog.warn[2] = false + libLog.error[2] = true + libLog.success[2] = true + elseif string.match(level, "success") then + -- everything off except success + libLog.debug[2] = false + libLog.info[2] = false + libLog.warn[2] = false + libLog.error[2] = false + libLog.success[2] = true + else + -- leave everything unchanged and return + return + end +end + +libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description", "Return_Value"}, + Name = [[get_level - get the current logging level]], + Synopsis = [[local log = require "lib/libLog" + + local result = libLog.get_level()]], + Description = "get_level returns a string representing the current log level.", + Return_Value = [[result - string - one of "debug", "info", "warn", "error", or "success"]], +} + +--[[ + NAME + get_level - get the current logging level + + SYNOPSIS + local log = require "lib/libLog" + + local result = log.get_level() + + DESCRIPTION + get_level returns a string representing the current log level. + + RETURN VALUE + result - string - one of "debug", "info", "warn", "error", or "success" + +]] + +function libLog.get_level() + local result = nil + if libLog.debug[2] == true then + result = "debug" + elseif libLog.info[2] == true then + result = "info" + elseif libLog.warn[2] == true then + result = "warn" + elseif libLog.error[2] == true then + result = "error" + elseif libLog.success[2] == true then + result = "success" + end + return result +end + +libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { + Sections = {"Name", "Synopsis", "Description"}, + Name = [[always - always write out a log message]], + Synopsis = [[local log = require "lib/libLog" + + log.always(level, ...) + level - number - the number of stack levels to go back to identify the caller + ... - string(s) - the message to print]], + Description = [[always is meant specifically for the dtutils.debug library, but may be used for other + purposes. always is independent of the log level setting so that it will always work. + The number of stack levels to look back for the caller may be specified. It is normally + 3 when called from a routine, but is 4 when called from the debugging routines since the + debugging routines add another stack level.]], +} + +--[[ + NAME + always - always write out a log message + + SYNOPSIS + local log = require "lib/libLog" + + log.always(level, ...) + level - number - the number of stack levels to go back to identify the caller + ... - string(s) - the message to print + + DESCRIPTION + always is meant specifically for the dtutils.debug library, but may be used for other + purposes. always is independent of the log level setting so that it will always work. + The number of stack levels to look back for the caller may be specified. It is normally + 3 when called from a routine, but is 4 when called from the debugging routines since the + debugging routines add another stack level. +]] + +function libLog.always(level, ...) + local message = {...} + libLog.print(libLog.caller(level), unpack(message)) +end + +return libLog diff --git a/official/debug-helpers.lua b/official/debug-helpers.lua deleted file mode 100644 index 568a678..0000000 --- a/official/debug-helpers.lua +++ /dev/null @@ -1,93 +0,0 @@ ---[[ -This file is part of darktable, -copyright (c) 2014 Jérémy Rosen - -darktable is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -darktable is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with darktable. If not, see . -]] ---[[ -DEBUG HELPERS -A collection of helper functions to help debugging lua scripts. - -require it as - -dhelpers = require "official/debug-helpers" - -Each function is documented in its own header - - -]] - - -local dt = require "darktable" -local io = require "io" -local table = require "table" -require "darktable.debug" -local M = {} -- The actual content of the module - ---[[ -A function which prints its name and its parameters -* name : the name of the tracepoint -* ... : anything, will be dumped using dt.debug -]] -function M.tracepoint(name,...) - print("***** "..name.." ****") - params = {...} - print(dt.debug.dump(params,"parameters")) - return ...; -end - - - ---[[ -A function that returns a tracepoint function with the given name -This is mainly used to debug callbacks, - -register_event(event, dhelpers.new_tracepoint("hit callback")) - -will print the following each time the callback is called - -**** hit callback **** - - -]] -function M.new_tracepoint(name) - return function(...) return M.tracepoint(name,...) end -end - - ---[[ -Wrapper around debug.dump, will directly print to stdout, -same calling covention -]] - -function M.dprint(...) - print(dt.debug.dump(...)) -end - ---[[ -sets dt.debug.known to shorten all images to a single line - -if you don't need to debug the content of images, this will avoid them flooding your logs -]] -function M.terse_dump() - for _,v in ipairs(dt.database) do - dt.debug.known[v] = tostring(v) - end -end - - - -return M --- vim: shiftwidth=2 expandtab tabstop=2 cindent --- kate: tab-indents: off; indent-width 2; replace-tabs on; remove-trailing-space on; diff --git a/tools/get_lib_manpages.lua b/tools/get_lib_manpages.lua new file mode 100644 index 0000000..4dbed6c --- /dev/null +++ b/tools/get_lib_manpages.lua @@ -0,0 +1,63 @@ +--[[ + get_lib_manpages.lua - retrieve the included library documentation and output it as man pages + + Copyright (c) 2016, Bill Ferguson +]] + +local dt = require "darktable" +local du = require "lib/dtutils" +local libname = nil + +dt.configuration.check_version(...,{3,0,0}) + +local function output_man(d) + local parts = du.split(d[d.Sections[1]], " - ") + if not libname then + libname = parts[1] + end + local fname = "/tmp/" .. parts[1] .. ".3" + local mf = io.open(fname, "w") + if mf then + mf:write(".TH " .. string.upper(parts[1]) .. " 3 \"\" \"\" \"Darktable " .. libname .. " functions\"\n") + for _,section in pairs(d.Sections) do + if d[section] then + mf:write(".SH " .. string.upper(string.gsub(section, "_", " ")) .. "\n") + mf:write(d[section] .. "\n") + end + end + mf:close() + os.execute("groff -man " .. fname .. " | ps2pdf - " .. fname .. ".pdf") + else + log.msg(log.error, "Can't open file " .. fname .. "for writing") + end +end + +-- find the libraries + +local output = io.popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort") + +-- loop through the libraries + +for line in output:lines() do + line = string.gsub(line, "/", ".") + local lib_name = line:sub(3,-5) + if lib_name:len() > 2 then + lib_name = "lib/" .. lib_name + local lib = require(lib_name) + + -- print the documentation for the library + if lib.libdoc then + local doc = lib.libdoc + if doc then + output_man(doc) + for _,fdoc in pairs(doc.functions) do + + -- print the documentation for each of the functions + output_man(fdoc) + end + end + end + end + libname = nil +end + diff --git a/tools/get_libdoc.lua b/tools/get_libdoc.lua new file mode 100644 index 0000000..706b025 --- /dev/null +++ b/tools/get_libdoc.lua @@ -0,0 +1,46 @@ +--[[ + get_libdoc.lua - retrieve the included library documentation and output it + + Copyright (c) 2016, Bill Ferguson +]] + +local dt = require "darktable" + +dt.configuration.check_version(...,{3,0,0}) + +local function output_doc(d) + for _,section in pairs(d.Sections) do + if d[section] then + print(string.upper(string.gsub(section, "_", " "))) + print("\t" .. d[section] .. "\n") + end + end + print("\f") +end + +-- find the libraries + +local output = io.popen("cd "..dt.configuration.config_dir.."/lua/lib ;find . -name \\*.lua -print | sort") + +-- loop through the libraries + +for line in output:lines() do + line = string.gsub(line, "/", ".") + local lib_name = line:sub(3,-5) + if lib_name:len() > 2 then + lib_name = "lib/" .. lib_name + local lib = require(lib_name) + + -- print the documentation for the library + if lib.libdoc then + local doc = lib.libdoc + output_doc(doc) + for _,fdoc in pairs(doc.functions) do + + -- print the documentation for each of the functions + output_doc(fdoc) + end + end + end +end + From 564fd20f235e29810d277e1951514c0b94e8acd6 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Thu, 20 Oct 2016 01:19:54 -0400 Subject: [PATCH 2/4] Moved lib/libLog.lua to lib/dtutils/log.lua. Rewrote most of it to make it more configurable and easier to use. Updated doc format to a fixed list of fields. Did away with the comment blocks and just relying on the libdoc comments. Update doc tools to use new formats. Moved dtutils/extensions.lua to dtutils/string.lua. Pulled dtutils/processor.lua back for now since there is no context for it. Removed unneeded functions and cleaned up others. --- lib/dtutils.lua | 357 +++----------- .../de_DE/LC_MESSAGES/dtutils.processor.po | 23 - lib/dtutils/debug.lua | 176 +++---- lib/dtutils/file.lua | 459 +++++++----------- lib/dtutils/log.lua | 291 +++++++++++ lib/dtutils/processor.lua | 266 ---------- lib/dtutils/{extensions.lua => string.lua} | 142 +++--- lib/libLog.lua | 378 --------------- tools/get_lib_manpages.lua | 16 +- tools/get_libdoc.lua | 7 +- 10 files changed, 654 insertions(+), 1461 deletions(-) delete mode 100644 lib/dtutils/de_DE/LC_MESSAGES/dtutils.processor.po create mode 100644 lib/dtutils/log.lua delete mode 100644 lib/dtutils/processor.lua rename lib/dtutils/{extensions.lua => string.lua} (58%) delete mode 100644 lib/libLog.lua diff --git a/lib/dtutils.lua b/lib/dtutils.lua index db2be0a..5b5986a 100644 --- a/lib/dtutils.lua +++ b/lib/dtutils.lua @@ -1,33 +1,16 @@ ---[[ - - dtutils.lua - common darktable lua functions - - Copyright (C) 2016 Bill Ferguson . - Copyright (C) 2016 Tobias Jakobs - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -]] - local dtutils = {} dtutils.libdoc = { - Sections = {"Name", "Synopsis", "Description", "See_Also", "License"}, - Name = [[dtutils - A Darktable lua utilities library]], - Synopsis = [[local du = require "lib/dtutils"]], + Name = [[dtutils]], + Synopsis = [[A Darktable lua utilities library]], + Usage = [[local du = require "lib/dtutils"]], Description = [[dtutils provides a common library of functions used to build lua scripts. There are also sublibraries that provide more functions.]], - See_Also = [[dtutils.debug(3), dtutils.extensionts(3), dtutils.file(3), dtutils.processor(3)]], + Return_Value = [[du - library - the library of functions]], + Limitations = [[]], + Example = [[]], + See_Also = [[dtutils.debug(3), dtutils.file(3), dtutils.log(3), dtutils.string(3)]], + Reference = [[]], License = [[This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or @@ -40,57 +23,40 @@ dtutils.libdoc = { You should have received a copy of the GNU General Public License along with this program. If not, see .]], + Copyright = [[Copyright (C) 2016 Bill Ferguson . + Copyright (C) 2016 Tobias Jakobs]], functions = {} } local dt = require "darktable" -local log = require "lib/libLog" +local log = require "lib/dtutils.log" dt.configuration.check_version(...,{3,0,0}) ---[[ - NAME - split - split a string on a specified separator - - SYNOPSIS - local du = require "lib/dtutils" - - local result = du.split(str, pat) - str - string - the string to split - pat - string - the pattern to split on - - DESCRIPTION - split separates a string into a table of strings. The strings are separated at each - occurrence of the supplied pattern. - - RETURN VALUE - result - a table of strings on success, or an empty table on error - - EXAMPLE - split("/a/long/path/name/to/a/file.txt", "/") would return a table like - {"a", "long", "path", "name", "to", "a", "file.txt"} - -]] - -dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value", "Example"}, - Name = [[split - split a string on a specified separator]], - Synopsis = [[local du = require "lib/dtutils" +dtutils.libdoc.functions["split"] = { + Name = [[split]], + Synopsis = [[split a string on a specified separator]], + Usage = [[local du = require "lib/dtutils" local result = du.split(str, pat) str - string - the string to split pat - string - the pattern to split on]], Description = [[split separates a string into a table of strings. The strings are separated at each - occurrence of the supplied pattern.]], + occurrence of the supplied pattern. The pattern may be any pattern as described in the lua docs. + Each match of the pattern is consumed and not returned.]], Return_Value = [[result - a table of strings on success, or an empty table on error]], + Limitations = [[]], Example = [[split("/a/long/path/name/to/a/file.txt", "/") would return a table like - {"a", "long", "path", "name", "to", "a", "file.txt"}]], + {a, "long", "path", "name", "to", a, "file.txt"}]], + See_Also = [[]], + Reference = [[http://lua-users.org/wiki/SplitJoin]], + License = [[]], + Copyright = [[]], } --- Thanks to http://lua-users.org/wiki/SplitJoin function dtutils.split(str, pat) - local t = {} -- NOTE: use {n = 0} in Lua-5.0 + local t = {} local fpat = "(.-)" .. pat local last_end = 1 local s, e, cap = str:find(fpat, 1) @@ -108,46 +74,26 @@ function dtutils.split(str, pat) return t end ---[[ - NAME - join - join a table of strings with a specified separator - - SYNOPSIS - local du = require "lib/dtutils" - - local result = du.join(tabl, pat) - tabl - a table of strings - pat - a separator - - DESCRIPTION - join assembles a table of strings into a string with the specified pattern - in between each string - - RETURN VALUE - result - the joined string on success, or an empty string on failure - - EXAMPLE - join({"a", "long", "path", "name", "to", "a", "file.txt"}, " ") would return the string - "a long path name to a file.txt" - -]] - -dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value", "Example"}, - Name = [[join - join a table of strings with a specified separator]], - Synopsis = [[local du = require "lib/dtutils" +dtutils.libdoc.functions["join"] = { + Name = [[join]], + Synopsis = [[join a table of strings with a specified separator]], + Usage = [[local du = require "lib/dtutils" local result = du.join(tabl, pat) tabl - a table of strings pat - a separator]], Description = [[join assembles a table of strings into a string with the specified pattern in between each string]], - Return_Value = [[result - the joined string on success, or an empty string on failure]], - Example = [[join({"a", "long", "path", "name", "to", "a", "file.txt"}, " ") would return the string + Return_Value = [[result - string - the joined string on success, or an empty string on failure]], + Limitations = [[]], + Example = [[join({a, "long", "path", "name", "to", a, "file.txt"}, " ") would return the string "a long path name to a file.txt"]], + See_Also = [[]], + Reference = [[http://lua-users.org/wiki/SplitJoin]], + License = [[]], + Copyright = [[]], } --- Thanks to http://lua-users.org/wiki/SplitJoin function dtutils.join(tabl, pat) returnstr = "" for i,str in pairs(tabl) do @@ -178,17 +124,24 @@ end ]] -dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value", "Example"}, - Name = [[prequire - a protected lua require]], - Synopsis = [[local du = require "lib/dtutils" +dtutils.libdoc.functions["prequire"] = { + Name = [[prequire]], + Synopsis = [[a protected lua require]], + Usage = [[local du = require "lib/dtutils" - local result = du.prequire(req_name) + local status, lib = du.prequire(req_name) req_name - the filename of the lua code to load without the ".lua" filetype]], Description = [[prequire is a protected require that can survive an error in the code being loaded without bringing down the calling routine.]], - Return_Value = [[result - the code or true on success, otherwise an error message]], - Example = [[prequire("lib/dtutils.file") which would load lib/dtutils/file.lua]], + Return_Value = [[status - boolean - true on success + lib - if status is true, then the code, otherwise an error message]], + Limitations = [[]], + Example = [[local status, lib = prequire("lib/dtutils.file") which would load lib/dtutils/file.lua which + would return a status of true and the reference to the library in lib.]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils.prequire(req_name) @@ -198,165 +151,13 @@ function dtutils.prequire(req_name) else log.msg(log.info, "Error loading " .. req_name) end - return lib + return status, lib end ---[[ - NAME - push - push a value on a stack - - SYNOPSIS - local du = require "lib/dtutils" - - du.push(stack, value) - stack - table - a table being used as the stack - value - any type - the value to be put on the stack - - DESCRIPTION - Push a value on a stack - - RETURN VALUE - none - -]] - -dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[push - push a value on a stack]], - Synopsis = [[local du = require "lib/dtutils" - - du.push(stack, value) - stack - table - a table being used as the stack - value - any type - the value to be put on the stack]], - Description = [[Push a value on a stack]], - Return_Value = [[none]], -} - -dtutils.push = table.insert - ---[[ - NAME - pop - pop a value from a stack - - SYNOPSIS - local du = require "lib/dtutils" - - local result = du.pop(stack) - stack - table - a table being used as a stack - - DESCRIPTION - Remove the last value pushed on the stack and return it - - RETURN VALUE - result = nil if stack isn't a table or the stack is empty, otherwise the value removed from the stack - -]] - -dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[pop - pop a value from a stack]], - Synopsis = [[local du = require "lib/dtutils" - - local result = du.pop(stack) - stack - table - a table being used as a stack]], - Description = [[Remove the last value pushed on the stack and return it]], - Return_Value = [[result = nil if stack isn't a table or the stack is empty, otherwise the value removed from the stack]], -} - -dtutils.pop = table.remove - ---[[ - NAME - update_combobox_choices - change the list of choices in a combobox - - SYNOPSIS - local du = require "lib/dtutils" - - du.update_combobox_choices(combobox_widget, choice_table) - combobox_widget - lua_combobox - a combobox widget - choice_table - table - a table of strings for the combobox choices - - DESCRIPTION - Set the combobox choices to the supplied list. Remove any extra choices from the end - - RETURN VALUE - none - -]] - -dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[update_combobox_choices - change the list of choices in a combobox]], - Synopsis = [[local du = require "lib/dtutils" - - du.update_combobox_choices(combobox_widget, choice_table) - combobox_widget - lua_combobox - a combobox widget - choice_table - table - a table of strings for the combobox choices]], - Description = [[Set the combobox choices to the supplied list. Remove any extra choices from the end]], - Return_Value = [[none]], -} - -function dtutils.update_combobox_choices(combobox, choice_table) - local items = #combobox - local choices = #choice_table - for i, name in ipairs(choice_table) do - log.msg(log.debug, "Setting choice " .. i .. " to " .. name) - combobox[i] = name - end - if choices < items then - for j = items, choices + 1, -1 do - log.msg(log.debug, "Removing choice " .. j) - combobox[j] = nil - end - end - combobox.value = 1 -end - ---[[ - NAME - spairs - an iterator that provides sorted pairs from a table - - SYNOPSIS - local du = require "lib/dtutils" - - for key, value in du.spairs(t, order) do - t - table - table of key, value pairs - order - function - an optional function to sort the pairs - if none is supplied, table.sort() is used - - DESCIRPTION - spairs is an iterator that returns key, value pairs from a table in sorted - order. The sorting order is the result of table.sort() if no function is - supplied, otherwise sorting is done as specified in the function. - - EXAMPLE - HighScore = { Robin = 8, Jon = 10, Max = 11 } - - -- basic usage, just sort by the keys - for k,v in spairs(HighScore) do - print(k,v) - end - --> Jon 10 - --> Max 11 - --> Robin 8 - - -- this uses an custom sorting function ordering by score descending - for k,v in spairs(HighScore, function(t,a,b) return t[b] < t[a] end) do - print(k,v) - end - --> Max 11 - --> Jon 10 - --> Robin 8 - - REFERENCE - Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua - -]] - -dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Example", "Reference"}, - Name = [[spairs - an iterator that provides sorted pairs from a table]], - Synopsis = [[local du = require "lib/dtutils" +dtutils.libdoc.functions["spairs"] = { + Name = [[spairs]], + Synopsis = [[an iterator that provides sorted pairs from a table]], + Usage = [[local du = require "lib/dtutils" for key, value in du.spairs(t, order) do t - table - table of key, value pairs @@ -365,6 +166,8 @@ dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { Description = [[spairs is an iterator that returns key, value pairs from a table in sorted order. The sorting order is the result of table.sort() if no function is supplied, otherwise sorting is done as specified in the function.]], + Return_Value = [[]], + Limitations = [[]], Example = [[HighScore = { Robin = 8, Jon = 10, Max = 11 } -- basic usage, just sort by the keys @@ -382,7 +185,10 @@ dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { --> Max 11 --> Jon 10 --> Robin 8]], + See_Also = [[]], Reference = [[Code copied from http://stackoverflow.com/questions/15706270/sort-a-table-in-lua]], + License = [[]], + Copyright = [[]], } -- Sort a table @@ -409,49 +215,4 @@ function dtutils.spairs(_table, order) -- Code copied from http://stackoverflow. end end ---[[ - - NAME - urlencode - encode a string in a websage manner - - SYNOPOIS - local du = require "lib/dtutils" - - local result = du.urlencode(str) - str - string - the string that needs to be made websafe - - DESCRIPTION - urlencode converts a string into a websafe version suitable for - use in a web browser. - - RETURN_VALUE - result - string - a websafe string - - REFERENCE - https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/ - -]] - -dtutils.libdoc.functions[#dtutils.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value", "Reference"}, - Name = [[urlencode - encode a string in a websage manner]], - Synopsis = [[local du = require "lib/dtutils" - - local result = du.urlencode(str) - str - string - the string that needs to be made websafe]], - Description = [[urlencode converts a string into a websafe version suitable for - use in a web browser.]], - Return_Value = [[result - string - a websafe string]], - Reference = [[https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/]], -} - -function dtutils.urlencode(str) - if (str) then - str = string.gsub (str, "\n", "\r\n") - str = string.gsub (str, "([^%w ])", function () return string.format ("%%%02X", string.byte()) end) - str = string.gsub (str, " ", "+") - end - return str -end - return dtutils diff --git a/lib/dtutils/de_DE/LC_MESSAGES/dtutils.processor.po b/lib/dtutils/de_DE/LC_MESSAGES/dtutils.processor.po deleted file mode 100644 index ba35c0d..0000000 --- a/lib/dtutils/de_DE/LC_MESSAGES/dtutils.processor.po +++ /dev/null @@ -1,23 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-10-01 00:36-0400\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: de_DE\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: dtutils.processor.lua:42 -#, lua-format -msgid "Export Image %i/%i" -msgstr "Exportiere Bild %i/%i" diff --git a/lib/dtutils/debug.lua b/lib/dtutils/debug.lua index 767d86f..bb5d02c 100644 --- a/lib/dtutils/debug.lua +++ b/lib/dtutils/debug.lua @@ -1,6 +1,7 @@ --[[ This file is part of darktable, -copyright (c) 2014 Jérémy Rosen +Copyright (c) 2014 Jérémy Rosen +Copyright (c) 2016 Bill Ferguson darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,7 +22,7 @@ A collection of helper functions to help debugging lua scripts. require it as -dhelpers = require "official/debug-helpers" +dhelpers = require "lib/dtutils.debug" Each function is documented in its own header @@ -33,53 +34,30 @@ local dt = require "darktable" local io = require "io" local table = require "table" require "darktable.debug" -local log = require "lib/libLog" +local log = require "lib/dtutils.log" local M = {} -- The actual content of the module M.libdoc = { - Sections = {"Name", "Synopsis", "Description", "License"}, - Name = [[dtutils.debug - debugging helpers used in developing darktable lua scripts]], - Synopsis = [[local dd = require "lib/dtutils.debug"]], + Name = [[dtutils.debug]], + Synopsis = [[debugging helpers used in developing darktable lua scripts]], + Usage = [[local dd = require "lib/dtutils.debug"]], Description = [[dtutils.debug provides an interface to the darktable debugging routines.]], - License = [[This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see .]], + Return_Value = [[dd - library - the darktable lua debugging helpers]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = log.libdoc.License, + Copyright = [[Copyright (c) 2014 Jérémy Rosen +Copyright (c) 2016 Bill Ferguson +]], functions = {} } ---[[ - NAME - tracepoint - print out a tracepoint and dump the arguments - - SYNOPSIS - local dd = require "lib/dtutils.debug" - - local result = tracepoint(name, ...) - name - string - the name of the tracepoint to print out - ... - arguments - variables to dump the contents of - - DESCRIPTION - tracepoint prints its name and dumps its parameters using - dt.debug - - RETURN VALUE - result - ... - the supplied argument list - -]] - -M.libdoc.functions[#M.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[tracepoint - print out a tracepoint and dump the arguments]], - Synopsis = [[local dd = require "lib/dtutils.debug" +M.libdoc.functions["tracepoint"] = { + Name = [[tracepoint]], + Synopsis = [[print out a tracepoint and dump the arguments]], + Usage = [[local dd = require "lib/dtutils.debug" local result = tracepoint(name, ...) name - string - the name of the tracepoint to print out @@ -87,50 +65,25 @@ M.libdoc.functions[#M.libdoc.functions + 1] = { Description = [[tracepoint prints its name and dumps its parameters using dt.debug]], Return_Value = [[result - ... - the supplied argument list]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function M.tracepoint(name,...) - log.always(4, "***** "..name.." ****") + log.msg(log.always, 4, "***** "..name.." ****") params = {...} - print(dt.debug.dump(params,"parameters")) + log.msg(log.always, 0, dt.debug.dump(params,"parameters")) return ...; end - - ---[[ - NAME - new_tracepoint - create a function returning a tracepoint - - SYNOPSIS - local dd = require "lib/dtutils.debug" - - local result = new_tracepoint(name, ...) - name - string - the name of the tracepoint to print out - ... - arguments - variables to dump the contents of - - - DESCRIPTION - A function that returns a tracepoint function with the given name - This is mainly used to debug callbacks. - - RETURN VALUE - result - function - a function that returns the result of a tracepoint - - EXAMPLE - register_event(event, dd.new_tracepoint("hit callback")) - - will print the following each time the callback is called - - **** hit callback **** - - -]] - -M.libdoc.functions[#M.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value", "Example"}, - Name = [[new_tracepoint - create a function returning a tracepoint]], - Synopsis = [[local dd = require "lib/dtutils.debug" +M.libdoc.functions["new_tracepoint"] = { + Name = [[new_tracepoint]], + Synopsis = [[create a function returning a tracepoint]], + Usage = [[local dd = require "lib/dtutils.debug" local result = new_tracepoint(name, ...) name - string - the name of the tracepoint to print out @@ -138,12 +91,17 @@ M.libdoc.functions[#M.libdoc.functions + 1] = { Description = [[A function that returns a tracepoint function with the given name This is mainly used to debug callbacks.]], Return_Value = [[result - function - a function that returns the result of a tracepoint]], + Limitations = [[]], Example = [[register_event(event, dd.new_tracepoint("hit callback")) will print the following each time the callback is called **** hit callback **** ]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function M.new_tracepoint(name) @@ -151,59 +109,43 @@ function M.new_tracepoint(name) end ---[[ - NAME - dprint - pass a variable to dt.debug.dump and print the results to stdout - - SYNOPSIS - local dd = require "lib/dtutils.debug" - - dd.dprint(var) - var - variable - any variable that you want to see the contents of - - DESCRIPTION - Wrapper around debug.dump, will directly print to stdout, - same calling convention - -]] - -M.libdoc.functions[#M.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description"}, - Name = [[dprint - pass a variable to dt.debug.dump and print the results to stdout]], - Synopsis = [[local dd = require "lib/dtutils.debug" +M.libdoc.functions["dprint"] = { + Name = [[dprint]], + Synopsis = [[pass a variable to dt.debug.dump and print the results to stdout]], + Usage = [[local dd = require "lib/dtutils.debug" dd.dprint(var) var - variable - any variable that you want to see the contents of]], Description = [[Wrapper around debug.dump, will directly print to stdout, same calling convention]], + Return_Value = [[]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function M.dprint(...) log.always(4, dt.debug.dump(...)) end ---[[ - NAME - terse_dump - set dt.debug.known to shorten all image dumps to a single line - - SYNOPSIS - local dd = require "lib/dtutils.debug" - - dd.terse_dump() - - DESCRIPTION - terse_dump sets dt.debug.known to shorten all images to a single line. - If you don't need to debug the content of images, this will avoid them flooding your logs -]] - -M.libdoc.functions[#M.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description"}, - Name = [[terse_dump - set dt.debug.known to shorten all image dumps to a single line]], - Synopsis = [[local dd = require "lib/dtutils.debug" +M.libdoc.functions["terse_dump"] = { + Name = [[terse_dump]], + Synopsis = [[set dt.debug.known to shorten all image dumps to a single line]], + Usage = [[local dd = require "lib/dtutils.debug" dd.terse_dump()]], Description = [[terse_dump sets dt.debug.known to shorten all images to a single line. If you don't need to debug the content of images, this will avoid them flooding your logs]], + Return_Value = [[]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function M.terse_dump() diff --git a/lib/dtutils/file.lua b/lib/dtutils/file.lua index ebeba68..fd20e46 100644 --- a/lib/dtutils/file.lua +++ b/lib/dtutils/file.lua @@ -1,49 +1,25 @@ ---[[ - - dtutils/file.lua - common darktable lua file functions - - Copyright (C) 2016 Bill Ferguson . - Copyright (C) 2016 Tobias Jakobs - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -]] - local dtutils_file = {} -dtutils_file.libdoc = { - Sections = {"Name", "Synopsis", "Description", "License"}, - Name = [[dtutils.file - common darktable lua file functions]], - Synopsis = [[local df = require "lib/dtutils.file"]], - Description = [[dtutils.file provides common file manipulation functions used in - constructing Darktable lua scripts]], - License = [[This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see .]], - functions = {} -} - local dt = require "darktable" -local log = require "lib/libLog" +local log = require "lib/dtutils.log" + +dtutils_file.libdoc = { + Name = [[dtutils.file]], + Synopsis = [[common darktable lua file functions]], + Usage = [[local df = require "lib/dtutils.file"]], + Description = [[[dtutils.file provides common file manipulation functions used in + constructing Darktable lua scripts]], + Return_Value = [[df - library - the file functions]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = log.libdoc.License, + Copyright = [[Copyright (C) 2016 Bill Ferguson .]], + Copyright = [[Copyright (C) 2016 Bill Ferguson . + Copyright (C) 2016 Tobias Jakobs]], + functions = {} +} local gettext = dt.gettext @@ -56,35 +32,22 @@ local function _(msgid) return gettext.dgettext("dtutils.file", msgid) end ---[[ - NAME - check_if_bin_exists - check if an executable is in the path - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.check_if_bin_exists(bin) - bin - string - the binary to check for - - DESCRIPTION - check_if_bin_exists checks to see if the specified binary executable is - in the path. - - RETURN VALUE - result - boolean - true if the executable was found, false if not - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[check_if_bin_exists - check if an executable is in the path]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["check_if_bin_exists"] = { + Name = [[check_if_bin_exists]], + Synopsis = [[check if an executable is in the path]], + Usage = [[local df = require "lib/dtutils.file" local result = df.check_if_bin_exists(bin) bin - string - the binary to check for]], Description = [[check_if_bin_exists checks to see if the specified binary executable is in the path.]], Return_Value = [[result - boolean - true if the executable was found, false if not]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.check_if_bin_exists(bin) @@ -95,71 +58,48 @@ function dtutils_file.check_if_bin_exists(bin) return result end ---[[ - NAME - split_filepath - split a filepath into parts - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.split_filepath(filepath) - filepath - string - path and filename - - DESCRIPTION - split_filepath splits a filepath into the path, filename, basename and filetype and puts - that in a table - - RETURN VALUE - result - table - a table containing the path, filename, basename, and filetype - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[split_filepath - split a filepath into parts]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["split_filepath"] = { + Name = [[split_filepath]], + Synopsis = [[split a filepath into parts]], + Usage = [[local df = require "lib/dtutils.file" local result = df.split_filepath(filepath) filepath - string - path and filename]], Description = [[split_filepath splits a filepath into the path, filename, basename and filetype and puts that in a table]], Return_Value = [[result - table - a table containing the path, filename, basename, and filetype]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.split_filepath(str) + -- strip out single quotes from quoted pathnames + str = string.gsub(str, "'", "") local result = {} -- Thank you Tobias Jakobs for the awesome regular expression, which I tweaked a little result["path"], result["filename"], result["basename"], result["filetype"] = string.match(str, "(.-)(([^\\/]-)%.?([^%.\\/]*))$") return result end ---[[ - NAME - get_path - get the path from a file path - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.get_path(filepath) - filepath - string - path and filename - - DESCRIPTION - get_path strips the filename and filetype from a path and returns the path - - RETURN VALUE - result - string - the path - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[get_path - get the path from a file path]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["get_path"] = { + Name = [[get_path]], + Synopsis = [[get the path from a file path]], + Usage = [[local df = require "lib/dtutils.file" local result = df.get_path(filepath) filepath - string - path and filename]], Description = [[get_path strips the filename and filetype from a path and returns the path]], Return_Value = [[result - string - the path]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.get_path(str) @@ -167,33 +107,21 @@ function dtutils_file.get_path(str) return parts["path"] end ---[[ - NAME - get_filename - get the filename and extension from a file path - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.get_filename(filepath) - filepath - string - path and filename - - DESCRIPTION - get_filename strips the path from a filepath and returns the filename - - RETURN VALUE - result - string - the file name and type - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[get_filename - get the filename and extension from a file path]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["get_filename"] = { + Name = [[get_filename]], + Synopsis = [[get the filename and extension from a file path]], + Usage = [[local df = require "lib/dtutils.file" local result = df.get_filename(filepath) filepath - string - path and filename]], Description = [[get_filename strips the path from a filepath and returns the filename]], Return_Value = [[result - string - the file name and type]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.get_filename(str) @@ -201,33 +129,22 @@ function dtutils_file.get_filename(str) return parts["filename"] end ---[[ - NAME - get_basename - get the filename without the path or extension - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.get_basename(filepath) - filepath - string - path and filename - - DESCRIPTION - get_basename returns the name of the file without the path or filetype - - RETURN VALUE - result - string - the basename of the file - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[get_basename - get the filename without the path or extension]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["get_basename"] = { + Name = [[get_basename]], + Synopsis = [[get the filename without the path or extension]], + Usage = [[local df = require "lib/dtutils.file" local result = df.get_basename(filepath) filepath - string - path and filename]], - Description = [[get_basename returns the name of the file without the path or filetype]], + Description = [[get_basename returns the name of the file without the path or filetype +]], Return_Value = [[result - string - the basename of the file]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.get_basename(str) @@ -235,33 +152,21 @@ function dtutils_file.get_basename(str) return parts["basename"] end ---[[ - NAME - get_filetype - get the filetype from a filename - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.get_filetype(filepath) - filepath - string - path and filename - - DESCRIPTION - get_filetype returns the filetype from the supplied filepath - - RETURN VALUE - result - string - the filetype - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[get_filetype - get the filetype from a filename]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["get_filetype"] = { + Name = [[get_filetype]], + Synopsis = [[get the filetype from a filename]], + Usage = [[local df = require "lib/dtutils.file" local result = df.get_filetype(filepath) filepath - string - path and filename]], Description = [[get_filetype returns the filetype from the supplied filepath]], Return_Value = [[result - string - the filetype]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.get_filetype(str) @@ -269,34 +174,23 @@ function dtutils_file.get_filetype(str) return parts["filetype"] end ---[[ - NAME - check_if_file_exists - check if a file or path exist - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.check_if_file_exists(filepath) - filepath - string - a file or path to check - - DESCRIPTION - check_if_file_exists checks to see if a file or path exists - - RETURN VALUE - result - boolean - true if the file or path exists, false if it doesn't - -]] -- Thanks Tobias Jakobs for the idea -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[check_if_file_exists - check if a file or path exist]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["check_if_file_exists"] = { + Name = [[check_if_file_exists]], + Synopsis = [[check if a file or path exist]], + Usage = [[local df = require "lib/dtutils.file" local result = df.check_if_file_exists(filepath) filepath - string - a file or path to check]], Description = [[check_if_file_exists checks to see if a file or path exists]], Return_Value = [[result - boolean - true if the file or path exists, false if it doesn't]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.check_if_file_exists(filepath) @@ -307,33 +201,21 @@ function dtutils_file.check_if_file_exists(filepath) return result end ---[[ - NAME - chop_filetype - remove a filetype from a filename - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.chop_filetype(path) - path - string - a filename with or without a path - - DESCRIPTION - chop_filetype removes the filetype from the filename - - RETURN VALUE - result - string - the path and filename without the filetype - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[chop_filetype - remove a filetype from a filename]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["chop_filetype"] = { + Name = [[chop_filetype]], + Synopsis = [[remove a filetype from a filename]], + Usage = [[local df = require "lib/dtutils.file" local result = df.chop_filetype(path) path - string - a filename with or without a path]], Description = [[chop_filetype removes the filetype from the filename]], Return_Value = [[result - string - the path and filename without the filetype]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.chop_filetype(path) @@ -341,30 +223,10 @@ function dtutils_file.chop_filetype(path) return string.sub(path, 1, -length) end ---[[ - NAME - file_copy - copy a file to another name/location - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.file_copy(fromFile, toFile) - fromFile - string - name of file to copy from - toFile - string - name of file to copy to - - DESCRIPTION - copy a file using a succession of methods from operating system - to a pure lua solution - - RETURN VALUE - result - boolean - nil on error, true on success - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[file_copy - copy a file to another name/location]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["file_copy"] = { + Name = [[file_copy]], + Synopsis = [[copy a file to another name/location]], + Usage = [[local df = require "lib/dtutils.file" local result = df.file_copy(fromFile, toFile) fromFile - string - name of file to copy from @@ -372,6 +234,12 @@ dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { Description = [[copy a file using a succession of methods from operating system to a pure lua solution]], Return_Value = [[result - boolean - nil on error, true on success]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.file_copy(fromFile, toFile) @@ -404,30 +272,10 @@ function dtutils_file.file_copy(fromFile, toFile) return result end ---[[ - NAME - file_move - move a file from one directory to another - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.file_move(fromFile, toFile) - fromFile - string - name of the original file - toFile - string - the new file location and name - - DESCRIPTION - Move a file from one place to another. Try a succession of methods from - builtin to operating system to a pure lua solution. - - RETURN VALUE - result - boolean - nil on error, some value on success - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[file_move - move a file from one directory to another]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["file_move"] = { + Name = [[file_move]], + Synopsis = [[move a file from one directory to another]], + Usage = [[local df = require "lib/dtutils.file" local result = df.file_move(fromFile, toFile) fromFile - string - name of the original file @@ -435,6 +283,12 @@ dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { Description = [[Move a file from one place to another. Try a succession of methods from builtin to operating system to a pure lua solution.]], Return_Value = [[result - boolean - nil on error, some value on success]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.file_move(fromFile, toFile) @@ -458,31 +312,10 @@ function dtutils_file.file_move(fromFile, toFile) return success -- nil on error, some value if success end ---[[ - NAME - filename_increment - add a two digit increment to a filename - - SYNOPSIS - local df = require "lib/dtutils.file" - - local result = df.filename_increment(filepath) - filepath - string - filename to increment - - DESCRIPTION - filename_increment solves the problem of filename confllict by adding an - increment to the filename. If the supplied filename has no increment then - "01" is added to the basename. If the filename already has an increment, then - 1 is added to it and the filename returned. - - RETURN VALUE - result - string - the incremented filename - -]] - -dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[filename_increment - add a two digit increment to a filename]], - Synopsis = [[local df = require "lib/dtutils.file" +dtutils_file.libdoc.functions["filename_increment"] = { + Name = [[filename_increment]], + Synopsis = [[add a two digit increment to a filename]], + Usage = [[local df = require "lib/dtutils.file" local result = df.filename_increment(filepath) filepath - string - filename to increment]], @@ -491,6 +324,12 @@ dtutils_file.libdoc.functions[#dtutils_file.libdoc.functions + 1] = { "01" is added to the basename. If the filename already has an increment, then 1 is added to it and the filename returned.]], Return_Value = [[result - string - the incremented filename]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], } function dtutils_file.filename_increment(filepath) @@ -520,4 +359,36 @@ function dtutils_file.filename_increment(filepath) return incremented_filepath end + +dtutils_file.libdoc.functions["create_unique_filename"] = { + Name = [[create_unique_filename]], + Synopsis = [[create a unique filename from the supplied argment]], + Usage = [[local df = require "lib/dtutils.file" + + local result = df.create_unique_filename(filepath) + filepath - string - the path and filename requested]], + Description = [[create_unique_filename takes a requested filepath and checks to see if + it exists. If if doesn't then it's returned intact. If it already exists, then a two + digit increment is added to the filename and it is tested again. The increment keeps + increasing until either a unique filename is found or there have been 100 attempts.]], + Return_Value = [[result - string - the incremented filename]], + Limitations = [[create_unique_filename will only attempt 100 increments.]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], +} + +function dtutils_file.create_unique_filename(filepath) + while dtutils_file.check_if_file_exists(filepath) do + filepath = dtutils_file.filename_increment(filepath) + -- limit to 99 more exports of the original export + if string.match(dtfileutils.get_basename(filepath), "_(d-)$") == "99" then + break + end + end + return filepath +end + return dtutils_file diff --git a/lib/dtutils/log.lua b/lib/dtutils/log.lua new file mode 100644 index 0000000..dcdc509 --- /dev/null +++ b/lib/dtutils/log.lua @@ -0,0 +1,291 @@ + +local dtutils_log = {} + +dtutils_log.libdoc = { + Name = [[dtutils.log]], + Synopsis = [[darktable lua logging library]], + Usage = [[local log = require "lib/dtutils.log"]], + Description = [[log provides a multi-level logging solution for use with + the darktable lua scripts. With this library you can leave log messages + scattered through out your code and only turn them on as necessary.]], + Return_Value = [[log - library - the darktable lua logging functions]], + Limitations = [[]], + Example = [[local log = require "lib/dtutils.log" + + local cur_level = log.log_level() + log.log_level(log.warn) + + print out warning, error and success messages as code is running + + log.log_level(debug) + + print out debugging messages too because this isnt working + + log.log_level(info) + + I want to make sure this is working ok + + log.log_level(cur_level) + + reset the logging level back to normal]], + See_Also = [[]], + Reference = [[]], + License = [[This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see .]], + Copyright = [[Copyright (C) 2016 Bill Ferguson .]], + functions = {} +} + +local dt = require "darktable" +local dt_print_error = dt.print_error +-- work around until dt.print_log() +local dt_print_log = dt.print_error +local dt_print = dt.print + +-- set the default log levels + +dtutils_log.debug = { + label = "DEBUG:", + enabled = false, + engine = dt_print_log, + level = 1, +} +dtutils_log.info = { + label = "INFO:", + enable = false, + engine = dt_print_log, + level = 2, +} +dtutils_log.warn = { + label = "WARN:", + enabled = false, + engine = dt_print_log, + level = 3, +} +dtutils_log.error = { + label = "ERROR:", + enabled = true, + engine = dt_print_error, + level = 4, +} +dtutils_log.success = { + label = "SUCCESS:", + enabled = true, + engine = dt_print_log, + level = 5, +} +dtutils_log.screen = { + label = "", + enabled = true, + engine = dt_print, + level = 9, +} +dtutils_log.always = { + label = "", + enabled = true, + engine = dt_print_log, + level = 9, +} +dtutils_log.critical = { + label = "CRITICAL:", + enabled = true, + engine = print, + level = 9, +} + +dtutils_log.libdoc.functions["caller"] = { + Name = [[caller]], + Synopsis = [[get the name and line number of the calling routine]], + Usage = [[local log = require "lib/dtutils.log" + +result = log.caller(level) + level - number - the number of stack levels to go down to retrieve the caller routine information]], + Description = [[caller gets the name and line number of the calling routine and returns it]], + Return_Value = [[result - string - the name and line number of the calling function or 'callback: ' if the attempt to get the + caller returns nil]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], +} + +function dtutils_log.caller(level) + local name = debug.getinfo(level).name + local lineno = nil + local source = nil + if name then + lineno = debug.getinfo(level).currentline + -- returns the path to the file prefixed with @ + source = debug.getinfo(level).source + -- we just need the filename, so grab it from the string + -- Thanks, Tobias Jakobs :-) + source = string.match(source, "@.-([^\\/]-%.?[^%.\\/]*)$") + return name .. ": " .. source .. ": " .. lineno .. ":" + else + return "callback:" + end +end + +dtutils_log.libdoc.functions["msg"] = { + Name = [[msg]], + Synopsis = [[print a log message]], + Usage = [[local log = require "lib/log" + + log.msg(level, ...) + level - table - the type of message, one of: + log.debug - debugging messages + log.info - informational messages + log.warn - warning messages + log.error - error messages + log.success - success messages + log.always - an internal message for debugging + log.screen - output 1 line of text to the screen + log.critical - print a critical message to the console + + ... - string(s) - the message to print, which could be a comma separated set of strings]], + Description = [[msg checks the level to see if it is enabled, then prints the level type and message if it is. + Messages are output using the engine configured in each log level.]], + Return_Value = [[]], + Limitations = [[If you use log.msg in a callback, the name of the calling routine can't be determined. A solution + is to include some means of reference such as the name of the callback as an argument, i.e. + + log.msg(log.debug, "libPlugin.format_combobox:", "value is " .. self.value) + + which would result in + + DEBUG: callback: libPlugin.format_combobox: value is JPEG]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], +} + +function dtutils_log.msg(level, ...) + if level.enabled then + local args = {...} + local call_level = 3 + if level == dtutils_log.always then + call_level = args[1] + table.remove(args, 1) + end + local log_msg = level.label + if level.engine ~= dt_screen and call_level ~= 0 then + log_msg = log_msg .. dtutils_log.caller(call_level) .. " " + elseif log_msg:len() > 2 then + log_msg = log_msg .. " " + end + for i = 1,#args do + log_msg = log_msg .. tostring(args[i]) .. " " + end + level.engine(log_msg) + end +end + +dtutils_log.libdoc.functions["log_level"] = { + Name = [[log_level]], + Synopsis = [[get or set the log level]], + Usage = [[local log = require "lib/log" + + local result = log.log_level(...) + ... - arguments - if none is supplied, then the current log level is returned as one of: + log.debug, log.info, log.warn, log.error, log.success. If one of log.debug, log.info, log.warn, + log.error, or log.success is supplied as the argument then the log level is set to that value. All + log levels greater than or equal in value will be enabled. Any levels of lesser value will be disabled.]], + Description = [[log_level gets and sets the logging level. When called with no arguments the current log level + is returned as one of log.debug, log.info, log.warn, log.error, or log.success. When called with one of log.debug, + log.info, log.warn, log.error or log.success then the log level is set. When setting the log level all levels + equal or greater are enabled and any of lesser value are disabled. See the example.]], + Return_Value = [[result - the log level, one of log.debug, log.info, log.warn, log.error or log.success]], + Limitations = [[]], + Example = [[Assume that the current log level is log.error. Calling log.log_level() will return log.error. + Calling log.log_level(log.info) will leave log.debug disabled, and enable log.info, log.warn, log.error and + log.success. log.info will be returned as the log_level.]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], +} + +function dtutils_log.log_level(...) + local levels = {"debug", "info", "warn", "error", "success"} + local args = {...} + local log_level = nil + if #args > 0 then + log_level = args[1] + if log_level == dtutils_log.critical or + log_level == dtutils_log.screen or + log_level == dtutils_log.always then + -- these aren't valid for setting levels + return nil + else + for _,v in ipairs(levels) do + if dtutils_log[v].level >= log_level.level then + dtutils_log[v].enabled = true + else + dtutils_log[v].enabled = false + end + end + end + else + for _,v in ipairs(levels) do + if dtutils_log[v].enabled == true then + log_level = dtutils_log[v] + end + end + end + return log_level +end + +dtutils_log.libdoc.functions["engine"] = { + Name = [[engine]], + Synopsis = [[get and set the output engine]], + Usage = [[local log = require "lib/dtutils.log" + +result = log.engine(level, ...) + level - table - the log level to get or set the engine for, one of log.debug, log.info, log.warn, log.error + log.success, log.always, log.screen, log.critical + ... - function - the output function, one of dt.print, dt.print_error, dt.print_log, print + if not function is included, the current engine is returned for the specified log level]], + Description = [[engine returns the output engine for the specified log level if a second argument is not + supplied. If a function is supplied as the second argment, then the output engine for the specified log level + is set to that.]], + Return_Value = [[result - function - the current output engine]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], + License = [[]], + Copyright = [[]], +} + +function dtutils_log.print_engine(level, ...) + local engines = {"dt_print", "dt_print_error", "dt_print_log", "print"} + local args = {...} + local cur_engine = "" + if #args == 0 then + cur_engine = level.engine + else + for _,v in ipairs(engines) do + if args[1] == v then + level.engine = args[1] + cur_engine = level.engine + end + end + end + return cur_engine +end + +return dtutils_log diff --git a/lib/dtutils/processor.lua b/lib/dtutils/processor.lua deleted file mode 100644 index b79e0b9..0000000 --- a/lib/dtutils/processor.lua +++ /dev/null @@ -1,266 +0,0 @@ ---[[ - This file is part of darktable, - copyright (c) 2016 Bill Ferguson - - darktable is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - darktable is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with darktable. If not, see . -]] - -local dtutils_processor = {} - -dtutils_processor.libdoc = { - Sections = {"Name", "Synopsis", "Description", "License"}, - Name = [[dtutils.processor - Darktable lua functions for building processor scripts]], - Synopsis = [[local dp = require "lib/dtutils.processor"]], - Description = [[dtutils.processor provides common functions used for building scripts - that send images out to an external process, process them, and return the result (i.e. processors).]], - License = [[This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see .]], - functions = {} -} - -local dt = require "darktable" -local dtutils = require "lib/dtutils" -local df = require "lib/dtutils.file" -local log = require "lib/libLog" - -local gettext = dt.gettext - -dt.configuration.check_version(...,{3,0,0}) - --- Tell gettext where to find the .mo file translating messages for a particular domain --- This should be $HOME/.config/darktable/lua/locale/ -gettext.bindtextdomain("dtutils",dt.configuration.config_dir.."/lua/locale/") - -local function _(msgid) - return gettext.dgettext("dtutils.processor", msgid) -end - ---[[ - NAME - exporter_status - show the status while exporting images - - SYNOPSIS - local dp = require "lib/dtutils.processor" - - local result = dp.exporter_status(storage, image, format, filename, number, total, high_quality, extra_data) - storage - dt_imageio_module_storage_t - the storage that the status is being shown for - image - dt_lua_image_t - the current image - format - dt_imageio_module_format_t - the format of the export image - filename - string - the filename being exported to - number - integer - the number of this image in the sequence - total - integer - the total number of images being exported - high_quality - boolean - extra_data - extra data from the storage - - DESCRIPTION - exporter_status runs prior to each image being exported and prints out a status that lets the user - know how many images, out of the total, have been exported - - RETURN VALUE - none - -]] - -dtutils_processor.libdoc.functions[#dtutils_processor.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[exporter_status - show the status while exporting images]], - Synopsis = [[local dp = require "lib/dtutils.processor" - - local result = dp.exporter_status(storage, image, format, filename, number, total, high_quality, extra_data) - storage - dt_imageio_module_storage_t - the storage that the status is being shown for - image - dt_lua_image_t - the current image - format - dt_imageio_module_format_t - the format of the export image - filename - string - the filename being exported to - number - integer - the number of this image in the sequence - total - integer - the total number of images being exported - high_quality - boolean - extra_data - extra data from the storage]], - Description = [[exporter_status runs prior to each image being exported and prints out a status that lets the user - know how many images, out of the total, have been exported]], - Return_Value = [[none]], -} - -function dtutils_processor.exporter_status(storage, image, format, filename, - number, total, high_quality, extra_data) - dt.print(string.format(_("Export Image %i/%i"), number, total)) -end - ---[[ - NAME - extract_image_list - assemble the exported image filenames from an image_table into a string - - SYNOPSIS - local dp = require "lib/dtutils.processor" - - result = dp.extract_image_list(image_table) - image_table - table - a table of images such as supplied by the exporter or by libPlugin.build_image_table - - DESCRIPTION - extract_image_list concatenates the exported image names into a space separated string suitable for - passing as an argument to a processor. Each filename is bracketed with single quotes to protect against - spaces and special characters in the filepath - - RETURN VALUE - result - string - the assembled image list on success, or an empty image list on error - -]] - -dtutils_processor.libdoc.functions[#dtutils_processor.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[extract_image_list - assemble the exported image filenames from an image_table into a string]], - Synopsis = [[local dp = require "lib/dtutils.processor" - - result = dp.extract_image_list(image_table) - image_table - table - a table of images such as supplied by the exporter or by libPlugin.build_image_table]], - Description = [[extract_image_list concatenates the exported image names into a space separated string suitable for - passing as an argument to a processor. Each filename is bracketed with single quotes to protect against - spaces and special characters in the filepath]], - Return_Value = [[result - string - the assembled image list on success, or an empty image list on error]], -} - -function dtutils_processor.extract_image_list(image_table) - local img_list = "" - for _,exp_img in pairs(image_table) do - img_list = img_list .. " " .. "'" .. exp_img .. "'" - end - return img_list -end - ---[[ - NAME - extract_collection_path - extract the collection path from an image table - - SYNOPSIS - local dp = require "lib/dtutils.processor" - - local result = dp.extract_collection_path(image_table) - image_table - table - a table of images such as supplied by the exporter or by libPlugin.build_image_table - - DESCRIPTION - extract_collection_path looks at the first image in the image_table and returns the path - - RETURN VALUE - result - string - the collection path on success, or nil if there was an error - - LIMITATIONS - The collection path is determined from the first image. If the table consists of images from different - collections, then only the first collection is used. - -]] - -dtutils_processor.libdoc.functions[#dtutils_processor.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value", "Limitations"}, - Name = [[extract_collection_path - extract the collection path from an image table]], - Synopsis = [[local dp = require "lib/dtutils.processor" - - local result = dp.extract_collection_path(image_table) - image_table - table - a table of images such as supplied by the exporter or by libPlugin.build_image_table]], - Description = [[extract_collection_path looks at the first image in the image_table and returns the path]], - Return_Value = [[result - string - the collection path on success, or nil if there was an error]], - Limitations = [[The collection path is determined from the first image. If the table consists of images from different - collections, then only the first collection is used.]], -} - -function dtutils_processor.extract_collection_path(image_table) - collection_path = nil - for i,_ in pairs(image_table) do - collection_path = i.path - break - end - return collection_path -end - ---[[ - NAME - make_output_filename- make an output filename from an image list - - SYNOPSIS - local dp = require "lib/dtutils.processor" - - local result = dtutils.make_output_filename(img_list) - img_list - string - a space separated list of filenames - - DESCRIPTION - make_output_filename takes a string of filenames, breaks them apart, then - combines them in a way that makes some sense. This is useful in routines - that do panoramas, hdr, or focus stacks. The returned filename is a representation - of the files used to construct the image. If there are 3 or fewer images, then the file - basenames are concatenated with a separator. If there is more than 3 images, the first and - last file basenames are concatenated with a separator. - - RETURN VALUE - result - string - the constructed filename on success, nil on error - -]] - -dtutils_processor.libdoc.functions[#dtutils_processor.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[make_output_filename- make an output filename from an image list]], - Synopsis = [[local dp = require "lib/dtutils.processor" - - local result = dtutils.make_output_filename(img_list) - img_list - string - a space separated list of filenames]], - Description = [[make_output_filename takes a string of filenames, breaks them apart, then - combines them in a way that makes some sense. This is useful in routines - that do panoramas, hdr, or focus stacks. The returned filename is a representation - of the files used to construct the image. If there are 3 or fewer images, then the file - basenames are concatenated with a separator. If there is more than 3 images, the first and - last file basenames are concatenated with a separator.]], - Return_Value = [[result - string - the constructed filename on success, nil on error]], -} - -function dtutils_processor.make_output_filename(img_list) - local images = {} - local cnt = 1 - local max_distinct_names = 3 - local name_separator = "-" - local outputFileName = nil - log.msg(log.debug, "img_list is ", img_list) - - local result = dtutils.split(img_list, " ") - table.sort(result) - for _,img in pairs(result) do - images[cnt] = df.get_basename(img) - cnt = cnt + 1 - end - - cnt = cnt - 1 - - if cnt > 1 then - if cnt > max_distinct_names then - -- take the first and last - outputFileName = images[1] .. name_separator .. images[cnt] - else - -- join them - outputFileName = dtutils.join(images, name_separator) - end - else - -- return the single name - outputFileName = images[cnt] - end - - return outputFileName -end - -return dtutils_processor diff --git a/lib/dtutils/extensions.lua b/lib/dtutils/string.lua similarity index 58% rename from lib/dtutils/extensions.lua rename to lib/dtutils/string.lua index ca37152..db04423 100644 --- a/lib/dtutils/extensions.lua +++ b/lib/dtutils/string.lua @@ -1,22 +1,15 @@ ---[[ - - NAME - dtutils/extensions.lua - a library of extenstions to the lua libraries - - SYNOPSIS - require "lib/dtutils.extensions" - - DESCRIPTION - This library contains extensions to the lua libraries. - -]] - -local dtutils_extensions = {} -dtutils_extensions.libdoc = { - Sections = {"Name", "Synopsis", "Description", "License"}, - Name = "dtutils.extensions - a library of extenstions to the lua libraries", - Synopsis = [[require "lib/dtutils.extensions"]], - Description = [[This library contains extensions to the lua libraries.]], +local dtutils_string = {} +dtutils_string.libdoc = { + Name = [[dtutils.string]], + Synopsis = [[a library of string utilities for use in darktable lua scripts]], + Usage = [[local ds = require "lib/dtutils.string"]], + Description = [[This library contains string manipulation routines to aid in building + darktable lua scripts.]], + Return_Value = [[du - library - the darktable lua string library]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[]], License = [[This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or @@ -29,44 +22,29 @@ dtutils_extensions.libdoc = { You should have received a copy of the GNU General Public License along with this program. If not, see .]], + Copyright = [[Copyright (c) 2016 Bill Ferguson ]], functions = {} } ---[[ - - NAME - string.strip_accents - strip accents from characters +dtutils_string.libdoc.functions["strip_accents"] = { + Name = [[strip_accents]], + Synopsis = [[strip accents from characters]], + Usage = [[local ds = require "lib/dtutils.string" - SYNOPSIS - require "lib/dtutils.extensions" - - result = string.strip_accents(str) - str - string - the string with characters that need accents removed - - DESCRIPTION - strip_accents removes accents from accented characters returning the - unaccented character. - - RETURN VALUE - result - string - the string containing unaccented characters - -]] - -dtutils_extensions.libdoc.functions[#dtutils_extensions.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[string.strip_accents - strip accents from characters]], - Synopsis = [[require "lib/dtutils.extensions" - - result = string.strip_accents(str) + local result = ds.strip_accents(str) str - string - the string with characters that need accents removed]], Description = [[strip_accents removes accents from accented characters returning the unaccented character.]], Return_Value = [[result - string - the string containing unaccented characters]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[Copied from https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/]], + License = [[]], + Copyright = [[]], } --- Strip accents from a string --- Copied from https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/ -function string.strip_accents( str ) +function dtutils_string.strip_accents( str ) local tableAccents = {} tableAccents["à"] = "a" tableAccents["á"] = "a" @@ -134,44 +112,27 @@ function string.strip_accents( str ) end ---[[ - - NAME - string.escape_xml_characters - escape characters for xml documents - - SYNOPSIS - require "lib/dtutils.extensions" +dtutils_string.libdoc.functions["escape_xml_characters"] = { + Name = [[escape_xml_characters]], + Synopsis = [[escape characters for xml documents]], + Usage = [[local ds = require "lib/dtutils.string" - result = string.escape_xml_characters(str) - str - string - the string that needs escaped - - DESCRIPTION - escape_xml_characters provides the escape sequences for - "&", '"', "'", "<", and ">" with the corresponding "&", - """, "'", "<", and ">". - - RETURNN VALUE - result - string - the string containing escapes for the xml characters - -]] - -dtutils_extensions.libdoc.functions[#dtutils_extensions.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = "string.escape_xml_characters - escape characters for xml documents", - Synopsis = [[ require "lib/dtutils.extensions" - - result = string.escape_xml_characters(str) + local result = ds.escape_xml_characters(str) str - string - the string that needs escaped]], Description = [[escape_xml_characters provides the escape sequences for "&", '"', "'", "<", and ">" with the corresponding "&", """, "'", "<", and ">".]], Return_Value = [[result - string - the string containing escapes for the xml characters]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents]], + License = [[]], + Copyright = [[]], } --- Escape XML characters -- Keep & first, otherwise it will double escape other characters --- https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents -function string.escape_xml_characters( str ) +function dtutils_string.escape_xml_characters( str ) str = string.gsub(str,"&", "&") str = string.gsub(str,"\"", """) @@ -182,4 +143,31 @@ function string.escape_xml_characters( str ) return str end -return dtutils_extensions +dtutils_string.libdoc.functions["urlencode"] = { + Name = [[urlencode]], + Synopsis = [[encode a string in a websage manner]], + Usage = [[local ds = require "lib/dtutils.string" + + local result = ds.urlencode(str) + str - string - the string that needs to be made websafe]], + Description = [[urlencode converts a string into a websafe version suitable for + use in a web browser.]], + Return_Value = [[result - string - a websafe string]], + Limitations = [[]], + Example = [[]], + See_Also = [[]], + Reference = [[https://forums.coronalabs.com/topic/43048-remove-special-characters-from-string/]], + License = [[]], + Copyright = [[]], +} + +function dtutils_string.urlencode(str) + if (str) then + str = string.gsub (str, "\n", "\r\n") + str = string.gsub (str, "([^%w ])", function () return string.format ("%%%02X", string.byte()) end) + str = string.gsub (str, " ", "+") + end + return str +end + +return dtutils_string diff --git a/lib/libLog.lua b/lib/libLog.lua deleted file mode 100644 index 052a9da..0000000 --- a/lib/libLog.lua +++ /dev/null @@ -1,378 +0,0 @@ ---[[ - - libLog.lua - darktable lua logging library - - Copyright (C) 2016 Bill Ferguson . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -]] - -local libLog = {} -libLog.libdoc = { - Sections = {"Name", "Synopsis", "Description", "License", "Copyright"}, - Name = "libLog - darktable lua logging library", - Synopsis = [[local log = require "lib/libLog"]], - Description = [[libLog provides a multi-level logging solution for use with - the darktable lua scripts.]], - License = [[This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see .]], - Copyright = "Copyright (C) 2016 Bill Ferguson .", - functions = {} -} - -local dt = require "darktable" - --- set the default log levels - -libLog.debug = {"DEBUG:", false} -libLog.info = {"INFO:", false} -libLog.warn = {"WARN:", false} -libLog.error = {"ERROR:", true} -libLog.success = {"SUCCESS:", true} - -libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = "caller - get the name of the calling routine", - Synopsis = [[local log = require "lib/libLog" - -result = log.caller(level) - level - number - the number of stack levels to go down to retrieve the caller routine information]], - Description = "caller gets the name of the calling routine and returns it", - Return_Value = [[result - string - the name and line number of the calling function or 'callback: ' if the attempt to get the - caller returns nil]], -} - ---[[ - NAME - caller - get the name of the calling routine - - SYNOPSIS - local log = require "lib/libLog" - - local result = log.caller(level) - level - number - the number of stack levels to go down to retrieve the caller routine information - - DESCRIPTION - caller gets the name of the calling routine and returns it - - RETURN VALUE - result - string - the name of the calling function and line number or 'callback: ' if the attempt to get the - caller returns nil - - -]] - -function libLog.caller(level) - local name = debug.getinfo(level).name - local lineno = nil - local source = nil - if name then - lineno = debug.getinfo(level).currentline - -- returns the path to the file prefixed with @ - source = debug.getinfo(level).source - -- we just need the filename, so grab it from the string - -- Thanks, Tobias Jakobs :-) - source = string.match(source, "@.-([^\\/]-%.?[^%.\\/]*)$") - return name .. ": " .. source .. ": " .. lineno .. ":" - else - return "callback:" - end -end - -libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Limitations"}, - Name = "msg - print a log message", - Synopsis = [[local log = require "lib/libLog" - - log.msg(level, ...) - level - table - the type of message, one of: - libLog.debug - debugging messages - libLog.info - informational messages - libLog.warn - warning messages - libLog.error - error messages - libLog.success - success messages - ... - string(s) - the message to print, which could be a comma separated set of strings]], - Description = [[msg checks the level to see if it is enabled, then prints the level type and message if it is. - debug messages print straight to the console, info and warn messages to dt.print_error() and error - and success to dt.print()]], - Limitations = [[If you use libLog.msg in a callback, the name of the calling routine can't be determined. A solution - is to include some means of reference such as the name of the callback as an argument, i.e. - - libLog.msg(libLog.debug, "libPlugin.format_combobox:", "value is " .. self.value) - - which would result in - - DEBUG: callback: libPlugin.format_combobox: value is JPEG]], -} - ---[[ - NAME - msg - print a log message - - SYNOPSIS - local log = require "lib/libLog" - - log.msg(level, ...) - level - table - the type of message, one of: - libLog.debug - debugging messages - libLog.info - informational messages - libLog.warn - warning messages - libLog.error - error messages - libLog.success - success messages - ... - string(s) - the message to print, which could be a comma separated set of strings - - DESCRIPTION - msg checks the level to see if it is enabled, then prints the level type and message if it is. - debug messages print straight to the console, info and warn messages to dt.print_error() and error - and success to dt.print() - - RETURN VALUE - none - - LIMITATIONS - If you use libLog.msg in a callback, the name of the calling routine can't be determined. A solution - is to include some means of reference such as the name of the callback as an argument, i.e. - - libLog.msg(libLog.debug, "libPlugin.format_combobox:", "value is " .. self.value) - - which would result in - - DEBUG: callback: libPlugin.format_combobox: value is JPEG - -]] - -function libLog.msg(level, ...) - local message = {...} - if level[2] == true then - libLog.print(level[1], libLog.caller(3), unpack(message)) - end -end - -libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value", "Reference"}, - Name = "print - print the supplied arguments", - Synopsis = [[local log = require "lib/libLog" - - log.print(...) - ... - arguments to be printed that are converted with tostring()]], - Description = [[print loops through the arguments converting each to a string then writing - them to stdout. Spaces are put between each argument on output.]], - Return_Value = "none", - Reference = "http://stackoverflow.com/questions/7148678/lua-print-on-the-same-line", -} - ---[[ - NAME - libLog.print - print the supplied arguments - - SYNOPSIS - local log = require "lib/libLog" - - log.print(...) - ... - arguments to be printed that are converted with tostring() - - DESCRIPTION - print loops through the arguments converting each to a string then writing - them to stdout. Spaces are put between each argument on output. - - RETURN VALUE - none - - REFERENCE - http://stackoverflow.com/questions/7148678/lua-print-on-the-same-line - -]] - -function libLog.print(...) - local write = io.write - local n = select("#",...) - for i = 1,n do - local v = tostring(select(i,...)) - write(v) - if i~=n then - write(' ') - end - end - write('\n') -end - -libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[set_level - set the logging level]], - Synopsis = [[local log = require "lib/libLog" - - log.set_level(level) - level - string - a string specifying the level, one of: "debug", "info", "warn", "error", "success"]], - Description = [[set_level sets the logging level to the level specified. Every level above the specified level - is also enabled, therefore specifying "debug" would turn on all levels and specifying "success" - would turn all levels off except libLog.success.]], - Return_Value = "none", -} - ---[[ - NAME - set_level - set the logging level - - SYNOPSIS - local log = require "lib/libLog" - - log.set_level(level) - level - string - a string specifying the level, one of: "debug", "info", "warn", "error", "success" - - DESCRIPTION - set_level sets the logging level to the level specified. Every level above the specified level - is also enabled, therefore specifying "debug" would turn on all levels and specifying "success" - would turn all levels off except libLog.success. - - RETURN VALUE - none - -]] - -function libLog.set_level(level) - level = level:lower() - if string.match(level, "debug") then - -- turn everything on - libLog.debug[2] = true - libLog.info[2] = true - libLog.warn[2] = true - libLog.error[2] = true - libLog.success[2] = true - elseif string.match(level, "info") then - -- turn off debug and everything else on - libLog.debug[2] = false - libLog.info[2] = true - libLog.warn[2] = true - libLog.error[2] = true - libLog.success[2] = true - elseif string.match(level, "warn") then - -- turn off debug and info and everything else on - libLog.debug[2] = false - libLog.info[2] = false - libLog.warn[2] = true - libLog.error[2] = true - libLog.success[2] = true - elseif string.match(level, "error") or string.match("reset") then - -- everything off except error and success - libLog.debug[2] = false - libLog.info[2] = false - libLog.warn[2] = false - libLog.error[2] = true - libLog.success[2] = true - elseif string.match(level, "success") then - -- everything off except success - libLog.debug[2] = false - libLog.info[2] = false - libLog.warn[2] = false - libLog.error[2] = false - libLog.success[2] = true - else - -- leave everything unchanged and return - return - end -end - -libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description", "Return_Value"}, - Name = [[get_level - get the current logging level]], - Synopsis = [[local log = require "lib/libLog" - - local result = libLog.get_level()]], - Description = "get_level returns a string representing the current log level.", - Return_Value = [[result - string - one of "debug", "info", "warn", "error", or "success"]], -} - ---[[ - NAME - get_level - get the current logging level - - SYNOPSIS - local log = require "lib/libLog" - - local result = log.get_level() - - DESCRIPTION - get_level returns a string representing the current log level. - - RETURN VALUE - result - string - one of "debug", "info", "warn", "error", or "success" - -]] - -function libLog.get_level() - local result = nil - if libLog.debug[2] == true then - result = "debug" - elseif libLog.info[2] == true then - result = "info" - elseif libLog.warn[2] == true then - result = "warn" - elseif libLog.error[2] == true then - result = "error" - elseif libLog.success[2] == true then - result = "success" - end - return result -end - -libLog.libdoc.functions[#libLog.libdoc.functions + 1] = { - Sections = {"Name", "Synopsis", "Description"}, - Name = [[always - always write out a log message]], - Synopsis = [[local log = require "lib/libLog" - - log.always(level, ...) - level - number - the number of stack levels to go back to identify the caller - ... - string(s) - the message to print]], - Description = [[always is meant specifically for the dtutils.debug library, but may be used for other - purposes. always is independent of the log level setting so that it will always work. - The number of stack levels to look back for the caller may be specified. It is normally - 3 when called from a routine, but is 4 when called from the debugging routines since the - debugging routines add another stack level.]], -} - ---[[ - NAME - always - always write out a log message - - SYNOPSIS - local log = require "lib/libLog" - - log.always(level, ...) - level - number - the number of stack levels to go back to identify the caller - ... - string(s) - the message to print - - DESCRIPTION - always is meant specifically for the dtutils.debug library, but may be used for other - purposes. always is independent of the log level setting so that it will always work. - The number of stack levels to look back for the caller may be specified. It is normally - 3 when called from a routine, but is 4 when called from the debugging routines since the - debugging routines add another stack level. -]] - -function libLog.always(level, ...) - local message = {...} - libLog.print(libLog.caller(level), unpack(message)) -end - -return libLog diff --git a/tools/get_lib_manpages.lua b/tools/get_lib_manpages.lua index 4dbed6c..24999f1 100644 --- a/tools/get_lib_manpages.lua +++ b/tools/get_lib_manpages.lua @@ -6,21 +6,25 @@ local dt = require "darktable" local du = require "lib/dtutils" +local log = require "lib/dtutils.log" local libname = nil dt.configuration.check_version(...,{3,0,0}) +local keys = {"Name", "Synopsis", "Usage", "Description", "Return_Value", "Limitations", + "Example", "See_Also", "Reference", "License", "Copyright"} + local function output_man(d) - local parts = du.split(d[d.Sections[1]], " - ") + local name = d["Name"] if not libname then - libname = parts[1] + libname = name end - local fname = "/tmp/" .. parts[1] .. ".3" + local fname = "/tmp/" .. name .. ".3" local mf = io.open(fname, "w") if mf then - mf:write(".TH " .. string.upper(parts[1]) .. " 3 \"\" \"\" \"Darktable " .. libname .. " functions\"\n") - for _,section in pairs(d.Sections) do - if d[section] then + mf:write(".TH " .. string.upper(name) .. " 3 \"\" \"\" \"Darktable " .. libname .. " functions\"\n") + for _,section in ipairs(keys) do + if d[section]:len() > 0 then mf:write(".SH " .. string.upper(string.gsub(section, "_", " ")) .. "\n") mf:write(d[section] .. "\n") end diff --git a/tools/get_libdoc.lua b/tools/get_libdoc.lua index 706b025..de6615d 100644 --- a/tools/get_libdoc.lua +++ b/tools/get_libdoc.lua @@ -8,9 +8,12 @@ local dt = require "darktable" dt.configuration.check_version(...,{3,0,0}) +local keys = {"Name", "Synopsis", "Usage", "Description", "Return_Value", "Limitations", + "Example", "See_Also", "Reference", "License", "Copyright"} + local function output_doc(d) - for _,section in pairs(d.Sections) do - if d[section] then + for _,section in ipairs(keys) do + if d[section]:len() > 0 then print(string.upper(string.gsub(section, "_", " "))) print("\t" .. d[section] .. "\n") end From 4fccfbf51dff378a1322b760007965cea1df527d Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Mon, 24 Oct 2016 12:09:04 -0400 Subject: [PATCH 3/4] Added checks for binaries used to generate the pdf man pages --- tools/get_lib_manpages.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/get_lib_manpages.lua b/tools/get_lib_manpages.lua index 24999f1..23400aa 100644 --- a/tools/get_lib_manpages.lua +++ b/tools/get_lib_manpages.lua @@ -6,6 +6,7 @@ local dt = require "darktable" local du = require "lib/dtutils" +local df = require "lib/dtutils.file" local log = require "lib/dtutils.log" local libname = nil @@ -30,7 +31,15 @@ local function output_man(d) end end mf:close() - os.execute("groff -man " .. fname .. " | ps2pdf - " .. fname .. ".pdf") + if df.check_if_bin_exists("groff") then + if df.check_if_bin_exists("ps2pdf") then + os.execute("groff -man " .. fname .. " | ps2pdf - " .. fname .. ".pdf") + else + log.msg(log.error, "Missing ps2pdf. Can't generate pdf man pages.") + end + else + log.msg(log.error, "Missing groff. Can't generate pdf man pages.") + end else log.msg(log.error, "Can't open file " .. fname .. "for writing") end From dab02823ff335a8b4cec2b0fc0117051f7f956c6 Mon Sep 17 00:00:00 2001 From: Bill Ferguson Date: Mon, 24 Oct 2016 19:23:04 -0400 Subject: [PATCH 4/4] Fixed log bug in dprint function --- lib/dtutils/debug.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dtutils/debug.lua b/lib/dtutils/debug.lua index bb5d02c..277aa8f 100644 --- a/lib/dtutils/debug.lua +++ b/lib/dtutils/debug.lua @@ -128,7 +128,7 @@ M.libdoc.functions["dprint"] = { } function M.dprint(...) - log.always(4, dt.debug.dump(...)) + log.msg(log.always, 4, dt.debug.dump(...)) end M.libdoc.functions["terse_dump"] = {