diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-04-13 04:50:49 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-04-13 04:50:49 +0800 |
| commit | d4f78be6f231b5289eb1c658d1f67006b7d884dd (patch) | |
| tree | 8d27785fb97745f231e9879eb9bff81e8c225f60 | |
| parent | 8449f5fcefc5406f1666257bacb3bb1afda978e1 (diff) | |
| download | rwebbrowser-d4f78be6f231b5289eb1c658d1f67006b7d884dd.tar.gz rwebbrowser-d4f78be6f231b5289eb1c658d1f67006b7d884dd.tar.xz | |
feat: move URL formatting to Browser class and update documentation
| -rw-r--r-- | README.md | 83 | ||||
| -rw-r--r-- | include/ricochet/core/browser.hh | 1 | ||||
| -rw-r--r-- | src/core/browser.cc | 50 | ||||
| -rw-r--r-- | src/main.cc | 17 |
4 files changed, 99 insertions, 52 deletions
@@ -9,6 +9,19 @@ Modern browsing has become a minefield of non-free scripts, tracking pixels, and * **Minimalist:** Focused entirely on text and structure. * **Distraction-Free:** No ads, no popups, no auto-playing media. Just the data you came for. +## Instructions +- Keyboard-Driven Navigation: Fully controllable via Vim-style keybindings (j/k for scrolling, H/L for history). + +- Link Hinting: Press f to highlight all links with two-letter codes. Jump instantly without using a mouse or typing long numbers. + +- Privacy First: Industrial-grade Cookie Domain Isolation ensures your session data is never leaked across sites. + +- Fast Search: Built-in "Find in Page" (n/N) with real-time ANSI highlighting. + +- Persistent Data: Bookmarks and Browsing History are automatically saved to ~/.ricochet/ for a seamless experience. + +- Highly Configurable: Customize your User-Agent and default Homepage via a simple config file. + ## Key Features - [x] **High-Performance C++ Core:** Native speed with minimal memory footprint. - [x] **Robust HTML5 Parser:** A custom, fault-tolerant DOM builder for the "wild" web. @@ -23,6 +36,40 @@ Ricochet is built with a strictly modular approach: * **`Layout`**: Calculates box models and word-wrapping for terminal constraints. * **`TUI`**: An event-driven terminal UI handling viewport rendering and user input. +## Usage +```bash +# Start with default homepage +./build/bin/ricochet + +# Open a specific URL +./build/bin/ricochet https://www.gnu.org + +# Use DuckDuckGo smart search +./build/bin/ricochet "linux kernel news" +``` + +## Navigation +| Key | Action | +| :--- | :--- | +| `j / k` | Scroll Down / Up | +| `f` | Follow Link (Hint Mode) | +| `n / N` | Find in Page / Next Match | +| `H / L` | History Back / Forward | +| `h` | View Browsing History | +| `b / B` | Add Bookmark / View Bookmarks | +| `/` | Open URL Prompt | +| `i` | Form Input Mode | +| `?` | Show Help Manual | +| `q` | Quit | + +## Configuration +Ricochet stores data in ~/.ricochet/. You can create config.txt to customize your experience: + +```plaintext +homepage=https://v2ex.com +user_agent=MyCustomBrowser/1.0 +``` + ## Getting Started ### Prerequisites @@ -33,26 +80,35 @@ To build Ricochet, ensure your environment meets the following requirements: * `clang-format` for automated code styling. * `clang-tidy` for static analysis and linting. -### Build Instructions +### Building from Source Ricochet enforces out-of-source builds to keep the project structure clean. By default, the project builds in Debug mode with Address and Undefined Behavior sanitizers enabled. +#### 1. Clone the repository ```bash -# 1. Clone the repository git clone https://github.com/yourusername/ricochet.git cd ricochet +``` -# 2. Configure the project -# This will generate compile commands and set the build type to Release +#### 2. Configure the project +This will generate compile commands and set the build type to Release +```bash cmake -B build -DCMAKE_BUILD_TYPE=Release +``` -# 3. Compile the project using all available cores +#### 3. Compile the project using all available cores +```bash cmake --build build -j$(nproc) +``` -# 4. Launch Ricochet -# The executable is located in the bin/ directory -./build/bin/ricochet https://wikipedia.org +### Install +To install Ricochet to your system (defaulting to /usr/local/bin), run the following command with root privileges: + +```bash +sudo cmake --install build ``` +This will install the `ricochet` executable to the `bin` destination and required libraries to `lib`. + ### Build Parameters & Configuration You can customize the build by passing `-D<VAR>=<VALUE>` to the initial `cmake -B build` command. @@ -94,15 +150,8 @@ To install the compiled binaries to your system, use: cmake --install build --prefix /usr/local ``` This installs the `ricochet` binary to `bin` and supporting libraries to `lib`. -## Navigation -| Key | Action | -| :--- | :--- | -| `j / k` | Scroll Down / Up | -| `Tab` | Cycle through links | -| `Enter` | Follow selected link | -| `b` | Go Back in history | -| `u` | Enter new URL | -| `q` | Quit Ricochet | + + ## Acknowledgments The low-level POSIX socket wrappers in `src/net/sys/` are adapted from the Minnow networking framework developed for Stanford University's CS144 course. These utilities are used gracefully to handle file descriptors and network interfaces. diff --git a/include/ricochet/core/browser.hh b/include/ricochet/core/browser.hh index 36e876d..ab7a473 100644 --- a/include/ricochet/core/browser.hh +++ b/include/ricochet/core/browser.hh @@ -33,6 +33,7 @@ public: Browser( Browser&& ) = delete; Browser& operator=( Browser&& ) = delete; + static std::string format_url( std::string input ); static std::string get_configured_homepage(); static int run( std::string_view initial_url ); }; diff --git a/src/core/browser.cc b/src/core/browser.cc index 571783a..c4dbb08 100644 --- a/src/core/browser.cc +++ b/src/core/browser.cc @@ -412,30 +412,6 @@ void draw_view( const tui::Terminal& terminal, std::cout.flush(); } -std::string format_url( std::string input ) -{ - if ( input.empty() ) { - return input; - } - - if ( input.starts_with( "http://" ) || input.starts_with( "https://" ) ) { - return input; - } - - const bool is_domain = input.contains( '.' ) && !input.contains( ' ' ); - if ( is_domain ) { - input.insert( 0, "https://" ); - return input; - } - - for ( char& ch : input ) { - if ( ch == ' ' ) { - ch = '+'; - } - } - return "https://lite.duckduckgo.com/lite/?q=" + input; -} - std::string get_url_input( const tui::Terminal& terminal ) { auto [width, height] = terminal.get_size(); @@ -468,7 +444,7 @@ std::string get_url_input( const tui::Terminal& terminal ) } terminal.show_cursor( false ); - return format_url( std::move( input ) ); + return Browser::format_url( std::move( input ) ); } // std::string get_link_input( const tui::Terminal& terminal ) @@ -1003,6 +979,30 @@ std::vector<std::string> wrap_lines( const std::vector<std::string>& original_li } // namespace +std::string Browser::format_url( std::string input ) +{ + if ( input.empty() ) { + return input; + } + + if ( input.starts_with( "http://" ) || input.starts_with( "https://" ) ) { + return input; + } + + const bool is_domain = input.contains( '.' ) && !input.contains( ' ' ); + if ( is_domain ) { + input.insert( 0, "https://" ); + return input; + } + + for ( char& ch : input ) { + if ( ch == ' ' ) { + ch = '+'; + } + } + return "https://lite.duckduckgo.com/lite/?q=" + input; +} + std::string Browser::get_configured_homepage() { std::ifstream file( get_config_path( "config.txt" ) ); diff --git a/src/main.cc b/src/main.cc index 562861a..d27ab55 100644 --- a/src/main.cc +++ b/src/main.cc @@ -16,7 +16,6 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#include <fstream> #include <iostream> #include <span> #include <string_view> @@ -42,13 +41,6 @@ int main( int argc, char* argv[] ) ricochet::core::print_license_notice(); - std::string start_url; - if ( args.size() < 2 ) { - start_url = ricochet::core::Browser::get_configured_homepage(); - } else { - start_url = std::string( args[1] ); - } - if ( args.size() >= 2 && args[1] == "show" ) { if ( args.size() >= 3 && args[2] == "w" ) { ricochet::core::show_warranty(); @@ -63,10 +55,15 @@ int main( int argc, char* argv[] ) return 1; } - if ( !start_url.starts_with( "http://" ) && !start_url.starts_with( "https://" ) ) { - start_url.insert( 0, "https://" ); + std::string start_url; + if ( args.size() < 2 ) { + start_url = ricochet::core::Browser::get_configured_homepage(); + } else { + start_url = std::string( args[1] ); } + start_url = ricochet::core::Browser::format_url( std::move( start_url ) ); + try { return ricochet::core::Browser::run( start_url ); } catch ( const std::exception& e ) { |
