[gnome-tetravex/arnaudb/gnome-tetravex-cli: 3/4] Add gnome-tetravex-cli.



commit 2b495b43b4d52b9c3e1bba8d34cd941f42c3c408
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date:   Wed Nov 6 22:52:27 2019 +0100

    Add gnome-tetravex-cli.

 data/gnome-tetravex-cli.6              | 100 +++++++++++++++++++++++
 data/meson.build                       | 119 +++++++++++++++------------
 data/org.gnome.TetravexCli.gschema.xml |  19 +++++
 meson.build                            |  21 +++--
 meson_options.txt                      |   2 +
 po/meson.build                         |   7 +-
 src/gnome-tetravex-cli.vala            | 145 +++++++++++++++++++++++++++++++++
 src/meson.build                        |  64 +++++++++++----
 8 files changed, 402 insertions(+), 75 deletions(-)
---
diff --git a/data/gnome-tetravex-cli.6 b/data/gnome-tetravex-cli.6
new file mode 100644
index 0000000..788d57c
--- /dev/null
+++ b/data/gnome-tetravex-cli.6
@@ -0,0 +1,100 @@
+.\"
+.\" Copyright (C) 2007 Sven Arvidsson <sa whiz se>
+.\" Copyright (C) 2019 Arnaud Bonatti <arnaud bonatti gmail com>
+.\"
+.\" GNOME Tetravex 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 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" GNOME Tetravex 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 GNOME Tetravex.  If not, see <https://www.gnu.org/licenses/>.
+.\"
+.TH gnome-tetravex-cli 6 "2019\-11\-07" "GNOME"
+.SH NAME
+Tetravex \- A simple puzzle game to play in CLI
+.SH SYNOPSIS
+.B gnome-tetravex-cli
+.RI [ OPTION... ]
+.RI [ COMMAND ]
+.SH DESCRIPTION
+GNOME Tetravex is a simple puzzle where pieces must be positioned so
+that the same numbers are touching each other.
+.br
+.br
+This is a CLI program; see also `gnome-tetravex` for the Gtk application.
+.SH OPTIONS
+.TP
+.B \-c, \-\-colors=NUMBER
+Set number of colors (2-10)
+.TP
+.B \-s, \-\-size=SIZE
+Set size of board (2-6)
+.TP
+.B \-v, \-\-version
+Print release version and exit
+.P
+.SH COMMAND
+.TP
+.B A1b2
+Invert two tiles, the one in A1, and the one in b2.
+.br
+An uppercase targets a tile from the initial board.
+.br
+A lowercase targets a tile in the left/final board.
+.br
+Digits specify the rows of the two tiles to invert.
+.br
+.br
+.PP
+.B (nothing)
+.br
+.B status
+.br
+.B show
+.RS 7
+Show the current puzzle.
+.RE
+.TP
+.B new
+Create a new puzzle; for changing size, use --size.
+.TP
+.B solve
+Give up with current puzzle, and view the solution.
+.PP
+.B finish
+.br
+.B end
+.RS 7
+Finish current puzzle, automatically. Works for puzzles solved right or if one tile left.
+.RE
+.PP
+.B up,\ \ \ \ l-up
+.br
+.B down,\ \ l-down
+.br
+.B left,\ \ l-left
+.br
+.B right,\ l-right
+.RS 7
+Move all left-board tiles up/down/left/right by one.
+.RE
+.PP
+.B r-up
+.br
+.B r-down
+.br
+.B r-left
+.br
+.B r-right
+.RS 7
+Move all right-board tiles up/down/left/right by one.
+.RE
+.SH AUTHORS
+.B gnome-tetravex-cli
+was written by Arnaud Bonatti.
diff --git a/data/meson.build b/data/meson.build
index 21be9fb..e29f5c2 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -1,68 +1,87 @@
 # Install icons
-foreach size: [ '16x16', '22x22', '24x24', '32x32', '48x48']
+if get_option('build_gui')
+  foreach size: [ '16x16', '22x22', '24x24', '32x32', '48x48']
     install_data (join_paths ('icons', 'hicolor', size, project_id + '.png'),
                   install_dir: join_paths (datadir, 'icons', 'hicolor', size, 'apps'))
