summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJedidiah Barber <contact@jedbarber.id.au>2021-10-24 23:42:05 +1300
committerJedidiah Barber <contact@jedbarber.id.au>2021-10-24 23:42:05 +1300
commit32a6db11b7e8ca95bac718baac019d19fff03845 (patch)
tree42266319bd2568ce838d4fa028e9d17c0e1b769b
Initial commit of mostly boilerplate
-rw-r--r--bin/.gitignore4
-rw-r--r--data/.gitignore8
-rw-r--r--freshdeck.gpr37
-rw-r--r--license.txt25
-rw-r--r--obj/.gitignore4
-rw-r--r--src/deck_convert.adb178
6 files changed, 256 insertions, 0 deletions
diff --git a/bin/.gitignore b/bin/.gitignore
new file mode 100644
index 0000000..ea7f887
--- /dev/null
+++ b/bin/.gitignore
@@ -0,0 +1,4 @@
+
+
+*
+!.gitignore
diff --git a/data/.gitignore b/data/.gitignore
new file mode 100644
index 0000000..fc50a55
--- /dev/null
+++ b/data/.gitignore
@@ -0,0 +1,8 @@
+
+
+# ignore all in this directory except this file
+
+*
+!.gitignore
+
+
diff --git a/freshdeck.gpr b/freshdeck.gpr
new file mode 100644
index 0000000..f3065e0
--- /dev/null
+++ b/freshdeck.gpr
@@ -0,0 +1,37 @@
+
+
+-- with "fltkada";
+with "zipada_lib";
+
+
+project Freshdeck is
+
+
+ for Languages use ("Ada");
+
+
+ for Source_Dirs use ("src/**");
+ for Object_Dir use "obj";
+ for Exec_Dir use "bin";
+ for Main use ("deck_convert.adb"); -- , "deck_convert_gui.adb");
+
+
+ package Builder is
+ for Executable ("deck_convert.adb") use "deckconv";
+ -- for Executable ("deck_convert_gui.adb") use "gdeckconv";
+ end Builder;
+
+
+ package Compiler is
+ for Default_Switches("Ada") use ("-gnaty4aAbcefhiklM100nprt");
+ end Compiler;
+
+
+ -- package Linker is
+ -- for Default_Switches("Ada") use ("-lfltk", "-lfltk_images");
+ -- end Linker;
+
+
+end Freshdeck;
+
+
diff --git a/license.txt b/license.txt
new file mode 100644
index 0000000..41c1fae
--- /dev/null
+++ b/license.txt
@@ -0,0 +1,25 @@
+
+
+SUNSET LICENSE
+Version 1.0, June 2017
+
+
+1. You may copy, modify, use, sell, or distribute this work, verbatim or
+modified, for any purpose.
+
+2. If you sell or distribute this work, whether verbatim or modified, you must
+include a copy of this license, and you must make the source code available for
+no extra charge.
+
+3. A modified version of this work must be clearly labeled as such.
+
+4. Derivative works must also be licensed under this license or a license of
+equivalent terms. As an exception, linking this work with another, whether
+statically or dynamically, does not impose any license requirements on the
+other work.
+
+5. If a minimum of 15 years have passed since the date of first publishing for
+a part of this work, then that part is placed into the public domain and you
+may do whatever you want with it, regardless of all other clauses.
+
+
diff --git a/obj/.gitignore b/obj/.gitignore
new file mode 100644
index 0000000..ea7f887
--- /dev/null
+++ b/obj/.gitignore
@@ -0,0 +1,4 @@
+
+
+*
+!.gitignore
diff --git a/src/deck_convert.adb b/src/deck_convert.adb
new file mode 100644
index 0000000..6d140a4
--- /dev/null
+++ b/src/deck_convert.adb
@@ -0,0 +1,178 @@
+
+
+with
+
+ Ada.Characters.Latin_1,
+ Ada.Characters.Handling,
+ GNAT.Command_Line,
+ GNAT.Strings,
+ Ada.Command_Line,
+ Ada.Directories,
+ Ada.Strings.Unbounded,
+ Ada.Text_IO,
+ UnZip;
+
+use
+
+ Ada.Text_IO;
+
+
+procedure Deck_Convert is
+
+
+ package Latin renames Ada.Characters.Latin_1;
+ package Charhand renames Ada.Characters.Handling;
+ package ACom renames Ada.Command_Line;
+ package GCom renames GNAT.Command_Line;
+ package GStr renames GNAT.Strings;
+ package File renames Ada.Directories;
+ package SU renames Ada.Strings.Unbounded;
+
+
+ use type File.File_Kind;
+ use type SU.Unbounded_String;
+
+
+ function "+"
+ (S : in String)
+ return SU.Unbounded_String
+ renames SU.To_Unbounded_String;
+
+ function "-"
+ (US : in SU.Unbounded_String)
+ return String
+ renames SU.To_String;
+
+
+ Config : GCom.Command_Line_Configuration;
+
+
+ Further_Help : String := "Try ""deckconv --help"" for more information.";
+
+
+ Verbose : aliased Boolean;
+ Help : aliased Boolean;
+ Overwrite : aliased Boolean;
+ Output_Format : aliased GStr.String_Access;
+ Input_Name : aliased GStr.String_Access;
+ Output_Name : aliased GStr.String_Access;
+
+
+ Temp : File_Type;
+ Temp_Name : SU.Unbounded_String;
+
+
+begin
+
+
+ GCom.Define_Switch
+ (Config => Config, Output => Verbose'Access,
+ Switch => "-v", Long_Switch => "--verbose",
+ Help => "chatty output on stderr");
+
+ GCom.Define_Switch
+ (Config => Config, Output => Help'Access,
+ Switch => "-h", Long_Switch => "--help",
+ Help => "show this help information");
+
+ GCom.Define_Switch
+ (Config => Config, Output => Overwrite'Access,
+ Switch => "-f", Long_Switch => "--force",
+ Help => "overwrite selected output file if present");
+
+ GCom.Define_Switch
+ (Config => Config, Output => Output_Format'Access,
+ Switch => "-t:", Long_Switch => "--type=",
+ Help => "format of output data, valid options are CSV or FMD");
+
+ GCom.Define_Switch
+ (Config => Config, Output => Input_Name'Access,
+ Switch => "-i:", Long_Switch => "--input=",
+ Help => "file name of input deck");
+
+ GCom.Define_Switch
+ (Config => Config, Output => Output_Name'Access,
+ Switch => "-o:", Long_Switch => "--output=",
+ Help => "file name to store output data");
+
+
+ GCom.Set_Usage
+ (Config => Config,
+ Usage => "[switches]",
+ Help =>
+ "Utility to convert Anki flashcard decks to Fresh Memory dictionaries." & Latin.LF &
+ "At minimum the type, input, and output options are required." & Latin.LF);
+
+
+ begin
+ GCom.Getopt (Config);
+ exception
+ when GCom.Exit_From_Command_Line =>
+ ACom.Set_Exit_Status (ACom.Failure);
+ return;
+ when GCom.Invalid_Switch =>
+ ACom.Set_Exit_Status (ACom.Failure);
+ return;
+ end;
+
+
+ if Charhand.To_Upper (Output_Format.all) /= "CSV" and
+ Charhand.To_Upper (Output_Format.all) /= "FMD"
+ then
+ Put_Line (Standard_Error, Output_Format.all);
+ Put_Line (Standard_Error, "Output deck format required. Valid options are CSV or FMD." &
+ Latin.LF & Further_Help);
+ ACom.Set_Exit_Status (ACom.Failure);
+ return;
+ end if;
+
+
+ if Input_Name.all = "" then
+ Put_Line (Standard_Error, "File name of input deck was not provided." &
+ Latin.LF & Further_Help);
+ ACom.Set_Exit_Status (ACom.Failure);
+ return;
+ end if;
+ if not File.Exists (Input_Name.all) then
+ Put_Line (Standard_Error, "Input deck does not exist." &
+ Latin.LF & Further_Help);
+ ACom.Set_Exit_Status (ACom.Failure);
+ return;
+ end if;
+
+
+ if Output_Name.all = "" then
+ Put_Line (Standard_Error, "File name for output deck was not provided." &
+ Latin.LF & Further_Help);
+ ACom.Set_Exit_Status (ACom.Failure);
+ return;
+ end if;
+ if File.Exists (Output_Name.all) and not Overwrite then
+ Put_Line (Standard_Error, "Output deck file name already exists." &
+ Latin.LF & Further_Help);
+ ACom.Set_Exit_Status (ACom.Failure);
+ return;
+ end if;
+
+
+ if File.Exists ("collection.anki2") and not Overwrite then
+ Put_Line (Standard_Error, "Temporary collection.anki2 file already exists." &
+ Latin.LF & Further_Help);
+ ACom.Set_Exit_Status (ACom.Failure);
+ return;
+ end if;
+
+
+ -- Generate a temporary filename
+ Create (File => Temp);
+ Temp_Name := +Name (Temp);
+ Close (Temp);
+
+ UnZip.Extract (Input_Name.all, "collection.anki2", (-Temp_Name));
+ Put_Line ("Extracted collection as " & (-Temp_Name));
+ File.Delete_File (-Temp_Name);
+
+
+end Deck_Convert;
+
+