Browse Source

Merge pull request #128 from tsoding/127

(#127) Introduce flag mistake correction mechanism
Alexey Kutepov 5 years ago
parent
commit
62278076cb
4 changed files with 77 additions and 6 deletions
  1. 20 5
      src/aids.hpp
  2. 1 0
      src/vodus.cpp
  3. 41 1
      src/vodus_video_params.cpp
  4. 15 0
      src/vodus_video_params.hpp

+ 20 - 5
src/aids.hpp

@@ -21,7 +21,7 @@
 //
 // ============================================================
 //
-// aids — 0.14.0 — std replacement for C++. Designed to aid developers
+// aids — 0.15.0 — std replacement for C++. Designed to aid developers
 // to a better programming experience.
 //
 // https://github.com/rexim/aids
@@ -30,6 +30,7 @@
 //
 // ChangeLog (https://semver.org/ is implied)
 //
+//   0.15.0 Make min() and max() variadic
 //   0.14.0 size_t String_View::count_chars(char x) const
 //   0.13.3 Fix control flow in utf8_get_code
 //   0.13.2 Fix magic constant types in utf8_get_code
@@ -88,15 +89,29 @@ namespace aids
     ////////////////////////////////////////////////////////////
 
     template <typename T>
-    T min(T a, T b)
+    T min(T x)
     {
-        return a < b ? a : b;
+        return x;
+    }
+
+    template <typename T, typename... Rest>
+    T min(T x, Rest... rest)
+    {
+        auto y = min(rest...);
+        return x < y ? x : y;
     }
 
     template <typename T>
-    T max(T a, T b)
+    T max(T x)
+    {
+        return x;
+    }
+
+    template <typename T, typename... Rest>
+    T max(T x, Rest... rest)
     {
-        return a > b ? a : b;
+        auto y = max(rest...);
+        return x < y ? y : x;
     }
 
     template <typename T>

+ 1 - 0
src/vodus.cpp

@@ -3,6 +3,7 @@
 #include <cstdint>
 #include <cmath>
 #include <ctime>
+#include <climits>
 
 #include <algorithm>
 

+ 41 - 1
src/vodus_video_params.cpp

@@ -121,6 +121,31 @@ void patch_video_params_from_file(Video_Params *params, String_View filepath)
     }
 }
 
+
+size_t levenshtein(String_View a, String_View b)
+{
+    size_t *dp = new size_t[(a.count + 1) * (b.count + 1)];
+#define DP(row, column) dp[(row) * (b.count + 1) + (column)]
+    defer(delete[] dp);
+    memset(dp, 0, sizeof(size_t) * (a.count + 1) * (b.count + 1));
+
+    for (size_t i = 0; i <= a.count; ++i) {
+        for (size_t j = 0; j <= b.count; ++j) {
+            if (min(i, j) == 0) {
+                DP(i, j) = max(i, j);
+            } else {
+                DP(i, j) = min(
+                    DP(i - 1, j) + 1,
+                    DP(i, j - 1) + 1,
+                    DP(i - 1, j - 1) + (a.data[i - 1] != b.data[j - 1]));
+            }
+        }
+    }
+
+    return DP(a.count, b.count);
+#undef DP
+}
+
 void patch_video_params_from_flag(Video_Params *params, String_View flag, String_View value)
 {
     if (flag == "fps"_sv) {
@@ -153,7 +178,22 @@ void patch_video_params_from_flag(Video_Params *params, String_View flag, String
             abort();
         }
     } else {
-        println(stderr, "Unknown flag `", flag, "`");
+        size_t n = ULONG_MAX;
+        String_View corrected_flag = {};
+        for (size_t i = 0; i < param_names_count; ++i) {
+            auto m = levenshtein(flag, param_names[i]);
+            if (m < n) {
+                n = m;
+                corrected_flag = param_names[i];
+            }
+        }
+
+        const size_t LEVENSHTEIN_CORRECTION_THRESHOLD = 5;
+        if (n <= LEVENSHTEIN_CORRECTION_THRESHOLD) {
+            println(stderr, "Unknown flag `", flag, "`. Maybe you meant `", corrected_flag, "`");
+        } else {
+            println(stderr, "Unknown flag `", flag, "`.");
+        }
         abort();
     }
 }

+ 15 - 0
src/vodus_video_params.hpp

@@ -22,6 +22,21 @@ struct Video_Params
     Maybe<size_t> messages_limit;
 };
 
+String_View param_names[] = {
+    "output_type"_sv,
+    "fps"_sv,
+    "width"_sv,
+    "height"_sv,
+    "font_size"_sv,
+    "background_color"_sv,
+    "nickname_color"_sv,
+    "text_color"_sv,
+    "bitrate"_sv,
+    "font"_sv,
+    "messages_limit"_sv,
+};
+const size_t param_names_count = sizeof(param_names) / sizeof(param_names[0]);
+
 void print1(FILE *stream, Video_Params params);
 
 Video_Params default_video_params();