-endforeach
-install_data (join_paths ('icons', 'hicolor', 'scalable', project_id + '.svg'),
-              install_dir: join_paths (datadir, 'icons', 'hicolor', 'scalable', 'apps'))
-install_data (join_paths ('icons', 'hicolor', 'scalable', project_id + '-symbolic.svg'),
-              install_dir: join_paths (datadir, 'icons', 'hicolor', 'scalable', 'apps'))
+  endforeach
+  install_data (join_paths ('icons', 'hicolor', 'scalable', project_id + '.svg'),
+                install_dir: join_paths (datadir, 'icons', 'hicolor', 'scalable', 'apps'))
+  install_data (join_paths ('icons', 'hicolor', 'scalable', project_id + '-symbolic.svg'),
+                install_dir: join_paths (datadir, 'icons', 'hicolor', 'scalable', 'apps'))
+endif
 
 # Install gschema
-install_data (project_id + '.gschema.xml',
-              install_dir: join_paths (datadir, 'glib-2.0', 'schemas'))
+if get_option('build_gui')
+  install_data (project_id + '.gschema.xml',
+                install_dir: join_paths (datadir, 'glib-2.0', 'schemas'))
+endif
+if get_option('build_cli')
+  install_data (cli_project_id + '.gschema.xml',
+                install_dir: join_paths (datadir, 'glib-2.0', 'schemas'))
+endif
 
 # Make D-Bus activatable
-service_conf = configuration_data()
-service_conf.set('bindir', bindir)
+if get_option('build_gui')
+  service_conf = configuration_data()
+  service_conf.set('bindir', bindir)
 
-service = project_id + '.service'
+  service = project_id + '.service'
 
-configure_file(
-  input: service + '.in',
-  output: service,
-  install: true,
-  install_dir: join_paths(datadir, 'dbus-1', 'services'),
-  configuration: service_conf
-)
+  configure_file(
+    input: service + '.in',
+    output: service,
+    install: true,
+    install_dir: join_paths(datadir, 'dbus-1', 'services'),
+    configuration: service_conf
+  )
+endif
 
 # Desktop file
-desktop_file = i18n.merge_file ('desktop-file',
-                 input: project_id + '.desktop.in',
-                 output: project_id + '.desktop',
-                 install: true,
-                 install_dir: join_paths (datadir, 'applications'),
-                 po_dir: '../po',
-                 type: 'desktop')
+if get_option('build_gui')
+  desktop_file = i18n.merge_file ('desktop-file',
+                           input: project_id + '.desktop.in',
+                          output: project_id + '.desktop',
+                         install: true,
+                     install_dir: join_paths (datadir, 'applications'),
+                          po_dir: '../po',
+                            type: 'desktop')
 
-# Validate desktop file
-if desktop_file_validate.found()
-  test(
-    'validate-desktop',
-    desktop_file_validate,
-    args: [
-      desktop_file.full_path()
-    ]
-  )
+  # Validate desktop file
+  if desktop_file_validate.found()
+    test(
+      'validate-desktop',
+      desktop_file_validate,
+      args: [
+        desktop_file.full_path()
+      ]
+    )
+  endif
 endif
 
 # AppData file
-appdata_file = i18n.merge_file ('appdata-file',
-                 input: project_id + '.appdata.xml.in',
-                 output: project_id + '.appdata.xml',
-                 install: true,
-                 install_dir: join_paths (datadir, 'metainfo'),
-                 po_dir: '../po')
+if get_option('build_gui')
+  appdata_file = i18n.merge_file ('appdata-file',
+                           input: project_id + '.appdata.xml.in',
+                          output: project_id + '.appdata.xml',
+                         install: true,
+                     install_dir: join_paths (datadir, 'metainfo'),
+                          po_dir: '../po')
 
-# Validate AppData file
-if appstream_util.found()
-  test(
-    'validate-appdata', appstream_util,
-    args: [
-      'validate', '--nonet', appdata_file.full_path()
-    ]
-  )
+  # Validate AppData file
+  if appstream_util.found()
+    test(
+      'validate-appdata', appstream_util,
+      args: [
+        'validate', '--nonet', appdata_file.full_path()
+      ]
+    )
+  endif
 endif
 
