Ver Fonte

Userland: Add minimal prompt support to less

GNU less has a pretty cool prompt format language. This patch adds
support for the language and specifiers for filename, linenumber, and
ending.
Peter Elliott há 4 anos atrás
pai
commit
30aa9b837c
1 ficheiros alterados com 75 adições e 2 exclusões
  1. 75 2
      Userland/Utilities/less.cpp

+ 75 - 2
Userland/Utilities/less.cpp

@@ -174,7 +174,19 @@ public:
 
     void status_line()
     {
-        out(m_tty, "\e[7m -- less -- (line {})\e[27m", m_line + 1);
+        out(m_tty, "\e[7m ");
+        render_status_line(m_prompt);
+        out(m_tty, " \e[27m");
+    }
+
+    void set_filename(StringView const& filename)
+    {
+        m_filename = filename;
+    }
+
+    void set_prompt(StringView const& prompt)
+    {
+        m_prompt = prompt;
     }
 
     bool read_line()
@@ -191,7 +203,63 @@ public:
         return true;
     }
 
+    bool at_end()
+    {
+        return (m_line + m_height - 1) >= m_lines.size() && feof(m_file);
+    }
+
 private:
+    size_t render_status_line(StringView const& prompt, size_t off = 0, char end = '\0', bool ignored = false)
+    {
+        for (; prompt[off] != end && off < prompt.length(); ++off) {
+            if (ignored)
+                continue;
+
+            if (off + 1 >= prompt.length()) {
+                // Don't parse any multi-character sequences if we are at the end of input.
+                out(m_tty, "{}", prompt[off]);
+                continue;
+            }
+
+            switch (prompt[off]) {
+            case '?':
+                switch (prompt[++off]) {
+                case 'f':
+                    off = render_status_line(prompt, off + 1, ':', m_file == stdin);
+                    off = render_status_line(prompt, off + 1, '.', m_file != stdin);
+                    break;
+                case 'e':
+                    off = render_status_line(prompt, off + 1, ':', !at_end());
+                    off = render_status_line(prompt, off + 1, '.', at_end());
+                    break;
+                default:
+                    // Unknown flags are never true.
+                    off = render_status_line(prompt, off + 1, ':', true);
+                    off = render_status_line(prompt, off + 1, '.', false);
+                }
+                break;
+            case '%':
+                switch (prompt[++off]) {
+                case 'f':
+                    out(m_tty, "{}", m_filename);
+                    break;
+                case 'l':
+                    out(m_tty, "{}", m_line);
+                    break;
+                default:
+                    out(m_tty, "?");
+                }
+                break;
+            case '\\':
+                ++off;
+                [[fallthrough]];
+            default:
+                out(m_tty, "{}", prompt[off]);
+            }
+        }
+        return off;
+    }
+
     Vector<String> m_lines;
     size_t m_line { 0 };
     FILE* m_file;
@@ -214,9 +282,12 @@ static String get_key_sequence()
 
 int main(int argc, char** argv)
 {
-    const char* filename = "-";
+    char const* filename = "-";
+    char const* prompt = "?f%f :.(line %l)?e (END):.";
+
     Core::ArgsParser args_parser;
     args_parser.add_positional_argument(filename, "The paged file", "file", Core::ArgsParser::Required::No);
+    args_parser.add_option(prompt, "Prompt line", "prompt", 'P', "Prompt");
     args_parser.parse(argc, argv);
 
     FILE* file;
@@ -229,6 +300,8 @@ int main(int argc, char** argv)
     setup_tty();
 
     Pager pager(file, stdout, g_wsize.ws_col, g_wsize.ws_row);
+    pager.set_filename(filename);
+    pager.set_prompt(prompt);
 
     pager.init();