From 9b14601d6f97b3b6550c3cbc3599764060937470 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 23 Aug 2018 21:55:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO | 5 ++ g/container/gmap/int_bool_map.go | 6 +-- g/container/gmap/int_int_map.go | 4 +- g/container/gmap/int_interface_map.go | 6 +-- g/container/gmap/int_string_map.go | 4 +- g/container/gmap/interface_interface_map.go | 6 +-- g/container/gmap/string_bool_map.go | 6 +-- g/container/gmap/string_int_map.go | 6 +-- g/container/gmap/string_interface_map.go | 6 +-- g/container/gmap/string_string_map.go | 6 +-- g/container/gmap/uint_interface_map.go | 6 +-- g/container/gqueue/gqueue.go | 2 +- g/frame/gins/gins.go | 8 ++++ g/frame/gmvc/view.go | 31 +++++++----- g/net/ghttp/ghttp_response.go | 10 ---- g/net/ghttp/ghttp_response_view.go | 47 +++++++++++++++++++ g/os/gview/gview.go | 39 ++++++++------- geg/os/gview/{ => basic}/gview.go | 0 geg/os/gview/{ => basic}/gview.tpl | 0 geg/os/gview/bind_func/gview_func.go | 22 +++++++++ geg/os/gview/bind_func/gview_func.tpl | 1 + .../{ => delimiters}/gview_delimiters.go | 0 .../{ => delimiters}/gview_delimiters.tpl | 0 .../{ => hot_update}/controller_hot_update.go | 0 .../{ => hot_update}/gview_hot_update.go | 0 .../gview/{ => hot_update}/web_hot_update.go | 0 26 files changed, 155 insertions(+), 66 deletions(-) create mode 100644 g/net/ghttp/ghttp_response_view.go rename geg/os/gview/{ => basic}/gview.go (100%) rename geg/os/gview/{ => basic}/gview.tpl (100%) create mode 100644 geg/os/gview/bind_func/gview_func.go create mode 100644 geg/os/gview/bind_func/gview_func.tpl rename geg/os/gview/{ => delimiters}/gview_delimiters.go (100%) rename geg/os/gview/{ => delimiters}/gview_delimiters.tpl (100%) rename geg/os/gview/{ => hot_update}/controller_hot_update.go (100%) rename geg/os/gview/{ => hot_update}/gview_hot_update.go (100%) rename geg/os/gview/{ => hot_update}/web_hot_update.go (100%) diff --git a/TODO b/TODO index b2852e81d..a5d3d1e1a 100644 --- a/TODO +++ b/TODO @@ -21,6 +21,11 @@ ghttp路由功能增加分组路由特性; 解决glog串日志情况; ghttp增加返回数据压缩机制; *any模糊匹配路由改进支持不带名字的*路由规则; +检查windows下的平滑重启失效问题; +gview中的template标签失效问题; +ghttp静态文件服务改进(特别是403返回状态的修改); + + DONE: 1. gconv完善针对不同类型的判断,例如:尽量减少sprintf("%v", xxx)来执行string类型的转换; diff --git a/g/container/gmap/int_bool_map.go b/g/container/gmap/int_bool_map.go index be3fd7f05..f586afddf 100644 --- a/g/container/gmap/int_bool_map.go +++ b/g/container/gmap/int_bool_map.go @@ -148,7 +148,7 @@ func (this *IntBoolMap) Size() int { // 哈希表是否为空 func (this *IntBoolMap) IsEmpty() bool { this.mu.RLock() - empty := (len(this.m) == 0) + empty := len(this.m) == 0 this.mu.RUnlock() return empty } @@ -163,13 +163,13 @@ func (this *IntBoolMap) Clear() { // 使用自定义方法执行加锁修改操作 func (this *IntBoolMap) LockFunc(f func(m map[int]bool)) { this.mu.Lock() + defer this.mu.Unlock() f(this.m) - this.mu.Unlock() } // 使用自定义方法执行加锁读取操作 func (this *IntBoolMap) RLockFunc(f func(m map[int]bool)) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } \ No newline at end of file diff --git a/g/container/gmap/int_int_map.go b/g/container/gmap/int_int_map.go index 78785939a..7fd5fc3ce 100644 --- a/g/container/gmap/int_int_map.go +++ b/g/container/gmap/int_int_map.go @@ -163,13 +163,13 @@ func (this *IntIntMap) Clear() { // 使用自定义方法执行加锁修改操作 func (this *IntIntMap) LockFunc(f func(m map[int]int)) { this.mu.Lock() + defer this.mu.Unlock() f(this.m) - this.mu.Unlock() } // 使用自定义方法执行加锁读取操作 func (this *IntIntMap) RLockFunc(f func(m map[int]int)) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } diff --git a/g/container/gmap/int_interface_map.go b/g/container/gmap/int_interface_map.go index 596d2fdb7..f7bc45ab9 100644 --- a/g/container/gmap/int_interface_map.go +++ b/g/container/gmap/int_interface_map.go @@ -148,7 +148,7 @@ func (this *IntInterfaceMap) Size() int { // 哈希表是否为空 func (this *IntInterfaceMap) IsEmpty() bool { this.mu.RLock() - empty := (len(this.m) == 0) + empty := len(this.m) == 0 this.mu.RUnlock() return empty } @@ -163,13 +163,13 @@ func (this *IntInterfaceMap) Clear() { // 使用自定义方法执行加锁修改操作 func (this *IntInterfaceMap) LockFunc(f func(m map[int]interface{})) { this.mu.Lock() + defer this.mu.Unlock() f(this.m) - this.mu.Unlock() } // 使用自定义方法执行加锁读取操作 func (this *IntInterfaceMap) RLockFunc(f func(m map[int]interface{})) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } diff --git a/g/container/gmap/int_string_map.go b/g/container/gmap/int_string_map.go index 10b685691..926f990a5 100644 --- a/g/container/gmap/int_string_map.go +++ b/g/container/gmap/int_string_map.go @@ -148,7 +148,7 @@ func (this *IntStringMap) Size() int { // 哈希表是否为空 func (this *IntStringMap) IsEmpty() bool { this.mu.RLock() - empty := (len(this.m) == 0) + empty := len(this.m) == 0 this.mu.RUnlock() return empty } @@ -170,6 +170,6 @@ func (this *IntStringMap) LockFunc(f func(m map[int]string)) { // 使用自定义方法执行加锁读取操作 func (this *IntStringMap) RLockFunc(f func(m map[int]string)) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } diff --git a/g/container/gmap/interface_interface_map.go b/g/container/gmap/interface_interface_map.go index 38b843a97..16966a01d 100644 --- a/g/container/gmap/interface_interface_map.go +++ b/g/container/gmap/interface_interface_map.go @@ -148,7 +148,7 @@ func (this *InterfaceInterfaceMap) Size() int { // 哈希表是否为空 func (this *InterfaceInterfaceMap) IsEmpty() bool { this.mu.RLock() - empty := (len(this.m) == 0) + empty := len(this.m) == 0 this.mu.RUnlock() return empty } @@ -163,13 +163,13 @@ func (this *InterfaceInterfaceMap) Clear() { // 使用自定义方法执行加锁修改操作 func (this *InterfaceInterfaceMap) LockFunc(f func(m map[interface{}]interface{})) { this.mu.Lock() + defer this.mu.Unlock() f(this.m) - this.mu.Unlock() } // 使用自定义方法执行加锁读取操作 func (this *InterfaceInterfaceMap) RLockFunc(f func(m map[interface{}]interface{})) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } diff --git a/g/container/gmap/string_bool_map.go b/g/container/gmap/string_bool_map.go index 1d9ee2aa2..50efb3e7d 100644 --- a/g/container/gmap/string_bool_map.go +++ b/g/container/gmap/string_bool_map.go @@ -148,7 +148,7 @@ func (this *StringBoolMap) Size() int { // 哈希表是否为空 func (this *StringBoolMap) IsEmpty() bool { this.mu.RLock() - empty := (len(this.m) == 0) + empty := len(this.m) == 0 this.mu.RUnlock() return empty } @@ -163,13 +163,13 @@ func (this *StringBoolMap) Clear() { // 使用自定义方法执行加锁修改操作 func (this *StringBoolMap) LockFunc(f func(m map[string]bool)) { this.mu.Lock() + defer this.mu.Unlock() f(this.m) - this.mu.Unlock() } // 使用自定义方法执行加锁读取操作 func (this *StringBoolMap) RLockFunc(f func(m map[string]bool)) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } diff --git a/g/container/gmap/string_int_map.go b/g/container/gmap/string_int_map.go index 17487dfc2..d333470a5 100644 --- a/g/container/gmap/string_int_map.go +++ b/g/container/gmap/string_int_map.go @@ -148,7 +148,7 @@ func (this *StringIntMap) Size() int { // 哈希表是否为空 func (this *StringIntMap) IsEmpty() bool { this.mu.RLock() - empty := (len(this.m) == 0) + empty := len(this.m) == 0 this.mu.RUnlock() return empty } @@ -163,13 +163,13 @@ func (this *StringIntMap) Clear() { // 使用自定义方法执行加锁修改操作 func (this *StringIntMap) LockFunc(f func(m map[string]int)) { this.mu.Lock() + defer this.mu.Unlock() f(this.m) - this.mu.Unlock() } // 使用自定义方法执行加锁读取操作 func (this *StringIntMap) RLockFunc(f func(m map[string]int)) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } diff --git a/g/container/gmap/string_interface_map.go b/g/container/gmap/string_interface_map.go index 8143038f9..9cb183998 100644 --- a/g/container/gmap/string_interface_map.go +++ b/g/container/gmap/string_interface_map.go @@ -148,7 +148,7 @@ func (this *StringInterfaceMap) Size() int { // 哈希表是否为空 func (this *StringInterfaceMap) IsEmpty() bool { this.mu.RLock() - empty := (len(this.m) == 0) + empty := len(this.m) == 0 this.mu.RUnlock() return empty } @@ -163,13 +163,13 @@ func (this *StringInterfaceMap) Clear() { // 使用自定义方法执行加锁修改操作 func (this *StringInterfaceMap) LockFunc(f func(m map[string]interface{})) { this.mu.Lock() + defer this.mu.Unlock() f(this.m) - this.mu.Unlock() } // 使用自定义方法执行加锁读取操作 func (this *StringInterfaceMap) RLockFunc(f func(m map[string]interface{})) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } diff --git a/g/container/gmap/string_string_map.go b/g/container/gmap/string_string_map.go index 33bea9847..812f3e333 100644 --- a/g/container/gmap/string_string_map.go +++ b/g/container/gmap/string_string_map.go @@ -148,7 +148,7 @@ func (this *StringStringMap) Size() int { // 哈希表是否为空 func (this *StringStringMap) IsEmpty() bool { this.mu.RLock() - empty := (len(this.m) == 0) + empty := len(this.m) == 0 this.mu.RUnlock() return empty } @@ -163,13 +163,13 @@ func (this *StringStringMap) Clear() { // 使用自定义方法执行加锁修改操作 func (this *StringStringMap) LockFunc(f func(m map[string]string)) { this.mu.Lock() + defer this.mu.Unlock() f(this.m) - this.mu.Unlock() } // 使用自定义方法执行加锁读取操作 func (this *StringStringMap) RLockFunc(f func(m map[string]string)) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } diff --git a/g/container/gmap/uint_interface_map.go b/g/container/gmap/uint_interface_map.go index 647b3e3bd..3ff1517de 100644 --- a/g/container/gmap/uint_interface_map.go +++ b/g/container/gmap/uint_interface_map.go @@ -147,7 +147,7 @@ func (this *UintInterfaceMap) Size() int { // 哈希表是否为空 func (this *UintInterfaceMap) IsEmpty() bool { this.mu.RLock() - empty := (len(this.m) == 0) + empty := len(this.m) == 0 this.mu.RUnlock() return empty } @@ -162,13 +162,13 @@ func (this *UintInterfaceMap) Clear() { // 使用自定义方法执行加锁修改操作 func (this *UintInterfaceMap) LockFunc(f func(m map[uint]interface{})) { this.mu.Lock() + defer this.mu.Unlock() f(this.m) - this.mu.Unlock() } // 使用自定义方法执行加锁读取操作 func (this *UintInterfaceMap) RLockFunc(f func(m map[uint]interface{})) { this.mu.RLock() + defer this.mu.RUnlock() f(this.m) - this.mu.RUnlock() } diff --git a/g/container/gqueue/gqueue.go b/g/container/gqueue/gqueue.go index 3eb3f090f..29ced8ed5 100644 --- a/g/container/gqueue/gqueue.go +++ b/g/container/gqueue/gqueue.go @@ -5,7 +5,7 @@ // You can obtain one at https://gitee.com/johng/gf. // 并发安全的动态队列. -// 优点: +// 特点: // 1、队列初始化速度快; // 2、可以向队头/队尾进行Push/Pop操作; // 3、取数据时如果队列为空那么会阻塞等待; diff --git a/g/frame/gins/gins.go b/g/frame/gins/gins.go index 956485680..d53084185 100644 --- a/g/frame/gins/gins.go +++ b/g/frame/gins/gins.go @@ -53,6 +53,8 @@ func View() *gview.View { if p := gfile.MainPkgPath(); gfile.Exists(p) { view.AddPath(p) } + // 框架内置函数 + view.BindFunc("config", funcConfig) Set(gFRAME_CORE_COMPONENT_NAME_VIEW, view) return view } @@ -84,3 +86,9 @@ func Config() *gcfg.Config { } return nil } + +// 模板内置方法:config +func funcConfig(pattern string, file...string) gview.HTML { + return gview.HTML(Config().GetString(pattern, file...)) +} + diff --git a/g/frame/gmvc/view.go b/g/frame/gmvc/view.go index d5f31abff..233ebd23d 100644 --- a/g/frame/gmvc/view.go +++ b/g/frame/gmvc/view.go @@ -17,7 +17,8 @@ import ( type View struct { mu sync.RWMutex // 并发互斥锁 view *gview.View // 底层视图对象 - data map[string]interface{} // 视图数据/模板变量 + data gview.Params // 视图数据/模板变量 + fmap gview.FuncMap // 绑定的模板函数 response *ghttp.Response // 数据返回对象 } @@ -25,13 +26,14 @@ type View struct { func NewView(w *ghttp.Response) *View { return &View { view : gins.View(), - data : make(map[string]interface{}), + data : make(gview.Params), + fmap : make(gview.FuncMap), response : w, } } // 批量绑定模板变量,即调用之后每个线程都会生效,因此有并发安全控制 -func (view *View) Assigns(data map[string]interface{}) { +func (view *View) Assigns(data gview.Params) { view.mu.Lock() for k, v := range data { view.data[k] = v @@ -46,34 +48,41 @@ func (view *View) Assign(key string, value interface{}) { view.mu.Unlock() } +// 绑定自定义模板函数 +func (view *View) BindFunc(name string, function interface{}){ + view.mu.Lock() + view.fmap[name] = function + view.mu.Unlock() +} + // 解析模板,并返回解析后的内容 func (view *View) Parse(file string) ([]byte, error) { view.mu.RLock() - buffer, err := view.view.Parse(file, view.data) - view.mu.RUnlock() + defer view.mu.RUnlock() + buffer, err := view.view.Parse(file, view.data, view.fmap) return buffer, err } // 直接解析模板内容,并返回解析后的内容 func (view *View) ParseContent(content string) ([]byte, error) { view.mu.RLock() - buffer, err := view.view.ParseContent(content, view.data) - view.mu.RUnlock() + defer view.mu.RUnlock() + buffer, err := view.view.ParseContent(content, view.data, view.fmap) return buffer, err } // 使用自定义方法对模板变量执行加锁修改操作 -func (view *View) LockFunc(f func(vars map[string]interface{})) { +func (view *View) LockFunc(f func(data gview.Params)) { view.mu.Lock() + defer view.mu.Unlock() f(view.data) - view.mu.Unlock() } // 使用自定义方法对模板变量执行加锁读取操作 -func (view *View) RLockFunc(f func(vars map[string]interface{})) { +func (view *View) RLockFunc(f func(data gview.Params)) { view.mu.RLock() + defer view.mu.RUnlock() f(view.data) - view.mu.RUnlock() } // 解析并显示指定模板 diff --git a/g/net/ghttp/ghttp_response.go b/g/net/ghttp/ghttp_response.go index a250cece2..8f355043d 100644 --- a/g/net/ghttp/ghttp_response.go +++ b/g/net/ghttp/ghttp_response.go @@ -13,7 +13,6 @@ import ( "gitee.com/johng/gf/g/encoding/gparser" "strconv" "fmt" - "gitee.com/johng/gf/g/frame/gins" ) // 服务端请求返回对象。 @@ -119,15 +118,6 @@ func (r *Response) WriteXml(content interface{}, rootTag...string) error { return nil } -func (r *Response) Template(tpl string, params...map[string]interface{}) error { - if b, err := gins.View().Parse(tpl, params...); err != nil { - return err - } else { - r.Write(b) - } - return nil -} - // 允许AJAX跨域访问 func (r *Response) SetAllowCrossDomainRequest(allowOrigin string, allowMethods string, maxAge...int) { age := 3628800 diff --git a/g/net/ghttp/ghttp_response_view.go b/g/net/ghttp/ghttp_response_view.go new file mode 100644 index 000000000..98975d2b0 --- /dev/null +++ b/g/net/ghttp/ghttp_response_view.go @@ -0,0 +1,47 @@ +// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. +// + +package ghttp + +import ( + "gitee.com/johng/gf/g/os/gview" + "gitee.com/johng/gf/g/frame/gins" +) + +// 展示模板,可以给定模板参数,及临时的自定义模板函数 +func (r *Response) Template(tpl string, params map[string]interface{}, funcmap...map[string]interface{}) error { + fmap := make(gview.FuncMap) + if len(funcmap) > 0 { + fmap = funcmap[0] + } + // 内置函数 + fmap["get"] = r.funcGet + fmap["post"] = r.funcPost + fmap["request"] = r.funcRequest + if b, err := gins.View().Parse(tpl, params, fmap); err != nil { + r.Write("Tpl Parsing Error: " + err.Error()) + return err + } else { + r.Write(b) + } + return nil +} + +// 模板内置函数: get +func (r *Response) funcGet(key string, def...string) gview.HTML { + return gview.HTML(r.request.GetQueryString(key, def...)) +} + +// 模板内置函数: post +func (r *Response) funcPost(key string, def...string) gview.HTML { + return gview.HTML(r.request.GetPostString(key, def...)) +} + +// 模板内置函数: request +func (r *Response) funcRequest(key string, def...string) gview.HTML { + return gview.HTML(r.request.Get(key, def...)) +} \ No newline at end of file diff --git a/g/os/gview/gview.go b/g/os/gview/gview.go index 329b4eea7..2590c3305 100644 --- a/g/os/gview/gview.go +++ b/g/os/gview/gview.go @@ -27,17 +27,21 @@ type View struct { delimiters []string // 模板变量分隔符号 } +// 输出到模板页面时保留HTML标签原意,不做自动escape处理 +type HTML = template.HTML + +// 模板变量 +type Params = map[string]interface{} + +// 函数映射表 +type FuncMap = map[string]interface{} + // 视图表 var viewMap = gmap.NewStringInterfaceMap() // 默认的视图对象 var viewObj = Get(".") -// 输出到模板页面时保留HTML标签原意,不做自动escape处理 -func HTML(content string) template.HTML { - return template.HTML(content) -} - // 直接解析模板内容,返回解析后的内容 func ParseContent(content string, params map[string]interface{}) ([]byte, error) { return viewObj.ParseContent(content, params) @@ -63,6 +67,7 @@ func New(path string) *View { delimiters : make([]string, 2), } view.SetDelimiters("{{", "}}") + // 内置方法 view.BindFunc("include", view.funcInclude) return view } @@ -78,26 +83,24 @@ func (view *View) AddPath(path string) error { } // 解析模板,返回解析后的内容 -func (view *View) Parse(file string, params...map[string]interface{}) ([]byte, error) { +func (view *View) Parse(file string, params map[string]interface{}, funcmap...map[string]interface{}) ([]byte, error) { path := view.paths.Search(file) if path == "" { return nil, errors.New("tpl \"" + file + "\" not found") } content := gfcache.GetContents(path) - - // 模板参数 - data := (map[string]interface{})(nil) - if len(params) > 0 { - data = params[0] - } // 执行模板解析,互斥锁主要是用于funcmap view.mu.RLock() defer view.mu.RUnlock() buffer := bytes.NewBuffer(nil) - if tpl, err := template.New(path).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap).Parse(content); err != nil { + tplobj := template.New(path).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap) + if len(funcmap) > 0 { + tplobj = tplobj.Funcs(funcmap[0]) + } + if tpl, err := tplobj.Parse(content); err != nil { return nil, err } else { - if err := tpl.Execute(buffer, data); err != nil { + if err := tpl.Execute(buffer, params); err != nil { return nil, err } } @@ -105,12 +108,16 @@ func (view *View) Parse(file string, params...map[string]interface{}) ([]byte, e } // 直接解析模板内容,返回解析后的内容 -func (view *View) ParseContent(content string, params map[string]interface{}) ([]byte, error) { +func (view *View) ParseContent(content string, params map[string]interface{}, funcmap...map[string]interface{}) ([]byte, error) { view.mu.RLock() defer view.mu.RUnlock() name := gconv.String(ghash.BKDRHash64([]byte(content))) buffer := bytes.NewBuffer(nil) - if tpl, err := template.New(name).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap).Parse(content); err != nil { + tplobj := template.New(name).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap) + if len(funcmap) > 0 { + tplobj = tplobj.Funcs(funcmap[0]) + } + if tpl, err := tplobj.Parse(content); err != nil { return nil, err } else { if err := tpl.Execute(buffer, params); err != nil { diff --git a/geg/os/gview/gview.go b/geg/os/gview/basic/gview.go similarity index 100% rename from geg/os/gview/gview.go rename to geg/os/gview/basic/gview.go diff --git a/geg/os/gview/gview.tpl b/geg/os/gview/basic/gview.tpl similarity index 100% rename from geg/os/gview/gview.tpl rename to geg/os/gview/basic/gview.tpl diff --git a/geg/os/gview/bind_func/gview_func.go b/geg/os/gview/bind_func/gview_func.go new file mode 100644 index 000000000..f68b19422 --- /dev/null +++ b/geg/os/gview/bind_func/gview_func.go @@ -0,0 +1,22 @@ +package main + + +import ( + "fmt" + "gitee.com/johng/gf/g" + "gitee.com/johng/gf/g/os/gview" +) + +// 用于测试的内置函数 +func funcTest() string { + return "test" +} + +func main() { + view := g.View() + b, err := view.Parse("gview.tpl", nil, gview.FuncMap{ + "test" : funcTest, + }) + fmt.Println(err) + fmt.Println(string(b)) +} \ No newline at end of file diff --git a/geg/os/gview/bind_func/gview_func.tpl b/geg/os/gview/bind_func/gview_func.tpl new file mode 100644 index 000000000..c905f153c --- /dev/null +++ b/geg/os/gview/bind_func/gview_func.tpl @@ -0,0 +1 @@ +{{test}} \ No newline at end of file diff --git a/geg/os/gview/gview_delimiters.go b/geg/os/gview/delimiters/gview_delimiters.go similarity index 100% rename from geg/os/gview/gview_delimiters.go rename to geg/os/gview/delimiters/gview_delimiters.go diff --git a/geg/os/gview/gview_delimiters.tpl b/geg/os/gview/delimiters/gview_delimiters.tpl similarity index 100% rename from geg/os/gview/gview_delimiters.tpl rename to geg/os/gview/delimiters/gview_delimiters.tpl diff --git a/geg/os/gview/controller_hot_update.go b/geg/os/gview/hot_update/controller_hot_update.go similarity index 100% rename from geg/os/gview/controller_hot_update.go rename to geg/os/gview/hot_update/controller_hot_update.go diff --git a/geg/os/gview/gview_hot_update.go b/geg/os/gview/hot_update/gview_hot_update.go similarity index 100% rename from geg/os/gview/gview_hot_update.go rename to geg/os/gview/hot_update/gview_hot_update.go diff --git a/geg/os/gview/web_hot_update.go b/geg/os/gview/hot_update/web_hot_update.go similarity index 100% rename from geg/os/gview/web_hot_update.go rename to geg/os/gview/hot_update/web_hot_update.go