<commit_before>package goat

import (
	"net/http"
	"sort"

	"github.com/julienschmidt/httprouter"
)

// Router represents a router
type Router struct {
	// Tree structure
	parent   *Router
	children []*Router

	// The prefix, default: /
	prefix string

	// The index, maps titles to urls
	index map[string]string

	// The router
	router *httprouter.Router
}

// Handle describes the function that should be used by handlers
type Handle func(http.ResponseWriter, *http.Request, Params)

// notFoundHandler handles (as you already know) the 404 error
func (r *Router) notFoundHandler(w http.ResponseWriter, req *http.Request) {
	WriteError(w, "404 Not Found")
}

// ServeHTTP calls the same method on the router
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	r.router.ServeHTTP(w, req)
}

// subPath returns the prefix of the router + the given path and eliminates
// duplicate slashes
func (r *Router) subPath(p string) string {
	pre := r.prefix

	if (pre == "/" || pre[:len(pre)-1] == "/") && p[:1] == "/" {
		pre = pre[:len(pre)-1]
	}

	return pre + p
}

// addRoute adds a route to the index and passes it over to the httprouter
func (r *Router) addRoute(m, p, t string, fn Handle) {

	path := r.subPath(p)

	// Add to index
	if len(t) > 0 && m == "GET" {
		// TODO: Display total path including host
		r.index[t] = path
	}

	// Wrapper function to bypass the parameter problem
	wf := func(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
		fn(w, req, paramsFromHTTPRouter(p))
	}

	if r.parent != nil {
		// We have a subrouter, let the main router handle it
		r.parent.router.Handle(m, path, wf)
	} else {
		r.router.Handle(m, path, wf)
	}
}

// Get adds a GET route
func (r *Router) Get(path, title string, fn Handle) {
	r.addRoute("GET", path, title, fn)
}

// Get adds a POST route
func (r *Router) Post(path, title string, fn Handle) {
	r.addRoute("POST", path, title, fn)
}

// Get adds a DELETE route
func (r *Router) Delete(path, title string, fn Handle) {
	r.addRoute("DELETE", path, title, fn)
}

// Get adds a PUT route
func (r *Router) Put(path, title string, fn Handle) {
	r.addRoute("PUT", path, title, fn)
}

// Subrouter creates and returns a subrouter
func (r *Router) Subrouter(path string) *Router {
	sr := &Router{}
	sr.index = make(map[string]string)
	sr.prefix = r.subPath(path)

	// Init relationships
	r.children = append(r.children, sr)
	sr.parent = r

	return sr
}

// IndexHandler writes the index of all GET methods to the ResponseWriter
func (r *Router) IndexHandler(w http.ResponseWriter, _ *http.Request, _ Params) {
	WriteJSON(w, r.Index())
}

// Index returns a string map with the titles and urls of all GET routes
func (r *Router) Index() map[string]string {
	// Sort
	sorted := make(map[string]string)
	var keys []string
	for k := range r.index {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		sorted[k] = r.index[k]
	}

	return sorted
}<commit_msg>Get index for subrouters too<commit_after>package goat

import (
	"net/http"
	"sort"

	"github.com/julienschmidt/httprouter"
)

// Router represents a router
type Router struct {
	// Tree structure
	parent   *Router
	children []*Router

	// The prefix, default: /
	prefix string

	// The index, maps titles to urls
	index map[string]string

	// The router
	router *httprouter.Router
}

// Handle describes the function that should be used by handlers
type Handle func(http.ResponseWriter, *http.Request, Params)

// notFoundHandler handles (as you already know) the 404 error
func (r *Router) notFoundHandler(w http.ResponseWriter, req *http.Request) {
	WriteError(w, "404 Not Found")
}

// ServeHTTP calls the same method on the router
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	r.router.ServeHTTP(w, req)
}

// subPath returns the prefix of the router + the given path and eliminates
// duplicate slashes
func (r *Router) subPath(p string) string {
	pre := r.prefix

	if (pre == "/" || pre[:len(pre)-1] == "/") && p[:1] == "/" {
		pre = pre[:len(pre)-1]
	}

	return pre + p
}

// addRoute adds a route to the index and passes it over to the httprouter
func (r *Router) addRoute(m, p, t string, fn Handle) {

	path := r.subPath(p)

	// Add to index
	if len(t) > 0 && m == "GET" {
		// TODO: Display total path including host
		r.index[t] = path
	}

	// Wrapper function to bypass the parameter problem
	wf := func(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
		fn(w, req, paramsFromHTTPRouter(p))
	}

	// TODO: Maybe let the subrouters do work too and only call them if
	// needed
	if r.parent != nil {
		// We have a subrouter, let the main router handle it
		r.parent.router.Handle(m, path, wf)
	} else {
		r.router.Handle(m, path, wf)
	}
}

// Get adds a GET route
func (r *Router) Get(path, title string, fn Handle) {
	r.addRoute("GET", path, title, fn)
}

// Get adds a POST route
func (r *Router) Post(path, title string, fn Handle) {
	r.addRoute("POST", path, title, fn)
}

// Get adds a DELETE route
func (r *Router) Delete(path, title string, fn Handle) {
	r.addRoute("DELETE", path, title, fn)
}

// Get adds a PUT route
func (r *Router) Put(path, title string, fn Handle) {
	r.addRoute("PUT", path, title, fn)
}

// Subrouter creates and returns a subrouter
func (r *Router) Subrouter(path string) *Router {
	sr := &Router{}
	sr.index = make(map[string]string)
	sr.prefix = r.subPath(path)

	// Init relationships
	r.children = append(r.children, sr)
	sr.parent = r

	return sr
}

// IndexHandler writes the index of all GET methods to the ResponseWriter
func (r *Router) IndexHandler(w http.ResponseWriter, _ *http.Request, _ Params) {
	WriteJSON(w, r.Index())
}

// Index returns a string map with the titles and urls of all GET routes
func (r *Router) Index() map[string]string {
	index := r.index

	// Recursion
	for _, sr := range r.children {
		si := sr.Index()

		for k, v := range si {
			index[k] = v
		}
	}

	// Sort
	sorted := make(map[string]string)
	var keys []string
	for k := range index {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		sorted[k] = index[k]
	}

	return sorted
}
{'fraction_non_alphanumeric': 0.13371335504885992, 'fraction_numerical': 0.003257328990228013, 'mean_word_length': 3.53880266075388, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1107234', 'n_tokens_mistral': 2194, 'n_tokens_neox': 2114, 'n_words': 740}