소스 검색

Utilities/tr: Rework squeezing to be supported during more operations

Tim Schumacher 3 년 전
부모
커밋
2e8330f78c
2개의 변경된 파일38개의 추가작업 그리고 24개의 파일을 삭제
  1. 1 1
      Base/usr/share/man/man1/tr.md
  2. 37 23
      Userland/Utilities/tr.cpp

+ 1 - 1
Base/usr/share/man/man1/tr.md

@@ -14,7 +14,7 @@ $ tr [--complement] [--delete] [--squeeze-repeats] <from> [to]
 * `--version`: Print version
 * `-c`, `--complement`: Take the complement of the first set
 * `-d`, `--delete`: Delete characters instead of replacing
-* `-s`, `--squeeze-repeats`: Omit repeated characters listed in the 'to' set from the output
+* `-s`, `--squeeze-repeats`: Omit repeated characters listed in the last given set from the output
 
 ## Arguments:
 

+ 37 - 23
Userland/Utilities/tr.cpp

@@ -92,19 +92,34 @@ int main(int argc, char** argv)
 {
     bool complement_flag = false;
     bool delete_flag = false;
-    bool squeeze_repeats = false;
+    bool squeeze_flag = false;
     const char* from_chars = nullptr;
     const char* to_chars = nullptr;
 
     Core::ArgsParser args_parser;
     args_parser.add_option(complement_flag, "Take the complement of the first set", "complement", 'c');
     args_parser.add_option(delete_flag, "Delete characters instead of replacing", "delete", 'd');
-    args_parser.add_option(squeeze_repeats, "Omit repeated characters listed in the 'to' set from the output", "squeeze-repeats", 's');
+    args_parser.add_option(squeeze_flag, "Omit repeated characters listed in the last given set from the output", "squeeze-repeats", 's');
     args_parser.add_positional_argument(from_chars, "Set of characters to translate from", "from");
     args_parser.add_positional_argument(to_chars, "Set of characters to translate to", "to", Core::ArgsParser::Required::No);
     args_parser.parse(argc, argv);
 
-    if (!to_chars && !delete_flag) {
+    bool transform_flag = to_chars && !delete_flag;
+
+    if (!transform_flag && !delete_flag && !squeeze_flag) {
+        warnln("tr: Missing operand");
+        args_parser.print_usage(stderr, argv[0]);
+        return 1;
+    }
+
+    if (delete_flag && squeeze_flag && !to_chars) {
+        warnln("tr: Combined delete and squeeze operations need two sets of characters");
+        args_parser.print_usage(stderr, argv[0]);
+        return 1;
+    }
+
+    if (delete_flag && !squeeze_flag && to_chars) {
+        warnln("tr: Only one set of characters may be given when deleting without squeezing");
         args_parser.print_usage(stderr, argv[0]);
         return 1;
     }
@@ -119,32 +134,31 @@ int main(int argc, char** argv)
         from_str = complement_set.to_string();
     }
 
-    if (delete_flag) {
-        for (;;) {
-            char ch = fgetc(stdin);
-            if (feof(stdin))
-                break;
-            if (!from_str.contains(ch))
-                putchar(ch);
+    auto to_str = build_set(to_chars);
+    String squeeze_string = build_set(to_chars ? to_chars : from_chars);
+    Optional<char> last_char;
+
+    for (;;) {
+        char ch = fgetc(stdin);
+        if (feof(stdin))
+            break;
+
+        if (delete_flag) {
+            if (from_str.contains(ch))
+                continue;
         }
-    } else {
-        auto to_str = build_set(to_chars);
-        Optional<char> last_char;
-
-        for (;;) {
-            char ch = fgetc(stdin);
-            if (feof(stdin))
-                break;
+
+        if (transform_flag) {
             auto match = from_str.find_last(ch);
             if (match.has_value())
                 ch = to_str[min(match.value(), to_str.length() - 1)];
+        }
 
-            if (squeeze_repeats && last_char.has_value() && last_char.value() == ch)
-                continue;
+        if (squeeze_flag && last_char.has_value() && last_char.value() == ch && squeeze_string.contains(ch))
+            continue;
 
-            last_char = ch;
-            putchar(ch);
-        }
+        last_char = ch;
+        putchar(ch);
     }
 
     return 0;