-# Install man page
-install_man ('gnome-tetravex.6')
+# Install man pages
+if get_option('build_gui')
+  install_man('gnome-tetravex.6')
+endif
+if get_option('build_cli')
+  install_man('gnome-tetravex-cli.6')
+endif
diff --git a/data/org.gnome.TetravexCli.gschema.xml b/data/org.gnome.TetravexCli.gschema.xml
new file mode 100644
index 0000000..b6b7bd4
--- /dev/null
+++ b/data/org.gnome.TetravexCli.gschema.xml
@@ -0,0 +1,19 @@
+<schemalist>
+  <schema id="org.gnome.TetravexCli" path="/org/gnome/Tetravex/" gettext-domain="gnome-tetravex-cli">
+    <key name="grid-size" type="i">
+      <default>3</default>
+      <range min="2" max="6" />
+      <!-- Translators: summary of a settings key, see 'dconf-editor /org/gnome/Tetravex/grid-size' -->
+      <summary>The size of the playing grid</summary>
+      <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/Tetravex/grid-size' -->
+      <description>The value of this key is used to decide the size of the playing grid.</description>
+    </key>
+    <key name="saved-game" type="m(yyda(yyyyyyyy)ua(yyyyu))">
+      <default>nothing</default>
+      <!-- Translators: summary of a settings key, see 'dconf-editor /org/gnome/Tetravex/saved-game' -->
+      <summary>Saved game, if any</summary>
+      <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/Tetravex/saved-game'; 
“nothing” is a technical keyword, you might want to translate it: « “nothing” (your translation) » -->
+      <description>The key has value “nothing” if there is no saved game. Else, it contains a description of 
the board, with its size, the number of colors, and the time elapsed, then the list of tiles, saved as 
properties: their current position (x and y), their colors (north, east, south and west), and their original 
position (x and y), and finally the history, with the last move index, and history entries saved as 
properties: coordinates of the two tiles swapped, and the move id.</description>
+    </key>
+  </schema>
+</schemalist>
diff --git a/meson.build b/meson.build
index 5063d6f..7e7cb31 100644
--- a/meson.build
+++ b/meson.build
@@ -7,10 +7,13 @@ project ('gnome-tetravex', ['vala', 'c'],
          ],
          meson_version: '>= 0.50.0')
 
-project_id = 'org.gnome.Tetravex'
+project_id      = 'org.gnome.Tetravex'
+cli_project_id  = 'org.gnome.TetravexCli'
 
 # used to install help
-gnome = import('gnome')
+if get_option('build_gui')
+  gnome = import('gnome')
+endif
 # used for internationalization
 i18n = import('i18n')
 
@@ -23,11 +26,15 @@ bindir      = join_paths (get_option ('prefix'), get_option ('bindir'))
 # Dependencies
 gio_dep     = dependency ('gio-2.0',    version: '>= 2.42.0')
 glib_dep    = dependency ('glib-2.0',   version: '>= 2.42.0')
-gtk_dep     = dependency ('gtk+-3.0',   version: '>= 3.14')
+if get_option('build_gui')
+  gtk_dep   = dependency ('gtk+-3.0',   version: '>= 3.14')
+endif
 # TODO build requires vala 0.46.3 for GLib vapi
 
-appstream_util          = find_program('appstream-util',        required: false)
-desktop_file_validate   = find_program('desktop-file-validate', required: false)
+if get_option('build_gui')
+  appstream_util        = find_program('appstream-util',        required: false)
+  desktop_file_validate = find_program('desktop-file-validate', required: false)
+endif
 glib_compile_schema     = find_program('glib-compile-schemas',  required: true) # useful?
 
 cc = meson.get_compiler('c')
@@ -35,7 +42,9 @@ libm_dep = cc.find_library('m')
 
 subdir ('po')
 subdir ('data')
