diff --git a/env.lua b/env.lua
index 73663aa..2f1c9a6 100644
--- a/env.lua
+++ b/env.lua
@@ -5,7 +5,7 @@ env.app = {
name = "gemwriter",
exec_name = "gemwriter",
version = "0.3",
- last_updated = "2022-08-05",
+ last_updated = "2022-08-06",
}
env.defaults = {
@@ -18,6 +18,7 @@ env.defaults = {
page = "page.gmi",
post = "post.gmi",
},
+ lang_opts = { "en_US", "fr_FR" },
post_slug = "untitled",
post_slug_date_format = "%Y-%m-%d",
-- Atom feed date format
@@ -27,13 +28,24 @@ env.defaults = {
page_slug = os.date("%Y%m%d-%H%M%S"),
}
+-- Command-line keywords
+env.cli_opts = {
+ config = "config",
+ page = "page",
+ post = "post",
+ index = "index",
+ publish = "publish",
+ help = "help",
+ version = "version",
+}
+
-- Configurable settings
env.toml_vars = {
general = "general",
capsules = "capsules",
}
env.general = {
- app_lang = "en",
+ app_lang = "en_US",
main_capsule = "main",
}
env.capsules = {
diff --git a/gemwriter.lua b/gemwriter.lua
index ef5b156..9557927 100644
--- a/gemwriter.lua
+++ b/gemwriter.lua
@@ -1,5 +1,5 @@
local env = require("env")
-local lang = require("lang.en")
+local lang = require("lang.en_US")
local util = require("util")
@@ -8,11 +8,32 @@ writer.docs = {}
writer.conf = {}
writer.posts = {}
+
+writer.docs.get_lang_opts = [[
+ Return a table of available language translations for the app interface.
+ ]]
+function writer.get_lang_opts()
+ local lang_opts = {}
+ for l = 1, #env.defaults.lang_opts do
+ if util.module_exists("lang." .. env.defaults.lang_opts[l]) then
+ table.insert(lang_opts, env.defaults.lang_opts[l])
+ end
+ end
+ return lang_opts
+end
+
+
writer.docs.gen_config = [[
Generate a default config directory.
]]
-function writer.gen_config()
- writer.conf.config_dir = util.replace_shell_vars(env.defaults.config_dir)
+function writer.gen_config(lang_pref)
+ -- Set lang
+ if lang_pref ~= nil and util.module_exists("lang." .. lang_pref) then
+ lang = require("lang." .. lang_pref)
+ env.defaults_toml = string.gsub(env.defaults_toml, env.general.app_lang,
+ lang_pref)
+ end
+
util.make_dir(writer.conf.config_dir)
for name, file in pairs(env.defaults.config_files) do
-- Check each file individually anyway to avoid overwriting existing
@@ -106,7 +127,9 @@ function writer.parse_config(config_file)
end
-- Set lang
- lang = require("lang." .. writer.conf.app_lang)
+ if util.module_exists("lang." .. writer.conf.app_lang) then
+ lang = require("lang." .. writer.conf.app_lang)
+ end
-- Custom templates override lang defaults (ignore config)
for name, file in pairs(env.defaults.config_files) do
@@ -119,40 +142,23 @@ end
writer.docs.load_config = [[
- Check whether there is an existing config and load it if found. Exit if a
- capsule is not found.
+ Load an existing config. Exit if a capsule is not found.
]]
function writer.load_config(cap_id)
- writer.conf.config_dir = util.replace_shell_vars(env.defaults.config_dir)
- local config_file = util.read_file(writer.conf.config_dir .. "/" ..
- env.defaults.config_files.config)
- local config_new = false
-
- -- No config found
- if (config_file == "") and (not config_new) then
- writer.gen_config()
- config_new = true
+ -- Check capsule id exists, abort if no valid capsule found
+ if (cap_id == nil) or (string.find(cap_id, " ") ~= nil) then
+ writer.conf.cap_id = env.general.main_capsule
+ else
+ writer.conf.cap_id = cap_id
end
-
- -- Config found, read the configuration and load the values to an
- -- associative table, writer.conf.
- if (config_file ~= "") and (not config_new) then
- -- Check capsule id exists, abort if no valid capsule found
- if (cap_id == nil) or (string.find(cap_id, " ") ~= nil) then
- writer.conf.cap_id = env.general.main_capsule
- else
- writer.conf.cap_id = cap_id
- end
- local cap_label = "%[" .. env.toml_vars.capsules .. "%." ..
- tostring(cap_id) .. "%]"
- if (string.find(config_file, cap_label) == nil) and
- (writer.conf.cap_id ~= env.general.main_capsule) then
- print(lang.errs.invalid_cap_id)
- os.exit()
- end
-
- writer.parse_config(config_file)
+ local cap_label = "%[" .. env.toml_vars.capsules .. "%." ..
+ tostring(cap_id) .. "%]"
+ if (string.find(writer.conf.config_file, cap_label) == nil) and
+ (writer.conf.cap_id ~= env.general.main_capsule) then
+ print(lang.errs.invalid_cap_id)
+ os.exit()
end
+ writer.parse_config(writer.conf.config_file)
end
@@ -348,40 +354,58 @@ cli.docs.handle_args = [[
any additional arguments to the functions.
]]
function cli.handle_args(args)
- if (args[1] ~= lang.opts.help) and (args[1] ~= lang.opts.version) then
- writer.load_config(args[2])
+ if (args[1] ~= env.cli_opts.help) or (args[1] ~= env.cli_opts.version) then
+ local config_new = false
+ writer.conf.config_dir = util.replace_shell_vars(env.defaults.config_dir)
+ writer.conf.config_file = util.read_file(writer.conf.config_dir .. "/" ..
+ env.defaults.config_files.config)
+ -- No config found
+ if (writer.conf.config_file == "") and (not config_new) then
+ writer.gen_config(args[2])
+ config_new = true
+ end
+ -- Config found, read the configuration and load the values to an
+ -- associative table, writer.conf.
+ if (writer.conf.config_file ~= "") and (not config_new) then
+ writer.load_config(args[2])
+ end
end
- if (args[1] == lang.opts.index) or (args[1] == lang.opts.publish) then
+ if (args[1] == env.cli_opts.index) or (args[1] == env.cli_opts.publish) then
writer.posts = writer.get_posts_meta()
if writer.conf.cap.gen_index_page then writer.gen_index_page() end
if writer.conf.cap.gen_atom_feed then writer.gen_atom_feed() end
end
- if args[1] == lang.opts.config then
- writer.load_config()
- print(lang.msgs.load_config .. writer.conf.config_dir)
+ if args[1] == env.cli_opts.config then
+ writer.gen_config(args[2])
+ print(string.format(lang.msgs.load_config, writer.conf.config_dir))
- elseif (args[1] == lang.opts.post) or (args[1] == lang.opts.page) then
+ elseif (args[1] == env.cli_opts.post) or (args[1] == env.cli_opts.page) then
local file_name = ""
if args[3] ~= nil then
file_name = writer.add_gemtext(args[3], args[1])
else
file_name = writer.add_gemtext(args[2], args[1])
end
- print(lang.msgs.add_gemtext .. file_name)
+ print(string.format(lang.msgs.add_gemtext, file_name))
- elseif args[1] == lang.opts.index then
+ elseif args[1] == env.cli_opts.index then
print(lang.msgs.index)
- elseif args[1] == lang.opts.publish then
+ elseif args[1] == env.cli_opts.publish then
writer.publish()
print(lang.msgs.publish)
- elseif args[1] == lang.opts.help then
- print(env.app.exec_name .. lang.msgs.help)
+ elseif args[1] == env.cli_opts.help then
+ print(string.format(lang.msgs.help_usage, env.app.exec_name) ..
+ string.format(lang.msgs.help_opts, env.cli_opts.config,
+ env.cli_opts.page, env.cli_opts.post, env.cli_opts.index,
+ env.cli_opts.publish, env.cli_opts.help, env.cli_opts.version) ..
+ string.format(lang.msgs.help_lang_opts,
+ table.concat(writer.get_lang_opts(), ", ")))
- elseif args[1] == lang.opts.version then
+ elseif args[1] == env.cli_opts.version then
print(env.app.name .. " " .. env.app.version ..
" (" .. env.app.last_updated .. ")")
end
diff --git a/lang/en.lua b/lang/en.lua
deleted file mode 100644
index 71222a2..0000000
--- a/lang/en.lua
+++ /dev/null
@@ -1,145 +0,0 @@
-local en = {}
-
--- Templates
-en.tpl_vars = {
- post = {
- author = "{{ post_author }}",
- content = "{{ post_content }}",
- date = "{{ post_date }}",
- summary = "{{ post_summary }}",
- tags = "{{ post_tags }}",
- title = "{{ post_title }}",
- url = "{{ post_url }}",
- },
- feed = {
- date = "{{ feed_date }}",
- url = "{{ feed_url }}",
- },
- index = {
- posts = "{{ posts }}",
- },
- log = {
- author = "{{ log_author }}",
- subtitle = "{{ log_subtitle }}",
- title = "{{ log_title }}",
- log_url = "{{ log_url }}",
- },
-}
-
-en.atom_header = [[
-
- {{ log_title }}
- {{ log_subtitle }}
- {{ feed_date }}
-
- {{ log_author }}
-
- {{ feed_url }}
-
-
-]]
-
-en.atom_entry = [[
-
- {{ post_url }}
-
- " .. [[
-
-
- {{ post_date }}
-
- {{ post_author }}
-
-
-
- " .. [[
-
-
-
- " .. [[
-
-
-
-]]
-
-en.atom_footer = [[]]
-
-en.post = [[---
-date: {{ post_date }}
----
-
-# {{ post_title }}
-
-
-
-
-## Links
-
-=> gemini:// link
-=> gemini:// link (img)
-=> https:// link (https)]]
-
-en.index = [[
-# {{ log_title }}
-{{ posts }}
-]]
-
-en.page = [[
-# {{ post_title }}
-
-## Heading 2
-### Heading 3
-
-List:
-
-*
-*
-*
-
-```
-Preformatted text
-```
-
-
-## Links
-
-=> gemini:// link
-=> gemini:// link (img)
-=> https:// link (https)]]
-
--- App command options and messages output
-en.opts = {
- config = "config",
- page = "page",
- post = "post",
- index = "index",
- publish = "publish",
- help = "help",
- version = "version",
-}
-
-en.msgs = {
- add_gemtext = "Created ",
- help = [[ [options] [capsule] [title]
-
-Options:
-
-config Generate a config directory
-page [capsule] [title] Add a new page with the given title
-post [capsule] [title] Add a new gemlog post with the given title
-index Generate an index page and feed of posts
-publish Index and copy posts remotely using scp
-help Show this help message
-version Print version info]],
- index = "Created index page and feed.",
- load_config = [[Created config files. Please edit them with the correct
-details before proceeding. The config files can be found at:
-]],
- publish = "Published capsule.",
-}
-
-en.errs = {
- invalid_cap_id = "Error: unknown capsule id.",
-}
-
-return en
diff --git a/lang/en_US.lua b/lang/en_US.lua
new file mode 100644
index 0000000..b7b8080
--- /dev/null
+++ b/lang/en_US.lua
@@ -0,0 +1,157 @@
+local en = {}
+
+-- Templates
+en.tpl_vars = {
+ post = {
+ author = "{{ author }}",
+ content = "{{ content }}",
+ date = "{{ date }}",
+ summary = "{{ summary }}",
+ -- This is not used in the templates yet.
+ tags = "{{ tags }}",
+ title = "{{ title }}",
+ url = "{{ url }}",
+ },
+ feed = {
+ date = "{{ date }}",
+ url = "{{ feed_url }}",
+ },
+ index = {
+ posts = "{{ posts }}",
+ },
+ log = {
+ author = "{{ author }}",
+ subtitle = "{{ subtitle }}",
+ title = "{{ title }}",
+ url = "{{ log_url }}",
+ },
+}
+
+en.atom_header = [[
+
+ {{ title }}
+ {{ subtitle }}
+ {{ date }}
+
+ {{ author }}
+
+ {{ feed_url }}
+
+
+]]
+
+en.atom_entry = [[
+
+ {{ url }}
+
+ " .. [[
+
+
+ {{ date }}
+
+ {{ author }}
+
+
+
+ " .. [[
+
+
+
+ " .. [[
+
+
+
+]]
+
+en.atom_footer = [[]]
+
+en.post = [[---
+date: {{ date }}
+---
+
+# {{ title }}
+
+
+
+
+## Links
+
+=> gemini:// link
+=> gemini:// link (img)
+=> https:// link (https)]]
+
+en.index = [[
+# {{ title }}
+{{ posts }}
+]]
+
+en.page = [[
+# {{ title }}
+
+## Heading 2
+### Heading 3
+
+List:
+
+*
+*
+*
+
+```
+Preformatted text
+```
+
+
+## Links
+
+=> gemini:// link
+=> gemini:// link (img)
+=> https:// link (https)]]
+
+
+en.msgs = {}
+
+-- %s: gemtext filename
+en.msgs.add_gemtext = "Created %s."
+
+-- %s: app executable name
+en.msgs.help_usage = [[%s [options] [capsule] [title]
+
+]]
+
+-- %s: command-line options
+-- (see env.lua env.cli_opts for the full list)
+en.msgs.help_opts = [[
+Options:
+
+%s [lang] Generate a config directory
+%s [capsule] [title] Add a new page with the given title
+%s [capsule] [title] Add a new gemlog post with the given title
+%s Generate an index page and feed of posts
+%s Index and copy posts remotely using scp
+%s Show this help message
+%s Print version info
+]]
+
+-- %s: list of language codes
+en.msgs.help_lang_opts = [[
+
+Config language options:
+
+%s]]
+
+en.msgs.index = "Created index page and feed."
+
+-- %s: config directory path
+en.msgs.load_config = [[Created config files. Please edit them with the correct
+details before proceeding. The config files can be found at:
+%s]]
+
+en.msgs.publish = "Published capsule."
+
+
+en.errs = {
+ invalid_cap_id = "Error: unknown capsule id.",
+}
+
+return en
diff --git a/lang/fr.lua b/lang/fr.lua
deleted file mode 100644
index d1f5cd8..0000000
--- a/lang/fr.lua
+++ /dev/null
@@ -1,157 +0,0 @@
-local fr = {}
-
--- Templates
-fr.tpl_vars = {
- post = {
- -- It might not be really necessary to mention post/feed/log each time
- -- since those occur in different templates?
- -- This would make the french translated tags much cleaner, because the
- -- proper way to do this translation would be "auteur_de_l'article"
- -- (author_of_the_post).
- author = "{{ auteur_article }}",
- content = "{{ contenu_article }}",
- date = "{{ date_article }}",
- summary = "{{ résumé_article }}",
- -- This is not used in the templates.
- tags = "{{ tags_article }}",
- title = "{{ titre_article }}",
- url = "{{ url_article }}",
- },
- feed = {
- date = "{{ date_flux }}",
- url = "{{ url_flux }}",
- },
- index = {
- posts = "{{ articles }}",
- },
- log = {
- -- The concept of a "gemlog" does not have a French translation
- -- as far as I know, so I used 'capsule' instead of 'log'.
- author = "{{ auteur_capsule }}",
- subtitle = "{{ sous_titre_capsule }}",
- title = "{{ titre_capsule }}",
- log_url = "{{ url_capsule }}",
- },
-}
-
-fr.atom_header = [[
-
- {{ titre_capsule }}
- {{ sous_titre_capsule }}
- {{ date_flux }}
-
- {{ auteur_capsule }}
-
- {{ url_flux }}
-
-
-]]
-
-fr.atom_entry = [[
-
- {{ url_article }}
-
- " .. [[
-
-
- {{ date_article }}
-
- {{ auteur_article }}
-
-
-
- " .. [[
-
-
-
- " .. [[
-
-
-
-]]
-
-fr.atom_footer = [[]]
-
-fr.post = [[---
-date: {{ date_article }}
----
-
-# {{ titre_article }}
-
-
-
-
-## Liens
-
-=> gemini:// lien
-=> gemini:// lien (image)
-=> https:// lien (https)]]
-
-fr.index = [[
-# {{ titre_capsule }}
-{{ articles }}
-]]
-
-fr.page = [[
-# {{ titre_article }}
-
-## Titre de niveau 2
-### Titre de niveau 3
-
-Liste :
-
-*
-*
-*
-
-```
-Texte préformaté
-```
-
-
-## Liens
-
-=> gemini:// lien
-=> gemini:// lien (image)
-=> https:// lien (https)]]
-
--- App command options and messages output
--- These probably should always stay untranslated, because having a CLI's
--- entire command line change depending on the language would be a mess.
--- Imagine writing bash in french…
-fr.opts = {
- config = "config",
- page = "page",
- post = "post",
- index = "index",
- publish = "publish",
- help = "help",
- version = "version",
-}
-
-fr.msgs = {
- add_gemtext = "Créé ",
- help = [[ [options] [capsule] [titre]
-
-Options :
-
-config Générer un dossier de configuration
-page [capsule] [titre] Ajouter une nouvelle page avec le titre fourni
-post [capsule] [titre] Ajouter un nouvel article avec le titre fourni
-index Générer une page d'accueil et un flux d'articles
-publish Générer les pages puis les publier via scp
-help Afficher ce message d'aide
-version Afficher les informations de version]],
- index = "Flux et page d'accueil créés.",
- load_config = [[Les fichiers de configuration ont été créés. Veuillez y
-inscrire les valeurs correctes avant de continuer.
-Les fichiers peuvent être trouvés dans :
-]],
- publish = "Capsule publiée.",
-}
-
-fr.errs = {
- invalid_cap_id = "Erreur: Identifiant de capsule inconnu.",
-}
-
-return fr
diff --git a/lang/fr_FR.lua b/lang/fr_FR.lua
new file mode 100644
index 0000000..c2b0a73
--- /dev/null
+++ b/lang/fr_FR.lua
@@ -0,0 +1,160 @@
+local fr = {}
+
+-- Templates
+fr.tpl_vars = {
+ post = {
+ author = "{{ auteur }}",
+ content = "{{ contenu }}",
+ date = "{{ date }}",
+ summary = "{{ résumé }}",
+ -- This is not used in the templates yet.
+ tags = "{{ tags }}",
+ title = "{{ titre }}",
+ url = "{{ url }}",
+ },
+ feed = {
+ date = "{{ date }}",
+ url = "{{ url_flux }}",
+ },
+ index = {
+ posts = "{{ articles }}",
+ },
+ log = {
+ -- The concept of a "gemlog" does not have a French translation,
+ -- the closest term after some discussion might be "journal".
+ author = "{{ auteur }}",
+ subtitle = "{{ sous_titre }}",
+ title = "{{ titre }}",
+ log_url = "{{ url_journal }}",
+ },
+}
+
+fr.atom_header = [[
+
+ {{ titre }}
+ {{ sous_titre }}
+ {{ date }}
+
+ {{ auteur }}
+
+ {{ url_flux }}
+
+
+]]
+
+fr.atom_entry = [[
+
+ {{ url }}
+
+ " .. [[
+
+
+ {{ date }}
+
+ {{ auteur }}
+
+
+
+ " .. [[
+
+
+
+ " .. [[
+
+
+
+]]
+
+fr.atom_footer = [[]]
+
+fr.post = [[---
+date: {{ date }}
+---
+
+# {{ titre }}
+
+
+
+
+## Liens
+
+=> gemini:// lien
+=> gemini:// lien (image)
+=> https:// lien (https)]]
+
+fr.index = [[
+# {{ titre }}
+{{ articles }}
+]]
+
+fr.page = [[
+# {{ titre }}
+
+## Titre de niveau 2
+### Titre de niveau 3
+
+Liste :
+
+*
+*
+*
+
+```
+Texte préformaté
+```
+
+
+## Liens
+
+=> gemini:// lien
+=> gemini:// lien (image)
+=> https:// lien (https)]]
+
+
+fr.msgs = {}
+
+-- %s: gemtext filename
+fr.msgs.add_gemtext = "%s créé."
+
+-- %s: app executable name
+fr.msgs.help_usage = [[%s [options] [capsule] [titre]
+
+]]
+
+-- %s: command-line options
+-- (see env.lua env.cli_opts for the full list)
+fr.msgs.help_opts = [[
+Options :
+
+%s [lang] Générer un dossier de configuration
+%s [capsule] [titre] Ajouter une nouvelle page avec le titre fourni
+%s [capsule] [titre] Ajouter un nouvel article avec le titre fourni
+%s Générer une page d'accueil et un flux d'articles
+%s Générer les pages puis les publier via scp
+%s Afficher ce message d'aide
+%s Afficher les informations de version
+]]
+
+-- %s: list of language codes
+fr.msgs.help_lang_opts = [[
+
+Langues disponibles :
+
+%s]]
+
+fr.msgs.index = "Flux et page d'accueil créés."
+
+-- %s: config directory path
+fr.msgs.load_config = [[Les fichiers de configuration ont été créés. Veuillez y
+inscrire les valeurs correctes avant de continuer.
+Les fichiers peuvent être trouvés dans :
+%s]]
+
+fr.msgs.publish = "Capsule publiée."
+
+
+fr.errs = {
+ invalid_cap_id = "Erreur: Identifiant de capsule inconnu.",
+}
+
+return fr
diff --git a/readme.md b/readme.md
index 2c22147..7de3296 100644
--- a/readme.md
+++ b/readme.md
@@ -25,17 +25,20 @@ version Print version info
## Build
-- Install Lua and [luastatic].
+- Install Lua (including development libraries and headers) and [luastatic].
- Clone this repository and change into the directory. Run:
```
- luastatic gemwriter.lua env.lua util.lua lang/en.lua \
- /usr/lib/liblua.so -I/usr/include -o gemwriter
+ luastatic gemwriter.lua env.lua util.lua lang/*.lua \
+ /usr/lib/[arch]/liblua[5.x].a -I/usr/include/lua[5.x] -static \
+ -o gemwriter
```
- The paths to `liblua.so` and the development headers (i.e.
- `/usr/include/lua.h`) may need to be adjusted for your distribution.
+ Replace `[arch]` with the OS architecture, e.g. `x86_64-linux-gnu`, and
+ `[5.x]` with the Lua version. The paths to `liblua.a` and the development
+ headers (i.e. `/usr/include/lua[5.x]/lua.h`) may need to be adjusted for
+ your distribution.
- Move the `gemwriter` executable to a location in your `$PATH`.
@@ -52,6 +55,13 @@ version Print version info
4. Publish your capsule: `gemwriter publish`
+## Credits
+
+Special thanks to the following contributors:
+
+- [lucidiot](https://tilde.town/~lucidiot/) — French translation
+
+
## License
BSD-3-Clause
diff --git a/util.lua b/util.lua
index e4409a3..1e9c825 100644
--- a/util.lua
+++ b/util.lua
@@ -139,6 +139,16 @@ function util.extract_file_date(dir, file)
end
+function util.module_exists(mod)
+ local check, err = pcall(require, mod)
+ if check then do
+ return true end
+ else
+ return false
+ end
+end
+
+
function util.read_file(file)
local fh = io.open(file, "r")
local text = ""