Repository: lapce/lapce
File: lapce-proxy/src/dispatch.rs (Rust)

Code before:
            let mut matches = IndexMap::new();
            let pattern = regex::escape(&pattern);
            if let Ok(matcher) = RegexMatcherBuilder::new()
                .case_insensitive(!case_sensitive)
                .build_literals(&[&pattern])
            {
                let mut searcher = SearcherBuilder::new().build();
                for path in ignore::Walk::new(workspace).flatten() {
                    if let Some(file_type) = path.file_type() {
                        if file_type.is_file() {
                            let path = path.into_path();
                            let mut line_matches = Vec::new();
                            let _ = searcher.search_path(
                                &matcher,
                                path.clone(),
                                UTF8(|lnum, line| {
                                    let mymatch =
                                        matcher.find(line.as_bytes())?.unwrap();
                                    // Shorten the line to avoid sending over absurdly long-lines
                                    // (such as in minified javascript)
                                    // Note that the start/end are column based, not absolute from the
                                    // start of the file.
                                    line_matches.push((
                                        lnum as usize,
                                        (mymatch.start(), mymatch.end()),
                                        line.chars()
                                            .skip(
                                                mymatch.start().saturating_sub(100),
                                            )
                                            .take(100)
                                            .collect::<String>(),
                                    ));
                                    Ok(true)
                                }),
                            );
                            if !line_matches.is_empty() {
                                matches.insert(path.clone(), line_matches);
                            }
                        }
                    }
                }
            }
            Ok(ProxyResponse::GlobalSearchResponse { matches })
        } else {
            Err(RpcError {
                code: 0,
                message: "no workspace set".to_string(),
            })
        };
        proxy_rpc.handle_response(id, result);
    }

Review comment (bug):
As with the previous pull request, there is a clear error here.  Regex returns the start of the match in bytes, not characters (https://docs.rs/grep-regex/0.1.10/grep_regex/struct.RegexMatcher.html#method.find).  Take a slice in the range mymatch.start(), mymatch.end(), it will be valid utf-8.

Code after:
    // This Regex isn't perfect, but it's good enough for now
    // git@github.com:rust-lang/rust.git
    // https://github.com/rust-lang/rust.git

    let git_repo_remote_regex = Regex::new(
        r"^(?:git@|https://)(?P<host>[^:/]+)[:/](?P<org>[^/]+)/(?P<repo>.+)$",
    )
    .unwrap();

    let (host, org, repo) =
        if let Some(v) = git_repo_remote_regex.captures(target_remote_file_url) {
            let host = v
                .name("host")
                .ok_or_else(|| anyhow!("can't to str"))?
                .as_str();
            let org = v
                .name("org")
                .ok_or_else(|| anyhow!("can't to str"))?
                .as_str();
            let repo = v
                .name("repo")
                .ok_or_else(|| anyhow!("can't to str"))?
                .as_str();
            (host, org, repo)
        } else {
            return Err(anyhow!("can't parse remote url"));
        };

    Ok(format!(
        "https://{}/{}/{}/blob/{}/{}",
        host,
        org,
        repo,
        head.peel_to_commit()?.id(),
        file.strip_prefix(workspace_path)?.to_str().unwrap()
    ))
}