-subdir ('help')
+if get_option('build_gui')
+  subdir ('help')
+endif
 subdir ('src')
 
 meson.add_install_script('build-aux/meson_post_install.py')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..415362d
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,2 @@
+option('build_cli', type : 'boolean', value : false, description : 'Build the command-line interface, 
`gnome-tetravex-cli`')
+option('build_gui', type : 'boolean', value : true , description : 'Build the graphical Gtk user interface, 
`gnome-tetravex`')
diff --git a/po/meson.build b/po/meson.build
index 7e27a58..f97b00f 100644
--- a/po/meson.build
+++ b/po/meson.build
@@ -1,3 +1,8 @@
-i18n.gettext ('gnome-tetravex', preset: 'glib')
+if get_option('build_gui')
+  i18n.gettext ('gnome-tetravex', preset: 'glib')
+endif
+if get_option('build_cli')
+  i18n.gettext ('gnome-tetravex-cli', preset: 'glib')
+endif
 
 podir = meson.current_source_dir ()
diff --git a/src/gnome-tetravex-cli.vala b/src/gnome-tetravex-cli.vala
new file mode 100644
index 0000000..129f9d3
--- /dev/null
+++ b/src/gnome-tetravex-cli.vala
@@ -0,0 +1,145 @@
+/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+
+   This file is part of GNOME Tetravex.
+
+   Copyright (C) 2019 Arnaud Bonatti
+
+   GNOME Tetravex 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 2 of the License, or
+   (at your option) any later version.
+
+   GNOME Tetravex 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 GNOME Tetravex.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+private class TetravexCli : GLib.Application
+{
+    private string help_text = "\n  A1b2          " + "Invert two tiles, the one in A1, and the one in b2."
+                             + "\n                " + "An uppercase targets a tile from the initial board."
+                             + "\n                " + "A lowercase targets a tile in the left/final board."
+                             + "\n                " + "Digits specify the rows of the two tiles to invert."
+                             + "\n"
+                             + "\n  (nothing)     " + "Show the current puzzle. Alias: “status” or “show”."
+                             + "\n  new           " + "Create a new puzzle; for changing size, use --size."
+                             + "\n  solve         " + "Give up with current puzzle, and view the solution."
+                             + "\n"
+                             + "\n  finish        " + "Finish current puzzle, automatically. Alias: “end”."
+                             + "\n                " + "Works for puzzles solved right or if one tile left."
+                             + "\n"
+                             + "\n  up            " + "Move all left-board tiles up by one."
+                             + "\n  down          " + "Move all left-board tiles down by one."
+                             + "\n  left          " + "Move all left-board tiles left by one."
+                             + "\n  right         " + "Move all left-board tiles right by one."
+                             + "\n"
+                             + "\n  r-up          " + "Move all right-board tiles up by one."
+                             + "\n  r-down        " + "Move all right-board tiles down by one."
+                             + "\n  r-left        " + "Move all right-board tiles left by one."
+                             + "\n  r-right       " + "Move all right-board tiles right by one."
+                             + "\n";
+
+    private const string KEY_GRID_SIZE = "grid-size";
+
+    private Variant saved_game;
+    private bool can_restore = false;
+
+    private static int game_size = int.MIN;
+    private static int colors = 10;
+    private static string? cli = null;
+
+    private GLib.Settings settings;
+
+    private Puzzle puzzle;
+
+    private static string? [] remaining = new string? [2];
+    private const OptionEntry [] option_entries =
+    {
+        /* Translators: command-line option description, see 'gnome-tetravex-cli --help' */
+        { "colors",  'c', OptionFlags.NONE, OptionArg.INT,  ref colors,                 N_("Set number of 
colors (2-10)"),
+
+        /* Translators: in the command-line options description, text to indicate the user should specify 
colors number, see 'gnome-tetravex-cli --help' */
+                                                                                        N_("NUMBER") },
+
+        /* Translators: command-line option description, see 'gnome-tetravex-cli --help' */
+        { "size",    's', OptionFlags.NONE, OptionArg.INT,  ref game_size,              N_("Set size of 
board (2-6)"),
+
+        /* Translators: in the command-line options description, text to indicate the user should specify 
size, see 'gnome-tetravex-cli --help' */
+                                                                                        N_("SIZE") },
+
+        /* Translators: command-line option description, see 'gnome-tetravex-cli --help' */
+        { "version", 'v', OptionFlags.NONE, OptionArg.NONE, null,                       N_("Print release 
version and exit"),   null },
+
+        { OPTION_REMAINING, 0, OptionFlags.NONE, OptionArg.STRING_ARRAY, ref remaining, "args", null },
+        {}
+    };
+
+    private static int main (string[] args)
+    {
+        Intl.setlocale (LocaleCategory.ALL, "");
+        Intl.bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+        Intl.bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+        Intl.textdomain (GETTEXT_PACKAGE);
+
+        TetravexCli app = new TetravexCli ();
+        return app.run (args);
+    }
+
+    private TetravexCli ()
+    {
+        Object (application_id: "org.gnome.TetravexCli", flags: ApplicationFlags.FLAGS_NONE);
+
+        set_option_context_parameter_string ("[COMMAND]");
+        set_option_context_description ("Available commands:" + help_text);
+        add_main_option_entries (option_entries);
+    }
+
+    protected override int handle_local_options (GLib.VariantDict options)
+    {
+        if (options.contains ("version")
+         || remaining [0] != null && (!) remaining [0] == "version")
+        {
+            /* NOTE: Is not translated so can be easily parsed */
+            stderr.printf ("%1$s %2$s\n", "gnome-tetravex-cli", VERSION);
+            return Posix.EXIT_SUCCESS;
+        }
+
+        if (game_size != int.MIN && (game_size < 2 || game_size > 6))
+        {
+            /* Translators: command-line error message, displayed on invalid game size request; see 
'gnome-tetravex-cli -s 1' */
+            stderr.printf (N_("Size could only be from 2 to 6.\n"));
+            return Posix.EXIT_FAILURE;
+        }
+
+        if (colors < 2 || colors > 10)
+        {
+            /* Translators: command-line error message, displayed for an invalid number of colors; see 
'gnome-tetravex-cli -c 1' */
+            stderr.printf (N_("There could only be between 2 and 10 colors.\n"));
+            return Posix.EXIT_FAILURE;
+        }
+
+        if (remaining [1] != null)
+        {
+            /* Translators: command-line error message, displayed for an invalid CLI command; see 
'gnome-tetravex-cli new A1b2' */
+            stderr.printf (N_("Failed to parse command-line arguments.\n"));
+            return Posix.EXIT_FAILURE;
+        }
+
+        cli = remaining [0] ?? "";
+
+        if ((!) cli == "help" || (!) cli == "HELP")
+        {
+            stdout.printf ("\n");
+            stdout.printf ("To use `gnome-tetravex-cli`, pass as arg:");
+            stdout.printf (help_text);
+            stdout.printf ("\n");
+            return Posix.EXIT_SUCCESS;
+        }
+
+        return CLI.play_cli ((!) cli, "org.gnome.TetravexCli", out settings, out saved_game, out 
can_restore, out puzzle, ref colors, ref game_size);
+    }
+}
diff --git a/src/meson.build b/src/meson.build
index 3c8f616..0ce04e9 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,8 +1,35 @@
-resources = gnome.compile_resources ('resources', 'gnome-tetravex.gresource.xml',
-                                     source_dir: '.',
-                                     c_name: 'resources')
+# CLI
+if get_option('build_cli')
+  cli_sources = files (
+    'cli.vala',
+    'config.vapi',
+    'gnome-tetravex-cli.vala',
+    'history.vala',
+    'puzzle.vala'
+  )
+
+  gnome_tetravex_cli = executable (
+    'gnome-tetravex-cli',
+    cli_sources,
+    dependencies: [ gio_dep,
+                    glib_dep,
+                    libm_dep ],
+    vala_args: [ '--pkg=posix',
+                 '--enable-experimental-non-null' ],
+    c_args: [ '-DVERSION="@0@"'.format (meson.project_version ()),
+              '-DGETTEXT_PACKAGE="gnome-tetravex-cli"',
+              '-DLOCALEDIR="@0@"'.format (localedir) ],
+    install: true
+  )
+endif
+
+# GUI
+if get_option('build_gui')
+  gui_resources = gnome.compile_resources ('resources', 'gnome-tetravex.gresource.xml',
+                                           source_dir: '.',
+                                           c_name: 'resources')
 
-sources = files (
+  gui_sources = files (
     'cli.vala',
     'config.vapi',
     'gnome-tetravex.vala',
@@ -15,19 +42,20 @@ sources = files (
     'theme-neoretro.vala',
     'theme-nostalgia.vala',
     'theme-synesthesia.vala'
-)
+  )
 
-gnome_tetravex = executable (
+  gnome_tetravex_gui = executable (
     'gnome-tetravex',
-     sources + resources,
-     dependencies: [ gio_dep,
-                     glib_dep,
-                     gtk_dep,
-                     libm_dep ],
-     vala_args: [ '--pkg=posix',
-                  '--enable-experimental-non-null' ],
-     c_args: [ '-DVERSION="@0@"'.format (meson.project_version ()),
-               '-DGETTEXT_PACKAGE="gnome-tetravex"',
-               '-DLOCALEDIR="@0@"'.format (localedir) ],
-     install: true
- )
+    gui_sources + gui_resources,
+    dependencies: [ gio_dep,
+                    glib_dep,
+                    gtk_dep,
+                    libm_dep ],
+    vala_args: [ '--pkg=posix',
+                 '--enable-experimental-non-null' ],
+    c_args: [ '-DVERSION="@0@"'.format (meson.project_version ()),
+              '-DGETTEXT_PACKAGE="gnome-tetravex"',
+              '-DLOCALEDIR="@0@"'.format (localedir) ],
+    install: true
+  )
+endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]