diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c39f893c0..1e9d82b0a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -225,14 +225,13 @@ struct NamedTargetMetrics { }; gb_global NamedTargetMetrics named_targets[] = { - { str_lit("essence_amd64"), &target_essence_amd64 }, { str_lit("darwin_amd64"), &target_darwin_amd64 }, + { str_lit("essence_amd64"), &target_essence_amd64 }, + { str_lit("js_wasm32"), &target_js_wasm32 }, { str_lit("linux_386"), &target_linux_386 }, { str_lit("linux_amd64"), &target_linux_amd64 }, { str_lit("windows_386"), &target_windows_386 }, { str_lit("windows_amd64"), &target_windows_amd64 }, - { str_lit("js_wasm32"), &target_js_wasm32 }, - { str_lit("wasm32"), &target_js_wasm32 }, }; NamedTargetMetrics *selected_target_metrics; diff --git a/src/main.cpp b/src/main.cpp index ea370a03f..d1c549b0f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -992,7 +992,33 @@ bool parse_build_flags(Array args) { } if (!found) { + struct DistanceAndTarget { + isize distance; + isize target_index; + }; + DistanceAndTarget distances[gb_count_of(named_targets)] = {}; + for (isize i = 0; i < gb_count_of(named_targets); i++) { + distances[i].target_index = i; + distances[i].distance = levenstein_distance_case_insensitive(str, named_targets[i].name); + } + gb_sort_array(distances, gb_count_of(distances), gb_isize_cmp(gb_offset_of(DistanceAndTarget, distance))); + gb_printf_err("Unknown target '%.*s'\n", LIT(str)); + + enum {MAX_SMALLEST_DISTANCE = 3}; + if (distances[0].distance <= MAX_SMALLEST_DISTANCE) { + gb_printf_err("Did you mean:\n"); + for (isize i = 0; i < gb_count_of(named_targets); i++) { + if (distances[i].distance > MAX_SMALLEST_DISTANCE) { + break; + } + gb_printf_err("\t%.*s\n", LIT(named_targets[distances[i].target_index].name)); + } + } + gb_printf_err("All supported targets:\n"); + for (isize i = 0; i < gb_count_of(named_targets); i++) { + gb_printf_err("\t%.*s\n", LIT(named_targets[i].name)); + } bad_flags = true; } diff --git a/src/string.cpp b/src/string.cpp index 165468965..fcf271d67 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -762,3 +762,42 @@ i32 unquote_string(gbAllocator a, String *s_, u8 quote=0, bool has_carriage_retu } return 2; } + + +isize levenstein_distance_case_insensitive(String const &a, String const &b) { + isize w = a.len+1; + isize h = b.len+1; + isize *matrix = gb_alloc_array(heap_allocator(), isize, w*h); + for (isize i = 0; i <= a.len; i++) { + matrix[i*w + 0] = i; + } + for (isize i = 0; i <= b.len; i++) { + matrix[0*w + i] = i; + } + + for (isize i = 1; i <= a.len; i++) { + char a_c = gb_char_to_lower(cast(char)a.text[i-1]); + for (isize j = 1; j <= b.len; j++) { + char b_c = gb_char_to_lower(cast(char)b.text[j-1]); + if (a_c == b_c) { + matrix[i*w + j] = matrix[(i-1)*w + j-1]; + } else { + isize remove = matrix[(i-1)*w + j] + 1; + isize insert = matrix[i*w + j-1] + 1; + isize substitute = matrix[(i-1)*w + j-1] + 1; + isize minimum = remove; + if (insert < minimum) { + minimum = insert; + } + if (substitute < minimum) { + minimum = substitute; + } + matrix[i*w + j] = minimum; + } + } + } + + isize res = matrix[a.len*w + b.len]; + gb_free(heap_allocator(), matrix); + return res; +}