fmt.Println(" \tRemove plugin(s)")
fmt.Println("-plugin update [PLUGIN]...")
fmt.Println(" \tUpdate plugin(s) (if no argument is given, updates all plugins)")
+ fmt.Println("-plugin search [PLUGIN]...")
+ fmt.Println(" \tSearch for a plugin")
+ fmt.Println("-plugin list")
+ fmt.Println(" \tList installed plugins")
+ fmt.Println("-plugin available")
+ fmt.Println(" \tList available plugins")
fmt.Print("\nMicro's options can also be set via command line arguments for quick\nadjustments. For real configuration, please use the settings.json\nfile (see 'help options').\n\n")
fmt.Println("-option value")
args := flag.Args()
- switch *flagPlugin {
- case "install":
- installedVersions := config.GetInstalledVersions(false)
- for _, plugin := range args {
- pp := config.GetAllPluginPackages().Get(plugin)
- if pp == nil {
- fmt.Println("Unknown plugin \"" + plugin + "\"")
- } else if err := pp.IsInstallable(); err != nil {
- fmt.Println("Error installing ", plugin, ": ", err)
- } else {
- for _, installed := range installedVersions {
- if pp.Name == installed.Pack().Name {
- if pp.Versions[0].Version.Compare(installed.Version) == 1 {
- fmt.Println(pp.Name, " is already installed but out-of-date: use 'plugin update ", pp.Name, "' to update")
- } else {
- fmt.Println(pp.Name, " is already installed")
- }
- }
- }
- pp.Install()
- }
- }
+ config.PluginCommand(os.Stdout, *flagPlugin, args)
- case "remove":
- removed := ""
- for _, plugin := range args {
- // check if the plugin exists.
- for _, p := range config.Plugins {
- if p.Name == plugin && p.Default {
- fmt.Println("Default plugins cannot be removed, but can be disabled via settings.")
- continue
- }
- if p.Name == plugin {
- config.UninstallPlugin(plugin)
- removed += plugin + " "
- continue
- }
- }
- }
- if removed != "" {
- fmt.Println("Removed ", removed)
- } else {
- fmt.Println("No plugins removed")
- }
- case "update":
- config.UpdatePlugins(args)
- case "list":
- plugins := config.GetInstalledVersions(false)
- fmt.Println("The following plugins are currently installed:")
- for _, p := range plugins {
- fmt.Printf("%s (%s)\n", p.Pack().Name, p.Version)
- }
- case "search":
- plugins := config.SearchPlugin(args)
- fmt.Println(len(plugins), " plugins found")
- for _, p := range plugins {
- fmt.Println("----------------")
- fmt.Println(p.String())
- }
- fmt.Println("----------------")
- case "available":
- packages := config.GetAllPluginPackages()
- fmt.Println("Available Plugins:")
- for _, pkg := range packages {
- fmt.Println(pkg.Name)
- }
- default:
- fmt.Println("Invalid plugin command")
- os.Exit(1)
- }
os.Exit(0)
}
}
}
}()
- action.InitBindings()
- action.InitCommands()
-
- err = config.InitColorscheme()
+ err = config.LoadAllPlugins()
if err != nil {
screen.TermMessage(err)
}
- err = config.LoadAllPlugins()
+ action.InitBindings()
+ action.InitCommands()
+
+ err = config.InitColorscheme()
if err != nil {
screen.TermMessage(err)
}
// Whether or not suggestions can be autocompleted must be shared because
// it changes based on how the buffer has changed
HasSuggestions bool
+
+ // Modifications is the list of modified regions for syntax highlighting
+ Modifications []Loc
}
func (b *SharedBuffer) insert(pos Loc, value []byte) {
b.isModified = true
b.HasSuggestions = false
b.LineArray.insert(pos, value)
+
+ // b.Modifications is cleared every screen redraw so it's
+ // ok to append duplicates
+ b.Modifications = append(b.Modifications, Loc{pos.Y, pos.Y + bytes.Count(value, []byte{'\n'})})
}
func (b *SharedBuffer) remove(start, end Loc) []byte {
b.isModified = true
b.HasSuggestions = false
+ b.Modifications = append(b.Modifications, Loc{start.Y, start.Y})
return b.LineArray.remove(start, end)
}
// This stores the highlighting rules and filetype detection info
SyntaxDef *highlight.Def
// The Highlighter struct actually performs the highlighting
- Highlighter *highlight.Highlighter
- // Modifications is the list of modified regions for syntax highlighting
- Modifications []Loc
+ Highlighter *highlight.Highlighter
HighlightLock sync.Mutex
// Hash of the original buffer -- empty if fastdirty is on
b.EventHandler.active = b.curCursor
b.EventHandler.Insert(start, text)
- // b.Modifications is cleared every screen redraw so it's
- // ok to append duplicates
- b.Modifications = append(b.Modifications, Loc{start.Y, start.Y + strings.Count(text, "\n")})
-
go b.Backup(true)
}
}
b.EventHandler.active = b.curCursor
b.EventHandler.Remove(start, end)
- b.Modifications = append(b.Modifications, Loc{start.Y, start.Y})
-
go b.Backup(true)
}
}
}
startpos.Y, err = strconv.Atoi(cursorPositions[0])
- startpos.Y -= 1
+ startpos.Y--
if err == nil {
if len(cursorPositions) > 1 {
startpos.X, err = strconv.Atoi(cursorPositions[1])
if startpos.X > 0 {
- startpos.X -= 1
+ startpos.X--
}
}
}
return string(b.LineBytes(i))
}
+func (b *Buffer) Write(bytes []byte) (n int, err error) {
+ b.EventHandler.InsertBytes(b.End(), bytes)
+ return len(bytes), nil
+}
+
// WriteLog writes a string to the log buffer
func WriteLog(s string) {
LogBuf.EventHandler.Insert(LogBuf.End(), s)
}
// Fetch retrieves all available PluginPackages from the given channels
-func (pc PluginChannels) Fetch() PluginPackages {
+func (pc PluginChannels) Fetch(out io.Writer) PluginPackages {
return fetchAllSources(len(pc), func(i int) PluginPackages {
- return pc[i].Fetch()
+ return pc[i].Fetch(out)
})
}
// Fetch retrieves all available PluginPackages from the given channel
-func (pc PluginChannel) Fetch() PluginPackages {
+func (pc PluginChannel) Fetch(out io.Writer) PluginPackages {
resp, err := http.Get(string(pc))
if err != nil {
- fmt.Println("Failed to query plugin channel:\n", err)
+ fmt.Fprintln(out, "Failed to query plugin channel:\n", err)
return PluginPackages{}
}
defer resp.Body.Close()
var repositories []PluginRepository
if err := decoder.Decode(&repositories); err != nil {
- fmt.Println("Failed to decode channel data:\n", err)
+ fmt.Fprintln(out, "Failed to decode channel data:\n", err)
return PluginPackages{}
}
return fetchAllSources(len(repositories), func(i int) PluginPackages {
- return repositories[i].Fetch()
+ return repositories[i].Fetch(out)
})
}
// Fetch retrieves all available PluginPackages from the given repository
-func (pr PluginRepository) Fetch() PluginPackages {
+func (pr PluginRepository) Fetch(out io.Writer) PluginPackages {
resp, err := http.Get(string(pr))
if err != nil {
- fmt.Println("Failed to query plugin repository:\n", err)
+ fmt.Fprintln(out, "Failed to query plugin repository:\n", err)
return PluginPackages{}
}
defer resp.Body.Close()
var plugins PluginPackages
if err := decoder.Decode(&plugins); err != nil {
- fmt.Println("Failed to decode repository data:\n", err)
+ fmt.Fprintln(out, "Failed to decode repository data:\n", err)
return PluginPackages{}
}
if len(plugins) > 0 {
}
// GetAllPluginPackages gets all PluginPackages which may be available.
-func GetAllPluginPackages() PluginPackages {
+func GetAllPluginPackages(out io.Writer) PluginPackages {
if allPluginPackages == nil {
getOption := func(name string) []string {
data := GetGlobalOption(name)
}
allPluginPackages = fetchAllSources(len(repos)+1, func(i int) PluginPackages {
if i == 0 {
- return channels.Fetch()
+ return channels.Fetch(out)
}
- return repos[i-1].Fetch()
+ return repos[i-1].Fetch(out)
})
}
return allPluginPackages
}
// IsInstallable returns true if the package can be installed.
-func (pp PluginPackage) IsInstallable() error {
- _, err := GetAllPluginPackages().Resolve(GetInstalledVersions(true), PluginDependencies{
+func (pp PluginPackage) IsInstallable(out io.Writer) error {
+ _, err := GetAllPluginPackages(out).Resolve(GetInstalledVersions(true), PluginDependencies{
&PluginDependency{
Name: pp.Name,
Range: semver.Range(func(v semver.Version) bool { return true }),
// SearchPlugin retrieves a list of all PluginPackages which match the given search text and
// could be or are already installed
-func SearchPlugin(texts []string) (plugins PluginPackages) {
+func SearchPlugin(out io.Writer, texts []string) (plugins PluginPackages) {
plugins = make(PluginPackages, 0)
pluginLoop:
- for _, pp := range GetAllPluginPackages() {
+ for _, pp := range GetAllPluginPackages(out) {
for _, text := range texts {
if !pp.Match(text) {
continue pluginLoop
}
}
- if err := pp.IsInstallable(); err == nil {
+ if err := pp.IsInstallable(out); err == nil {
plugins = append(plugins, pp)
}
}
}
for _, p := range Plugins {
+ if !p.IsEnabled() {
+ continue
+ }
version := GetInstalledPluginVersion(p.Name)
if pv := newStaticPluginVersion(p.Name, version); pv != nil {
result = append(result, pv)
}
// DownloadAndInstall downloads and installs the given plugin and version
-func (pv *PluginVersion) DownloadAndInstall() error {
- fmt.Printf("Downloading %q (%s) from %q\n", pv.pack.Name, pv.Version, pv.Url)
+func (pv *PluginVersion) DownloadAndInstall(out io.Writer) error {
+ fmt.Fprintf(out, "Downloading %q (%s) from %q\n", pv.pack.Name, pv.Version, pv.Url)
resp, err := http.Get(pv.Url)
if err != nil {
return err
return selectedVersions, nil
}
-func (pv PluginVersions) install() {
+func (pv PluginVersions) install(out io.Writer) {
anyInstalled := false
currentlyInstalled := GetInstalledVersions(true)
shouldInstall := true
if pv := currentlyInstalled.find(sel.pack.Name); pv != nil {
if pv.Version.NE(sel.Version) {
- fmt.Println("Uninstalling", sel.pack.Name)
- UninstallPlugin(sel.pack.Name)
+ fmt.Fprintln(out, "Uninstalling", sel.pack.Name)
+ UninstallPlugin(out, sel.pack.Name)
} else {
shouldInstall = false
}
}
if shouldInstall {
- if err := sel.DownloadAndInstall(); err != nil {
- fmt.Println(err)
+ if err := sel.DownloadAndInstall(out); err != nil {
+ fmt.Fprintln(out, err)
return
}
anyInstalled = true
}
}
if anyInstalled {
- fmt.Println("One or more plugins installed.")
+ fmt.Fprintln(out, "One or more plugins installed.")
} else {
- fmt.Println("Nothing to install / update")
+ fmt.Fprintln(out, "Nothing to install / update")
}
}
// UninstallPlugin deletes the plugin folder of the given plugin
-func UninstallPlugin(name string) {
+func UninstallPlugin(out io.Writer, name string) {
for _, p := range Plugins {
+ if !p.IsEnabled() {
+ continue
+ }
if p.Name == name {
p.Loaded = false
if err := os.RemoveAll(filepath.Join(ConfigDir, "plug", p.DirName)); err != nil {
- fmt.Println(err)
+ fmt.Fprintln(out, err)
return
}
+ break
}
}
}
// Install installs the plugin
-func (pl PluginPackage) Install() {
- selected, err := GetAllPluginPackages().Resolve(GetInstalledVersions(true), PluginDependencies{
+func (pl PluginPackage) Install(out io.Writer) {
+ selected, err := GetAllPluginPackages(out).Resolve(GetInstalledVersions(true), PluginDependencies{
&PluginDependency{
Name: pl.Name,
Range: semver.Range(func(v semver.Version) bool { return true }),
}})
if err != nil {
- fmt.Println(err)
+ fmt.Fprintln(out, err)
return
}
- selected.install()
+ selected.install(out)
}
// UpdatePlugins updates the given plugins
-func UpdatePlugins(plugins []string) {
+func UpdatePlugins(out io.Writer, plugins []string) {
// if no plugins are specified, update all installed plugins.
if len(plugins) == 0 {
for _, p := range Plugins {
+ if !p.IsEnabled() {
+ continue
+ }
plugins = append(plugins, p.Name)
}
}
- fmt.Println("Checking for plugin updates")
+ fmt.Fprintln(out, "Checking for plugin updates")
microVersion := PluginVersions{
newStaticPluginVersion(CorePluginName, util.Version),
}
}
}
- selected, err := GetAllPluginPackages().Resolve(microVersion, updates)
+ selected, err := GetAllPluginPackages(out).Resolve(microVersion, updates)
if err != nil {
- fmt.Println(err)
+ fmt.Fprintln(out, err)
return
}
- selected.install()
+ selected.install(out)
+}
+
+func PluginCommand(out io.Writer, cmd string, args []string) {
+ switch cmd {
+ case "install":
+ installedVersions := GetInstalledVersions(false)
+ for _, plugin := range args {
+ pp := GetAllPluginPackages(out).Get(plugin)
+ if pp == nil {
+ fmt.Fprintln(out, "Unknown plugin \""+plugin+"\"")
+ } else if err := pp.IsInstallable(out); err != nil {
+ fmt.Fprintln(out, "Error installing ", plugin, ": ", err)
+ } else {
+ for _, installed := range installedVersions {
+ if pp.Name == installed.Pack().Name {
+ if pp.Versions[0].Version.Compare(installed.Version) == 1 {
+ fmt.Fprintln(out, pp.Name, " is already installed but out-of-date: use 'plugin update ", pp.Name, "' to update")
+ } else {
+ fmt.Fprintln(out, pp.Name, " is already installed")
+ }
+ }
+ }
+ pp.Install(out)
+ }
+ }
+
+ case "remove":
+ removed := ""
+ for _, plugin := range args {
+ // check if the plugin exists.
+ for _, p := range Plugins {
+ if p.Name == plugin && p.Default {
+ fmt.Fprintln(out, "Default plugins cannot be removed, but can be disabled via settings.")
+ continue
+ }
+ if p.Name == plugin {
+ UninstallPlugin(out, plugin)
+ removed += plugin + " "
+ continue
+ }
+ }
+ }
+ if removed != "" {
+ fmt.Fprintln(out, "Removed ", removed)
+ } else {
+ fmt.Fprintln(out, "No plugins removed")
+ }
+ case "update":
+ UpdatePlugins(out, args)
+ case "list":
+ plugins := GetInstalledVersions(false)
+ fmt.Fprintln(out, "The following plugins are currently installed:")
+ for _, p := range plugins {
+ fmt.Fprintf(out, "%s (%s)\n", p.Pack().Name, p.Version)
+ }
+ case "search":
+ plugins := SearchPlugin(out, args)
+ fmt.Fprintln(out, len(plugins), " plugins found")
+ for _, p := range plugins {
+ fmt.Fprintln(out, "----------------")
+ fmt.Fprintln(out, p.String())
+ }
+ fmt.Fprintln(out, "----------------")
+ case "available":
+ packages := GetAllPluginPackages(out)
+ fmt.Fprintln(out, "Available Plugins:")
+ for _, pkg := range packages {
+ fmt.Fprintln(out, pkg.Name)
+ }
+ default:
+ fmt.Fprintln(out, "Invalid plugin command")
+ }
}