@ 261101.7

261024.31 · 30121df19b286fd695eb04bdd2e20920b19b0921

Forge links and pasted URLs lead to online repos

The web address was reachable only from one line on the index, which a reader seldom sees. Now a doc's link to a repo on GitHub, GitLab, Codeberg or Bitbucket, or to a file or directory in one, is followed by a small raised www that opens it on the web address. A forge URL typed or pasted into the search box, with or without https://, adds a result under "online" above the others, so Enter opens it.

webPath maps both and drops the branch or commit a file link names, since the web address serves the commit it fetched. Issues, accounts and other hosts get no mark. A share offers neither.

reading declarations

Changes to search.go. All files

search.go

@@ -55,6 +55,8 @@ type found struct { 	Lines []hit `json:"lines"` 	Files int   `json:"files"` // files searched for content 	Cut   bool  `json:"cut"`   // stopped at the time budget or the hit limits+	// Web reads the query on the web address, when it is a forge's URL.+	Web *hit `json:"web,omitempty"` }  // serveSearch answers ?search=q below name: names that hold q first, then@@ -65,11 +67,35 @@ func (t *tree) serveSearch(w http.ResponseWriter, r *http.Request, name, q strin 	ctx, cancel := context.WithTimeout(r.Context(), searchBudget) 	defer cancel() 	res := t.search(ctx, name, q)+	res.Web = t.webHit(q) 	w.Header().Set("Content-Type", "application/json") 	w.Header().Set("Cache-Control", "no-store") 	json.NewEncoder(w).Encode(res) } +// webHit reads the query on the web address when it is a link to a repo+// on a forge, or a file in one, with or without its scheme, eg+// github.com/junegunn/fzf.+func (t *tree) webHit(q string) *hit {+	base := t.webBase()+	q = strings.TrimSpace(q)+	if base == nil || strings.ContainsAny(q, " \t") {+		return nil+	}+	if !strings.Contains(q, "://") {+		q = "https://" + q+	}+	u, err := url.Parse(q)+	if err != nil {+		return nil+	}+	_, p := webPath(u)+	if p == "" {+		return nil+	}+	return &hit{Href: *base + (&url.URL{Path: p, Fragment: u.Fragment}).String(), Path: strings.TrimPrefix(p, "/")}+}+ func (t *tree) search(ctx context.Context, dir, q string) found { 	res := found{Names: []hit{}, Lines: []hit{}} 	lq := strings.ToLower(strings.TrimSpace(q))