diff --git a/conf/wide.go b/conf/wide.go index 131e27a..8611ead 100644 --- a/conf/wide.go +++ b/conf/wide.go @@ -1,4 +1,4 @@ -// Wide 配置相关,所有配置(包括用户配置)都是保存在 wide.json 中. +// Configurations manipulations, all configurations (including user configurations) are stored in wide.json. package conf import ( @@ -18,60 +18,60 @@ import ( ) const ( - PathSeparator = string(os.PathSeparator) // 系统文件路径分隔符 - PathListSeparator = string(os.PathListSeparator) // 系统路径列表分隔符 + PathSeparator = string(os.PathSeparator) // OS-specific path separator + PathListSeparator = string(os.PathListSeparator) // OS-specific path list separator ) -// 最后一次会话内容结构. +// The latest session content. type LatestSessionContent struct { - FileTree []string // 文件树展开的路径集 - Files []string // 编辑器打开的文件路径集 - CurrentFile string // 当前编辑器文件路径 + FileTree []string // paths of expanding nodes of file tree + Files []string // paths of files of opening editor tabs + CurrentFile string // path of file of the current focused editor tab } -// 用户结构. +// User. type User struct { Name string Password string - Workspace string // 该用户的工作空间 GOPATH 路径 + Workspace string // the GOPATH of this user Locale string GoFormat string LatestSessionContent *LatestSessionContent } -// 配置结构. +// Configuration. type conf struct { - Server string // 服务地址({IP}:7070) - StaticServer string // 静态资源服务地址(http://{IP}:7070) - EditorChannel string // 编辑器通道地址(ws://{IP}:7070) - OutputChannel string // 输出窗口通道地址(ws://{IP}:7070) - ShellChannel string // Shell 通道地址(ws://{IP}:7070) - SessionChannel string // Wide 会话通道地址(ws://{IP}:7070) - HTTPSessionMaxAge int // HTTP 会话失效时间(秒) - StaticResourceVersion string // 静态资源版本 - MaxProcs int // 并发执行数 - RuntimeMode string // 运行模式 - Pwd string // 工作目录 - Workspace string // 主工作空间 GOPATH 路径 - Locale string // 默认的区域 - Users []*User // 用户集 + Server string // server host and port ({IP}:7070) + StaticServer string // static resources server scheme, host and port (http://{IP}:7070) + EditorChannel string // editor channel (ws://{IP}:7070) + OutputChannel string // output channel (ws://{IP}:7070) + ShellChannel string // shell channel(ws://{IP}:7070) + SessionChannel string // wide session channel (ws://{IP}:7070) + HTTPSessionMaxAge int // HTTP session max age (in seciond) + StaticResourceVersion string // version of static resources + MaxProcs int // Go max procs + RuntimeMode string // runtime mode (dev/prod) + Pwd string // current working direcitory + Workspace string // path of master workspace + Locale string // default locale + Users []*User // configurations of users } -// 配置. +// Configuration variable. var Wide conf -// 维护非变化部分的配置. +// A raw copy of configuration variable. // -// 只有 Users 是会运行时变化的,保存回写文件时要使用这个变量. +// Save function will use this variable to persist. var rawWide conf -// 定时检查 Wide 运行环境. +// FixedTimeCheckEnv checks Wide runtime enviorment periodically (7 minutes). // -// 如果是特别严重的问题(比如 $GOPATH 不存在)则退出进程,另一些不太严重的问题(比如 gocode 不存在)则放入全局通知队列. +// Exits process if found fatal issues (such as not found $GOPATH), +// Notifies user by notification queue if found warning issues (such as not found gocode). func FixedTimeCheckEnv() { go func() { - // 7 分钟进行一次检查环境 for _ = range time.Tick(time.Minute * 7) { if "" == os.Getenv("GOPATH") { glog.Fatal("Not found $GOPATH") @@ -106,9 +106,9 @@ func FixedTimeCheckEnv() { }() } -// 定时(1 分钟)保存配置. +// FixedTimeSave saves configurations (wide.json) periodically (1 minute). // -// 主要目的是保存用户会话内容,以备下一次用户打开 Wide 时进行会话还原. +// Main goal of this function is to save user session content, for restoring session content while user open Wide next time. func FixedTimeSave() { go func() { // 1 分钟进行一次配置保存 @@ -118,11 +118,12 @@ func FixedTimeSave() { }() } -// 获取 username 指定的用户的工作空间路径,查找不到时返回空字符串. +// GetUserWorkspace gets workspace path with the specified username, returns "" if not found. func (c *conf) GetUserWorkspace(username string) string { for _, user := range c.Users { if user.Name == username { ret := strings.Replace(user.Workspace, "{pwd}", c.Pwd, 1) + return filepath.FromSlash(ret) } } @@ -130,16 +131,16 @@ func (c *conf) GetUserWorkspace(username string) string { return "" } -// 获取主工作空间路径. +// GetWorkspace gets the master workspace path. // -// 相比起使用 Wide.Workspace,该函数会做如下处理: -// 1. 替换里面的 {pwd} 变量为实际的目录路径 -// 2. 把 / 替换为 \\ (Windows) +// Compared to the use of Wide.Workspace, this function will be processed as follows: +// 1. Replace {pwd} variable with the actual directory path +// 2. Replace "/" with "\\" (Windows) func (c *conf) GetWorkspace() string { return filepath.FromSlash(strings.Replace(c.Workspace, "{pwd}", c.Pwd, 1)) } -// 获取 username 指定的用户的 Go 源码格式化工具路径,查找不到时返回 "gofmt". +// GetGoFmt gets the path of Go format tool, returns "gofmt" if not found. func (c *conf) GetGoFmt(username string) string { for _, user := range c.Users { if user.Name == username { @@ -158,16 +159,16 @@ func (c *conf) GetGoFmt(username string) string { return "gofmt" } -// 获取用户的工作空间路径. +// GetWorkspace gets workspace path of the user. // -// 相比起使用 User.Workspace,该函数会做如下处理: -// 1. 替换里面的 {pwd} 变量为实际的目录路径 -// 2. 把 / 替换为 \\ (Windows) +// Compared to the use of Wide.Workspace, this function will be processed as follows: +// 1. Replace {pwd} variable with the actual directory path +// 2. Replace "/" with "\\" (Windows) func (u *User) GetWorkspace() string { return filepath.FromSlash(strings.Replace(u.Workspace, "{pwd}", Wide.Pwd, 1)) } -// 获取 username 指定的用户配置. +// GetUser gets configuration of the user specified by the given username, returns nil if not found. func (*conf) GetUser(username string) *User { for _, user := range Wide.Users { if user.Name == username { @@ -178,9 +179,9 @@ func (*conf) GetUser(username string) *User { return nil } -// 获取 GOBIN 中 executable 指定的文件路径. +// GetExecutableInGOBIN gets executable file under GOBIN path. // -// 函数内部会判断操作系统,如果是 Windows 则在 executable 实参后加入 .exe 后缀. +// The specified executable should not with extension, this function will append .exe if on Windows. func (*conf) GetExecutableInGOBIN(executable string) string { if util.OS.IsWindows() { executable += ".exe" @@ -214,12 +215,12 @@ func (*conf) GetExecutableInGOBIN(executable string) string { return os.Getenv("GOBIN") + PathSeparator + executable } -// 保存 Wide 配置. +// Save saves Wide configurations. func Save() bool { - // 只有 Users 是会运行时变化的,其他属性只能手工维护 wide.json 配置文件 + // just the Users field are volatile rawWide.Users = Wide.Users - // 原始配置文件内容 + // format bytes, err := json.MarshalIndent(rawWide, "", " ") if nil != err { @@ -237,7 +238,7 @@ func Save() bool { return true } -// 加载 Wide 配置. +// Load loads the configurations from wide.json. func Load() { bytes, _ := ioutil.ReadFile("conf/wide.json") @@ -248,7 +249,7 @@ func Load() { os.Exit(-1) } - // 保存未经变量替换处理的原始配置文件,用于写回时 + // keep the raw content json.Unmarshal(bytes, &rawWide) ip, err := util.Net.LocalIP() @@ -275,9 +276,9 @@ func Load() { initWorkspaceDirs() } -// 初始化主工作空间、各个用户的工作空间目录. +// initWorkspaceDirs initializes the directories of master workspace, users' workspaces. // -// 如果不存在 Workspace 配置所指定的目录路径则创建该目录. +// Creates directories if not found on path of workspace. func initWorkspaceDirs() { paths := filepath.SplitList(Wide.GetWorkspace()) @@ -291,27 +292,20 @@ func initWorkspaceDirs() { } } -// 在 path 指定的路径下创建工作空间目录. +// createWorkspaceDir creates directories on the path. // -// 1. 根目录:{path} -// 2. 源码目录:{path}/src -// 3. 包目录:{path}/pkg -// 4. 可执行文件目录:{path}/bin +// 1. root directory:{path} +// 2. src directory: {path}/src +// 3. package directory: {path}/pkg +// 4. binary directory: {path}/bin func createWorkspaceDir(path string) { - // {path}, workspace root createDir(path) - - // {path}/src createDir(path + PathSeparator + "src") - - // {path}/pkg createDir(path + PathSeparator + "pkg") - - // {path}/bin createDir(path + PathSeparator + "bin") } -// 在 path 指定的路径下不存在目录或文件则创建目录. +// createDir creates a directory on the path if it not exists. func createDir(path string) { if !isExist(path) { if err := os.MkdirAll(path, 0775); nil != err { @@ -324,9 +318,7 @@ func createDir(path string) { } } -// 检查文件或目录是否存在. -// -// 如果由 filename 指定的文件或目录存在则返回 true,否则返回 false. +// isExist determines whether the file spcified by the given filename is exists. func isExist(filename string) bool { _, err := os.Stat(filename) diff --git a/main.go b/main.go index e8f344a..1e56ad8 100644 --- a/main.go +++ b/main.go @@ -25,37 +25,30 @@ import ( ) const ( - Ver = "1.0.1" // Wide 版本 - CodeMirrorVer = "4.7" // 编辑器版本 + Ver = "1.0.1" // wide version + CodeMirrorVer = "4.7" // editor version ) -// Wide 中唯一一个 init 函数. +// The only one init function in Wide. func init() { - // TODO: 默认启动参数 + // TODO: args flag.Set("logtostderr", "true") flag.Set("v", "3") flag.Parse() - // 加载事件处理 event.Load() - // 加载配置 conf.Load() - - // 定时检查运行环境 conf.FixedTimeCheckEnv() - - // 定时保存配置 conf.FixedTimeSave() - // 定时检查无效会话 session.FixedTimeRelease() } -// 登录. +// loginHandler handles request of user login. func loginHandler(w http.ResponseWriter, r *http.Request) { if "GET" == r.Method { - // 展示登录页面 + // show the login page model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(conf.Wide.Locale), "locale": conf.Wide.Locale, "ver": Ver} @@ -74,7 +67,8 @@ func loginHandler(w http.ResponseWriter, r *http.Request) { return } - // 非 GET 请求当作是登录请求 + // non-GET request as login request + succ := false data := map[string]interface{}{"succ": &succ} @@ -102,7 +96,7 @@ func loginHandler(w http.ResponseWriter, r *http.Request) { return } - // 创建 HTTP 会话 + // create a HTTP session httpSession, _ := session.HTTPSession.Get(r, "wide-session") httpSession.Values["username"] = args.Username httpSession.Values["id"] = strconv.Itoa(rand.Int()) @@ -112,7 +106,7 @@ func loginHandler(w http.ResponseWriter, r *http.Request) { glog.Infof("Created a HTTP session [%s] for user [%s]", httpSession.Values["id"].(string), args.Username) } -// 退出(登出). +// logoutHandler handles request of user logout (exit). func logoutHandler(w http.ResponseWriter, r *http.Request) { data := map[string]interface{}{"succ": true} defer util.RetJSON(w, r, data) @@ -123,7 +117,7 @@ func logoutHandler(w http.ResponseWriter, r *http.Request) { httpSession.Save(r, w) } -// Wide 首页. +// indexHandler handles request of Wide index. func indexHandler(w http.ResponseWriter, r *http.Request) { httpSession, _ := session.HTTPSession.Get(r, "wide-session") @@ -136,7 +130,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Save(r, w) - // 创建一个 Wide 会话 + // create a Wide session wideSession := session.WideSessions.New(httpSession) username := httpSession.Values["username"].(string) @@ -163,14 +157,14 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { t.Execute(w, model) } -// 单个文件资源请求处理. +// serveSingle registers the handler function for the given pattern and filename. func serveSingle(pattern string, filename string) { http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, filename) }) } -// 起始页请求处理. +// startHandler handles request of start page. func startHandler(w http.ResponseWriter, r *http.Request) { httpSession, _ := session.HTTPSession.Get(r, "wide-session") @@ -202,7 +196,7 @@ func startHandler(w http.ResponseWriter, r *http.Request) { t.Execute(w, model) } -// 键盘快捷键页请求处理. +// keyboardShortcutsHandler handles request of keyboard shortcuts page. func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) { httpSession, _ := session.HTTPSession.Get(r, "wide-session") @@ -232,7 +226,7 @@ func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) { t.Execute(w, model) } -// 关于页请求处理. +// aboutHandle handles request of about page. func aboutHandler(w http.ResponseWriter, r *http.Request) { httpSession, _ := session.HTTPSession.Get(r, "wide-session") @@ -263,7 +257,7 @@ func aboutHandler(w http.ResponseWriter, r *http.Request) { t.Execute(w, model) } -// 主程序入口. +// Main. func main() { runtime.GOMAXPROCS(conf.Wide.MaxProcs) @@ -279,18 +273,18 @@ func main() { http.HandleFunc("/about", handlerWrapper(aboutHandler)) http.HandleFunc("/keyboard_shortcuts", handlerWrapper(keyboardShortcutsHandler)) - // 静态资源 + // static resources http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) serveSingle("/favicon.ico", "./static/favicon.ico") - // 库资源 + // workspaces http.Handle("/data/", http.StripPrefix("/data/", http.FileServer(http.Dir("data")))) - // 会话 + // session http.HandleFunc("/session/ws", handlerWrapper(session.WSHandler)) http.HandleFunc("/session/save", handlerWrapper(session.SaveContent)) - // 运行相关 + // run http.HandleFunc("/build", handlerWrapper(output.BuildHandler)) http.HandleFunc("/run", handlerWrapper(output.RunHandler)) http.HandleFunc("/stop", handlerWrapper(output.StopHandler)) @@ -299,7 +293,7 @@ func main() { http.HandleFunc("/go/install", handlerWrapper(output.GoInstallHandler)) http.HandleFunc("/output/ws", handlerWrapper(output.WSHandler)) - // 文件树 + // file tree http.HandleFunc("/files", handlerWrapper(file.GetFiles)) http.HandleFunc("/file", handlerWrapper(file.GetFile)) http.HandleFunc("/file/save", handlerWrapper(file.SaveFile)) @@ -307,7 +301,7 @@ func main() { http.HandleFunc("/file/remove", handlerWrapper(file.RemoveFile)) http.HandleFunc("/file/search/text", handlerWrapper(file.SearchText)) - // 编辑器 + // editor http.HandleFunc("/editor/ws", handlerWrapper(editor.WSHandler)) http.HandleFunc("/go/fmt", handlerWrapper(editor.GoFmtHandler)) http.HandleFunc("/autocomplete", handlerWrapper(editor.AutocompleteHandler)) @@ -317,20 +311,17 @@ func main() { http.HandleFunc("/html/fmt", handlerWrapper(editor.HTMLFmtHandler)) http.HandleFunc("/json/fmt", handlerWrapper(editor.JSONFmtHandler)) - // Shell + // shell http.HandleFunc("/shell/ws", handlerWrapper(shell.WSHandler)) http.HandleFunc("/shell", handlerWrapper(shell.IndexHandler)) - // 通知 + // notification http.HandleFunc("/notification/ws", handlerWrapper(notification.WSHandler)) - // 用户 + // user http.HandleFunc("/user/new", handlerWrapper(session.AddUser)) http.HandleFunc("/user/repos/init", handlerWrapper(session.InitGitRepos)) - // 文档 - http.Handle("/doc/", http.StripPrefix("/doc/", http.FileServer(http.Dir("doc")))) - glog.V(0).Infof("Wide is running [%s]", conf.Wide.Server) err := http.ListenAndServe(conf.Wide.Server, nil) @@ -339,12 +330,11 @@ func main() { } } -// HTTP Handler 包装,完成共性处理. -// -// 共性处理: +// handlerWrapper wraps the HTTP Handler for some common processes. // // 1. panic recover -// 2. 请求计时 +// 2. request stopwatch +// 3. i18n func handlerWrapper(f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) { handler := panicRecover(f) handler = stopwatch(handler) @@ -353,17 +343,16 @@ func handlerWrapper(f func(w http.ResponseWriter, r *http.Request)) func(w http. return handler } -// 国际化处理包装. +// i18nLoad wraps the i18n process. func i18nLoad(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { i18n.Load() - // Handler 处理 handler(w, r) } } -// Handler 包装请求计时. +// stopwatch wraps the request stopwatch process. func stopwatch(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { start := time.Now() @@ -372,24 +361,22 @@ func stopwatch(handler func(w http.ResponseWriter, r *http.Request)) func(w http glog.V(5).Infof("[%s] [%s]", r.RequestURI, time.Since(start)) }() - // Handler 处理 handler(w, r) } } -// Handler 包装 recover panic. +// panicRecover wraps the panic recover process. func panicRecover(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { defer util.Recover() - // Handler 处理 handler(w, r) } } -// 初始化 mime. +// initMime initializes mime types. // -// 有的操作系统(例如 Windows XP)上运行时根据文件后缀获取不到对应的 mime 类型,会导致响应的 HTTP content-type 不正确。 +// We can't get the mime types on some OS (such as Windows XP) by default, so initializes them here. func initMime() { mime.AddExtensionType(".css", "text/css") mime.AddExtensionType(".js", "application/x-javascript")