<commit_before>package view

import (
	"fmt"
	"html/template"
	"os"
	"path/filepath"
)

type Writer interface {
	Write(p []byte) (n int, err error)
}

type ViewSet struct {
	diver *template.Template
	page  map[string]*template.Template
}

func NewViewSet() *ViewSet {
	v := &ViewSet{}
	v.page = make(map[string]*template.Template)
	return v
}

type View struct {
	Root    string
	Set     map[string]*ViewSet
	current string
}

func (v *View) Parse(set string) error {
	_, ok := v.Set[set]
	if ok {
		v.current = set
		return nil
	}

	setFolder := filepath.Join(v.Root, set)
	tmpl := template.Must(template.ParseGlob(filepath.Join(setFolder, "shared", "*.tmpl")))
	vs := NewViewSet()
	vs.diver = tmpl

	//parse page
	root, err := os.Open(setFolder)
	if err != nil {
		return err
	}

	files, err := root.Readdir(-1)
	if err != nil {
		return err
	}
	for _, file := range files {
		if !file.IsDir() {
			p, err := tmpl.Clone()
			if err != nil {
				continue
			}

			_, err = p.ParseFiles(filepath.Join(setFolder, file.Name()))
			if err == nil {
				vs.page[file.Name()] = p
			}
		}
	}

	v.Set[set] = vs
	v.current = set
	return nil
}

func (v *View) Load(w Writer, pageName string, data interface{}) {
	p, ok := v.Set[v.current].page[pageName]
	if ok {
		p.Execute(w, data)
		return
	}
	fmt.Fprintf(w, "data: %#v", data)
}

func NewView(root string) *View {
	v := &View{}
	v.Root = root
	v.Set = make(map[string]*ViewSet)<commit_msg>view: add shared template function feature<commit_after>package view

import (
	"fmt"
	"html/template"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
)

type Writer interface {
	Write(p []byte) (n int, err error)
}

type ViewSet struct {
	diver *template.Template
	page  map[string]*template.Template
}

func NewViewSet() *ViewSet {
	v := &ViewSet{}
	v.page = make(map[string]*template.Template)
	return v
}

type View struct {
	Root     string
	Set      map[string]*ViewSet
	current  string
	funcsMap template.FuncMap
}

func (v *View) AddFunc(name string, f interface{}) error {
	if r := reflect.TypeOf(f); r.Kind() == reflect.Func {
		if r.NumOut() > 2 {
			return fmt.Errorf("view: %s", "function must have no more than 2 output parameter")
		}
		if r.NumOut() == 2 {
			o := r.Out(1)
			_, ok := o.MethodByName("Error")
			if !ok {
				return fmt.Errorf("view: %s", "function must have the last output parameter implements error")
			}
		}
		v.funcsMap[name] = f
		return nil
	}
	return fmt.Errorf("view: %s", "AddFunc require a valid function")
}

func (v *View) Parse(set string) error {
	_, ok := v.Set[set]
	if ok {
		v.current = set
		return nil
	}

	setFolder := filepath.Join(v.Root, set)

	tmpl := template.Must(template.New("layout.tmpl").Funcs(v.funcsMap).ParseGlob(filepath.Join(setFolder, "shared", "*.tmpl")))
	vs := NewViewSet()
	vs.diver = tmpl
	//parse page
	root, err := os.Open(setFolder)
	if err != nil {
		return err
	}

	files, err := root.Readdir(-1)
	if err != nil {
		return err
	}
	for _, file := range files {
		if !file.IsDir() {
			p, err := tmpl.Clone()
			if err != nil {
				continue
			}
			//read file
			b, err := ioutil.ReadFile(filepath.Join(setFolder, file.Name()))
			if err != nil {
				continue
			}
			_, err = p.Parse(string(b))
			if err == nil {
				vs.page[file.Name()] = p
			}
		}
	}

	v.Set[set] = vs
	v.current = set
	return nil
}

func (v *View) Load(w Writer, pageName string, data interface{}) {
	p, ok := v.Set[v.current].page[pageName]
	if ok {
		p.ExecuteTemplate(w, "layout.tmpl", data)
		return
	}
	fmt.Fprintf(w, "%#v", data)
}

func NewView(root string) *View {
	v := &View{}
	v.Root = root
	v.Set = make(map[string]*ViewSet)
	v.funcsMap = template.FuncMap{}

{'fraction_non_alphanumeric': 0.1613344271260596, 'fraction_numerical': 0.0016406890894175555, 'mean_word_length': 3.2534883720930234, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, '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': '6220857', 'n_tokens_mistral': 1515, 'n_tokens_neox': 1422, 'n_words': 364}