diff --git a/project.clj b/project.clj index 6a01432..92a7fed 100644 --- a/project.clj +++ b/project.clj @@ -3,7 +3,8 @@ :url "https://gitlab.com/KKlochko/cipher-analytical-machine" :license {:name "LGPL" :url "http://www.gnu.org/licenses/lgpl-3.0.txt"} - :dependencies [[org.clojure/clojure "1.11.1"]] + :dependencies [[org.clojure/clojure "1.11.1"] + [org.clojure/tools.cli "1.0.219"]] :main ^:skip-aot cipher-analytical-machine.core :target-path "target/%s" :profiles {:uberjar {:aot :all diff --git a/src/cipher_analytical_machine/cli.clj b/src/cipher_analytical_machine/cli.clj new file mode 100644 index 0000000..f0c3b9d --- /dev/null +++ b/src/cipher_analytical_machine/cli.clj @@ -0,0 +1,82 @@ +(ns cipher-analytical-machine.cli + (:require + [cipher-analytical-machine.caesar :as caesar] + [clojure.string :as cs] + [clojure.tools.cli :refer [parse-opts]]) + (:gen-class)) + +(def cipher-options + #{"Caesar"}) + +(def cli-options + [["-m" "--message MESSAGE" "The message will be encrypted or decrypted."] + ["-k" "--key KEY" "The key will be used to encrypt or decrypt."] + ["-c" "--cipher CIPHER" "The cipher will be used to encrypt or decrypt a message." + :default "Caesar"] + ["-e" "--encrypt" "Encrypt the message."] + ["-d" "--decrypt" "Decrypt the message."] + ["-h" "--help"]]) + +(defn usage [options-summary] + (->> ["This is cipher-analytical-machine. It can help you to learn how ciphers works." + "" + "Usage: cipher-analytical-machine [options]" + "" + "Options:" + options-summary + ""] + (cs/join \newline))) + +(defn error-msg [errors] + (str "The following errors occurred while parsing your command:\n\n" + (cs/join \newline errors))) + +(defn map-has-keys? + "Return true if all keys in the map." + [map keys] + (every? #(contains? map %) keys)) + +(defn validate-args + "Validate command line arguments. Either return a map indicating the program + should exit (with an error message, and optional ok status), or a map + indicating the action the program should take and the options provided." + [args] + (let [{:keys [options arguments errors summary]} (parse-opts args cli-options)] + (cond + (:help options) + {:exit-message (usage summary) :ok? true} + + errors + {:exit-message (error-msg errors)} + + (map-has-keys? options [:encrypt, :decrypt]) + {:exit-message (error-msg ["You can't use enctypt and decrypt mode at the same time!!!"])} + + (and (map-has-keys? options [:cipher, :key]) + (contains? options :message) + (or (contains? options :encrypt) + (contains? options :decrypt))) + {:options options :arguments arguments} + + :else + {:exit-message (usage summary)}))) + +(defn exit + [exit-message status] + (println exit-message) + (System/exit (if status 0 1))) + +(defn actions + [options arguments] + (println (str options arguments)) + (let [message (:message options) + key (Integer/parseInt (:key options)) + symbols "abc"] + (println + (cond + (contains? options :encrypt) + (caesar/encrypt-message message key symbols) + + (contains? options :decrypt) + (caesar/decrypt-message message key symbols))))) + diff --git a/src/cipher_analytical_machine/core.clj b/src/cipher_analytical_machine/core.clj index 00a2e4e..3c19ef0 100644 --- a/src/cipher_analytical_machine/core.clj +++ b/src/cipher_analytical_machine/core.clj @@ -1,7 +1,12 @@ (ns cipher-analytical-machine.core + (:require + [cipher-analytical-machine.cli :as cli]) (:gen-class)) (defn -main - "I don't do a whole lot ... yet." [& args] - (println "Hello, World!")) + (let [{:keys [options arguments exit-message ok?]} (cli/validate-args args)] + (if exit-message + (cli/exit exit-message ok?) + (cli/actions options arguments)))) +