5

I have configured vim to automatically decompile ".class" files similar to the instructions in: http://vim.wikia.com/wiki/VimTip54.

I have made a minor change to use cfr_0_115 as below:

augr class
au!
au bufreadpost,filereadpost *.class silent %!java -jar /blah/cfr_0_115.jar %
au bufreadpost,filereadpost *.class set readonly
au bufreadpost,filereadpost *.class set ft=java
au bufreadpost,filereadpost *.class silent normal gg=G
au bufreadpost,filereadpost *.class set nomodified
augr END

This works fine when opening files from the shell.

Sometimes I work with JAR files and would like to achieve the following workflow:

  1. :Explore (and navigate to the JAR file)
  2. View the JAR file and select a Class
  3. When this Class is opened, it should be ran through CFR.

Currently, when I get to step "3" the class is not decompiled for viewing. I'd love to know how I can get the class file from a JAR opened 'through' the class decompiler.

Edit 1 - With Vim logging enabled, when I open a class file that is NOT within a JAR file, I see Executing BufRead Auto commands for "*.class include the command I wish to run. However, when I open the class file from within a jar, I do not see the command in the logs.

Edit 2 - Relevant log entries when opening a JAR:

Executing BufReadCmd Auto commands for "zipfile:*/*"
autocommand call zip#Read(expand("<amatch>"), 1)

Calling shell to execute: "(unzip -p -- '/blah/original-httpclienttest-1.0.jar' 'com/atlassianlabs/sslclient/Main.class') >/var/folders/ys/18xytj217f749_vx7rhs4t7w0000gp/T/vwqRYKe/1 2>&1"
chdir(zipfile:/blah/original-httpclienttest-1.0.jar::com/)
fchdir() to previous dir
Reading viminfo file "/blah/.viminfo" marks

and later:

Executing BufRead Auto commands for "*.class"
autocommand setf stata

However when I open a class file by navigating to it directly with the file explore (:Explore) I see:

Executing BufRead Auto commands for "*.class"
autocommand silent %!java -jar /blah/cfr_0_115.jar

Follow-up

I don't know why the autocmd's that exist are not getting picked up when opening from a JAR, because VIM is actually running some autocmd, just not the one I want and "autocommand setf stata" is not even present when opening a class. I'm blocked in terms of how to debug this further.

More Follow-up

I got this working to some extent by adding a function to the filetype.vim file on class files. However, vim reports the file name in the format: ZIPFILEPATH::PATHTOCLASS in the JAR.. I was hoping it would send though the temp file path instead.

2
  • 1
    I don't know why the autocommand doesn't trigger when you open the file from a JAR but a workaround could be to put in your vimrc a function which will execute your list of commands, bind a key to call the function and use it to manually decompile the file.
    – statox
    Commented May 11, 2016 at 7:25
  • 3
    How are you looking within the JAR? 7-zip or something? I'm not sure but I'm guessing that the fact that the file is compressed is messing with vim.
    – Tumbler41
    Commented May 11, 2016 at 13:23

1 Answer 1

2

By starting vim using: vim -V9aLogFile.log I was able to determine that when :Explore opens a file, it checks the content of filetype.vim and autocmd's are working from there.

Because vim reports the filename of a class inside a jar file in the format zipfile::path-to-jar::path-to-class I needed to workaround that as my Java decompiler couldn't handle this type of file path.

I created a shell "wrapper" script:

#!/bin/sh

pathToDecompiler=/blah/cfr_0_115.jar


fileType=$(echo $* | cut -f1 -d:)
jarFile=$(echo $* | cut -f2 -d:) 
classFile=$(echo $* | cut -f4 -d:) 
uuid=$(uuidgen)


if [ $fileType = "zipfile" ]
then
    tmpDir=/tmp/$uuid
    unzip -qq $jarFile $classFile -d $tmpDir 
    java -jar $pathToDecompiler $tmpDir/$classFile
    rm -rf /tmp/$uuid/ >&/dev/null
else
    java -jar $pathToDecompiler $*
fi

The above script handles two cases, when opening a normal class file, and when opening a class file from the Explore Command, it creates a file in temp. Note: when writing this, I found entering rm -rf ... particularly scary in the event a variable didn't get populated. I decided to play it safe and hard-code '/tmp'.

Then I created a function back in the filetype.vim file:

" Java Class
au BufRead *.class call SetClassOptions()
function SetClassOptions()
     setf stata
     silent %!/blah/get-class-from-jar.sh %
     set readonly
     set ft=java
     silent normal gg=G
     set nomodified
endfunction

It's a little hacky, and I am sure it could be polished or completed in a more 'vim' way, but at least it has my usecase sorted.

final result is recorded: https://giphy.com/gifs/l41Yf8WlUQWj3R6hy

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.