diff --git a/Userland/Applications/TextEditor/CMakeLists.txt b/Userland/Applications/TextEditor/CMakeLists.txt index 6550582a02..33f0934ac6 100644 --- a/Userland/Applications/TextEditor/CMakeLists.txt +++ b/Userland/Applications/TextEditor/CMakeLists.txt @@ -2,6 +2,7 @@ compile_gml(TextEditorWindow.gml TextEditorWindowGML.h text_editor_window_gml) set(SOURCES main.cpp + FileArgument.cpp MainWidget.cpp TextEditorWindowGML.h ) diff --git a/Userland/Applications/TextEditor/FileArgument.cpp b/Userland/Applications/TextEditor/FileArgument.cpp new file mode 100644 index 0000000000..182268f908 --- /dev/null +++ b/Userland/Applications/TextEditor/FileArgument.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, ry755 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "FileArgument.h" +#include +#include +#include +#include + +FileArgument::FileArgument(String file_argument) +{ + m_line = {}; + m_column = {}; + + if (Core::File::exists(file_argument)) { + // A file exists with the full specified name, don't attempt to parse it. + m_file_name = file_argument; + return; + } + + // A file doesn't exist with the full specified name, maybe the user entered line/column coordinates? + Regex re("^(.+?)(:([0-9]+):?([0-9]+)?)?$"); + RegexResult result = match(file_argument, re, PosixFlags::Global | PosixFlags::Multiline | PosixFlags::Ungreedy); + auto& groups = result.capture_group_matches.at(0); + + // Match 0 group 0: file name + // Match 0 group 1: line number + // Match 0 group 2: column number + + if (groups.size() > 3) { + // Both a line and column number were specified. + auto file_name = groups.at(0).view.to_string(); + auto initial_line_number = groups.at(1).view.to_string().to_int(); + auto initial_column_number = groups.at(2).view.to_string().to_int(); + + m_file_name = file_name; + if (initial_line_number.has_value() && initial_line_number.value() > 0) + m_line = initial_line_number.value(); + if (initial_column_number.has_value()) + m_column = initial_column_number.value(); + } else if (groups.size() == 3) { + // Only a line number was specified. + auto file_name = groups.at(0).view.to_string(); + auto initial_line_number = groups.at(1).view.to_string().to_int(); + + m_file_name = file_name; + if (initial_line_number.has_value() && initial_line_number.value() > 0) + m_line = initial_line_number.value(); + } else { + // A colon was found at the end of the file name but no values were found after it. + auto file_name = groups.at(0).view.to_string(); + + m_file_name = file_name; + } +} + +FileArgument::~FileArgument() +{ +} diff --git a/Userland/Applications/TextEditor/FileArgument.h b/Userland/Applications/TextEditor/FileArgument.h new file mode 100644 index 0000000000..630b3477c3 --- /dev/null +++ b/Userland/Applications/TextEditor/FileArgument.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021, ry755 + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +class FileArgument final { +public: + FileArgument(String); + ~FileArgument(); + + String file_name() { return m_file_name; } + Optional line() { return m_line; } + Optional column() { return m_column; } + +private: + String m_file_name; + Optional m_line; + Optional m_column; +}; diff --git a/Userland/Applications/TextEditor/main.cpp b/Userland/Applications/TextEditor/main.cpp index 6451c53912..a2246f2eb8 100644 --- a/Userland/Applications/TextEditor/main.cpp +++ b/Userland/Applications/TextEditor/main.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include "FileArgument.h" #include "MainWidget.h" #include #include @@ -27,12 +28,10 @@ int main(int argc, char** argv) } const char* preview_mode = "auto"; - int initial_line_number = 0; const char* file_to_edit = nullptr; Core::ArgsParser parser; parser.add_option(preview_mode, "Preview mode, one of 'none', 'html', 'markdown', 'auto'", "preview-mode", '\0', "mode"); - parser.add_option(initial_line_number, "Start at line number", "line-number", 'l', "line"); - parser.add_positional_argument(file_to_edit, "File to edit", "file", Core::ArgsParser::Required::No); + parser.add_positional_argument(file_to_edit, "File to edit, with optional starting line and column number", "file[:line[:column]]", Core::ArgsParser::Required::No); parser.parse(argc, argv); @@ -71,15 +70,14 @@ int main(int argc, char** argv) window->set_menubar(menubar); if (file_to_edit) { - if (!text_widget.open_file(file_to_edit)) + // A file name was passed, parse any possible line and column numbers included. + FileArgument parsed_argument(file_to_edit); + if (!text_widget.open_file(parsed_argument.file_name())) return 1; + text_widget.editor().set_cursor_and_focus_line(parsed_argument.line().value_or(1) - 1, parsed_argument.column().value_or(0)); } - text_widget.update_title(); - if (initial_line_number != 0) - text_widget.editor().set_cursor_and_focus_line(initial_line_number - 1, 0); - window->show(); window->set_icon(app_icon.bitmap_for_size(16));