Repository: zyedidia/micro
File: internal/action/command.go (Go)

Code before:
			})
		} else {
			open()
		}
	} else {
		InfoBar.Error("No filename")
	}
}

// ToggleLogCmd toggles the log view
func (h *BufPane) ToggleLogCmd(args []string) {
	if h.Buf.Type != buffer.BTLog {
		h.OpenLogBuf()
	} else {
		h.Quit()
	}
}

// ReloadCmd reloads all files (syntax files, colorschemes, plugins...)
func (h *BufPane) ReloadCmd(args []string) {
	reloadRuntime(true)
}

// ReloadConfig reloads only the configuration
func ReloadConfig() {
	reloadRuntime(false)
}

func reloadRuntime(reloadAll bool) {
	config.InitRuntimeFiles()
	err := config.ReadSettings()
	if err != nil {
		screen.TermMessage(err)
	}
	err = config.InitGlobalSettings()
	if err != nil {
		screen.TermMessage(err)
	}

	if reloadAll {
		err = config.RunPluginFn("deinit")
		if err != nil {
			screen.TermMessage(err)
		}
		err = config.LoadAllPlugins()
		if err != nil {
			screen.TermMessage(err)
		}
	}

	InitBindings()

Review comment (bug):
AFAICS this `realoadAll=false` case is broken. This is what I'm seeing when calling `Reload()` from a plugin:

```
Lua Error: initlua.toggleTabtospaceClick does not exist

Press enter to continue
Lua Error: search.searchClick does not exist

Press enter to continue
Lua Error: nav.jumpBack does not exist

Press enter to continue
Lua Error: initlua.commandDown does not exist

Press enter to continue
Lua Error: initlua.commandUp does not exist

Press enter to continue
Lua Error: comment.comment does not exist

Press enter to continue
...
```

The reason is that I have a bunch of keybindings bound to various lua functions, and with `reloadAll=false`, all the plugins have been removed by `initRuntimeVars()`, and haven't been loaded again by `LoadAllPlugins()`, so those lua functions don't exist, thus `InitBindings()` fails to bind keys to them. (And indeed, those keybindings stop working for me.)

So I think the distinction between `reloadAll=true` and `reloadAll=false` modes should be made not here but in `InitRuntimeFiles()`: in the `reloadAll=false` case we should not re-initialize the list of plugins.

In other words: your PR is fixing the problem of duplicated plugins by emptying the list of plugins before reinitializing it. Instead it should fix it by avoiding reinilializing the list of plugins in the first place, in the general case; it should only reinitialize it in the `reloadAll=true` case (together with properly `deinit`'ing and reloading the plugins themselves, which your PR is already doing).

Now comes a question: do we need to bother about the `reloadAll=false` mode (i.e. just reloading settings without reloading plugins) at all? Perhaps we could just disallow plugins to do any kind of reload? I think we still need the `reloadAll=false` mode regardless, since  we also call `InitRuntimeFiles()` in `SetOptionNative()` when the user runs `set filetype ...`, and that is exactly the case when we want a properly working `reloadAll=false` mode, I believe. We don't want to reload or reinitialize plugins when the user does `set filetype ...`. We want plugins to continue working without abruptions (i.e. keeping their present state, not reinitializing it) in this case.

Code after:
			})
		} else {
			open()
		}
	} else {
		InfoBar.Error("No filename")
	}
}

// ToggleLogCmd toggles the log view
func (h *BufPane) ToggleLogCmd(args []string) {
	if h.Buf.Type != buffer.BTLog {
		h.OpenLogBuf()
	} else {
		h.Quit()
	}
}

// ReloadCmd reloads all files (syntax files, colorschemes, plugins...)
func (h *BufPane) ReloadCmd(args []string) {
	reloadRuntime(true)
}

// ReloadConfig reloads only the configuration
func ReloadConfig() {
	reloadRuntime(false)
}

func reloadRuntime(reloadPlugins bool) {
	if reloadPlugins {
		err := config.RunPluginFn("deinit")
		if err != nil {
			screen.TermMessage(err)
		}
	}

	config.InitRuntimeFiles()

	if reloadPlugins {
		config.InitPlugins()
	}

	err := config.ReadSettings()
	if err != nil {
		screen.TermMessage(err)
	}
	err = config.InitGlobalSettings()
	if err != nil {
		screen.TermMessage(err)
	}