robertmeta / plug.kak

Plugin manager for Kakoune
MIT License
54 stars 4 forks source link

Call require-module automaticaly ? #9

Open Pantoofle opened 4 years ago

Pantoofle commented 4 years ago

I recently discovered that all plugins by alexherbo2 are broken with plug.kak, because they seem to use the require-module function, so even after calling plug "alexherbo2/auto-pairs.kak" The auto-pairs plugin will not be enabled, we need to add require-module auto-pairs after the plug for the functions to be accessible.

Could it be possible to automatically try to call require-module in plug so that we don't have to manually require all modules ?

caksoylar commented 4 years ago

There is already some support throught the defer/demand mechanism, such as

plug "alexherbo2/surround.kak" defer "surround" %{
    map global normal "'" ': enter-user-mode surround<ret>' -docstring "enter surround mode"
} demand

The only annoying bit for me is that you need to specify an empty parameter if you have no settings after defer "surround" (I haven't looked into it too much whether this is avoidable). Note that demanding automatically is tricky since the "module" name (surround, which is specified with defer) is different than the plugin name (surround.kak).

SeerLite commented 3 years ago

When I don't have any specific configuration for plugins like these, I prefer using require-module explicitly inside the config, but omitting the config keyword and scope delimiters:

plug "https://github.com/alexherbo2/prelude.kak" require-module prelude

Looks nicer than a forced empty parameter for defer/demand.

alexherbo2 commented 3 years ago

@Pantoofle If you source and require the module immediately, you will introduce order loading issues for the plugins having dependencies.

You will also break the ModuleLoaded hook for the later scripts, as the module will already be loaded.

Pantoofle commented 3 years ago

@alexherbo2 So we can't use @SeerLite 's answer ? If I understand well, the generic config would be plug <pluggin> defer <pluggin_name> %{} demand ?

Or put all the require-module calls after all plug calls ?

SeerLite commented 3 years ago

@alexherbo2 In what way would ModuleLoaded break? Wouldn't it be executed in the plug command anyway? Or are you talking about other plugins that aren't loaded through require-module like yours?

Also, there wouldn't be dependency problems if they are plugged in order, right?

alexherbo2 commented 3 years ago

connect.kak

provide-module connect %{
}

yank-ring-connect.kak

hook global ModuleLoaded connect %{
  require-module yank-ring-connect
}

provide-module yank-ring-connect %{
}

kakrc

source connect.kak
require-module connect
source yank-ring-connect.kak

ModuleLoaded is not executed, as the module has already been loaded.

For the second point, the issue is it requires you to know the implementation to plug in the correct order.

SeerLite commented 3 years ago

Ohh I see! Then would the right way to do it be to require-module after all plug calls?

alexherbo2 commented 3 years ago

Yep

SeerLite commented 3 years ago

Got it, thanks!

Also I think I understand the purpose of modules and plugins inside modules now. One could easily replace plug '...' config %{ with hook global ModuleLoaded '...' %{.

Disabling plugins and not running a plugin's configuration when it's not available were the main reasons I started using plug.kak in the first place.

alexherbo2 commented 3 years ago

Yeah, I feel like plug.kak is redundant now we have modules.

SeerLite commented 3 years ago

Well, it's still a nice syntax for fetching plugins from github/gitlab in case you don't want to mess too much with git submodules in autoload.

:plug-update as an alternative to git submodule update also feels nice (although maybe a command can be defined for this purpose in kakrc).

SeerLite commented 3 years ago

@alexherbo2

plug 'alexherbo2/connect.kak' config %{
    hook global KakBegin .* %{
        require-module connect
    }
}

I even think it's possible to make it a new keyword/attribute for plug.kak, somethink like demand-delay.

plug 'alexherbo2/connect.kak' demand-delay connect

Sorry, it's just that I find using plug.kak a lot more organized than manually setting up plugins.

Edit: Why I think it's better than require-module after all plugs: If a plugin isn't installed yet, Kakoune wont complain about not finding a module. A workaround is to put each require-module in its own ŧry but that looks ugly.

alexherbo2 commented 3 years ago

A tiny PoC using the autoload with 0 sh call if possible:

~/.config/kak/autoload/plug/rc/plug.kak

provide-module plug %{
  define-command plug-core -params 0..1 -docstring 'plug-core [config]' %{
    nop %sh{
      if ! [ -e "$kak_config/autoload/core" ]; then
        mkdir -p "$kak_config/autoload"
        ln -s "$kak_runtime/autoload" "$kak_config/autoload/core"
      fi
    }
    evaluate-commands %arg{1}
  }

  define-command plug -params 2..3 -docstring 'plug <module> <url> [config]' %{
    hook global ModuleLoaded %arg{1} %arg{3}
    hook global KakBegin .* "plug-require-module %arg{1} %arg{2}"
  }

  define-command -hidden plug-require-module -params 2 -docstring 'plug <module> <url>' %{
    try %{
      require-module %arg{1}
    } catch %{
      nop %sh{
        git clone "$2" "$kak_config/autoload/$1"
      }
    }
  }

  # Plugins with no module
  define-command plug-old -params 2..3 -docstring 'plug-old <module> <url> [config]' %{
    nop %sh{
      if ! [ -e "$kak_config/autoload/$1" ]; then
        git clone "$2" "$kak_config/autoload/$1"
      fi
    }
    evaluate-commands %arg{3}
  }

  define-command plug-execute -params 2.. -shell-script-candidates 'cd "${kak_config}/autoload" && ls -1' -docstring 'plug-execute <module> <command>' %{
    nop %sh{
      cd "$kak_config/autoload/$1"
      shift
      "$@"
    }
  }

  define-command plug-execute-all -params 1.. -docstring 'plug-execute-all <command>' %{
    nop %sh{
      for plugin in "$kak_config/autoload/"*; do
        (cd "$plugin"; "$@")
      done
    }
  }

  define-command plug-update -params 1 -shell-script-candidates 'cd "${kak_config}/autoload" && ls -1' -docstring 'plug-update <module>' %{
    plug-execute %arg{1} git pull
  }

  define-command plug-update-all -docstring 'plug-update-all' %{
    plug-execute-all git pull
  }
}

~/.config/kak/kakrc

require-module plug

plug-core %{
  # Tools
  set-option global makecmd 'make -j 8'
  set-option global grepcmd 'rg --column --with-filename'
}
plug prelude https://github.com/alexherbo2/prelude.kak
plug connect https://github.com/alexherbo2/connect.kak %{
  # Modules
  require-module connect-fzf
  require-module connect-broot

  # Mappings
  map -docstring 'New tab' global normal <c-t> ': connect-terminal<ret>'
  map -docstring 'New window' global normal <c-n> ': connect-shell alacritty<ret>'
}
plug-old state-save https://gitlab.com/Screwtapello/kakoune-state-save %{
  # Starting
  hook global KakBegin .* %{
    state-save-reg-load colon
    state-save-reg-load pipe
    state-save-reg-load slash
  }

  # Quitting
  hook global KakEnd .* %{
    state-save-reg-save colon
    state-save-reg-save pipe
    state-save-reg-save slash
  }
}
plug my-module ~/projects/my-plugin.kak %{
  my-plugin-enable
}
SeerLite commented 3 years ago

Wow woah, that's actually really nice! I love it already!

I found a problem with plug-old: [config] will fail if it depends on the plugin already being sourced, so the whole installation process will break. That can be solved by recursively source .kak files inside the plugin's directory on installation, before running config. Alternatively, don't execute config at all on the first run.

Another issue with plug-old is that, since everything is in autoload, you can't really disable (by commenting out) "old"-style plugins. A solution I see to that is to use a plugins directory for old-style plugins (would require recursive sourcing for each plugin though :/) and just autoload for module-style plugins.

In general, it's really fast. Are you planning on making a repository for it?

Edit: What do you think about putting all plugins in a autoload/plugins/ subfolder? That way it can be .gitignored easily.

alexherbo2 commented 3 years ago

Yep, but I’m not satisfied with the implementation yet. I want it to be simple and close to the way Kakoune works without plugin manager, by using the autoload, to be a thin wrapper around the require-module command and ModuleLoaded hook — with Git support — to help users to structure their kakrc (into blocks).

I do not have a solution for plug-old. We could wrap the commands under the provided module name, but as I said I want the implementation to be simple and would prefer to push authors to use modules.

andreyorst commented 3 years ago

When I don't have any specific configuration for plugins like these, I prefer using require-module explicitly inside the config, but omitting the config keyword and scope delimiters:

plug "https://github.com/alexherbo2/prelude.kak" require-module prelude

Looks nicer than a forced empty parameter for defer/demand.

I'm surprised that it works! :D

alexherbo2 commented 3 years ago

https://github.com/alexherbo2/plug.kak