mirror of
https://github.com/lxsang/antos-frontend.git
synced 2024-12-26 09:28:21 +01:00
add extension maker
This commit is contained in:
parent
a29a449eaf
commit
c94cb0963d
@ -12,10 +12,16 @@ class TreeViewItemPrototype extends Ant.OS.GUI.BaseTag
|
||||
@setopt "selected", false
|
||||
@setopt "treepath", @aid()
|
||||
|
||||
update: (p) ->
|
||||
return unless p
|
||||
return unless p is @get("treepath")
|
||||
@set "open", true
|
||||
|
||||
__data__: (v) ->
|
||||
return unless v
|
||||
@set "nodes", v.nodes if v.nodes
|
||||
@set "open", v.open
|
||||
@set "treepath", v.path if v.path
|
||||
|
||||
__selected__: (v) ->
|
||||
$(@refs.wrapper).removeClass()
|
||||
@ -152,7 +158,7 @@ class TreeViewTag extends Ant.OS.GUI.BaseTag
|
||||
@setopt "fetch", undefined
|
||||
@setopt "treepath", @aid()
|
||||
@indexcounter = 0
|
||||
|
||||
|
||||
__selectedItem: (v) ->
|
||||
return unless v
|
||||
@get("selectedItem").set "selected", false if @get("selectedItem")
|
||||
@ -176,6 +182,7 @@ class TreeViewTag extends Ant.OS.GUI.BaseTag
|
||||
__data__: (v) ->
|
||||
return unless v
|
||||
$(@root).empty()
|
||||
@set "treepath", v.path if v.path
|
||||
el = $("<#{@get "itemtag"}>").appendTo @root
|
||||
el[0].uify undefined
|
||||
el[0].set "treeroot", if @is_root() then @ else @get "treeroot"
|
||||
|
@ -10,7 +10,7 @@ class Ant.OS.GUI.BaseTag
|
||||
@root.get = (k) => @get k
|
||||
@root.aid = () => @aid()
|
||||
@root.calibrate = () => @calibrate()
|
||||
@root.sync = () => @sync()
|
||||
@root.sync = (d) => @sync(d)
|
||||
@mounted = false
|
||||
@root.setup = () => @setup()
|
||||
@refs = {}
|
||||
@ -67,9 +67,9 @@ class Ant.OS.GUI.BaseTag
|
||||
return @opts if opt is "*"
|
||||
@opts[opt]
|
||||
|
||||
sync: () ->
|
||||
@update()
|
||||
$(@root).children().each () -> @update()
|
||||
sync: (d) ->
|
||||
@update(d)
|
||||
$(@root).children().each () -> @update(d)
|
||||
@root
|
||||
|
||||
setup: () ->
|
||||
@ -116,9 +116,9 @@ Element.prototype.mount = () ->
|
||||
$(@).children().each () -> @mount()
|
||||
@
|
||||
|
||||
Element.prototype.update = () ->
|
||||
return @sync() if @sync
|
||||
$(@).children().each () -> @update()
|
||||
Element.prototype.update = (d) ->
|
||||
return @sync(d) if @sync
|
||||
$(@).children().each () -> @update(d)
|
||||
@
|
||||
|
||||
Element.prototype.uify = (observable) ->
|
||||
|
@ -255,7 +255,8 @@ class RemoteFileHandle extends Ant.OS.API.VFS.BaseFileHandle
|
||||
@b64(t)
|
||||
.then (r) =>
|
||||
Ant.OS.API.handle.write @path, r
|
||||
.then (result) -> resolve result
|
||||
.then (result) ->
|
||||
resolve result
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
coffee_files = coffees/CommandPalette.coffee coffees/main.coffee
|
||||
coffee_files = coffees/CommandPalette.coffee coffees/main.coffee coffees/BaseExtension.coffee
|
||||
|
||||
module_dir = extensions
|
||||
module_dir_src = coffees/extensions
|
||||
|
125
src/packages/CodePad/coffees/BaseExtension.coffee
Normal file
125
src/packages/CodePad/coffees/BaseExtension.coffee
Normal file
@ -0,0 +1,125 @@
|
||||
class CodePad.BaseExtension
|
||||
|
||||
constructor: (@app) ->
|
||||
|
||||
preload: () ->
|
||||
Ant.OS.API.require @dependencies()
|
||||
|
||||
import: (lib) ->
|
||||
Ant.OS.API.requires lib
|
||||
|
||||
basedir: () ->
|
||||
"#{@app.meta().path}/extensions"
|
||||
|
||||
notify: (m) ->
|
||||
@app.notify m
|
||||
|
||||
error: (m) ->
|
||||
@app.error m
|
||||
|
||||
dependencies: () ->
|
||||
[]
|
||||
|
||||
cat: (list, data) ->
|
||||
new Promise (resolve, reject) =>
|
||||
return resolve data if list.length is 0
|
||||
file = (list.splice 0, 1)[0].asFileHandle()
|
||||
file
|
||||
.read()
|
||||
.then (text) =>
|
||||
data = data + "\n" + text
|
||||
@cat list, data
|
||||
.then (d) -> resolve d
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
copy: (files, to) ->
|
||||
new Promise (resolve, reject) =>
|
||||
return resolve() if files.length is 0
|
||||
file = (files.splice 0, 1)[0].asFileHandle()
|
||||
tof = "#{to}/#{file.basename}".asFileHandle()
|
||||
file.read("binary")
|
||||
.then (data) =>
|
||||
tof.setCache(new Blob [data], { type: file.info.mime })
|
||||
.write(file.info.mime)
|
||||
.then (d) =>
|
||||
@copy files, to
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
mkar: (src, dest) ->
|
||||
@notify __("Preparing for release")
|
||||
new Promise (r, e) =>
|
||||
@import("os://scripts/jszip.min.js").then () ->
|
||||
src.asFileHandle()
|
||||
.read().then (d) ->
|
||||
return e d.error if d.error
|
||||
r d.result
|
||||
.catch (ex) -> e ex
|
||||
.catch (ex) -> e ex
|
||||
.then (files) =>
|
||||
new Promise (r, e) =>
|
||||
zip = new JSZip()
|
||||
fn = (list) =>
|
||||
return r zip if list.length is 0
|
||||
f = (list.splice 0, 1)[0].path.asFileHandle()
|
||||
return fn list if f.type is "dir"
|
||||
f.read("binary").then (d) =>
|
||||
zip.file f.basename, d, { binary: true }
|
||||
@notify __("add {0} to zip", f.basename)
|
||||
fn list
|
||||
.catch (ex) -> e ex
|
||||
fn files
|
||||
.then (zip) =>
|
||||
zip.generateAsync({ type: "base64" }).then (data) =>
|
||||
dest.asFileHandle()
|
||||
.setCache('data:application/zip;base64,' + data)
|
||||
.write("base64").then (r) =>
|
||||
return @error __("Cannot save the zip file: {0}", r.error) if r.error
|
||||
@notify __("Package is generated in release folder")
|
||||
.catch (e) => @error e.toString()
|
||||
.catch (e) => @error e.toString()
|
||||
|
||||
mkdirAll: (list) ->
|
||||
new Promise (resolve, reject) =>
|
||||
return resolve() if list.length is 0
|
||||
path = (list.splice 0, 1)[0].asFileHandle()
|
||||
path.parent().mk path.basename
|
||||
.then (d) =>
|
||||
@mkdirAll list
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
mkfileAll: (list, path, name) ->
|
||||
new Promise (resolve, reject) =>
|
||||
return resolve() if list.length is 0
|
||||
item = (list.splice 0, 1)[0]
|
||||
"#{@basedir()}/#{item[0]}"
|
||||
.asFileHandle()
|
||||
.read()
|
||||
.then (data) =>
|
||||
file = item[1].asFileHandle()
|
||||
.setCache(data.format name, "#{path}/#{name}")
|
||||
.write "text/plain"
|
||||
.then () =>
|
||||
@mkfileAll list, path, name
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
metadata: (file) ->
|
||||
new Promise (resolve, reject) =>
|
||||
if not @app.currdir
|
||||
return reject @app._api.throwe __("Current folder is not found")
|
||||
"#{@app.currdir.path}/#{file}"
|
||||
.asFileHandle()
|
||||
.read("json")
|
||||
.then (data) ->
|
||||
resolve data
|
||||
.catch (e) =>
|
||||
reject @app._api.throwe __("Unable to read meta-data")
|
||||
|
||||
CodePad.extensions = {}
|
@ -25,7 +25,7 @@ class App.extensions.AntOSDK extends App.BaseExtension
|
||||
@mktpl dir.parent().path, dir.basename
|
||||
|
||||
buildnrun: () ->
|
||||
@metadata().then (meta) =>
|
||||
@metadata("project.json").then (meta) =>
|
||||
@build(meta).then () =>
|
||||
@run(meta).catch (e) => @error.toString()
|
||||
.catch (e) =>
|
||||
@ -33,9 +33,9 @@ class App.extensions.AntOSDK extends App.BaseExtension
|
||||
.catch (e) => @error e.toString()
|
||||
|
||||
release: () ->
|
||||
@metadata().then (meta) =>
|
||||
@metadata("project.json").then (meta) =>
|
||||
@build(meta).then () =>
|
||||
@mkar(meta)
|
||||
@mkar("#{meta.root}/build/debug", "#{meta.root}/build/release/#{meta.name}.zip")
|
||||
.then () ->
|
||||
.catch (e) => @error.toString()
|
||||
.catch (e) =>
|
||||
@ -46,7 +46,6 @@ class App.extensions.AntOSDK extends App.BaseExtension
|
||||
# private functions
|
||||
mktpl: (path, name, flag) ->
|
||||
rpath = "#{path}/#{name}"
|
||||
console.log rpath
|
||||
dirs = [
|
||||
"#{rpath}/build",
|
||||
"#{rpath}/build/release",
|
||||
@ -58,11 +57,11 @@ class App.extensions.AntOSDK extends App.BaseExtension
|
||||
]
|
||||
dirs.unshift rpath if flag
|
||||
files = [
|
||||
["main.tpl", "#{rpath}/coffees/main.coffee"],
|
||||
["package.tpl", "#{rpath}/package.json"],
|
||||
["project.tpl", "#{rpath}/project.json"],
|
||||
["README.tpl", "#{rpath}/README.md"],
|
||||
["scheme.tpl", "#{rpath}/assets/scheme.html"]
|
||||
["templates/sdk-main.tpl", "#{rpath}/coffees/main.coffee"],
|
||||
["templates/sdk-package.tpl", "#{rpath}/package.json"],
|
||||
["templates/sdk-project.tpl", "#{rpath}/project.json"],
|
||||
["templates/sdk-README.tpl", "#{rpath}/README.md"],
|
||||
["templates/sdk-scheme.tpl", "#{rpath}/assets/scheme.html"]
|
||||
]
|
||||
@mkdirAll dirs
|
||||
.then () =>
|
||||
@ -73,48 +72,6 @@ class App.extensions.AntOSDK extends App.BaseExtension
|
||||
@app.openFile "#{rpath}/README.md".asFileHandle()
|
||||
.catch (e) => @error e.stack
|
||||
.catch (e) => @error e.stack
|
||||
|
||||
mkdirAll: (list) ->
|
||||
new Promise (resolve, reject) =>
|
||||
return resolve() if list.length is 0
|
||||
path = (list.splice 0, 1)[0].asFileHandle()
|
||||
console.log path.parent().path, path.basename
|
||||
path.parent().mk path.basename
|
||||
.then (d) =>
|
||||
@mkdirAll list
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
mkfileAll: (list, path, name) ->
|
||||
new Promise (resolve, reject) =>
|
||||
return resolve() if list.length is 0
|
||||
item = (list.splice 0, 1)[0]
|
||||
"#{@basedir()}/AntOSDK/templates/#{item[0]}"
|
||||
.asFileHandle()
|
||||
.read()
|
||||
.then (data) =>
|
||||
file = item[1].asFileHandle()
|
||||
.setCache(data.format name, "#{path}/#{name}")
|
||||
.write "text/plain"
|
||||
.then () =>
|
||||
@mkfileAll list, path, name
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
metadata: () ->
|
||||
new Promise (resolve, reject) =>
|
||||
if not @app.currdir
|
||||
return reject @app._api.throwe __("Project folder is not found")
|
||||
"#{@app.currdir.path}/project.json"
|
||||
.asFileHandle()
|
||||
.read("json")
|
||||
.then (data) ->
|
||||
resolve data
|
||||
.catch (e) =>
|
||||
reject @app._api.throwe __("Unable to read project meta-data")
|
||||
|
||||
verify: (list) ->
|
||||
new Promise (resolve, reject) =>
|
||||
@ -133,7 +90,7 @@ class App.extensions.AntOSDK extends App.BaseExtension
|
||||
|
||||
compile: (meta) ->
|
||||
new Promise (resolve, reject) =>
|
||||
@import("#{@basedir()}/AntOSDK/coffeescript.js").then () =>
|
||||
@import("#{@basedir()}/coffeescript.js").then () =>
|
||||
list = ("#{meta.root}/#{v}" for v in meta.coffees)
|
||||
@verify((f for f in list)).then () =>
|
||||
@cat(list).then (code) =>
|
||||
@ -192,66 +149,4 @@ class App.extensions.AntOSDK extends App.BaseExtension
|
||||
@notify __("Installing...")
|
||||
@app.systemsetting.system.packages[meta.name] = v
|
||||
@notify __("Running {0}...", meta.name)
|
||||
@app._gui.forceLaunch meta.name
|
||||
|
||||
cat: (list, data) ->
|
||||
new Promise (resolve, reject) =>
|
||||
return resolve data if list.length is 0
|
||||
file = (list.splice 0, 1)[0].asFileHandle()
|
||||
file
|
||||
.read()
|
||||
.then (text) =>
|
||||
data = data + "\n" + text
|
||||
@cat list, data
|
||||
.then (d) -> resolve d
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
copy: (files, to) ->
|
||||
new Promise (resolve, reject) =>
|
||||
return resolve() if files.length is 0
|
||||
file = (files.splice 0, 1)[0].asFileHandle()
|
||||
tof = "#{to}/#{file.basename}".asFileHandle()
|
||||
file.read("binary")
|
||||
.then (data) =>
|
||||
tof.setCache(new Blob [data], { type: file.info.mime })
|
||||
.write(file.info.mime)
|
||||
.then (d) =>
|
||||
@copy files, to
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
mkar: (meta) ->
|
||||
@notify __("Preparing for release")
|
||||
new Promise (r, e) =>
|
||||
@import("os://scripts/jszip.min.js").then () ->
|
||||
"#{meta.root}/build/debug".asFileHandle()
|
||||
.read().then (d) ->
|
||||
return e d.error if d.error
|
||||
r d.result
|
||||
.catch (ex) -> e ex
|
||||
.catch (ex) -> e ex
|
||||
.then (files) =>
|
||||
new Promise (r, e) =>
|
||||
zip = new JSZip()
|
||||
fn = (list) =>
|
||||
return r zip if list.length is 0
|
||||
f = (list.splice 0, 1)[0].path.asFileHandle()
|
||||
return fn list if f.type is "dir"
|
||||
f.read("binary").then (d) =>
|
||||
zip.file f.basename, d, { binary: true }
|
||||
@notify __("add {0} to zip", f.basename)
|
||||
fn list
|
||||
.catch (ex) -> e ex
|
||||
fn files
|
||||
.then (zip) =>
|
||||
zip.generateAsync({ type: "base64" }).then (data) =>
|
||||
"#{meta.root}/build/release/#{meta.name}.zip"
|
||||
.asFileHandle()
|
||||
.setCache('data:application/zip;base64,' + data)
|
||||
.write("base64").then (r) =>
|
||||
return @error __("Cannot save the zip file: {0}", r.error) if r.error
|
||||
@notify __("Package is generated in release folder")
|
||||
.catch (e) => @error e.toString()
|
||||
.catch (e) => @error e.toString()
|
||||
@app._gui.forceLaunch meta.name
|
217
src/packages/CodePad/coffees/extensions/ExtensionMaker.coffee
Normal file
217
src/packages/CodePad/coffees/extensions/ExtensionMaker.coffee
Normal file
@ -0,0 +1,217 @@
|
||||
# import the CodePad application module
|
||||
App = this.OS.APP.CodePad
|
||||
|
||||
# define the extension
|
||||
class App.extensions.ExtensionMaker extends App.BaseExtension
|
||||
constructor: (app) ->
|
||||
super app
|
||||
|
||||
# public functions
|
||||
create: () ->
|
||||
@app.openDialog("FileDialog", {
|
||||
title: "__(New CodePad extension at)",
|
||||
file: { basename: __("ExtensionName") },
|
||||
mimes: ["dir"]
|
||||
}).then (d) =>
|
||||
@mktpl d.file.path, d.name
|
||||
|
||||
buildnrun: () ->
|
||||
@metadata("extension.json").then (meta) =>
|
||||
@build(meta).then () =>
|
||||
@run(meta).catch (e) => @error.toString()
|
||||
.catch (e) =>
|
||||
@error e.toString()
|
||||
.catch (e) => @error e.toString()
|
||||
|
||||
release: () ->
|
||||
@metadata("extension.json").then (meta) =>
|
||||
@build(meta).then () =>
|
||||
@mkar("#{meta.root}/build/debug",
|
||||
"#{meta.root}/build/release/#{meta.meta.name}.zip")
|
||||
.then () ->
|
||||
.catch (e) => @error.toString()
|
||||
.catch (e) =>
|
||||
@error e.toString()
|
||||
.catch (e) => @error e.toString()
|
||||
|
||||
install: () ->
|
||||
@app.openDialog("FileDialog", {
|
||||
title: "__(Select extension archive)",
|
||||
mimes: [".*/zip"]
|
||||
}).then (d) =>
|
||||
@installZip d.file.path
|
||||
.then () =>
|
||||
@notify __("Extension installed")
|
||||
@app.loadExtensionMetaData()
|
||||
.catch (e) => @error e.stack
|
||||
# private functions
|
||||
mktpl: (path, name) ->
|
||||
rpath = "#{path}/#{name}"
|
||||
dirs = [
|
||||
rpath,
|
||||
"#{rpath}/build",
|
||||
"#{rpath}/build/release",
|
||||
"#{rpath}/build/debug"
|
||||
]
|
||||
files = [
|
||||
["templates/ext-main.tpl", "#{rpath}/#{name}.coffee"],
|
||||
["templates/ext-extension.tpl", "#{rpath}/extension.json"],
|
||||
]
|
||||
@mkdirAll dirs
|
||||
.then () =>
|
||||
@mkfileAll(files, path, name)
|
||||
.then () =>
|
||||
@app.currdir = rpath.asFileHandle()
|
||||
@app.initSideBar()
|
||||
@app.openFile "#{rpath}/#{name}.coffee".asFileHandle()
|
||||
.catch (e) => @error e.stack
|
||||
.catch (e) => @error e.stack
|
||||
|
||||
|
||||
verify: (list) ->
|
||||
new Promise (resolve, reject) =>
|
||||
return resolve() if list.length is 0
|
||||
file = (list.splice 0, 1)[0].asFileHandle()
|
||||
@notify __("Verifying: {0}", file.path)
|
||||
file.read().then (data) =>
|
||||
try
|
||||
CoffeeScript.nodes data
|
||||
@verify list
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
catch ex
|
||||
reject ex
|
||||
.catch (e) -> reject e
|
||||
|
||||
compile: (meta) ->
|
||||
new Promise (resolve, reject) =>
|
||||
@import("#{@basedir()}/coffeescript.js").then () =>
|
||||
list = ("#{meta.root}/#{v}" for v in meta.coffees)
|
||||
@verify((f for f in list)).then () =>
|
||||
@cat(list).then (code) =>
|
||||
jsrc = CoffeeScript.compile code
|
||||
@notify __("Compiled successful")
|
||||
resolve jsrc
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
build: (meta) ->
|
||||
new Promise (resolve, reject) =>
|
||||
@compile(meta).then (src) =>
|
||||
@cat ("#{meta.root}/#{v}" for v in meta.javascripts), src
|
||||
.then (jsrc) ->
|
||||
new Promise (r, e) ->
|
||||
"#{meta.root}/build/debug/#{meta.meta.name}.js"
|
||||
.asFileHandle()
|
||||
.setCache jsrc
|
||||
.write("text/plain")
|
||||
.then (d) ->
|
||||
return e d if d.error
|
||||
r()
|
||||
.catch (ex) -> e ex
|
||||
.then () ->
|
||||
new Promise (r, e) ->
|
||||
"#{meta.root}/build/debug/extension.json"
|
||||
.asFileHandle()
|
||||
.setCache meta.meta
|
||||
.write("object")
|
||||
.then (data) ->
|
||||
return e data.error if data.error
|
||||
r data
|
||||
.catch (ex) -> e ex
|
||||
.then () =>
|
||||
@copy ("#{meta.root}/#{v}" for v in meta.copies), "#{meta.root}/build/debug"
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
run: (meta) ->
|
||||
path = "#{meta.root}/build/debug/#{meta.meta.name}.js"
|
||||
delete @app._api.shared[path] if @app._api.shared[path]
|
||||
@app._api.requires path
|
||||
.then () =>
|
||||
if @app.extensions[meta.meta.name]
|
||||
@app.extensions[meta.meta.name].child = []
|
||||
@app.extensions[meta.meta.name].addAction v for v in meta.meta.actions
|
||||
else
|
||||
@app.extensions[meta.meta.name] = new App.CMDMenu meta.meta.text
|
||||
@app.extensions[meta.meta.name].name = meta.meta.name
|
||||
@app.extensions[meta.meta.name].addAction v for v in meta.meta.actions
|
||||
@app.spotlight.addAction @app.extensions[meta.meta.name]
|
||||
@app.extensions[meta.meta.name].onchildselect (e) =>
|
||||
@app.loadAndRunExtensionAction e.data.item.get "data"
|
||||
@app.spotlight.run @app
|
||||
.catch (e) => @error e.toString()
|
||||
|
||||
|
||||
installExtension: (files, zip) ->
|
||||
new Promise (resolve, reject) =>
|
||||
idx = files.indexOf "extension.json"
|
||||
reject(@app._api.throwe __("No meta-data found")) if idx < 0
|
||||
metafile = (files.splice idx, 1)[0]
|
||||
# read the meta file
|
||||
zip.file(metafile).async("uint8array").then (d) =>
|
||||
meta = JSON.parse(new TextDecoder("utf-8").decode(d))
|
||||
@installFiles files, zip, meta
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
installFiles: (files, zip, meta) ->
|
||||
return @installMeta(meta) if files.length is 0
|
||||
new Promise (resolve, reject) =>
|
||||
file = (files.splice 0, 1)[0]
|
||||
path = "#{@basedir()}/#{file}"
|
||||
zip.file(file).async("uint8array").then (d) =>
|
||||
path.asFileHandle()
|
||||
.setCache(new Blob [d], { type: "octet/stream" })
|
||||
.write("text/plain").then (r) =>
|
||||
return reject r.error if r.error
|
||||
@installFiles files, zip, meta
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
installMeta: (meta) ->
|
||||
new Promise (resolve, reject) =>
|
||||
file = "#{@app.meta().path}/extensions.json".asFileHandle()
|
||||
file.read("json").then (data) ->
|
||||
names = (v.name) for v in data
|
||||
idx = name.indexOf meta.name
|
||||
data.splice idx, 1 if idx >= 0
|
||||
data.push meta
|
||||
file.setCache data
|
||||
.write("object")
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
|
||||
installZip: (path) ->
|
||||
new Promise (resolve, reject) =>
|
||||
@import("os://scripts/jszip.min.js").then () =>
|
||||
path.asFileHandle().read("binary").then (data) =>
|
||||
JSZip.loadAsync(data).then (zip) =>
|
||||
pth = @basedir()
|
||||
dir = []
|
||||
files = []
|
||||
for name, file of zip.files
|
||||
if file.dir
|
||||
dir.push(pth + "/" + name)
|
||||
else
|
||||
files.push name
|
||||
if dir.length > 0
|
||||
@mkdirAll dir
|
||||
.then () =>
|
||||
@installExtension files, zip
|
||||
.then () -> resolve()
|
||||
.catch(e) -> reject(e)
|
||||
.catch (e) -> reject e
|
||||
else
|
||||
@installExtension files, zip
|
||||
.then () -> resolve()
|
||||
.catch (e) -> reject(e)
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
||||
.catch (e) -> reject e
|
@ -0,0 +1,17 @@
|
||||
{
|
||||
"root": "{1}",
|
||||
"javascripts": [],
|
||||
"coffees": ["{0}.coffee"],
|
||||
"copies": [],
|
||||
"meta": {
|
||||
"name": "{0}",
|
||||
"text": "{0}",
|
||||
"version": "0.0.1-a",
|
||||
"actions" : [
|
||||
{
|
||||
"text": "__(Example action)",
|
||||
"name": "test"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# import the CodePad application module
|
||||
App = this.OS.APP.CodePad
|
||||
|
||||
# define the extension
|
||||
class App.extensions.{0} extends App.BaseExtension
|
||||
constructor: (app) ->
|
||||
super app
|
||||
|
||||
test: () ->
|
||||
@notify "Test action is invoked"
|
@ -92,6 +92,17 @@ class CodePad extends this.OS.GUI.BaseApplication
|
||||
}]
|
||||
m.show e
|
||||
|
||||
@fileview.contextmenuHandle = (e, m) =>
|
||||
m.set "items", [
|
||||
{ text: "__(New file)", id: "new" },
|
||||
{ text: "__(New folder)", id: "newdir" },
|
||||
{ text: "__(Rename)", id: "rename" },
|
||||
{ text: "__(Delete)", id: "delete" }
|
||||
]
|
||||
m.set "onmenuselect", (e) =>
|
||||
@ctxFileMenuHandle e
|
||||
m.show e
|
||||
|
||||
@bindKey "ALT-N", () => @menuAction "new"
|
||||
@bindKey "ALT-O", () => @menuAction "open"
|
||||
@bindKey "ALT-F", () => @menuAction "opendir"
|
||||
@ -221,7 +232,7 @@ class CodePad extends this.OS.GUI.BaseApplication
|
||||
.then (d) =>
|
||||
for ext in d
|
||||
if @extensions[ext.name]
|
||||
@extensions[ext.name].child = {}
|
||||
@extensions[ext.name].child = []
|
||||
@extensions[ext.name].addAction v for v in ext.actions
|
||||
else
|
||||
@extensions[ext.name] = new CMDMenu ext.text
|
||||
@ -271,6 +282,86 @@ class CodePad extends this.OS.GUI.BaseApplication
|
||||
@menuAction e.data.item.get("data").dataid, r
|
||||
}
|
||||
|
||||
ctxFileMenuHandle: (e) ->
|
||||
el = e.data.item
|
||||
return unless el
|
||||
data = el.get("data")
|
||||
return unless data
|
||||
file = @fileview.get "selectedFile"
|
||||
dir = @currdir
|
||||
dir = file.path.asFileHandle() if file and file.type is "dir"
|
||||
dir = file.path.asFileHandle().parent() if file and file.type is "file"
|
||||
|
||||
switch data.id
|
||||
when "new"
|
||||
return unless dir
|
||||
@openDialog("PromptDialog", {
|
||||
title: "__(New file)",
|
||||
label: "__(File name)"
|
||||
})
|
||||
.then (d) =>
|
||||
fp = "#{dir.path}/#{d}".asFileHandle()
|
||||
fp.write("text/plain")
|
||||
.then (r) =>
|
||||
return @error __("Fail to create {0}: {1}", d, r.error) if r.error
|
||||
@fileview.update dir.path
|
||||
.catch (e) =>
|
||||
@error __("Fail to create: {0}", e.stack)
|
||||
|
||||
when "newdir"
|
||||
return unless dir
|
||||
@openDialog("PromptDialog", {
|
||||
title: "__(New folder)",
|
||||
label: "__(Folder name)"
|
||||
})
|
||||
.then (d) =>
|
||||
dir.mk(d)
|
||||
.then (r) =>
|
||||
return @error __("Fail to create {0}: {1}", d, r.error) if r.error
|
||||
@fileview.update dir.path
|
||||
.catch (e) =>
|
||||
@error __("Fail to create: {0}", e.stack)
|
||||
|
||||
when "rename"
|
||||
return unless file
|
||||
@openDialog("PromptDialog", {
|
||||
title: "__(Rename)",
|
||||
label: "__(File name)",
|
||||
value: file.filename
|
||||
})
|
||||
.then (d) =>
|
||||
return if d is file.filename
|
||||
file = file.path.asFileHandle()
|
||||
dir = file.parent()
|
||||
file.move "#{dir.path}/#{d}"
|
||||
.then (r) =>
|
||||
return @error __("Fail to rename to {0}: {1}", d, r.error) if r.error
|
||||
@fileview.update dir.path
|
||||
.catch (e) =>
|
||||
console.log e
|
||||
@error __("Fail to rename: {0}", e.stack)
|
||||
|
||||
when "delete"
|
||||
return unless file
|
||||
@openDialog("YesNoDialog", {
|
||||
title: "__(Delete)",
|
||||
iconclass: "fa fa-question-circle",
|
||||
text: __("Do you really want to delete: {0}?", file.filename)
|
||||
})
|
||||
.then (d) =>
|
||||
return unless d
|
||||
file = file.path.asFileHandle()
|
||||
dir = file.parent()
|
||||
file.remove()
|
||||
.then (r) =>
|
||||
return @error __("Fail to delete {0}: {1}", file.filename, r.error) if r.error
|
||||
@fileview.update dir.path
|
||||
.catch (e) =>
|
||||
@error __("Fail to delete: {0}", e.stack)
|
||||
|
||||
else
|
||||
|
||||
|
||||
save: (file) ->
|
||||
file.write("text/plain")
|
||||
.then (d) =>
|
||||
@ -352,28 +443,6 @@ class CodePad extends this.OS.GUI.BaseApplication
|
||||
]
|
||||
menu
|
||||
|
||||
class CodePad.BaseExtension
|
||||
|
||||
constructor: (@app) ->
|
||||
|
||||
preload: () ->
|
||||
Ant.OS.API.require @dependencies()
|
||||
|
||||
import: (lib) ->
|
||||
Ant.OS.API.requires lib
|
||||
|
||||
basedir: () ->
|
||||
"#{@app.meta().path}/extensions"
|
||||
|
||||
notify: (m) ->
|
||||
@app.notify m
|
||||
|
||||
error: (m) ->
|
||||
@app.error m
|
||||
|
||||
dependencies: () ->
|
||||
[]
|
||||
|
||||
class CMDMenu
|
||||
constructor: (@text, @shortcut) ->
|
||||
@child = []
|
||||
@ -411,8 +480,6 @@ CMDMenu.fromMenu = (mn) ->
|
||||
|
||||
CodePad.CMDMenu = CMDMenu
|
||||
|
||||
CodePad.extensions = {}
|
||||
|
||||
CodePad.dependencies = [
|
||||
"os://scripts/ace/ace.js",
|
||||
"os://scripts/ace/ext-language_tools.js",
|
||||
|
@ -21,5 +21,28 @@
|
||||
"name": "release"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ExtensionMaker",
|
||||
"text": "CodePad Extension",
|
||||
"version": "0.0.1-a",
|
||||
"actions" : [
|
||||
{
|
||||
"text": "__(New Extension)",
|
||||
"name": "create"
|
||||
},
|
||||
{
|
||||
"text": "__(Build and Run)",
|
||||
"name": "buildnrun"
|
||||
},
|
||||
{
|
||||
"text": "__(Build release)",
|
||||
"name": "release"
|
||||
},
|
||||
{
|
||||
"text": "__(Install extension)",
|
||||
"name": "install"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user