Skip to content

Conversation

@smoeding
Copy link
Contributor

Emacs 25 introduced the xref package providing a generic framework to jump to function definitions. This PR updates puppet-mode to hook into this framework and implements easy navigation to classes, defined types, data types and functions located in other modules.

The idea for this feature was also introduced in #29.

Usage:

Imagine you are editing the following acme class:

# a class managing everything
class acme (
  Stdlib::Absolutepath $www_root,
  Boolean              $enable,
) inherits acme::params {

  include nginx

  nginx::resource::server { 'test2.local':
    ensure   => stdlib::ensure($enable),
    www_root => $www_root,
    require  => Class['postgresql::server'],
  }
}

The following navigation options are available:

  1. Point is on the Stdlib::Absolutepath data type: M-. opens the data type definition
  2. Point is on the acme::params subclass: M-. opens the class definition
  3. Point is on the nginx class: M-. opens the class definition
  4. Point is on the nginx::resource::server defined type: M-. opens the type definition
  5. Point is on the stdlib::ensure function: M-. opens the function definition
  6. Point is on the postgresql::server string: M-. opens the class definition

Navigation to foreign classes only needs a list of directories to search. After jumping to a definition you can return back using M-,. These keybindings are defined by the xref package.

Implementation:

The code takes the identifier at point, dissects it into a module name and possible file paths below that module where the identifier could be defined according to Puppet's auto-loader rules. For foo::bar the following paths are checked: manifests/bar.pp, types/bar.pp and functions/bar.pp.

First these paths are checked for the current module. In this case the module name does not need to be a path component (e.g. coding the module in ~/src/puppet-acme would work, so you can check out modules from Github into your home directory). Then all directories from the new customization option puppet-module-path are checked. This option should have all directories where you keep modules (default: /etc/puppetlabs/code/environments/production). In this case there is a requirement, that the module directory must be named after the module as Puppet dictates.

Then the code visits every file that actually exists and looks for the definition. It returns the file name and line number back to the xref framework to perform the heavy lifting.

Look-ups are performed on the fly when needed since the number of possible candidate files is small due to the auto-loader rules. Therefore it seems adequate to handle it without maintaining some sort of 'database' like a TAGS file (which could get out of sync).

Caveats:

  • xref is only available out of the box for Emacs 25 or later.

This code seems to work for my use cases. Obviously more people testing it would be a bonus!
Your feedback is appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant