Search Selected Text Anywhere in Windows

In my previous article, I shared how I streamlined my search process on Linux by creating a tool that allows me to quickly Google selected text without interrupting my workflow. After a week of enjoying that solution, I found myself wanting to replicate that same efficiency in my Windows environment.

While Windows lacks the “clipboard at selection” functionality I enjoyed on Linux, I realized I could still leverage the classic Ctrl+C shortcut to access clipboard content. This led me to develop a simple application that allows me to quickly search selected text in my preferred browser, all while keeping my workflow intact.

The Challenge and Solution

My goal was to create a tool that could:

  1. Access the clipboard content.
  2. Format it into a search URL.
  3. Open a browser in incognito mode with that URL.

To achieve this, I opted for a straightforward, hardcoded solution (for now). Plus, it was a great opportunity to use Rust!

The Development Process

Here’s a detailed overview of how I built this tool:

  1. Setting Up the Environment: I first installed the Windows build tools and Rustup to prepare my system for development.

  2. Creating the Project: I created a new Rust project and added the necessary dependencies:

    1
    2
    3
    cargo new sst_app
    cd sst_app
    cargo add clap clipboard urlencoding winres
  3. Writing the Code: this is the full implementation of the tool in src/main.rs:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    use clipboard::{ClipboardContext, ClipboardProvider};
    use clap::{Parser, ValueEnum};
    use std::process::Command;

    /// A simple program to search using the clipboard content.
    #[derive(Parser, Debug)]
    #[command(
    version="0.1",
    author="Donovan RATEFISON",
    about="Quick search from clipboard",
    long_about = None)]
    struct Args {
    /// Browser to use for opening the search
    #[arg(short = 'b', long, default_value = "chrome")]
    browser: String,

    /// Search engine to use
    #[arg(short = 'e', long, value_enum, default_value_t = SearchEngine::Google)]
    engine: SearchEngine,
    #[arg(long)]
    custom_prompt: Option<String>,
    }

    /// Supported search engines
    #[derive(ValueEnum, Clone, Debug)]
    enum SearchEngine {
    Google,
    Bing,
    Duckduckgo,
    Perplexity,
    Phind,
    Youtube,
    }

    fn main() {
    let mut ctx: ClipboardContext = ClipboardProvider::new().unwrap();
    let mut clipboard_content = ctx.get_contents().unwrap();

    // Parse command-line arguments
    let args = Args::parse();
    if let Some(prompt) = &args.custom_prompt {
    if matches!(args.engine, SearchEngine::Phind | SearchEngine::Perplexity) {
    clipboard_content = prompt.to_owned() + &clipboard_content;
    }
    }

    // Construct the search URL based on the chosen search engine
    let search_url = match args.engine {
    SearchEngine::Google => format!("https://www.google.com/search?q={}", urlencoding::encode(&clipboard_content)),
    SearchEngine::Bing => format!("https://www.bing.com/search?q={}", urlencoding::encode(&clipboard_content)),
    SearchEngine::Duckduckgo => format!("https://www.duckduckgo.com/?q={}", urlencoding::encode(&clipboard_content)),
    SearchEngine::Perplexity => format!("https://www.perplexity.ai/search?q={}", urlencoding::encode(&clipboard_content)),
    SearchEngine::Phind => format!("https://www.phind.com/search?q={}", urlencoding::encode(&clipboard_content)),
    SearchEngine::Youtube => format!("https://www.youtube.com/results?search_query={}", urlencoding::encode(&clipboard_content)),
    };

    open_browser(&search_url, &args.browser);
    }

    fn open_browser(url: &str, browser: &str) {
    let command = match browser.to_lowercase().as_str() {
    "firefox" => format!("start firefox --private-window {}", url),
    "chrome" => format!("start chrome --incognito {}", url),
    "brave" => format!("start brave --private {}", url),
    "edge" => format!("start msedge {}", url),
    _ => format!("start chrome --incognito {}", url), // Default to Chrome
    };

    if let Err(e) = Command::new("cmd")
    .arg("/C")
    .arg(command)
    .output()
    {
    eprintln!("Failed to open browser: {}", e);
    }
    }
  4. Configuring Dependencies: I tweaked up the Cargo.toml file a little to include the required dependencies and build settings necessary for winres:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [package]
    name = "sst_app"
    version = "0.1.0"
    edition = "2024"
    build = "build.rs"

    [build-dependencies]
    winres = "0.1.12"

    [dependencies]
    clap = { version = "4.5.20", features = ["derive"] }
    clipboard = "0.5.0"
    urlencoding = "2.1.3"
    winres = "0.1.12"
  5. Adding an Icon: for the icon resource to be included during build, another file was needed build.rs

    1
    2
    3
    4
    5
    6
    7
    8
    9
    use std::io;
    use winres::WindowsResource;

    fn main() -> io::Result<()> {
    WindowsResource::new()
    .set_icon("icon.ico")
    .compile()?;
    Ok(())
    }
  6. Building the Project: Finally, built the project with cargo build --release.

Using the Tool

To use this new search tool:

  1. Create a shortcut on your desktop that links to the executable.
  2. Add arguments in the shortcut properties. For example: c:/path/to/sst_app.exe -b chrome -e phind.
  3. Assign a key binding to the shortcut (I personally use Ctrl+Alt+S).

Now, whenever you select text and press Ctrl+C, you can immediately use your assigned key binding to search that text in your preferred browser and search engine.
You can get help on available options by running sst_app --help in the command prompt.

Conclusion

While this solution is already very good, there are plenty of opportunities for enhancement. In the future, I may look into integrating the Ctrl+C functionality directly into the app or maybe adding more customization options.
If you’re interested in trying out this tool or want to collaborate on its development, feel free to reach out.
Happy searching (again)!