javavimultisnips

UltiSnips expand java package


I want to be able to write a vim snippet that automatically turns into the required package.

E.g. expanding pkg while inside of .../com/theonlygust/project/Main.java would become

package com.theonlygusti.project;

I think the ways to do this are to either: read up the directory tree until seeing a TLD directory name (com, io, net, etc.) and then use the encountered directory names to build the package string, or to look up the directory tree for the pom.xml and find the package from there.

I learned about python interpolation.

I'm now trying this:

snippet pkg "Create package" b
package `!p

import os
from xml.etree import ElementTree

def get_package_name(pom_file_path):
  namespaces = {'xmlns' : 'http://maven.apache.org/POM/4.0.0'}

  tree = ElementTree.parse(pom_file_path)
  root = tree.getroot()

  groupId = root.find(".//xmlns:groupId", namespaces=namespaces)
  artifactId = root.find(".//xmlns:artifactId", namespaces=namespaces)
  return groupId.text + '.' + artifactId.text

def find_nearest_pom():
  absolute_path = os.path.abspath(os.path.dirname('__file__')).split("/")
  pom_dir_index = -1

  # Find index of 'base_dir_name' element
  while not os.path.isfile('/'.join(absolute_path[:pom_dir_index]) + '/pom.xml'):
    pom_dir_index -= 1

  return '/'.join(absolute_path[:pom_dir_index]) + '/pom.xml'

snip.rv = get_package_name(find_nearest_pom())`;
endsnippet

But I get the error

Name __file__ does not exist

And os.getcwd() doesn't work because that returns the directory from which vim was opened, not the directory that contains the current buffer.

I had a look at the snip object because I know it provides snip.fn to get the filename, but I couldn't find out if it provides the current file's directory.

Nevermind, finally learned that UltiSnips sets a global variable "path"


Solution

  • I use a combination of the file path and the groupId and the artifactId from the nearest pom.xml (upwards)

    global !p
    import os
    from xml.etree import ElementTree
    
    def get_package_name(pom_file_path):
      namespaces = {'xmlns' : 'http://maven.apache.org/POM/4.0.0'}
    
      tree = ElementTree.parse(pom_file_path)
      root = tree.getroot()
    
      groupId = root.find(".//xmlns:groupId", namespaces=namespaces)
      artifactId = root.find(".//xmlns:artifactId", namespaces=namespaces)
      return groupId.text + '.' + artifactId.text
    
    def find_nearest_pom():
      current_file_dir = '/'.join((os.getcwd() + ('/' if os.getcwd()[-1] != '/' else '') + path).split('/')[:-1])
      absolute_path = current_file_dir.split("/")
      pom_dir_index = -1
    
      if os.path.isfile('/'.join(absolute_path) + '/pom.xml'):
        return '/'.join(absolute_path) + '/pom.xml'
    
      # Find index of 'base_dir_name' element
      while not os.path.isfile('/'.join(absolute_path[:pom_dir_index]) + '/pom.xml'):
        pom_dir_index -= 1
    
      return '/'.join(absolute_path[:pom_dir_index]) + '/pom.xml'
    
    def get_file_package():
      current_file_location = '.'.join((os.getcwd() + ('/' if os.getcwd()[-1] != '/' else '') + path).split('/')[:-1])
      package = get_package_name(find_nearest_pom())
      return package + current_file_location.split(package)[1]
    
    endglobal
    
    snippet pkg "package" b
    package `!p snip.rv = get_file_package()`;
    endsnippet