1
0
forked from x/icebergs
This commit is contained in:
harveyshao 2022-12-11 20:18:08 +08:00
parent b791c5aa77
commit 3de5a53832
56 changed files with 566 additions and 634 deletions

View File

@ -18,6 +18,7 @@ const (
CENTOS = "centos"
ALPINE = "alpine"
BUSYBOX = "busybox"
RELEASE = "release"
)
const MIRRORS = "mirrors"
@ -40,6 +41,7 @@ func init() {
}
var _release = ""
func release(m *ice.Message) string {
osid := runtime.GOOS
if osid != "linux" {
@ -71,4 +73,6 @@ func insert(m *ice.Message, sys, cmd string, arg ...string) bool {
func IsAlpine(m *ice.Message, arg ...string) bool { return insert(m, ALPINE, "system apk add", arg...) }
func IsCentos(m *ice.Message, arg ...string) bool { return insert(m, CENTOS, "yum install -y", arg...) }
func IsUbuntu(m *ice.Message, arg ...string) bool { return insert(m, UBUNTU, "apt get -y", arg...) }
func IsSystem(m *ice.Message, arg ...string) bool { return IsAlpine(m, arg...) || IsCentos(m, arg...) || IsUbuntu(m, arg...) }
func IsSystem(m *ice.Message, arg ...string) bool {
return IsAlpine(m, arg...) || IsCentos(m, arg...) || IsUbuntu(m, arg...)
}

View File

@ -11,6 +11,7 @@ import (
"shylinux.com/x/go-qrcode"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits"
)
@ -76,7 +77,7 @@ func _qrcode_cli(m *ice.Message, text string) {
}
m.Echo(ice.NL)
}
m.Echo(text)
m.Echo(text).Echo(ice.NL)
}
func _qrcode_web(m *ice.Message, text string) {
qr, _ := qrcode.New(text, qrcode.Medium)
@ -148,3 +149,12 @@ func Color(m *ice.Message, c string, str ice.Any) string {
func ColorRed(m *ice.Message, str ice.Any) string { return Color(m, RED, str) }
func ColorGreen(m *ice.Message, str ice.Any) string { return Color(m, GREEN, str) }
func ColorYellow(m *ice.Message, str ice.Any) string { return Color(m, YELLOW, str) }
func PushText(m *ice.Message, text string) {
m.OptionFields(ice.MSG_DETAIL)
if m.PushScript(nfs.SCRIPT, text); strings.HasPrefix(text, ice.HTTP) {
m.PushQRCode(QRCODE, text)
m.PushAnchor(text)
}
m.Echo(text)
}

View File

@ -2,10 +2,11 @@ package log
import (
"path"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/nfs"
)
const ERROR = "error"
func init() {

View File

@ -3,10 +3,10 @@ package log
import (
"path"
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits"
)

View File

@ -220,6 +220,7 @@ func HashSelects(m *ice.Message, arg ...string) *ice.Message {
return HashSelect(m, arg...)
}
func HashSelectValue(m *ice.Message, cb Any) *ice.Message {
m.OptionFields(m.Config(FIELD))
defer RLock(m, m.PrefixKey(), "")()
Richs(m, m.PrefixKey(), nil, FOREACH, func(key string, value Map) { _mdb_select(m, cb, key, value, nil, nil) })
return m

View File

@ -197,9 +197,14 @@ const (
CACHE_FIELD = "cache.field"
)
func Grows(m *ice.Message, prefix string, chain Any, match string, value string, cb Any) Map {
cache := m.Confm(prefix, chain)
if cache == nil {
type Message interface {
Confv(arg ...Any) (val Any)
Option(key string, arg ...Any) string
}
func Grows(m Message, prefix string, chain Any, match string, value string, cb Any) Map {
cache, ok := m.Confv(prefix, chain).(ice.Map)
if cache == nil || !ok {
return nil
}
limit := kit.Int(m.Option(CACHE_LIMIT))
@ -216,9 +221,9 @@ func Grows(m *ice.Message, prefix string, chain Any, match string, value string,
kit.Int(kit.Select("10", m.Option(CACHE_LIMIT))),
match, value, cb)
}
func Grow(m *ice.Message, prefix string, chain Any, data Any) int {
cache := m.Confm(prefix, chain)
if cache == nil {
func Grow(m Message, prefix string, chain Any, data Any) int {
cache, ok := m.Confv(prefix, chain).(ice.Map)
if cache == nil || !ok {
cache = kit.Data()
m.Confv(prefix, chain, cache)
}

View File

@ -25,7 +25,7 @@ func _zone_inputs(m *ice.Message, prefix, chain, zone string, field, value strin
func _zone_insert(m *ice.Message, prefix, chain, zone string, arg ...string) {
h := _hash_select_field(m, prefix, chain, zone, HASH)
if h == "" {
h = _hash_insert(m, prefix, chain, _mdb_getmeta(m, prefix, chain, SHORT), zone)
h = _hash_insert(m, prefix, chain, kit.Select(ZONE, _mdb_getmeta(m, prefix, chain, SHORT)), zone)
}
m.Assert(h != "")
defer Lock(m, prefix, chain)()
@ -193,7 +193,7 @@ func ZoneSelect(m *ice.Message, arg ...string) *ice.Message {
arg = kit.Slice(arg, 0, 2)
m.Fields(len(arg), kit.Select(kit.Fields(TIME, m.Config(SHORT), COUNT), m.Config(FIELDS)), ZoneField(m))
if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg, logs.FileLineMeta(-1)); len(arg) == 0 {
m.Sort(ZoneShort(m)).StatusTimeCount().PushAction(m.Config(ACTION), REMOVE)
m.StatusTimeCount().PushAction(m.Config(ACTION), REMOVE).Sort(ZoneShort(m))
} else if len(arg) == 1 {
m.StatusTimeCountTotal(_mdb_getmeta(m, "", kit.Keys(HASH, HashSelectField(m, arg[0], HASH)), COUNT))
}

View File

@ -80,19 +80,19 @@ func StatFile(m Message, p string) (os.FileInfo, error) {
func OpenFile(m Message, p string) (io.ReadCloser, error) {
return OptionFiles(m).OpenFile(p)
}
func CreateFile(m *ice.Message, p string) (io.WriteCloser, string, error) {
func CreateFile(m Message, p string) (io.WriteCloser, string, error) {
return OptionFiles(m).CreateFile(p)
}
func AppendFile(m *ice.Message, p string) (io.ReadWriteCloser, string, error) {
func AppendFile(m Message, p string) (io.ReadWriteCloser, string, error) {
file := OptionFiles(m)
w, e := file.AppendFile(p)
return w, p, e
}
func WriteFile(m *ice.Message, p string, b []byte) error {
func WriteFile(m Message, p string, b []byte) error {
return OptionFiles(m).WriteFile(p, b)
}
func ReadDir(m *ice.Message, p string) ([]os.FileInfo, error) {
func ReadDir(m Message, p string) ([]os.FileInfo, error) {
list, e := OptionFiles(m).ReadDir(p)
for i := 0; i < len(list)-1; i++ {
for j := i + 1; j < len(list); j++ {
@ -103,23 +103,23 @@ func ReadDir(m *ice.Message, p string) ([]os.FileInfo, error) {
}
return list, e
}
func MkdirAll(m *ice.Message, p string) error {
func MkdirAll(m Message, p string) error {
return OptionFiles(m).MkdirAll(p, ice.MOD_DIR)
}
func RemoveAll(m *ice.Message, p string) error {
func RemoveAll(m Message, p string) error {
return OptionFiles(m).RemoveAll(p)
}
func Remove(m *ice.Message, p string) error {
func Remove(m Message, p string) error {
return OptionFiles(m).Remove(p)
}
func Rename(m *ice.Message, oldname string, newname string) error {
func Rename(m Message, oldname string, newname string) error {
MkdirAll(m, path.Dir(newname))
return OptionFiles(m).Rename(oldname, newname)
}
func Symlink(m *ice.Message, oldname string, newname string) error {
func Symlink(m Message, oldname string, newname string) error {
return OptionFiles(m).Symlink(oldname, newname)
}
func Link(m *ice.Message, oldname string, newname string) error {
func Link(m Message, oldname string, newname string) error {
return OptionFiles(m).Link(oldname, newname)
}
@ -133,7 +133,7 @@ func ExistsFile(m Message, p string) bool {
}
return false
}
func ReadFile(m *ice.Message, p string) ([]byte, error) {
func ReadFile(m Message, p string) ([]byte, error) {
if f, e := OptionFiles(m).OpenFile(p); e == nil {
defer f.Close()
return ioutil.ReadAll(f)
@ -141,7 +141,7 @@ func ReadFile(m *ice.Message, p string) ([]byte, error) {
return nil, e
}
}
func CloseFile(m *ice.Message, p ice.Any) {
func CloseFile(m Message, p ice.Any) {
if w, ok := p.(io.Closer); ok {
w.Close()
}

View File

@ -72,8 +72,8 @@ func init() {
}
}},
PUBLISH: {Hand: func(m *ice.Message, arg ...string) {
if strings.Contains(arg[0], "://"+LOCALHOST) {
arg[0] = strings.Replace(arg[0], "://"+LOCALHOST, "://"+m.Cmd("").Append(aaa.IP), 1)
if strings.Contains(arg[0], LOCALHOST) {
arg[0] = strings.Replace(arg[0], LOCALHOST, m.Cmd("").Append(aaa.IP), 1)
}
m.Echo(arg[0])
}},

View File

@ -171,6 +171,13 @@ func init() {
})
ctx.Upload = Upload
}
func RenderCache(m *ice.Message, h string) {
if msg := m.Cmd(CACHE, h); msg.Append(nfs.FILE) == "" {
m.RenderResult(msg.Append(mdb.TEXT))
} else {
m.RenderDownload(msg.Append(mdb.FILE), msg.Append(mdb.TYPE), msg.Append(mdb.NAME))
}
}
func Upload(m *ice.Message) []string {
if up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)); len(up) == 1 {
if m.Cmdy(CACHE, UPLOAD).Optionv(ice.MSG_UPLOAD, kit.Simple(m.Append(mdb.HASH), m.Append(mdb.NAME), m.Append(nfs.SIZE))); m.Option(ice.MSG_USERPOD) != "" {

View File

@ -31,11 +31,15 @@ const (
func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
if cmd == ice.RENDER_VOID {
return true
} else if cmd != "" {
defer func() { m.Logs(mdb.EXPORT, cmd, args) }()
}
switch arg := kit.Simple(args...); cmd {
arg := kit.Simple(args...)
if len(arg) == 0 {
args = nil
}
if cmd != "" {
defer func() { m.Logs("Render", cmd, args) }()
}
switch cmd {
case COOKIE: // value [name [path [expire]]]
RenderCookie(m, arg[0], arg[1:]...)
@ -63,7 +67,9 @@ func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
if len(arg) > 0 { // [str [arg...]]
m.W.Write([]byte(kit.Format(arg[0], args[1:]...)))
} else {
args = append(args, nfs.SIZE, len(m.Result()))
if m.Result() == "" && m.Length() > 0 {
m.Table()
}
m.W.Write([]byte(m.Result()))
}

View File

@ -58,9 +58,12 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
if m.Logs(r.Header.Get(ice.MSG_USERIP), r.Method, r.URL.String()); m.Config(LOGHEADERS) == ice.TRUE {
kit.Fetch(r.Header, func(k string, v []string) { m.Logs("Header", k, v) })
}
if r.Method == http.MethodGet && r.URL.Path != PP(SPACE) {
if r.Method == http.MethodGet && r.URL.Path != PP(SPACE) && !strings.HasPrefix(r.URL.Path, "/code/bash") {
repos := kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get(UserAgent), MOZILLA))
if msg := gdb.Event(m.Spawn(w, r), SERVE_REWRITE, r.Method, r.URL.Path, path.Join(m.Conf(SERVE, kit.Keym(repos, nfs.PATH)), r.URL.Path), repos); msg.Option(ice.MSG_OUTPUT) != "" {
if p := path.Join(ice.USR, repos, r.URL.Path); r.URL.Path != ice.PS && nfs.ExistsFile(m, p) {
Render(m.Spawn(w, r), ice.RENDER_DOWNLOAD, p)
return false
} else if msg := gdb.Event(m.Spawn(w, r), SERVE_REWRITE, r.Method, r.URL.Path, path.Join(m.Conf(SERVE, kit.Keym(repos, nfs.PATH)), r.URL.Path), repos); msg.Option(ice.MSG_OUTPUT) != "" {
Render(msg, msg.Option(ice.MSG_OUTPUT), kit.List(msg.Optionv(ice.MSG_ARGS))...)
return false
}
@ -73,9 +76,7 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response
kit.Fetch(u.Query(), func(k string, v []string) { m.Logs("Refer", k, v).Optionv(k, v) })
}
for k, v := range kit.ParseQuery(r.URL.RawQuery) {
if m.IsCliUA() {
v = kit.Simple(v, func(v string) (string, error) { return url.QueryUnescape(v) })
}
kit.If(m.IsCliUA(), func() { v = kit.Simple(v, func(v string) (string, error) { return url.QueryUnescape(v) }) })
m.Optionv(k, v)
}
switch r.Header.Get(ContentType) {
@ -85,7 +86,10 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response
kit.Fetch(data, func(k string, v ice.Any) { m.Optionv(k, v) })
default:
r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength))))
kit.Fetch(r.PostForm, func(k string, v []string) { m.Logs("Form", k, kit.Join(v, ice.SP)).Optionv(k, v) })
kit.Fetch(r.PostForm, func(k string, v []string) {
kit.If(m.IsCliUA(), func() { v = kit.Simple(v, func(v string) (string, error) { return url.QueryUnescape(v) }) })
m.Logs("Form", k, kit.Join(v, ice.SP)).Optionv(k, v)
})
}
kit.Fetch(r.Cookies(), func(k, v string) { m.Optionv(k, v) })
m.OptionDefault(ice.HEIGHT, "480", ice.WIDTH, "320")
@ -95,6 +99,8 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response
if m.Option(ice.MSG_USERWEB, _serve_domain(m)); m.Option(ice.POD) != "" {
m.Option(ice.MSG_USERPOD, m.Option(ice.POD))
}
u := OptionUserWeb(m)
m.Option(ice.MSG_USERHOST, u.Scheme+"//"+u.Host)
m.Option(ice.MSG_SESSID, m.Option(CookieName(m.Option(ice.MSG_USERWEB))))
if m.Optionv(ice.MSG_CMDS) == nil {
if p := strings.TrimPrefix(r.URL.Path, key); p != "" {
@ -121,7 +127,7 @@ func _serve_domain(m *ice.Message) string {
)
}
func _serve_login(m *ice.Message, key string, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) {
if aaa.SessCheck(m, m.Option(ice.MSG_SESSID)); m.Option(ice.MSG_USERNAME) == "" && r.URL.Path != PP(SPACE) {
if aaa.SessCheck(m, m.Option(ice.MSG_SESSID)); m.Option(ice.MSG_USERNAME) == "" && r.URL.Path != PP(SPACE) && !strings.HasPrefix(r.URL.Path, "/sync") {
gdb.Event(m, SERVE_LOGIN)
}
if _, ok := m.Target().Commands[WEB_LOGIN]; ok {

View File

@ -99,7 +99,7 @@ func init() {
ice.Index.Register(Index, &Frame{}, BROAD, SERVE, SPACE, DREAM, SHARE, CACHE, SPIDE)
}
func ApiAction(arg ...string) ice.Actions { return ice.Actions{kit.Select(ice.PS, arg, 0): {}} }
func Prefix(arg ...string) string { return kit.Keys(WEB, arg) }
func Prefix(arg ...string) string { return kit.Keys(WEB, arg) }
func P(arg ...string) string { return path.Join(ice.PS, path.Join(arg...)) }
func PP(arg ...string) string { return P(arg...) + ice.PS }

View File

@ -189,6 +189,7 @@ const ( // MSG
MSG_USERNICK = "user.nick"
MSG_USERZONE = "user.zone"
MSG_LANGUAGE = "user.lang"
MSG_USERHOST = "user.host"
MSG_TITLE = "sess.title"
MSG_TOPIC = "sess.topic"

View File

@ -27,7 +27,7 @@ func _action_exec(m *ice.Message, river, storm, index string, arg ...string) {
}
func _action_auth(m *ice.Message, share string) *ice.Message {
msg := m.Cmd(web.SHARE, share)
if web.IsNotValidShare(m, msg.Append(mdb.TIME)) {
if web.IsNotValidShare(m, msg.Append(mdb.TIME)) {
msg.Append(mdb.TYPE, "")
return msg
}

View File

@ -137,4 +137,4 @@ var _binpack_template_end = `
}
}
}
`
`

View File

@ -58,7 +58,7 @@ func _css_show(m *ice.Message, arg ...string) {
}
func _css_exec(m *ice.Message, arg ...string) {
if arg[2] == ice.USR_VOLCANOS && strings.HasPrefix(arg[1], ice.PLUGIN_LOCAL) {
key := ctx.GetFileCmd("/require/shylinux.com/x/icebergs/core/"+strings.TrimPrefix(arg[1], ice.PLUGIN_LOCAL))
key := ctx.GetFileCmd("/require/shylinux.com/x/icebergs/core/" + strings.TrimPrefix(arg[1], ice.PLUGIN_LOCAL))
ctx.ProcessCommand(m, kit.Select("can.plugin", key), kit.Simple())
return
}

View File

@ -21,11 +21,10 @@ func _install_path(m *ice.Message, link string) string {
link = kit.Select(m.Option(mdb.LINK), link)
if p := path.Join(ice.USR_INSTALL, kit.TrimExt(link)); nfs.ExistsFile(m, p) {
return p
} else if p := path.Join(ice.USR_INSTALL, path.Base(link)); nfs.ExistsFile(m, p) {
return path.Join(ice.USR_INSTALL, strings.Split(m.Cmd(nfs.TAR, p, "", "1").Append(nfs.FILE), ice.PS)[0])
} else if pp := path.Join(ice.USR_INSTALL, path.Base(link)); nfs.ExistsFile(m, pp) {
return path.Join(ice.USR_INSTALL, strings.Split(m.Cmd(nfs.TAR, pp, "", "1").Append(nfs.FILE), ice.PS)[0])
} else {
m.Assert(true)
return ""
return p
}
}
func _install_download(m *ice.Message) {

View File

@ -45,6 +45,15 @@ func _publish_bin_list(m *ice.Message, dir string) {
}
m.SortTimeR(mdb.TIME)
}
func PublishScript(m *ice.Message, arg ...string) {
u := web.OptionUserWeb(m)
host := tcp.PublishLocalhost(m, strings.Split(u.Host, ice.DF)[0])
m.Option(cli.CTX_ENV, kit.Select("", ice.SP+kit.JoinKV(ice.EQ, ice.SP, cli.CTX_POD, m.Option(ice.MSG_USERPOD)), m.Option(ice.MSG_USERPOD) != ""))
m.Option("httphost", fmt.Sprintf("%s://%s:%s", u.Scheme, host, kit.Select(kit.Select("443", "80", u.Scheme == ice.HTTP), strings.Split(u.Host, ice.DF), 1)))
for _, v := range arg {
m.EchoScript(kit.Renders(v, m))
}
}
func _publish_contexts(m *ice.Message, arg ...string) {
u := web.OptionUserWeb(m)
host := tcp.PublishLocalhost(m, strings.Split(u.Host, ice.DF)[0])
@ -75,7 +84,7 @@ const PUBLISH = "publish"
func init() {
Index.MergeCommands(ice.Commands{
PUBLISH: {Name: "publish path auto create volcanos icebergs intshell", Help: "发布", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Config(ice.CONTEXTS, _contexts) }},
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { m.Config(ice.CONTEXTS, _contexts) }},
web.SERVE_START: {Hand: func(m *ice.Message, arg ...string) { _publish_file(m, ice.ICE_BIN) }},
ice.VOLCANOS: {Help: "火山架", Hand: func(m *ice.Message, arg ...string) {
defer func() { m.EchoQRCode(m.Option(ice.MSG_USERWEB)) }()
@ -91,9 +100,9 @@ func init() {
_publish_list(m, kit.ExtReg(`(sh|vim|conf)`))
}},
ice.CONTEXTS: {Hand: func(m *ice.Message, arg ...string) { _publish_contexts(m, arg...) }},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(nfs.DIR, arg[1:]).Cut("path,size,time").ProcessAgain() }},
mdb.CREATE: {Name: "create file", Help: "添加", Hand: func(m *ice.Message, arg ...string) { _publish_file(m, m.Option(nfs.FILE)) }},
nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.Trash(m, path.Join(ice.USR_PUBLISH, m.Option(nfs.PATH))) }},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(nfs.DIR, arg[1:]).Cut("path,size,time").ProcessAgain() }},
mdb.CREATE: {Name: "create file", Help: "添加", Hand: func(m *ice.Message, arg ...string) { _publish_file(m, m.Option(nfs.FILE)) }},
nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.Trash(m, path.Join(ice.USR_PUBLISH, m.Option(nfs.PATH))) }},
}, ctx.ConfAction(ice.CONTEXTS, _contexts), aaa.RoleAction()), Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(nfs.DIR, kit.Select("", arg, 0), nfs.DIR_WEB_FIELDS, kit.Dict(nfs.DIR_ROOT, ice.USR_PUBLISH)).SortTimeR(mdb.TIME)
}},

View File

@ -17,9 +17,11 @@ const SHY = "shy"
func init() {
Index.MergeCommands(ice.Commands{
SHY: {Name: "shy path auto", Help: "脚本", Actions: ice.MergeActions(ice.Actions{
mdb.RENDER: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessCommand(m, web.WIKI_WORD, kit.Simple(path.Join(arg[2], arg[1]))) }},
mdb.RENDER: {Hand: func(m *ice.Message, arg ...string) {
ctx.ProcessCommand(m, web.WIKI_WORD, kit.Simple(path.Join(arg[2], arg[1])))
}},
mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(ssh.SOURCE, path.Join(arg[2], arg[1])) }},
TEMPLATE: {Hand: func(m *ice.Message, arg ...string) { m.Echo(`chapter "hi"`) }},
TEMPLATE: {Hand: func(m *ice.Message, arg ...string) { m.Echo(`chapter "hi"`) }},
}, PlugAction()), Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 && kit.Ext(arg[0]) == m.CommandKey() {
m.Cmdy(web.WIKI_WORD, path.Join(ice.SRC, strings.TrimPrefix(arg[0], "src/")))

View File

@ -15,8 +15,12 @@ import (
kit "shylinux.com/x/toolkits"
)
func _volcanos(m *ice.Message, file ...string) string { return path.Join(ice.USR_VOLCANOS, path.Join(file...)) }
func _publish(m *ice.Message, file ...string) string { return path.Join(ice.USR_PUBLISH, path.Join(file...)) }
func _volcanos(m *ice.Message, file ...string) string {
return path.Join(ice.USR_VOLCANOS, path.Join(file...))
}
func _publish(m *ice.Message, file ...string) string {
return path.Join(ice.USR_PUBLISH, path.Join(file...))
}
func _webpack_can(m *ice.Message) {
m.Option(nfs.DIR_ROOT, "")
m.Cmd(nfs.COPY, _volcanos(m, PAGE_CAN_CSS), _volcanos(m, PAGE_INDEX_CSS), _volcanos(m, PAGE_CACHE_CSS))
@ -162,4 +166,4 @@ var _webpack_template = `
<script>%s</script>
<script>%s</script>
</body>
`
`

View File

@ -78,6 +78,7 @@ func init() {
FEEL, DRAW, DATA, WORD,
)
}
func Prefix(arg ...string) string { return web.Prefix(WIKI, kit.Keys(arg)) }
func WikiAction(dir string, ext ...string) ice.Actions {
return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(nfs.PATH, dir, lex.REGEXP, kit.FileReg(ext...)),

View File

@ -37,7 +37,7 @@ func (m *Message) join(arg ...Any) (string, []Any) {
case time.Time:
arg[i+1] = v.Format(MOD_TIME)
case []string:
arg[i+1] = kit.Join(v, " ")
arg[i+1] = kit.Join(v, SP)
}
list = append(list, key+kit.Select("", DF, !strings.Contains(key, DF)), kit.Format(arg[i+1]))
}

View File

@ -507,3 +507,6 @@ func (m *Message) Result(arg ...Any) string {
}
return strings.Join(m.Resultv(arg...), "")
}
func (m *Message) Results(arg ...Any) string {
return kit.Select("", strings.TrimSpace(m.Result()), !m.IsErr())
}

View File

@ -105,7 +105,7 @@ func (m *Message) RenameAppend(arg ...string) *Message {
func (m *Message) AppendSimple(key ...string) (res []string) {
if len(key) == 0 {
if m.FieldsIsDetail() {
key = append(key, m.Appendv(KEY)...)
key = append(key, m.meta[KEY]...)
} else {
key = append(key, m.Appendv(MSG_APPEND)...)
}
@ -173,7 +173,7 @@ func (m *Message) _fileline() string {
}
}
func (m *Message) ActionHand(cmd *Command, key, sub string, arg ...string) *Message {
if action, ok := cmd.Actions[sub]; !m.Warn(!ok, ErrNotFound, sub, cmd.GetFileLines()) {
if action, ok := cmd.Actions[sub]; !m.Warn(!ok, ErrNotFound, sub, cmd.GetFileLine()) {
return m.Target()._action(m, cmd, key, sub, action, arg...)
}
return m

View File

@ -20,62 +20,43 @@ const (
type alpha struct {
ice.Zone
field string `data:"word,translation,definition"`
store string `data:"usr/local/export"`
store string `data:"usr/local/export/"`
fsize string `data:"300000"`
limit string `data:"50000"`
least string `data:"1000"`
load string `name:"load file=usr/word-dict/ecdict name=ecdict" help:"加载"`
list string `name:"list method=word,line word auto" help:"词典"`
load string `name:"load file=usr/word-dict/ecdict zone=ecdict"`
list string `name:"list method=word,line word auto load" help:"词典"`
}
func (s alpha) Load(m *ice.Message, arg ...string) {
// 清空数据
lib := kit.Select(path.Base(m.Option(nfs.FILE)), m.Option(mdb.ZONE))
m.Assert(nfs.RemoveAll(m.Message, path.Join(m.Config(mdb.STORE), lib)))
m.Assert(nfs.RemoveAll(m, path.Join(m.Config(mdb.STORE), lib)))
s.Zone.Remove(m, mdb.ZONE, lib)
s.Zone.Create(m, kit.Simple(mdb.ZONE, lib, m.ConfigSimple(mdb.FIELD, mdb.LIMIT, mdb.LEAST, mdb.STORE, mdb.FSIZE))...)
prefix := kit.Keys(mdb.HASH, m.Result())
// 加载配置
m.Cmd(mdb.IMPORT, m.PrefixKey(), prefix, mdb.LIST, m.Option(nfs.FILE))
// 保存词库
m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LIMIT)), 0)
m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LEAST)), 0)
m.Echo("%s: %d", lib, mdb.Grow(m.Message, m.PrefixKey(), prefix, kit.Dict(WORD, ice.SP)))
m.Echo("%s: %d", lib, mdb.Grow(m, m.PrefixKey(), prefix, kit.Dict(WORD, ice.SP)))
}
func (s alpha) List(m *ice.Message, arg ...string) {
if len(arg) < 2 || arg[1] == "" {
m.Cmdy(cache{}, kit.Slice(arg, 1))
return // 缓存列表
return
}
switch arg[1] = strings.TrimSpace(arg[1]); arg[0] {
case LINE:
case WORD:
if m.Cmdy(cache{}, kit.Slice(arg, 1)); m.Length() > 0 {
return // 查询缓存
return
}
defer func() {
if m.Length() > 0 { // 写入缓存
m.Cmd(cache{}, mdb.CREATE, m.AppendSimple())
}
}()
// 精确匹配
defer func() { kit.If(m.Length() > 0, func() { m.Cmd(cache{}, mdb.CREATE, m.AppendSimple()) }) }()
m.OptionFields(ice.FIELDS_DETAIL)
arg[1] = "^" + arg[1] + ice.FS
}
// 搜索词汇
wiki.CSV(m.Message, m.Cmdx(cli.SYSTEM, "grep", "-rih", arg[1], m.Config(mdb.STORE)), kit.Split(m.Config(mdb.FIELD))...).Tables(func(value ice.Maps) {
if m.FieldsIsDetail() {
m.PushDetail(value, m.Config(mdb.FIELD))
} else {
m.PushRecord(value, m.Config(mdb.FIELD))
}
wiki.CSV(m.Message.Spawn(), m.Cmdx(cli.SYSTEM, "grep", "-rih", arg[1], m.Config(mdb.STORE)), kit.Split(m.Config(mdb.FIELD))...).Tables(func(value ice.Maps) {
kit.If(m.FieldsIsDetail(), func() { m.PushDetail(value, m.Config(mdb.FIELD)) }, func() { m.PushRecord(value, m.Config(mdb.FIELD)) })
}).StatusTimeCount()
}
func init() { ice.Cmd("web.wiki.alpha.alpha", alpha{}) }
func init() { ice.WikiCtxCmd(alpha{}) }

View File

@ -1,3 +0,0 @@
chapter "alpha"
field web.wiki.alpha.alpha

View File

@ -11,4 +11,4 @@ type cache struct {
list string `name:"list word auto create prunes" help:"缓存"`
}
func init() { ice.Cmd("web.wiki.alpha.cache", cache{}) }
func init() { ice.WikiCtxCmd(cache{}) }

View File

@ -12,11 +12,11 @@ const BASH = "bash"
var Index = &ice.Context{Name: BASH, Help: "命令行", Commands: ice.Commands{
BASH: {Name: "bash path auto order build download", Help: "命令行", Actions: ice.MergeActions(ice.Actions{
cli.ORDER: {Name: "order", Help: "加载", Hand: func(m *ice.Message, arg ...string) {
cli.ORDER: {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, cli.ORDER, m.Config(nfs.SOURCE), "_install/bin")
}},
}, code.InstallAction(nfs.SOURCE, "http://mirrors.tencent.com/macports/distfiles/bash/5.1_1/bash-5.1.tar.gz")), Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, nfs.SOURCE, m.Config(nfs.SOURCE), arg)
m.Cmdy(code.INSTALL, m.ConfigSimple(nfs.SOURCE), arg)
}},
}}

View File

@ -28,7 +28,6 @@ cd ./_install
`
chapter "应用"
field "文件夹" web.chat.files
field "命令行" web.code.bash.bash
field "会话流" web.code.bash.sess
field "同步流" web.code.bash.sync

View File

@ -4,18 +4,19 @@ import (
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/web"
)
const CONFIGS = "configs"
func init() {
Index.MergeCommands(ice.Commands{
"/configs": {Name: "/configs", Help: "配置", Hand: func(m *ice.Message, arg ...string) {
m.Cmd("web.code.git.configs", func(value ice.Maps) {
if strings.HasPrefix(value[mdb.NAME], "url") {
m.Echo(`git config --global "%s" "%s"`, value[mdb.NAME], value[mdb.VALUE])
m.Echo(ice.NL)
}
})
web.P(CONFIGS): {Hand: func(m *ice.Message, arg ...string) {
if strings.Contains(m.Option(cli.RELEASE), cli.ALPINE) {
m.Echo("sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories && apk update").Echo(ice.NL)
m.Echo("TZ=Asia/Shanghai; apk add tzdata && cp /usr/share/zoneinfo/${TZ} /etc/localtime && echo ${TZ} > /etc/timezone").Echo(ice.NL)
}
}},
})
}

View File

@ -2,29 +2,34 @@ package bash
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
)
const (
_DOWNLOAD = "_download"
)
func init() {
Index.MergeCommands(ice.Commands{
"/download": {Name: "/download", Help: "下载", Hand: func(m *ice.Message, arg ...string) {
web.P(web.DOWNLOAD): {Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 || arg[0] == "" {
m.Cmdy("web.chat.files").Table()
return // 文件列表
m.Cmdy(FAVOR, _DOWNLOAD).Table()
} else {
m.Cmdy(web.CACHE, m.Cmd(FAVOR, _DOWNLOAD, arg[0]).Append(mdb.TEXT))
m.Render(kit.Select(ice.RENDER_DOWNLOAD, ice.RENDER_RESULT, m.Append(nfs.FILE) == ""), m.Append(mdb.TEXT))
}
// 下载文件
m.Cmdy(web.CACHE, m.Cmd("web.chat.files", arg[0]).Append(mdb.DATA))
m.Render(kit.Select(ice.RENDER_DOWNLOAD, ice.RENDER_RESULT, m.Append(nfs.FILE) == ""), m.Append(mdb.TEXT))
}},
"/upload": {Name: "/upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) {
msg := m.Cmd("web.chat.files", web.UPLOAD) // 上传文件
for _, k := range []string{mdb.DATA, mdb.TIME, mdb.TYPE, mdb.NAME, nfs.SIZE} {
m.Echo("%s: %s\n", k, msg.Append(k))
}
web.P(web.UPLOAD): {Hand: func(m *ice.Message, arg ...string) {
m.Optionv(ice.MSG_UPLOAD, web.UPLOAD)
up := web.Upload(m)
m.Cmd(FAVOR, mdb.INSERT, _DOWNLOAD, mdb.TYPE, kit.Ext(up[1]), mdb.NAME, up[1], mdb.TEXT, up[0], m.OptionSimple(cli.PWD, aaa.USERNAME, tcp.HOSTNAME))
m.Echo(up[0]).Echo(ice.NL)
}},
})
}

View File

@ -5,6 +5,8 @@ import (
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
)
@ -12,30 +14,34 @@ const FAVOR = "favor"
func init() {
Index.MergeCommands(ice.Commands{
"/favor": {Name: "/favor", Help: "收藏", Actions: ice.Actions{
mdb.EXPORT: {Name: "export zone name", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
m.Echo("#!/bin/sh\n\n")
m.Cmdy(FAVOR, m.Option(mdb.ZONE), func(value ice.Maps) {
FAVOR: {Name: "favor zone id auto insert", Help: "收藏夹", Actions: ice.MergeActions(ice.Actions{
mdb.INSERT: {Name: "insert zone*=demo type=shell name=1 text=pwd pwd=/home"},
cli.SYSTEM: {Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 && arg[0] == ice.RUN {
if msg := mdb.ZoneSelect(m.Spawn(), m.Option(mdb.ZONE), m.Option(mdb.ID)); nfs.ExistsFile(m, msg.Append(cli.PWD)) {
m.Option(cli.CMD_DIR, msg.Append(cli.PWD))
}
ctx.ProcessField(m, cli.SYSTEM, nil, arg...)
} else {
ctx.ProcessField(m, cli.SYSTEM, kit.Split(m.Option(mdb.TEXT)))
}
}},
web.DOWNLOAD: {Hand: func(m *ice.Message, arg ...string) { web.RenderCache(m, m.Option(mdb.TEXT)) }},
}, mdb.ZoneAction(mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) {
if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
m.Action(mdb.EXPORT, mdb.IMPORT)
} else {
m.PushAction(kit.Select(cli.SYSTEM, web.DOWNLOAD, arg[0] == _DOWNLOAD))
}
}},
web.PP(FAVOR): {Actions: ice.Actions{
mdb.EXPORT: {Name: "export zone* name", Hand: func(m *ice.Message, arg ...string) {
m.Echo("#!/bin/sh\n\n").Cmdy(FAVOR, m.Option(mdb.ZONE), func(value ice.Maps) {
if m.Option(mdb.NAME) == "" || m.Option(mdb.NAME) == value[mdb.NAME] {
m.Echo("# %v\n%v\n\n", value[mdb.NAME], value[mdb.TEXT])
m.Echo("# %s\n%s\n\n", value[mdb.NAME], value[mdb.TEXT])
}
})
}},
}, Hand: func(m *ice.Message, arg ...string) { m.Cmdy(FAVOR).Table() }},
FAVOR: {Name: "favor zone id auto", Help: "收藏夹", Actions: ice.MergeActions(ice.Actions{
mdb.INSERT: {Name: "insert zone=系统命令 type=shell name=1 text=pwd pwd=/home", Help: "添加"},
cli.SYSTEM: {Name: "system", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
m.Option(cli.CMD_DIR, m.Option(cli.PWD))
ctx.ProcessCommand(m, cli.SYSTEM, kit.Split(m.Option(mdb.TEXT)), arg...)
ctx.ProcessCommandOpt(m, arg, cli.PWD)
}},
}, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) {
if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
m.Action(mdb.CREATE, mdb.EXPORT, mdb.IMPORT)
} else {
m.PushAction(cli.SYSTEM)
m.StatusTimeCount()
}
}},
})
}

View File

@ -2,7 +2,9 @@ package bash
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits"
)
@ -10,20 +12,14 @@ const GRANT = "grant"
func init() {
Index.MergeCommands(ice.Commands{
GRANT: {Name: "grant hash auto", Help: "授权", Actions: ice.MergeActions(ice.Actions{
"confirm": {Name: "confirm", Help: "同意", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SESS, mdb.MODIFY, GRANT, m.Option(ice.MSG_USERNAME))
}},
"revert": {Name: "revert", Help: "撤销", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SESS, mdb.MODIFY, GRANT, "")
}},
}, mdb.HashAction()), Hand: func(m *ice.Message, arg ...string) {
GRANT: {Name: "grant hash auto", Help: "授权", Actions: ice.Actions{
mdb.MODIFY: {Help: "同意", Hand: func(m *ice.Message, arg ...string) { m.Cmd(SESS, mdb.MODIFY, GRANT, m.Option(ice.MSG_USERNAME)) }},
mdb.REVERT: {Help: "撤销", Hand: func(m *ice.Message, arg ...string) { m.Cmd(SESS, mdb.MODIFY, GRANT, "") }},
}, Hand: func(m *ice.Message, arg ...string) {
if m.Cmdy(SESS, arg); len(arg) > 0 && m.Append(GRANT) == "" {
m.ProcessConfirm("授权设备")
m.Echo("请授权 %s@%s 访问 %s", m.Append(aaa.USERNAME), m.Append(tcp.HOSTNAME), m.Option(ice.MSG_USERHOST))
}
m.Tables(func(value ice.Maps) {
m.PushButton(kit.Select("revert", "confirm", value[GRANT] == ""), mdb.REMOVE)
})
m.Tables(func(value ice.Maps) { m.PushButton(kit.Select(mdb.REVERT, mdb.MODIFY, value[GRANT] == "")) })
}},
})
}

View File

@ -14,8 +14,6 @@ import (
)
func _run_action(m *ice.Message, cmd *ice.Command, script string, arg ...string) {
m.SetResult().Echo("#/bin/bash\n")
list, args := []string{}, []string{}
kit.Fetch(cmd.Meta["_trans"], func(k string, v string) {
list = append(list, k)
@ -25,7 +23,7 @@ func _run_action(m *ice.Message, cmd *ice.Command, script string, arg ...string)
})
args = append(args, kit.Format(` ;;`))
})
m.SetResult().Echo("#/bin/sh\n")
m.Echo(`
ish_sys_dev_run_source() {
select action in %s; do
@ -37,7 +35,6 @@ ish_sys_dev_run_source() {
done
}
`, kit.Join(list, ice.SP), arg[0], kit.Join(args, ice.NL))
m.Echo(`
ish_sys_dev_run_action() {
select action in %s; do
@ -50,40 +47,73 @@ ish_sys_dev_run_action() {
done
}
`, kit.Join(list, ice.SP), arg[0], kit.Join(args, ice.NL))
m.Echo(`
ish_sys_dev_run_command() {
ish_sys_dev_run %s "$@"
}
`, arg[0])
m.Echo(kit.Select("cat $1", script))
}
func _run_command(m *ice.Message, key string, arg ...string) {
m.Search(key, func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
m.Echo(kit.Join(m.Cmd(key, arg).Appendv(kit.Format(kit.Value(cmd.List, kit.Keys(len(arg), mdb.NAME)))), ice.SP))
})
}
func _run_actions(m *ice.Message, key, sub string, arg ...string) (res []string) {
m.Search(key, func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
if sub == "" {
res = kit.SortedKey(cmd.Meta)
} else if len(arg)%2 == 0 {
kit.Fetch(kit.Value(cmd.Meta, sub), func(value ice.Map) { res = append(res, kit.Format(value[mdb.NAME])) })
kit.Fetch(arg, func(k, v string) { res[kit.IndexOf(res, k)] = "" })
} else {
msg := m.Cmd(key, mdb.INPUTS, kit.Select("", arg, -1), kit.Dict(arg))
res = msg.Appendv(kit.Select("", msg.Appendv(ice.MSG_APPEND), 0))
}
m.Echo(kit.Join(res, ice.SP))
})
return nil
}
const RUN = "run"
func init() {
Index.MergeCommands(ice.Commands{
"/run/": {Name: "/run/", Help: "执行", Actions: ice.Actions{
ctx.COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
web.PP(RUN): {Actions: ice.Actions{
"check": {Name: "check sid*", Hand: func(m *ice.Message, arg ...string) { m.Echo(m.Cmd(SESS, m.Option(SID)).Append(GRANT)) }},
"complete": {Hand: func(m *ice.Message, arg ...string) {
switch arg = kit.Split(m.Option("line")); m.Option("cword") {
case "1":
m.Echo("action ")
m.Echo(strings.Join(m.Cmd(ctx.COMMAND, mdb.SEARCH, ctx.COMMAND, ice.OptionFields(ctx.INDEX)).Appendv(ctx.INDEX), ice.SP))
default:
if kit.Int(m.Option("cword"))+1 == len(arg) {
arg = kit.Slice(arg, 0, -1)
}
if kit.Select("", arg, 2) == ctx.ACTION {
_run_actions(m, arg[1], kit.Select("", arg, 3), kit.Slice(arg, 4)...)
} else {
_run_command(m, arg[1], arg[2:]...)
}
}
}},
ctx.COMMAND: {Hand: func(m *ice.Message, arg ...string) {
m.Search(arg[0], func(_ *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
if p := strings.ReplaceAll(kit.Select("/app/cat.sh", cmd.Meta[ctx.DISPLAY]), ".js", ".sh"); strings.HasPrefix(p, ice.PS+ice.REQUIRE) {
if p := kit.ExtChange(kit.Select("/app/cat.sh", cmd.Meta[ctx.DISPLAY]), nfs.SH); strings.HasPrefix(p, ice.PS+ice.REQUIRE) {
m.Cmdy(web.SPIDE, ice.DEV, web.SPIDE_RAW, p)
} else {
m.Cmdy(nfs.CAT, path.Join(ice.USR_INTSHELL, p))
}
if m.IsErrNotFound() {
m.SetResult()
}
_run_action(m, cmd, m.Result(), arg...)
_run_action(m, cmd, m.Results(), arg...)
})
}},
ice.RUN: {Name: "run", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
ice.RUN: {Hand: func(m *ice.Message, arg ...string) {
if !ctx.PodCmd(m, arg) && aaa.Right(m, arg) {
m.Cmdy(arg)
}
if m.Result() == "" {
m.Table()
if m.Result() != "" && !strings.HasSuffix(m.Result(), ice.NL) {
m.Echo(ice.NL)
}
}},
}},

View File

@ -10,6 +10,8 @@ import (
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/code"
kit "shylinux.com/x/toolkits"
)
const (
@ -25,48 +27,42 @@ func init() {
if f, _, e := m.R.FormFile(SUB); e == nil {
defer f.Close()
if b, e := ioutil.ReadAll(f); e == nil {
m.Option(SUB, string(b)) // 文件参数
m.Option(SUB, string(b))
}
}
switch m.RenderResult(); arg[0] {
case "/qrcode", "/sess":
return // 登录入口
case web.P(cli.QRCODE), web.PP(SESS):
return
}
if m.Warn(m.Option(SID, strings.TrimSpace(m.Option(SID))) == "", ice.ErrNotLogin, arg) {
return
} else if msg := m.Cmd(SESS, m.Option(SID)); msg.Append(GRANT) == "" {
aaa.SessAuth(m, ice.Maps{aaa.USERNAME: msg.Append(aaa.USERNAME), aaa.USERNICK: msg.Append(aaa.USERNAME), aaa.USERROLE: aaa.VOID}).Options(msg.AppendSimple(aaa.USERNAME, tcp.HOSTNAME, cli.RELEASE))
} else {
aaa.SessAuth(m, kit.Dict(aaa.USERNAME, msg.Append(GRANT), aaa.USERNICK, aaa.UserNick(m, msg.Append(GRANT)), aaa.USERROLE, aaa.UserRole(m, msg.Append(GRANT)))).Options(msg.AppendSimple(aaa.USERNAME, tcp.HOSTNAME, cli.RELEASE))
}
msg := m.Cmd(SESS, m.Option(SID))
m.Option(ice.MSG_USERNAME, msg.Append(GRANT))
m.Option(ice.MSG_USERROLE, aaa.UserRole(m, msg.Append(GRANT)))
m.Option(tcp.HOSTNAME, msg.Append(tcp.HOSTNAME))
m.Auth(aaa.USERROLE, m.Option(ice.MSG_USERROLE), aaa.USERNAME, m.Option(ice.MSG_USERNAME))
if arg[0] == "/run/" {
return
}
m.Warn(m.Option(ice.MSG_USERNAME) == "", ice.ErrNotLogin, arg)
}},
"/qrcode": {Name: "/qrcode", Help: "二维码", Hand: func(m *ice.Message, arg ...string) {
web.P(cli.QRCODE): {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(cli.QRCODE, m.Option(mdb.TEXT), m.Option(cli.FG), m.Option(cli.BG))
}},
"/sess": {Name: "/sess", Help: "会话", Actions: ice.Actions{
aaa.LOGOUT: {Name: "logout", Help: "退出", Hand: func(m *ice.Message, arg ...string) {
mdb.HashModify(m, mdb.HASH, m.Option(SID), mdb.STATUS, aaa.LOGOUT)
web.PP(SESS): {Actions: ice.Actions{
aaa.LOGOUT: {Hand: func(m *ice.Message, arg ...string) {
if !m.Warn(m.Option(SID) == "", ice.ErrNotValid, SID) {
mdb.HashModify(m, mdb.HASH, m.Option(SID), mdb.STATUS, aaa.LOGOUT)
}
}},
}, Hand: func(m *ice.Message, arg ...string) {
if m.Option(SID) == "" { // 终端登录
m.Option(SID, mdb.HashCreate(m, mdb.STATUS, aaa.LOGIN, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME, cli.PID, cli.PWD)))
} else { // 更新状态
if m.Option(SID) == "" {
m.Option(SID, mdb.HashCreate(m, mdb.STATUS, aaa.LOGIN, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME, cli.PID, cli.PWD, cli.RELEASE)))
} else {
mdb.HashModify(m, mdb.HASH, m.Option(SID), mdb.STATUS, aaa.LOGIN)
m.Echo(m.Option(SID))
}
}},
SESS: {Name: "sess hash auto prunes", Help: "会话流", Actions: ice.MergeActions(ice.Actions{
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
mdb.HashPrunesValue(m, mdb.STATUS, aaa.LOGOUT)
SESS: {Name: "sess hash auto invite prunes", Help: "会话流", Actions: ice.MergeActions(ice.Actions{
aaa.INVITE: {Hand: func(m *ice.Message, arg ...string) {
code.PublishScript(m, `export ctx_dev={{.Option "httphost"}}; ctx_temp=$(mktemp); curl -o $ctx_temp -fsSL $ctx_dev; source $ctx_temp`)
}},
}, mdb.HashAction(mdb.FIELD, "time,hash,status,username,hostname,pid,pwd,grant"))},
}, mdb.HashAction(mdb.FIELD, "time,hash,status,username,hostname,release,pid,pwd,grant"))},
})
}

View File

@ -8,41 +8,45 @@ import (
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
)
const SYNC = "sync"
func init() {
const (
HISTORY = "history"
SHELL = "shell"
)
Index.MergeCommands(ice.Commands{
"/sync": {Name: "/sync", Help: "同步", Actions: ice.Actions{
"history": {Name: "history", Help: "历史", Hand: func(m *ice.Message, arg ...string) {
SYNC: {Name: "sync id auto page export import", Help: "同步流", Actions: ice.MergeActions(ice.Actions{
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(FAVOR, mdb.INPUTS, arg) }},
cli.SYSTEM: {Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 && arg[0] == ice.RUN {
if msg := mdb.ListSelect(m.Spawn(), m.Option(mdb.ID)); nfs.ExistsFile(m, msg.Append(cli.PWD)) {
m.Option(cli.CMD_DIR, msg.Append(cli.PWD))
}
ctx.ProcessField(m, cli.SYSTEM, nil, arg...)
} else {
ctx.ProcessField(m, cli.SYSTEM, kit.Split(m.Option(mdb.TEXT)))
}
}},
FAVOR: {Name: "favor zone=demo type name text pwd", Help: "收藏", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(FAVOR, mdb.INSERT, arg, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME))
}},
}, mdb.PageListAction(mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) {
mdb.PageListSelect(m, arg...).PushAction(cli.SYSTEM, FAVOR)
}},
web.PP(SYNC): {Actions: ice.Actions{
HISTORY: {Hand: func(m *ice.Message, arg ...string) {
ls := strings.SplitN(strings.TrimSpace(m.Option(ARG)), ice.SP, 4)
if text := strings.TrimSpace(strings.Join(ls[3:], ice.SP)); text != "" {
m.Cmd(SYNC, mdb.INSERT, mdb.TIME, ls[1]+ice.SP+ls[2],
mdb.TYPE, "shell", mdb.NAME, ls[0], mdb.TEXT, text,
m.OptionSimple(cli.PWD, aaa.USERNAME, tcp.HOSTNAME, tcp.HOSTNAME))
m.Cmd(SYNC, mdb.INSERT, mdb.TIME, ls[1]+ice.SP+ls[2], mdb.TYPE, SHELL, mdb.NAME, ls[0], mdb.TEXT, text, m.OptionSimple(cli.PWD, aaa.USERNAME, tcp.HOSTNAME))
}
}},
}},
SYNC: {Name: "sync id auto page export import", Help: "同步流", Actions: ice.MergeActions(ice.Actions{
cli.SYSTEM: {Name: "system", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
m.Option(cli.CMD_DIR, m.Option(cli.PWD))
ctx.ProcessCommand(m, cli.SYSTEM, kit.Split(m.Option(mdb.TEXT)), arg...)
ctx.ProcessCommandOpt(m, arg, cli.PWD)
}},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(FAVOR, mdb.INPUTS, arg)
}},
FAVOR: {Name: "favor zone=some@key type name text pwd", Help: "收藏", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(FAVOR, mdb.INSERT)
}},
}, mdb.ListAction(mdb.FIELD, "time,id,type,name,text,pwd,username,hostname")), Hand: func(m *ice.Message, arg ...string) {
mdb.OptionPage(m, kit.Slice(arg, 1)...)
mdb.ListSelect(m, kit.Slice(arg, 0, 1)...)
m.PushAction(cli.SYSTEM, FAVOR)
m.StatusTimeCountTotal(m.Config(mdb.COUNT))
}},
})
}

View File

@ -3,51 +3,35 @@ package bash
import (
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/tcp"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
)
const (
FROM = "from"
TO = "to"
)
const TRASH = "trash"
func init() {
const (
FROM = "from"
TO = "to"
)
Index.MergeCommands(ice.Commands{
TRASH: {Name: "TRASH hash path auto prunes", Help: "回收站", Actions: ice.MergeActions(ice.Actions{
mdb.INSERT: {Name: "insert from to", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
TRASH: {Name: "trash hash path auto", Help: "回收站", Actions: mdb.HashAction(mdb.FIELD, "time,hash,username,hostname,size,from,to")},
web.PP(TRASH): {Actions: ice.MergeActions(ice.Actions{
mdb.INSERT: {Name: "insert from to", Hand: func(m *ice.Message, arg ...string) {
mdb.HashCreate(m, m.OptionSimple(aaa.USERNAME, tcp.HOSTNAME, nfs.SIZE, FROM, TO))
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
if !m.Warn(m.Option(TO) == "", ice.ErrNotValid, TO) {
mdb.HashRemove(m, m.OptionSimple(mdb.HASH))
nfs.RemoveAll(m, m.Option(TO))
}
mdb.REVERT: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, m.Option(mdb.HASH))
defer mdb.HashRemove(m, m.OptionSimple(mdb.HASH))
m.Echo("mv %s %s", m.Append(TO), m.Append(FROM))
}},
mdb.REVERT: {Name: "revert", Help: "恢复", Hand: func(m *ice.Message, arg ...string) {
if !m.Warn(m.Option(FROM) == "" && m.Option(TO) == "", ice.ErrNotValid, FROM, TO) {
nfs.Rename(m, m.Option(TO), m.Option(FROM))
mdb.HashRemove(m, m.OptionSimple(mdb.HASH))
}
}},
mdb.PRUNES: {Name: "prunes before@date", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
mdb.HashPrunes(m, func(value ice.Map) bool {
return true
}).Tables(func(value ice.Maps) {
nfs.RemoveAll(m, value[TO])
})
}},
nfs.CAT: {Name: "cat", Help: "查看", Hand: func(m *ice.Message, arg ...string) {
m.Option(nfs.DIR_ROOT, m.Option(TO))
ctx.ProcessCommand(m, nfs.CAT, []string{}, arg...)
ctx.ProcessCommandOpt(m, arg, TO)
}},
}, mdb.HashAction(mdb.FIELD, "time,hash,username,hostname,size,from,to"), web.ApiAction("/trash")), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, arg...).PushAction(nfs.CAT, mdb.REVERT, mdb.REMOVE)
}), Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelectValue(m, func(key string, fields []string, value, val ice.Map) {
kit.If(value[tcp.HOSTNAME] == m.Option(tcp.HOSTNAME), func() { m.Push(key, value, fields, val) })
})
}},
})
}

View File

@ -12,11 +12,11 @@ const ZSH = "zsh"
func init() {
Index.MergeCommands(ice.Commands{
ZSH: {Name: "zsh path auto order build download", Help: "命令行", Actions: ice.MergeActions(ice.Actions{
cli.ORDER: {Name: "order", Help: "加载", Hand: func(m *ice.Message, arg ...string) {
cli.ORDER: {Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, cli.ORDER, m.Config(nfs.SOURCE), "_install/bin")
}},
}, code.InstallAction(nfs.SOURCE, "https://nchc.dl.sourceforge.net/project/zsh/zsh/5.8/zsh-5.8.tar.xz")), Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, nfs.SOURCE, m.Config(nfs.SOURCE), arg)
m.Cmdy(code.INSTALL, m.ConfigSimple(nfs.SOURCE), arg)
}},
})
}

View File

@ -2,23 +2,20 @@ package git
import (
"path"
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/nfs"
"shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/code"
kit "shylinux.com/x/toolkits"
)
func _git_url(m *ice.Message, repos string) string { return web.MergeLink(m, "/x/"+path.Join(repos)+".git") }
func _git_url(m *ice.Message, repos string) string {
return web.MergeLink(m, "/x/"+path.Join(repos)+".git")
}
func _git_dir(arg ...string) string { return path.Join(path.Join(arg...), ".git") }
func _git_cmd(m *ice.Message, arg ...string) *ice.Message { return m.Cmd(cli.SYSTEM, GIT, arg) }
func _git_cmds(m *ice.Message, arg ...string) string {
msg := _git_cmd(m, arg...)
return kit.Select("", strings.TrimSpace(msg.Result()), !msg.IsErr())
}
func _git_cmds(m *ice.Message, arg ...string) string { return _git_cmd(m, arg...).Results() }
const GIT = "git"

View File

@ -2,7 +2,6 @@ package git
import (
"path"
"runtime"
"strings"
"time"
@ -114,9 +113,8 @@ func _status_stat(m *ice.Message, files, adds, dels int) (int, int, int) {
}
func _status_list(m *ice.Message) (files, adds, dels int, last time.Time) {
ReposList(m).Tables(func(value ice.Maps) {
if m.Option(cli.CMD_DIR, value[nfs.PATH]); runtime.GOOS != cli.DARWIN {
files, adds, dels = _status_stat(m, files, adds, dels)
}
m.Option(cli.CMD_DIR, value[nfs.PATH])
files, adds, dels = _status_stat(m, files, adds, dels)
if repos, e := gogit.OpenRepository(_git_dir(value[nfs.PATH])); e == nil {
if ci, e := repos.GetCommit(); e == nil && ci.Author.When.After(last) {
last = ci.Author.When

View File

@ -27,24 +27,28 @@ const (
type input struct {
ice.Zone
insert string `name:"insert zone=person text code weight" help:"添加"`
load string `name:"load file=usr/wubi-dict/wubi86 zone=wubi86" help:"加载"`
save string `name:"save file=usr/wubi-dict/person zone=person" help:"保存"`
list string `name:"list method code auto" help:"输入法"`
insert string `name:"insert zone=person text code weight"`
load string `name:"load file=usr/wubi-dict/wubi86 zone=wubi86"`
save string `name:"save file=usr/wubi-dict/person zone=person"`
list string `name:"list method code auto load" help:"输入法"`
}
func (s input) Inputs(m *ice.Message, arg ...string) {
switch s.Zone.Inputs(m, arg...); arg[0] {
case nfs.FILE:
m.Cmdy(nfs.DIR, "usr/wubi-dict/", nfs.PATH)
case mdb.ZONE:
m.Push(arg[0], path.Base(m.Option(nfs.FILE)))
}
}
func (s input) Load(m *ice.Message, arg ...string) {
if f, e := nfs.OpenFile(m.Message, m.Option(nfs.FILE)); !m.Warn(e) {
if f, e := nfs.OpenFile(m, m.Option(nfs.FILE)); !m.Warn(e) {
defer f.Close()
// 清空数据
lib := kit.Select(path.Base(m.Option(nfs.FILE)), m.Option(mdb.ZONE))
m.Assert(nfs.RemoveAll(m.Message, path.Join(m.Config(mdb.STORE), lib)))
m.Assert(nfs.RemoveAll(m, path.Join(m.Config(mdb.STORE), lib)))
s.Zone.Remove(m, mdb.ZONE, lib)
s.Zone.Create(m, kit.Simple(mdb.ZONE, lib, m.ConfigSimple(mdb.LIMIT, mdb.LEAST, mdb.STORE, mdb.FSIZE))...)
prefix := kit.Keys(mdb.HASH, m.Result())
// 加载词库
for bio := bufio.NewScanner(f); bio.Scan(); {
if strings.HasPrefix(bio.Text(), "# ") {
continue
@ -55,17 +59,14 @@ func (s input) Load(m *ice.Message, arg ...string) {
}
mdb.Grow(m.Message, m.PrefixKey(), prefix, kit.Dict(TEXT, line[0], CODE, line[1], WEIGHT, kit.Select("999999", line, 2)))
}
// 保存词库
m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LIMIT)), 0)
m.Conf(m.PrefixKey(), kit.Keys(prefix, kit.Keym(mdb.LEAST)), 0)
m.Echo("%s: %d", lib, mdb.Grow(m.Message, m.PrefixKey(), prefix, kit.Dict(TEXT, "成功", CODE, "z", WEIGHT, "0")))
}
}
func (s input) Save(m *ice.Message, arg ...string) {
func (s input) Save(m *ice.Message, arg ...string) (n int) {
if f, p, e := nfs.CreateFile(m.Message, m.Option(nfs.FILE)); m.Assert(e) {
defer f.Close()
n := 0
m.Option(mdb.CACHE_LIMIT, -2)
for _, lib := range kit.Split(m.Option(mdb.ZONE)) {
mdb.Richs(m.Message, m.PrefixKey(), "", lib, func(key string, value ice.Map) {
@ -80,6 +81,7 @@ func (s input) Save(m *ice.Message, arg ...string) {
m.Logs(mdb.EXPORT, nfs.FILE, p, mdb.COUNT, n)
m.Echo("%s: %d", p, n)
}
return
}
func (s input) List(m *ice.Message, arg ...string) {
if len(arg) < 2 || arg[1] == "" {
@ -90,23 +92,14 @@ func (s input) List(m *ice.Message, arg ...string) {
case WORD:
arg[1] = "^" + arg[1] + ice.FS
}
// 搜索词汇
res := m.Cmdx(cli.SYSTEM, "grep", "-rn", arg[1], m.Config(mdb.STORE))
bio := csv.NewReader(bytes.NewBufferString(strings.Replace(res, ":", ",", -1)))
bio := csv.NewReader(bytes.NewBufferString(strings.Replace(res, ice.DF, ice.FS, -1)))
for i := 0; i < kit.Int(10); i++ {
if line, e := bio.Read(); e != nil {
break
} else if len(line) < 3 {
} else { // 输出词汇
m.Push(mdb.ID, line[3])
m.Push(CODE, line[2])
m.Push(TEXT, line[4])
m.Push(WEIGHT, line[6])
} else if len(line) > 3 {
m.Push(mdb.ID, line[3]).Push(CODE, line[2]).Push(TEXT, line[4]).Push(WEIGHT, line[6])
}
}
m.SortIntR(WEIGHT)
m.StatusTimeCount()
m.StatusTimeCount().SortIntR(WEIGHT)
}

View File

@ -1,4 +0,0 @@
section "input"
field web.code.input.wubi

View File

@ -11,31 +11,26 @@ import (
type wubi struct {
input
short string `data:"zone"`
field string `data:"time,zone,id,text,code,weight"`
store string `data:"usr/local/export/"`
field string `data:"time,id,text,code,weight"`
fsize string `data:"100000"`
limit string `data:"10000"`
least string `data:"1000"`
load string `name:"load file=usr/wubi-dict/wubi86 zone=wubi86" help:"加载"`
save string `name:"save file=usr/wubi-dict/person zone=person" help:"保存"`
list string `name:"list method=word,line code auto" help:"五笔"`
load string `name:"load file=usr/wubi-dict/wubi86 zone=wubi86"`
save string `name:"save file=usr/wubi-dict/person zone=person"`
list string `name:"list method=word,line code auto load" help:"五笔"`
}
func (w wubi) Input(m *ice.Message, arg ...string) {
if arg[0] = strings.TrimSpace(arg[0]); strings.HasPrefix(arg[0], "ice") {
switch list := kit.Split(arg[0]); list[1] {
case "add": // ice add 想你 shwq [9999 [person]]
m.Cmd(w, mdb.INSERT, mdb.TEXT, list[2], cli.CODE, list[3], mdb.VALUE, kit.Select("999999", list, 4), mdb.ZONE, kit.Select("person", list, 5))
w.Insert(m, mdb.ZONE, kit.Select("person", list, 5), mdb.TEXT, list[2], cli.CODE, list[3], mdb.VALUE, kit.Select("999999", list, 4))
m.Echo(list[3] + ice.NL)
}
return
}
m.Cmd(w, WORD, arg[0], func(value ice.Maps) {
m.Echo(value[mdb.TEXT] + ice.NL)
})
m.Cmd(w, WORD, arg[0], func(value ice.Maps) { m.Echo(value[mdb.TEXT] + ice.NL) })
}
func init() { ice.CodeCtxCmd(wubi{}) }

View File

@ -1,16 +1,18 @@
git
ssh
input
alpha
tmux
vim
bash
tmux
coder
java
node
mp
wx
lark
wework
webview
chrome
alpha
input
coder
java
node
webview

View File

@ -16,7 +16,6 @@ func _ssh_watch(m *ice.Message, h string, output io.Writer, input io.Reader) io.
r, w := io.Pipe()
bio := io.TeeReader(input, w)
m.Go(func() { io.Copy(output, r) })
i, buf := 0, make([]byte, ice.MOD_BUFS)
m.Go(func() {
for {
@ -24,7 +23,6 @@ func _ssh_watch(m *ice.Message, h string, output io.Writer, input io.Reader) io.
if e != nil {
break
}
switch buf[i] {
case '\r', '\n':
cmd := strings.TrimSpace(string(buf[:i]))
@ -46,9 +44,7 @@ func init() {
psh.Index.MergeCommands(ice.Commands{
CHANNEL: {Name: "channel hash id auto", Help: "通道", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelectUpdate(m, mdb.FOREACH, func(value ice.Map) {
kit.Value(value, mdb.STATUS, tcp.CLOSE)
})
mdb.HashSelectUpdate(m, mdb.FOREACH, func(value ice.Map) { kit.Value(value, mdb.STATUS, tcp.CLOSE) })
}},
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
mdb.ZoneInsert(m, m.OptionSimple(mdb.HASH), mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD))
@ -57,23 +53,15 @@ func init() {
m.Sleep300ms()
}
}},
mdb.REPEAT: {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("", ctx.COMMAND, CMD, m.Option(mdb.TEXT))
}},
}, mdb.HashAction(mdb.FIELD, "time,hash,status,tty,count,username,hostport")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { // 通道列表
m.Action(mdb.PRUNES)
mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
mdb.REPEAT: {Help: "执行", Hand: func(m *ice.Message, arg ...string) { m.Cmdy("", ctx.COMMAND, CMD, m.Option(mdb.TEXT)) }},
}, mdb.HashAction(mdb.FIELDS, "time,hash,status,tty,count,username,hostport", mdb.FIELD, "time,id,type,text")), Hand: func(m *ice.Message, arg ...string) {
if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
m.Tables(func(value ice.Maps) {
m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE)
})
return
}).Action(mdb.PRUNES)
} else {
m.PushAction(mdb.REPEAT).Action(ctx.COMMAND)
}
// 通道命令
m.Action(ctx.COMMAND)
m.Fields(len(arg[1:]), "time,id,type,text")
mdb.ZoneSelect(m, arg...)
m.PushAction(mdb.REPEAT)
}},
})
}

View File

@ -24,22 +24,16 @@ import (
func _ssh_open(m *ice.Message, arg ...string) {
_ssh_dial(m, func(c net.Conn) {
// 保存界面
fd := int(os.Stdin.Fd())
if oldState, err := terminal.MakeRaw(fd); err == nil {
defer terminal.Restore(fd, oldState)
}
// 设置宽高
w, h, _ := terminal.GetSize(fd)
c.Write([]byte(fmt.Sprintf("#height:%d,width:%d\n", h, w)))
// 初始命令
for _, item := range kit.Simple(m.Optionv("init")) {
for _, item := range kit.Simple(m.Optionv(ice.INIT)) {
m.Sleep300ms()
c.Write([]byte(item + ice.NL))
}
m.Go(func() { io.Copy(c, os.Stdin) })
io.Copy(os.Stdout, c)
}, arg...)
@ -48,62 +42,58 @@ func _ssh_dial(m *ice.Message, cb func(net.Conn), arg ...string) {
p := kit.HomePath(".ssh", fmt.Sprintf("%s@%s:%s", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT)))
if nfs.ExistsFile(m, p) {
if c, e := net.Dial("unix", p); e == nil {
cb(c) // 会话复用
cb(c)
return
}
nfs.Remove(m, p)
}
_ssh_conn(m, func(client *ssh.Client) {
if l, e := net.Listen("unix", p); m.Assert(e) {
if l, e := net.Listen("unix", p); !m.Warn(e, ice.ErrNotValid) {
defer func() { nfs.Remove(m, p) }()
defer l.Close()
m.Go(func() {
for {
c, e := l.Accept()
if e != nil {
break
}
func(c net.Conn) {
w, h, _ := terminal.GetSize(int(os.Stdin.Fd()))
buf := make([]byte, ice.MOD_BUFS)
if n, e := c.Read(buf); m.Assert(e) {
fmt.Sscanf(string(buf[:n]), "#height:%d,width:%d", &h, &w)
}
m.Go(func() {
defer c.Close()
s, e := client.NewSession()
if e != nil {
return
}
s.Stdin, s.Stdout, s.Stderr = c, c, c
s.RequestPty(kit.Env(cli.TERM), h, w, ssh.TerminalModes{ssh.ECHO: 1, ssh.TTY_OP_ISPEED: 14400, ssh.TTY_OP_OSPEED: 14400})
defer s.Wait()
gdb.SignalNotify(m, 28, func() {
w, h, _ := terminal.GetSize(int(os.Stdin.Fd()))
s.WindowChange(h, w)
})
s.Shell()
})
}(c)
}
})
}
if c, e := net.Dial("unix", p); e == nil {
cb(c) // 会话连接
cb(c)
}
}, arg...)
}
func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) {
methods := []ssh.AuthMethod{}
methods = append(methods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) {
key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE)))))
return []ssh.Signer{key}, err
}))
methods = append(methods, ssh.PasswordCallback(func() (string, error) { return m.Option(aaa.PASSWORD), nil }))
methods = append(methods, ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (res []string, err error) {
for _, q := range questions {
p := strings.TrimSpace(strings.ToLower(q))
@ -114,7 +104,7 @@ func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) {
fmt.Scanf("%s\n", &verify)
res = append(res, verify)
} else {
res = append(res, aaa.TOTP_GET(verify, 6, 30))
res = append(res, aaa.TOTP_GET(verify, 30, 6))
}
case strings.HasSuffix(p, "password:"):
res = append(res, m.Option(aaa.PASSWORD))
@ -123,21 +113,14 @@ func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) {
}
return
}))
methods = append(methods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) {
key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE)))))
return []ssh.Signer{key}, err
}))
methods = append(methods, ssh.PasswordCallback(func() (string, error) {
return m.Option(aaa.PASSWORD), nil
}))
m.Cmdy(tcp.CLIENT, tcp.DIAL, mdb.TYPE, SSH, mdb.NAME, m.Option(tcp.HOST), m.OptionSimple(tcp.HOST, tcp.PORT), arg, func(c net.Conn) {
conn, chans, reqs, err := ssh.NewClientConn(c, m.Option(tcp.HOST)+ice.DF+m.Option(tcp.PORT), &ssh.ClientConfig{
User: m.Option(aaa.USERNAME), Auth: methods, BannerCallback: func(message string) error { return nil },
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil },
})
m.Assert(err)
cb(ssh.NewClient(conn, chans, reqs))
if !m.Warn(err) {
cb(ssh.NewClient(conn, chans, reqs))
}
})
}
@ -147,6 +130,13 @@ const CONNECT = "connect"
func init() {
psh.Index.MergeCommands(ice.Commands{
CONNECT: {Name: "connect name auto", Help: "连接", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m).Tables(func(value ice.Maps) {
if value[mdb.STATUS] == tcp.OPEN {
m.Cmd("", tcp.DIAL, mdb.NAME, value[mdb.NAME], value)
}
})
}},
tcp.OPEN: {Name: "open authfile username=shy password verfiy host=shylinux.com port=22 private=.ssh/id_rsa", Help: "终端", Hand: func(m *ice.Message, arg ...string) {
defer m.Echo("exit %s@%s:%s\n", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT))
_ssh_open(nfs.OptionLoad(m, m.Option("authfile")), arg...)
@ -157,20 +147,19 @@ func init() {
mdb.HashCreate(m.Spawn(), m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT, aaa.USERNAME), mdb.STATUS, tcp.OPEN, kit.Dict(mdb.TARGET, client))
m.Cmd("", SESSION, m.OptionSimple(mdb.NAME))
}, arg...)
})
m.Sleep300ms()
}).Sleep300ms()
}},
SESSION: {Name: "session", Help: "会话", Hand: func(m *ice.Message, arg ...string) {
if c, e := _ssh_session(m, mdb.HashSelectTarget(m, m.Option(mdb.NAME), nil).(*ssh.Client)); m.Assert(e) {
SESSION: {Help: "会话", Hand: func(m *ice.Message, arg ...string) {
if c, e := _ssh_session(m, mdb.HashSelectTarget(m, m.Option(mdb.NAME), nil).(*ssh.Client)); !m.Warn(e, ice.ErrNotValid) {
defer c.Wait()
c.Shell()
}
}},
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
client := mdb.HashSelectTarget(m, m.Option(mdb.NAME), nil).(*ssh.Client)
if s, e := client.NewSession(); m.Assert(e) {
if s, e := client.NewSession(); !m.Warn(e, ice.ErrNotValid) {
defer s.Close()
if b, e := s.CombinedOutput(m.Option(ice.CMD)); m.Assert(e) {
if b, e := s.CombinedOutput(m.Option(ice.CMD)); !m.Warn(e, ice.ErrNotValid) {
m.Echo(string(b))
}
}

View File

@ -23,31 +23,37 @@ const (
const RSA = "rsa"
func init() {
const (
TITLE = "title"
BITS = "bits"
KEY = "key"
PUB = "pub"
)
aaa.Index.MergeCommands(ice.Commands{
RSA: {Name: "rsa hash auto", Help: "密钥", Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Name: "create bits=2048,4096 title=some", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
if key, err := rsa.GenerateKey(rand.Reader, kit.Int(m.Option("bits"))); m.Assert(err) {
if pub, err := ssh.NewPublicKey(key.Public()); m.Assert(err) {
mdb.HashCreate(m, m.OptionSimple("title"), PUBLIC, string(ssh.MarshalAuthorizedKey(pub)),
mdb.CREATE: {Name: "create bits=2048,4096 title=some", Hand: func(m *ice.Message, arg ...string) {
if key, err := rsa.GenerateKey(rand.Reader, kit.Int(m.Option(BITS))); !m.Warn(err, ice.ErrNotValid) {
if pub, err := ssh.NewPublicKey(key.Public()); !m.Warn(err, ice.ErrNotValid) {
mdb.HashCreate(m, m.OptionSimple(TITLE), PUBLIC, string(ssh.MarshalAuthorizedKey(pub)),
PRIVATE, string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})),
)
}
}
}},
mdb.EXPORT: {Name: "export key=.ssh/id_rsa pub=.ssh/id_rsa.pub", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
mdb.EXPORT: {Name: "export key=.ssh/id_rsa pub=.ssh/id_rsa.pub", Hand: func(m *ice.Message, arg ...string) {
mdb.HashSelect(m, m.Option(mdb.HASH)).Tables(func(value ice.Maps) {
m.Cmdx(nfs.SAVE, kit.HomePath(m.Option("key")), value[PRIVATE])
m.Cmdx(nfs.SAVE, kit.HomePath(m.Option("pub")), value[PUBLIC])
m.Cmd(nfs.SAVE, kit.HomePath(m.Option(KEY)), value[PRIVATE])
m.Cmd(nfs.SAVE, kit.HomePath(m.Option(PUB)), value[PUBLIC])
})
}},
mdb.IMPORT: {Name: "import key=.ssh/id_rsa pub=.ssh/id_rsa.pub", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
m.Conf("", kit.Keys(mdb.HASH, path.Base(m.Option("key"))), kit.Data(mdb.TIME, m.Time(),
"title", kit.Format("%s@%s", ice.Info.Username, ice.Info.Hostname),
PRIVATE, m.Cmdx(nfs.CAT, kit.HomePath(m.Option("key"))),
PUBLIC, m.Cmdx(nfs.CAT, kit.HomePath(m.Option("pub"))),
mdb.IMPORT: {Name: "import key=.ssh/id_rsa pub=.ssh/id_rsa.pub", Hand: func(m *ice.Message, arg ...string) {
m.Conf("", kit.Keys(mdb.HASH, path.Base(m.Option(KEY))), kit.Data(mdb.TIME, m.Time(),
TITLE, kit.Format("%s@%s", ice.Info.Username, ice.Info.Hostname),
PRIVATE, m.Cmdx(nfs.CAT, kit.HomePath(m.Option(KEY))),
PUBLIC, m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PUB))),
))
}},
}, mdb.HashAction(mdb.SHORT, mdb.HASH, mdb.FIELD, "time,hash,title,public,private")), Hand: func(m *ice.Message, arg ...string) {
}, mdb.HashAction(mdb.SHORT, PRIVATE, mdb.FIELD, "time,hash,title,public,private")), Hand: func(m *ice.Message, arg ...string) {
if mdb.HashSelect(m, arg...).PushAction(mdb.EXPORT, mdb.REMOVE); len(arg) == 0 {
m.Action(mdb.CREATE, mdb.IMPORT)
}

View File

@ -32,20 +32,19 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
if tcp.IsLocalHost(m, meta[tcp.HOSTPORT]) {
m.Auth(aaa.USERNAME, meta[aaa.USERNAME], tcp.HOSTPORT, meta[tcp.HOSTPORT])
err = nil // 本机用户
m.Auth(kit.SimpleKV(kit.Fields(aaa.USERNAME, tcp.HOSTPORT), meta))
err = nil
} else {
mdb.ZoneSelectCB(m, h, func(value ice.Maps) {
if !strings.HasPrefix(value[mdb.NAME], meta[aaa.USERNAME]+"@") {
return
}
if s, e := base64.StdEncoding.DecodeString(value[mdb.TEXT]); !m.Warn(e) {
if pub, e := ssh.ParsePublicKey([]byte(s)); !m.Warn(e) {
if s, e := base64.StdEncoding.DecodeString(value[mdb.TEXT]); !m.Warn(e, ice.ErrNotValid, value[mdb.TEXT]) {
if pub, e := ssh.ParsePublicKey([]byte(s)); !m.Warn(e, ice.ErrNotValid, value[mdb.TEXT]) {
if bytes.Compare(pub.Marshal(), key.Marshal()) == 0 {
meta[tcp.HOSTNAME] = kit.Select("", kit.Split(value[mdb.NAME], "@"), 1)
m.Auth(aaa.USERNAME, meta[aaa.USERNAME], tcp.HOSTPORT, meta[tcp.HOSTPORT], tcp.HOSTNAME, meta[tcp.HOSTNAME])
err = nil // 认证成功
m.Auth(kit.SimpleKV(kit.Fields(aaa.USERNAME, tcp.HOSTPORT, tcp.HOSTNAME), meta))
err = nil
}
}
}
@ -55,16 +54,14 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
},
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
m.Debug("what %v", string(password))
if aaa.UserLogin(m, meta[aaa.USERNAME], string(password)) {
m.Auth(aaa.USERNAME, meta[aaa.USERNAME], tcp.HOSTPORT, meta[tcp.HOSTPORT], aaa.PASSWORD, strings.Repeat("*", len(string(password))))
err = nil // 密码登录
m.Auth(kit.SimpleKV(kit.Fields(aaa.USERNAME, tcp.HOSTPORT, tcp.HOSTNAME), meta))
err = nil
}
return &ssh.Permissions{Extensions: meta}, err
},
}
if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE))))); !m.Warn(err) {
if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE))))); !m.Warn(err, ice.ErrNotValid, m.Option(PRIVATE)) {
config.AddHostKey(key)
}
return config
@ -75,15 +72,14 @@ func _ssh_accept(m *ice.Message, h string, c net.Conn) {
return
}
m.Go(func() { ssh.DiscardRequests(reqs) })
for ch := range chans {
channel, requests, err := ch.Accept()
if m.Warn(err) {
continue
}
m.Go(func() {
m.Logs(CHANNEL, tcp.HOSTPORT, c.RemoteAddr().String(), "->", c.LocalAddr().String())
defer m.Logs("dischan", tcp.HOSTPORT, c.RemoteAddr().String(), "->", c.LocalAddr().String())
m.Logs(CHANNEL, tcp.HOSTPORT, c.RemoteAddr().String()+" -> "+c.LocalAddr().String())
defer m.Logs("dischan", tcp.HOSTPORT, c.RemoteAddr().String()+" -> "+c.LocalAddr().String())
_ssh_prepare(m.Spawn(conn.Permissions.Extensions), channel, requests)
})
}
@ -94,47 +90,40 @@ func _ssh_prepare(m *ice.Message, channel ssh.Channel, requests <-chan *ssh.Requ
return
}
defer tty.Close()
list := []string{cli.PATH + "=" + kit.Env(cli.PATH)}
list := kit.EnvSimple(cli.PATH)
for request := range requests {
m.Logs(REQUEST, tcp.HOSTPORT, m.Option(tcp.HOSTPORT), mdb.TYPE, request.Type)
m.Logs(REQUEST, m.OptionSimple(tcp.HOSTPORT), mdb.TYPE, request.Type)
switch request.Type {
case "pty-req":
termLen := request.Payload[3]
termEnv := string(request.Payload[4 : termLen+4])
_ssh_size(pty.Fd(), request.Payload[termLen+4:])
list = append(list, "TERM="+termEnv)
list = append(list, cli.TERM, termEnv)
case "window-change":
_ssh_size(pty.Fd(), request.Payload)
case "env":
var env struct{ Name, Value string }
if err := ssh.Unmarshal(request.Payload, &env); err != nil {
continue
}
list = append(list, env.Name+"="+env.Value)
list = append(list, env.Name, env.Value)
case "shell":
_ssh_handle(m, channel, pty, tty)
_ssh_handle(m, channel, pty, tty, list)
case "exec":
defer channel.Close()
m.Optionv(cli.CMD_OUTPUT, channel)
m.Options(cli.CMD_OUTPUT, channel, cli.CMD_ENV, list)
m.Cmd(cli.SYSTEM, kit.Select("sh", kit.Env(cli.SHELL)), "-c", string(request.Payload[4:request.Payload[3]+4]))
return
}
request.Reply(true, nil)
}
}
func _ssh_handle(m *ice.Message, channel ssh.Channel, pty, tty *os.File) {
func _ssh_handle(m *ice.Message, channel ssh.Channel, pty, tty *os.File, list []string) {
h := m.Cmdx(mdb.INSERT, m.Prefix(CHANNEL), "", mdb.HASH, mdb.STATUS, tcp.OPEN, TTY, tty.Name(), m.OptionSimple(aaa.USERNAME, tcp.HOSTPORT), kit.Dict(mdb.TARGET, pty))
m.Go(func() { io.Copy(channel, pty) })
p := _ssh_watch(m, h, pty, channel)
m.Optionv(cli.CMD_INPUT, tty)
m.Optionv(cli.CMD_OUTPUT, tty)
m.Go(func() { io.Copy(channel, pty) })
channel.Write([]byte(m.Config(WELCOME)))
m.Options(cli.CMD_INPUT, tty, cli.CMD_OUTPUT, tty)
m.Cmd(cli.DAEMON, kit.Select("sh", kit.Env(cli.SHELL)), func() {
defer m.Cmd(mdb.MODIFY, m.Prefix(CHANNEL), "", mdb.HASH, mdb.HASH, h, mdb.STATUS, tcp.CLOSE)
channel.Write([]byte(m.Config(GOODBYE)))
@ -161,31 +150,26 @@ func init() {
}
})
}},
tcp.LISTEN: {Name: "listen port=9022 private=.ssh/id_rsa authkey=.ssh/authorized_keys", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
tcp.LISTEN: {Name: "listen port=9022 private=.ssh/id_rsa authkey=.ssh/authorized_keys", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
if mdb.HashSelect(m, m.Option(tcp.PORT)).Length() > 0 {
mdb.HashModify(m, m.Option(tcp.PORT), mdb.STATUS, tcp.OPEN)
} else {
mdb.HashCreate(m.Spawn(), m.OptionSimple(mdb.HashField(m)), mdb.STATUS, tcp.OPEN)
m.Cmd("", ctx.LOAD, m.OptionSimple(AUTHKEY))
}
m.Go(func() {
m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, SSH, mdb.NAME, tcp.PORT, m.OptionSimple(tcp.PORT), func(c net.Conn) {
m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, SSH, mdb.NAME, m.Option(tcp.PORT), m.OptionSimple(tcp.PORT), func(c net.Conn) {
m.Go(func() { _ssh_accept(m, kit.Hashs(m.Option(tcp.PORT)), c) })
})
})
}},
mdb.INSERT: {Name: "insert text:textarea", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
if ls := kit.Split(m.Option(mdb.TEXT)); len(ls) > 2 {
m.Cmdy(mdb.INSERT, m.Prefix(SERVICE), kit.Keys(mdb.HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST,
mdb.TYPE, ls[0], mdb.NAME, ls[len(ls)-1], mdb.TEXT, strings.Join(ls[1:len(ls)-1], "+"))
mdb.ZoneInsert(m, m.OptionSimple(tcp.PORT), mdb.TYPE, ls[0], mdb.NAME, ls[len(ls)-1], mdb.TEXT, strings.Join(ls[1:len(ls)-1], "+"))
}
}},
ctx.LOAD: {Name: "load authkey=.ssh/authorized_keys", Help: "加载", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(nfs.CAT, kit.HomePath(m.Option(AUTHKEY)), func(pub string) {
m.Cmd(SERVICE, mdb.INSERT, mdb.TEXT, pub)
})
m.Cmd(nfs.CAT, kit.HomePath(m.Option(AUTHKEY)), func(pub string) { m.Cmd(SERVICE, mdb.INSERT, mdb.TEXT, pub) })
}},
ctx.SAVE: {Name: "save authkey=.ssh/authorized_keys", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
list := []string{}
@ -196,24 +180,20 @@ func init() {
m.Cmdy(nfs.SAVE, kit.HomePath(m.Option(AUTHKEY)), strings.Join(list, ice.NL)+ice.NL)
}
}},
aaa.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
m.Option(cli.HOSTNAME, web.OptionUserWeb(m).Hostname())
aaa.INVITE: {Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
m.Option(cli.HOSTNAME, tcp.PublishLocalhost(m, web.OptionUserWeb(m).Hostname()))
if buf, err := kit.Render(`ssh -p {{.Option "port"}} {{.Option "user.name"}}@{{.Option "hostname"}}`, m); err == nil {
m.EchoScript(string(buf))
}
}},
}, mdb.StatusHashAction(
mdb.SHORT, tcp.PORT, mdb.FIELD, "time,port,status,private,authkey,count",
mdb.SHORT, tcp.PORT, mdb.FIELD, "time,port,status,private,authkey,count", mdb.FIELDS, "time,id,type,name,text",
WELCOME, "welcome to contexts world\r\n", GOODBYE, "goodbye of contexts world\r\n",
)), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { // 服务列表
mdb.HashSelect(m, arg...).PushAction(aaa.INVITE, mdb.INSERT, ctx.LOAD, ctx.SAVE)
return
m.Fields(len(arg), m.Config(mdb.FIELD), m.Config(mdb.FIELDS))
if mdb.ZoneSelect(m, arg...); len(arg) == 0 {
m.PushAction(aaa.INVITE, mdb.INSERT, ctx.LOAD, ctx.SAVE)
}
// 公钥列表
m.Fields(len(arg[1:]), "time,id,type,name,text")
mdb.ZoneSelect(m, arg...)
}},
})
}

View File

@ -11,7 +11,6 @@ type Winsize struct{ Height, Width, x, y uint16 }
func _ssh_size(fd uintptr, b []byte) {
w := binary.BigEndian.Uint32(b)
h := binary.BigEndian.Uint32(b[4:])
ws := &Winsize{Width: uint16(w), Height: uint16(h)}
syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
}

View File

@ -20,9 +20,7 @@ func _ssh_session(m *ice.Message, client *ssh.Client) (*ssh.Session, error) {
m.Assert(e)
in, e := s.StdinPipe()
m.Assert(e)
h := m.Cmdx(SESSION, mdb.CREATE, mdb.STATUS, tcp.OPEN, CONNECT, m.Option(mdb.NAME), kit.Dict(mdb.TARGET, in))
m.Go(func() {
buf := make([]byte, ice.MOD_BUFS)
for {
@ -53,29 +51,23 @@ const SESSION = "session"
func init() {
psh.Index.MergeCommands(ice.Commands{
SESSION: {Name: "session hash id auto", Help: "会话", Actions: ice.MergeActions(ice.Actions{
mdb.REPEAT: {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("", ctx.COMMAND, CMD, m.Option(mdb.TEXT))
}},
mdb.REPEAT: {Help: "执行", Hand: func(m *ice.Message, arg ...string) { m.Cmdy("", ctx.ACTION, ctx.COMMAND, CMD, m.Option(mdb.TEXT)) }},
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
m.Cmd("", mdb.INSERT, m.OptionSimple(mdb.HASH), mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD))
w := mdb.HashSelectTarget(m, m.Option(mdb.HASH), nil).(io.Writer)
w.Write([]byte(m.Option(CMD) + ice.NL))
m.Sleep300ms()
mdb.ZoneInsert(m, m.OptionSimple(mdb.HASH), mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD))
if w, ok := mdb.HashSelectTarget(m, m.Option(mdb.HASH), nil).(io.Writer); ok {
w.Write([]byte(m.Option(CMD) + ice.NL))
m.Sleep300ms()
}
}},
}, mdb.ZoneAction(mdb.FIELD, "time,hash,count,status,connect")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 {
mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
}, mdb.PageZoneAction(mdb.FIELD, "time,hash,count,status,connect", mdb.FIELDS, "time,id,type,text")), Hand: func(m *ice.Message, arg ...string) {
m.Fields(len(kit.Slice(arg, 0, 2)), m.Config(mdb.FIELD), m.Config(mdb.FIELDS))
if mdb.PageZoneSelect(m, arg...); len(arg) == 0 {
m.Tables(func(value ice.Maps) {
m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE)
})
return
} else {
m.Tables(func(value ice.Maps) { m.PushButton(kit.Select("", mdb.REPEAT, value[mdb.TYPE] == CMD)) }).Action(ctx.COMMAND, mdb.PAGE)
}
m.Action(ctx.COMMAND, mdb.PAGE)
mdb.OptionPage(m, kit.Slice(arg, 2)...)
m.Fields(len(kit.Slice(arg, 1, 2)), "time,id,type,text")
mdb.ZoneSelect(m, kit.Slice(arg, 0, 2)...).Tables(func(value ice.Maps) {
m.PushButton(kit.Select("", mdb.REPEAT, value[mdb.TYPE] == CMD))
})
}},
})
}

View File

@ -4,6 +4,7 @@ import (
"strings"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits"
@ -14,55 +15,39 @@ const (
TEXT = "text"
)
const (
SET_BUFFER = "set-buffer"
SHOW_BUFFER = "show-buffer"
LIST_BUFFER = "list-buffers"
SET_BUFFER = "set-buffer"
SHOW_BUFFER = "show-buffer"
LIST_BUFFER = "list-buffers"
DELETE_BUFFER = "delete-buffer"
)
func init() {
Index.MergeCommands(ice.Commands{
BUFFER: {Name: "buffer name value auto", Help: "缓存", Actions: ice.Actions{
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case mdb.TEXT:
_tmux_cmd(m, SET_BUFFER, "-b", m.Option(mdb.NAME), arg[1])
}
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {}},
mdb.CREATE: {Name: "create value*", Hand: func(m *ice.Message, arg ...string) { _tmux_cmd(m, SET_BUFFER, m.Option(mdb.VALUE)) }},
mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) { _tmux_cmd(m, DELETE_BUFFER, "-b", m.Option(mdb.NAME)) }},
mdb.MODIFY: {Hand: func(m *ice.Message, arg ...string) {
kit.If(arg[0] == mdb.VALUE, func() { _tmux_cmd(m, SET_BUFFER, "-b", m.Option(mdb.NAME), arg[1]) })
}},
}, Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 1 && arg[1] != "" { // 设置缓存
_tmux_cmd(m, SET_BUFFER, "-b", arg[0], arg[1])
}
if len(arg) > 0 { // 查看缓存
m.Echo(_tmux_cmd(m, SHOW_BUFFER, "-b", arg[0]).Result())
if kit.If(len(arg) > 1 && arg[0] != "" && arg[1] != "", func() { _tmux_cmd(m, SET_BUFFER, "-b", arg[0], arg[1]) }); len(arg) > 0 && arg[0] != "" {
cli.PushText(m, _tmux_cmds(m, SHOW_BUFFER, "-b", arg[0]))
return
}
// 缓存列表
for i, v := range kit.Split(_tmux_cmd(m, LIST_BUFFER).Result(), ice.NL, ice.NL, ice.NL) {
for i, v := range kit.SplitLine(_tmux_cmd(m, LIST_BUFFER).Result()) {
ls := strings.SplitN(v, ": ", 3)
m.Push(mdb.NAME, ls[0])
m.Push(nfs.SIZE, ls[1])
if i < 3 {
m.Push(mdb.TEXT, _tmux_cmd(m, SHOW_BUFFER, "-b", ls[0]).Result())
if m.Push(mdb.NAME, ls[0]).Push(nfs.SIZE, ls[1]); i < 3 {
m.Push(mdb.VALUE, _tmux_cmd(m, SHOW_BUFFER, "-b", ls[0]).Result())
} else {
m.Push(mdb.TEXT, ls[2][1:len(ls[2])-1])
m.Push(mdb.VALUE, ls[2][1:len(ls[2])-1])
}
}
m.StatusTimeCount().PushAction(mdb.REMOVE).Action(mdb.CREATE)
}},
TEXT: {Name: "text auto save text:textarea", Help: "文本", Actions: ice.Actions{
nfs.SAVE: {Name: "save", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 && arg[0] != "" {
_tmux_cmd(m, SET_BUFFER, arg[0])
}
m.Cmdy(TEXT)
}},
}, Hand: func(m *ice.Message, arg ...string) {
text := _tmux_cmd(m, SHOW_BUFFER).Result()
if m.EchoQRCode(text).Echo(ice.NL); strings.HasPrefix(text, ice.HTTP) {
m.EchoAnchor(text)
} else {
m.EchoScript(text)
}
TEXT: {Name: "text auto text:textarea", Help: "文本", Hand: func(m *ice.Message, arg ...string) {
kit.If(len(arg) > 0, func() { _tmux_cmd(m, SET_BUFFER, arg[0]) })
cli.PushText(m, _tmux_cmds(m, SHOW_BUFFER))
}},
})
}

View File

@ -10,7 +10,7 @@ const SCRIPT = "script"
func init() {
Index.MergeCommands(ice.Commands{
SCRIPT: {Name: "script name auto create export import", Help: "脚本", Actions: ice.MergeActions(ice.Actions{
mdb.CREATE: {Name: "create type=shell,tmux,vim name=hi text:textarea=pwd", Help: "添加"},
mdb.CREATE: {Name: "create type=shell,tmux,vim name=hi text:textarea=pwd"},
}, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text"))},
})
}

View File

@ -9,7 +9,6 @@ import (
"shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/web"
"shylinux.com/x/icebergs/core/code"
kit "shylinux.com/x/toolkits"
)
@ -24,12 +23,8 @@ func _tmux_key(arg ...string) string {
return "miss"
}
}
func _tmux_cmd(m *ice.Message, arg ...string) *ice.Message {
return m.Cmd(cli.SYSTEM, TMUX, arg)
}
func _tmux_cmds(m *ice.Message, arg ...string) string {
return _tmux_cmd(m, arg...).Result()
}
func _tmux_cmd(m *ice.Message, arg ...string) *ice.Message { return m.Cmd(cli.SYSTEM, TMUX, arg) }
func _tmux_cmds(m *ice.Message, arg ...string) string { return _tmux_cmd(m, arg...).Results() }
const (
FORMAT = "format"
@ -69,24 +64,22 @@ const (
func init() {
Index.Merge(&ice.Context{Configs: ice.Configs{
SESSION: {Name: SESSION, Help: "会话", Value: kit.Data(
SESSION: {Value: kit.Data(
FORMAT, "#{session_id},#{session_attached},#{session_name},#{session_windows},#{session_height},#{session_width}",
FIELDS, "id,tag,session,windows,height,width",
)},
WINDOW: {Name: WINDOW, Help: "窗口", Value: kit.Data(
WINDOW: {Value: kit.Data(
FORMAT, "#{window_id},#{window_active},#{window_name},#{window_panes},#{window_height},#{window_width}",
FIELDS, "id,tag,window,panes,height,width",
)},
PANE: {Name: PANE, Help: "终端", Value: kit.Data(
PANE: {Value: kit.Data(
FORMAT, "#{pane_id},#{pane_active},#{pane_index},#{pane_tty},#{pane_height},#{pane_width},#{pane_current_command}",
FIELDS, "id,tag,pane,tty,height,width,cmd",
)},
}, Commands: ice.Commands{
SESSION: {Name: "session session window pane cmd auto", Help: "会话管理", Actions: ice.Actions{
web.DREAM_CREATE: {Name: "dream.create", Help: "梦想", Hand: func(m *ice.Message, arg ...string) {
if m.Cmd("", m.Option(mdb.NAME)).Length() == 0 {
m.Cmd("", mdb.CREATE)
}
SESSION: {Name: "session session window pane cmd auto", Help: "会话管理", Actions: ice.MergeActions(ice.Actions{
web.DREAM_CREATE: {Hand: func(m *ice.Message, arg ...string) {
kit.If(m.Cmd("", m.Option(mdb.NAME)).Length() == 0, func() { m.Cmd("", mdb.CREATE) })
}},
mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) {
if m.Option(ctx.ACTION) == SCRIPT {
@ -98,24 +91,18 @@ func init() {
m.Cmdy(web.DREAM).Cut("name,size,time")
}
}},
mdb.CREATE: {Name: "create name", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Option(cli.CMD_ENV, "TMUX", "")
if m.Option(PANE) != "" { // 创建终端
mdb.CREATE: {Name: "create name", Hand: func(m *ice.Message, arg ...string) {
if m.Option(cli.CMD_ENV, "TMUX", ""); m.Option(PANE) != "" {
_tmux_cmd(m, SPLIT_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)))
} else if m.Option(WINDOW) != "" { // 创建终端
} else if m.Option(WINDOW) != "" {
_tmux_cmd(m, SPLIT_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW)))
} else if m.Option(SESSION) != "" { // 创建窗口
} else if m.Option(SESSION) != "" {
_tmux_cmd(m, NEW_WINDOW, "-d", "-t", m.Option(SESSION), "-n", m.Option(mdb.NAME))
} else { // 创建会话
} else {
m.Option(cli.CMD_DIR, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME)))
ls := kit.Split(m.Option(mdb.NAME), "-")
name := kit.Select(ls[0], ls, 1)
_tmux_cmd(m, NEW_SESSION, "-d", "-s", m.Option(mdb.NAME), "-n", name)
name = _tmux_key(m.Option(mdb.NAME), name)
_tmux_cmd(m, SPLIT_WINDOW, "-t", kit.Keys(name, "1"), "-p", "40")
m.Go(func() {
@ -123,103 +110,76 @@ func init() {
_tmux_cmd(m, SEND_KEYS, "-t", kit.Keys(name, "2"), "ish_miss_log", ENTER)
_tmux_cmd(m, SEND_KEYS, "-t", kit.Keys(name, "1"), "vi etc/miss.sh", ENTER)
})
_tmux_cmd(m, LINK_WINDOW, "-s", name, "-t", "miss:")
if m.Cmd(PANE, _tmux_key("miss", name)).Length() == 0 {
_tmux_cmd(m, LINK_WINDOW, "-s", name, "-t", "miss:")
}
}
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
if m.Option(PANE) != "" { // 删除终端
_tmux_cmd(m, KILL_PANE, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)))
} else if m.Option(WINDOW) != "" { // 删除窗口
// _tmux_cmd(m, KILL_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW)))
_tmux_cmd(m, KILL_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(mdb.ID)))
} else if m.Option(SESSION) != "" { // 删除会话
mdb.REMOVE: {Hand: func(m *ice.Message, arg ...string) {
if m.Option(PANE) != "" {
_tmux_cmd(m, KILL_PANE, "-t", kit.Select(_tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), m.Option(mdb.ID)))
} else if m.Option(WINDOW) != "" {
_tmux_cmd(m, KILL_WINDOW, "-t", kit.Select(_tmux_key(m.Option(SESSION), m.Option(WINDOW)), m.Option(mdb.ID)))
} else if m.Option(SESSION) != "" {
_tmux_cmd(m, KILL_SESSION, "-t", m.Option(SESSION))
}
}},
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
mdb.MODIFY: {Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case WINDOW: // 重命名窗口
case WINDOW:
_tmux_cmd(m, RENAME_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW)), arg[1])
case SESSION: // 重命名会话
case SESSION:
_tmux_cmd(m, RENAME_SESSION, "-t", m.Option(SESSION), arg[1])
}
}},
mdb.SELECT: {Name: "select", Help: "进入", Hand: func(m *ice.Message, arg ...string) {
_tmux_cmd(m, SWITCH_CLIENT, "-t", m.Option(SESSION))
if m.Option(WINDOW) != "" { // 切换窗口
_tmux_cmd(m, SELECT_WINDOW, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW)))
mdb.SELECT: {Help: "切入", Hand: func(m *ice.Message, arg ...string) {
if _tmux_cmd(m, SWITCH_CLIENT, "-t", m.Option(SESSION)); m.Option(WINDOW) != "" {
_tmux_cmd(m, SELECT_WINDOW, "-t", kit.Select(_tmux_key(m.Option(SESSION), m.Option(WINDOW)), m.Option(mdb.ID)))
}
if m.Option(PANE) != "" { // 切换终端
if m.Option(PANE) != "" {
_tmux_cmd(m, SELECT_PANE, "-t", _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)))
}
}},
code.XTERM: {Name: "xterm", Help: "终端", Hand: func(m *ice.Message, arg ...string) {
ctx.Process(m, code.XTERM, []string{mdb.TYPE, "tmux attach -t " + m.Option(SESSION)}, arg...)
}},
SCRIPT: {Name: "script name", Help: "脚本", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SCRIPT, m.Option(mdb.NAME), func(value ice.Maps) {
switch value[mdb.TYPE] {
case "shell":
for _, line := range kit.Split(value[mdb.TEXT], ice.NL, ice.NL, ice.NL) {
m.Cmd(CMD, _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), line)
}
case "vim":
for _, line := range kit.Split(value[mdb.TEXT], ice.NL, ice.NL, ice.NL) {
m.Cmd(CMD, _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), line)
}
case "tmux":
for _, line := range kit.Split(value[mdb.TEXT], ice.NL, ice.NL, ice.NL) {
_tmux_cmd(m, line)
}
}
})
m.Sleep30ms()
kit.Fetch(kit.SplitLine(value[mdb.TEXT]), func(line string) {
kit.Switch(value[mdb.TYPE],
"shell", func() { m.Cmd(CMD, _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), line) },
"vim", func() { m.Cmd(CMD, _tmux_key(m.Option(SESSION), m.Option(WINDOW), m.Option(PANE)), line) },
"tmux", func() { _tmux_cmd(m, line) },
)
})
}).Sleep30ms()
}},
}, Hand: func(m *ice.Message, arg ...string) {
m.Action(SCRIPT)
if len(arg) > 3 { // 执行命令
}, ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) {
if m.Action(SCRIPT); len(arg) > 3 {
m.Cmd(CMD, _tmux_key(arg[0], arg[1], arg[2]), arg[3:])
}
if len(arg) > 2 { // 终端内容
if len(arg) > 2 {
m.Echo(strings.TrimSpace(m.Cmdx(VIEW, _tmux_key(arg[0], arg[1], arg[2]))))
return
}
m.Action(mdb.CREATE)
if len(arg) > 1 { // 终端列表
if m.Action(mdb.CREATE); len(arg) > 1 {
m.Cmdy(PANE, _tmux_key(arg[0], arg[1]))
} else if len(arg) > 0 { // 窗口列表
} else if len(arg) > 0 {
m.Cmdy(WINDOW, arg[0])
} else { // 会话列表
} else {
m.Split(_tmux_cmd(m, LIST_SESSION, "-F", m.Config(FORMAT)).Result(), m.Config(FIELDS), ice.FS, ice.NL)
}
m.Tables(func(value ice.Maps) {
switch value["tag"] {
case "1":
m.PushButton(code.XTERM, "")
default:
m.PushButton(code.XTERM, mdb.SELECT, mdb.REMOVE)
}
})
kit.If(value["tag"] == "1", func() { m.PushButton("") }, func() { m.PushButton(mdb.SELECT, mdb.REMOVE) })
}).StatusTimeCount()
}},
WINDOW: {Name: "windows", Help: "窗口", Hand: func(m *ice.Message, arg ...string) {
WINDOW: {Hand: func(m *ice.Message, arg ...string) {
m.Split(m.Cmdx(cli.SYSTEM, TMUX, LIST_WINDOWS, "-t", kit.Select("", arg, 0), "-F", m.Config(FORMAT)), m.Config(FIELDS), ice.FS, ice.NL)
}},
PANE: {Name: "panes", Help: "终端", Hand: func(m *ice.Message, arg ...string) {
PANE: {Hand: func(m *ice.Message, arg ...string) {
m.Split(_tmux_cmds(m, LIST_PANES, "-t", kit.Select("", arg, 0), "-F", m.Config(FORMAT)), m.Config(FIELDS), ice.FS, ice.NL)
}},
VIEW: {Name: "view", Help: "内容", Hand: func(m *ice.Message, arg ...string) {
VIEW: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(_tmux_cmds(m, CAPTURE_PANE, "-p", "-t", kit.Select("", arg, 0)))
}},
CMD: {Name: "cmd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
CMD: {Hand: func(m *ice.Message, arg ...string) {
_tmux_cmd(m, SEND_KEYS, "-t", arg[0], strings.Join(arg[1:], ice.SP), ENTER)
}},
}})

View File

@ -13,14 +13,14 @@ const TMUX = "tmux"
var Index = &ice.Context{Name: TMUX, Help: "工作台", Commands: ice.Commands{
TMUX: {Name: "tmux path auto start order build download", Help: "服务", Actions: ice.MergeActions(ice.Actions{
cli.START: {Name: "start", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
cli.START: {Help: "启动", Hand: func(m *ice.Message, arg ...string) {
m.Optionv(code.PREPARE, func(p string) []string {
return []string{"-S", kit.Path(m.Option(cli.CMD_DIR, p), "tmux.socket"), NEW_SESSION, "-d", "-n", "miss"}
})
m.Cmdy(code.INSTALL, cli.START, m.Config(nfs.SOURCE), "bin/tmux")
}},
}, code.InstallAction(nfs.SOURCE, "http://mirrors.tencent.com/macports/distfiles/tmux/tmux-3.2.tar.gz")), Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(code.INSTALL, nfs.SOURCE, m.Config(nfs.SOURCE), arg)
m.Cmdy(code.INSTALL, m.ConfigSimple(nfs.SOURCE), arg)
}},
}}

View File

@ -17,22 +17,18 @@ type WebView struct {
}
func (w WebView) Menu() bool {
list := []string{}
link := ""
link, list := "", []string{}
w.Cmd(nfs.CAT, w.Source, func(ls []string, line string) {
if strings.HasPrefix(line, "# ") {
return
}
if len(ls) > 1 {
list = append(list, kit.Format(`<button onclick=%s()>%s</button>`, ls[0], ls[0]))
} else if len(ls) > 1 {
link, list = ls[1], append(list, kit.Format(`<button onclick=%s()>%s</button>`, ls[0], ls[0]))
w.WebView.Bind(ls[0], func() { w.navigate(ls[1]) })
link = ls[1]
}
})
if len(list) == 0 {
return false
}
if len(list) == 1 {
} else if len(list) == 1 {
if ls := kit.Split(w.Cmdx(nfs.CAT, "etc/webview.size")); len(ls) > 1 {
w.WebView.SetSize(kit.Int(ls[0]), kit.Int(ls[1])+28, webview.HintNone)
} else {
@ -40,11 +36,57 @@ func (w WebView) Menu() bool {
}
w.WebView.Navigate(link)
return true
} else {
w.WebView.SetTitle(ice.CONTEXTS)
w.WebView.SetSize(200, 60*len(list), webview.HintNone)
w.WebView.Navigate(kit.Format(_menu_template, kit.Join(list, ice.NL)))
return true
}
}
func (w WebView) Title(text string) { w.WebView.SetTitle(text) }
func (w WebView) Webview(url string) { w.WebView.Navigate(url) }
func (w WebView) Open(url string) { w.WebView.Navigate(url) }
func (w WebView) OpenUrl(url string) { w.Cmd(cli.SYSTEM, cli.OPEN, url) }
func (w WebView) OpenApp(app string) { w.Cmd(cli.SYSTEM, cli.OPEN, "-a", app) }
func (w WebView) OpenCmd(cmd string) {
w.Cmd(nfs.SAVE, kit.HomePath(".bash_temp"), cmd)
w.Cmd(cli.SYSTEM, cli.OPEN, "-a", "Terminal")
}
func (w WebView) SetSize(width, height int) {
w.Cmd(nfs.SAVE, "etc/webview.size", kit.Format("%v,%v", width, height))
}
func (w WebView) System(arg ...string) string { return w.Cmdx(cli.SYSTEM, arg) }
func (w WebView) Power() string {
ls := strings.Split(w.Cmdx(cli.SYSTEM, "pmset", "-g", "ps"), ice.NL)
for _, line := range ls[1:] {
ls := kit.Split(line, "\t ;", "\t ;")
return ls[2]
}
return ""
}
func (w WebView) Close() {
if !w.Menu() {
w.WebView.Terminate()
}
}
func (w WebView) Terminate() { w.WebView.Terminate() }
func (w WebView) navigate(url string) {
w.WebView.SetSize(1200, 800, webview.HintNone)
w.WebView.Navigate(url)
}
w.WebView.SetTitle(ice.CONTEXTS)
w.WebView.SetSize(200, 60*len(list), webview.HintNone)
w.WebView.Navigate(kit.Format(`data:text/html,
func Run(cb func(*WebView) ice.Any) {
w := webview.New(true)
defer w.Destroy()
defer w.Run()
view := &WebView{Source: "etc/webview.txt", WebView: w, Message: ice.Pulse}
kit.Reflect(cb(view), func(name string, value ice.Any) { w.Bind(name, value) })
if !view.Menu() {
view.navigate("http://localhost:9020")
}
}
var _menu_template = `data:text/html,
<!doctype html>
<html>
<head>
@ -60,52 +102,4 @@ func (w WebView) Menu() bool {
</script>
</head>
<body>%s</body>
</html>`, kit.Join(list, ice.NL)))
return true
}
func (w WebView) Title(text string) { w.WebView.SetTitle(text) }
func (w WebView) Webview(url string) { w.WebView.Navigate(url) }
func (w WebView) Open(url string) { w.WebView.Navigate(url) }
func (w WebView) OpenUrl(url string) { w.Cmd(cli.SYSTEM, "open", url) }
func (w WebView) OpenApp(app string) { w.Cmd(cli.SYSTEM, "open", "-a", app) }
func (w WebView) OpenCmd(cmd string) {
w.Cmd(nfs.SAVE, kit.HomePath(".bash_temp"), cmd)
w.Cmd(cli.SYSTEM, "open", "-a", "Terminal")
}
func (w WebView) SetSize(width, height int) {
w.Cmd(nfs.SAVE, "etc/webview.size", kit.Format("%v,%v", width, height))
}
func (w WebView) System(arg ...string) string {
return w.Cmdx(cli.SYSTEM, arg)
}
func (w WebView) Power() string {
ls := strings.Split(w.Cmdx(cli.SYSTEM, "pmset", "-g", "ps"), ice.NL)
for _, line := range ls[1:] {
ls := kit.Split(line, "\t ;", "\t ;")
return ls[2]
}
return ""
}
func (w WebView) Terminate() { w.WebView.Terminate() }
func (w WebView) Close() {
if !w.Menu() {
w.WebView.Terminate()
}
}
func (w WebView) navigate(url string) {
w.WebView.SetSize(1200, 800, webview.HintNone)
w.WebView.Navigate(url)
}
func Run(cb func(*WebView) ice.Any) {
w := webview.New(true)
defer w.Destroy()
defer w.Run()
view := &WebView{Source: "etc/webview.txt", WebView: w, Message: ice.Pulse}
kit.Reflect(cb(view), func(name string, value ice.Any) { w.Bind(name, value) })
if !view.Menu() {
view.navigate("http://localhost:9020")
}
}
</html>`