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"
UltiSnips stores Java snippets in java.snippets, which on my machine is ~/.vim/bundle/vim-snippets/UltiSnips/java.snippets (I am usinghonza/vim-snippets` as well).
Snippets for Java are implemented using Python, so I have implemented the snippet below using Python as well (you can do it using multiple languages in UltiSnips).
There is already a snippet for package, which adds simply "package" word followed with a placeholder:
snippet pa "package" b
package $0
endsnippet
Let's create a pad snippet that will automatically insert package name, based on the directory chain, instead of the $0 placeholder:
snippet pad "package" b
package `!p
def get_package_string(base_dir_name):
import os
# Get absolute path of the package (without filename)
absolute_path = os.getcwd().split("/")
src_dir_index = 0
# Find index of 'base_dir_name' element
while absolute_path[src_dir_index] != base_dir_name:
src_dir_index+=1
# Create a 'package ' string, joining with dots
package_string = ".".join(absolute_path[src_dir_index+1:])
return package_string
# snip.rv is UltiSnips' return value we want to paste between ``
snip.rv = get_package_string("java")`
endsnippet
Note that this solution is based on the fact that in many Java projects, there is an src directory with main/java and test/java directories in it and you are editing one of the files in java directory (e.g. for src/main/com/google/common it will return com.google.common). You may need to modify this to be more flexible.
You can find more information about creating snippets in screencasts linked in its README.
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
Related
We write our jenkins pipeline using groovy script. Is there any way to identify the folder size or file size.
Our goal is to identify size of two zip files and calculate the difference between them.
I tried below code but its not working.
stage('Calculate Opatch size')
{
def sampleDir = new File('${BuildPathPublishRoot}')
def sampleDirSize = sampleDir.directorySize()
echo sampleDirSize
}
Getting below error :-
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.io.File.directorySize() is applicable for argument types: () values: []
Possible solutions: directorySize()
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:154)
Here's what worked for me. Grab all the files in a directory and sum the lengths.
Please note that you'll need to use quotes (") in order for string interpolation to work, i.e. "${BuildPathPublishRoot}" places the value of the BuildPathPublishRoot variable into the string, whereas '${BuildPathPublishRoot}' is taken literally to be the directory name.
workspaceSize = directorySize("${BuildPathPublishRoot}")
/** Computes bytes in the directory*/
public def directorySize(directory){
long bytes = 0
directory = (directory?:'').replace('\\','/')
directory = (directory =='') ? '' : (directory.endsWith('/') ? directory : "${directory}/")
def files=findFiles(glob: "${directory}*.*")
for (file in files) {
if (!file.isDirectory()){
bytes += file.length
}
}
return bytes
}
I have a child java project which has groovy files added in classpath using eclipse. Parent java project triggers some functionality in child which uses Groovy library to run the scripts. So import works fine in eclipse environment with opened child project but if I run it from command line or if I close child project then I get groovy compilation error at import statement. How can I resolve this ? I want to avoid using evaluate() method.
Following is my master groovy:
package strides_business_script
abstract class Business_Script extends Script {
//some stuff
}
Following is the another groovy:
import static strides_business_script.StridesBusiness_Script.*;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
String Key = Part_Product_PartDetails
boolean containsData = checkIncomingMessage(Key)
if(containsData) {
def edgeKeyList = [PPR]
JSONArray partDetails = appendEdgeValueToMsg(edgeKeyList,Key,vertex,messageIterator);
//deleteMessages(Key);
JSONObject jsonObject = constructInfoWithPropertyJSON("NAME,PRODUCTTYPE,FGTYPE,UOM,ITEMCLASSIFICATIONBYMARKET");
jsonObject.put("PARTS",partDetails);
send(Product_AggPO_ProductDetails,convertJSONToString(jsonObject));
}
Edit:
My master script Business_Script.groovy resides in scripts/strides_business_script/ folder. All other scripts are in scripts/StridesComputationScripts/ folder and they import the Business_Script.groovy.
I run the application with remote debugging enabled like this:
java -cp "./lib/*:./scripts/strides_business_script/Business_Script.groovy" -Xdebug -Xrunjdwp:transport=dt_socket,address=6969,server=y -Dhibernate.cfg.xml.path=./conf/hibernate.cfg.xml -Dlog4j.configuration=file:./conf/log4j.properties com.biglabs.dataExtractor.dataDump.DataDumpDriver 7
and here I am trying to parse all computation scripts.
for (String scriptName : files) {
Script script = groovyShell.parse(new File(
SCRIPT_PLACED_AT + Constants.SLASH
+ SCRIPT_FILE_FOLDER + Constants.SLASH
+ scriptName));
scriptMping.put(scriptName, script);
}
It throws following exception while parsing using groovy shell:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/home/manoj/strides/release/strides/scripts/StridesComputationScripts/PRODUCT-script.groovy: 2: unable to resolve class strides_business_script.StridesBusiness_Script
# line 2, column 1.
import static strides_business_script.Business_Script.*;
^
/home/manoj/strides/release/strides/scripts/StridesComputationScripts/PRODUCT-script.groovy: 2: unable to resolve class strides_business_script.StridesBusiness_Script
# line 2, column 1.
import static strides_business_script.Business_Script.*;
^
2 errors
Fixed it by adding script path in comiler configuration:
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
String path = SCRIPT_PLACED_AT;
if(!SCRIPT_PLACED_AT.endsWith("/")){
path = path+ "/";
}
compilerConfiguration.setClasspath(path);
GroovyShell groovyShell = new GroovyShell(
compilerConfiguration);
for (String scriptName : files) {
Script script = groovyShell.parse(new File(
SCRIPT_PLACED_AT + Constants.SLASH
+ SCRIPT_FILE_FOLDER + Constants.SLASH
+ scriptName));
scriptMping.put(scriptName, script);
}
If I try to use a path that contains spaces in Linux I get FileNotFoundException, obviously. But if I try to add double/single quotes in the path as workaround, I get the same exception.
I was trying to check the reason and I found out that the generated absolute path when using quotes became: the user.home system property + specified path.
For example:
If I use this path:
/home/db2inst1/Desktop/testing - Development Environmet/64_dev/testing/logs
This is the absolute path I get when trying to use quotes:
/home/db2inst1/"/home/db2inst1/Desktop/testing - Development Environmet/64_dev/testing/logs"
I also tried to replace the spaces with "\ " instead of adding quotes, but it did not work.
I tried a lot of API's and it happens every time, made this code just for testing:
System.out.println("- regular path: ");
System.out.println(new File(path).getPath());
System.out.println(new File(path).getAbsolutePath());
System.out.println("- quoted path: ");
System.out.println(new File(quotedPath).getPath());
System.out.println(new File(quotedPath).getAbsolutePath());
And this is the output:
- regular path:
/home/db2inst1/Desktop/testing - Development Environmet/64_dev/testing/logs/testing.log
/home/db2inst1/Desktop/testing - Development Environmet/64_dev/testing/logs/testing.log
- absolute path:
"/home/db2inst1/Desktop/testing - Development Environmet/64_dev/testing/logs/testing.log"
/home/db2inst1/"/home/db2inst1/Desktop/testing - Development Environmet/64_dev/testing/logs/testing.log"
Does anyone know why this is happening and how to make it work?
From your description it seems that you are calling the File(java.lang.String pathname) constructor.
If so, the String used to represent your path should not use quotes.
Quotes are not considered as special characters in the abstract pathname definition, as described in the java.io.File documentation.
An abstract pathname has two components:
An optional system-dependent prefix string, such as a disk-drive specifier, "/" for the UNIX >root directory, or "\\" for a Microsoft Windows UNC pathname, and
A sequence of zero or more string names.
Since quotes are not special characters, they are considered part of a name.
Example:
public static void main(String[] args) {
File quotes = new File("\"C:\\myFolder\"");
File noQuotes = new File("C:\\myFolder");
System.out.println("Absolute path with quotes:" + quotes.getAbsolutePath());
System.out.println("Absolute path without quotes:" + noQuotes.getAbsolutePath());
System.out.println("Equal: " + quotes.equals(noQuotes));
File empty = new File("");
File emptyQuotes = new File("\"\"");
System.out.println("Empty path with quotes:" + empty.getAbsolutePath());
System.out.println("Empty path without quotes:"
+ emptyQuotes.getAbsolutePath());
System.out.println("Equal: " + empty.equals(emptyQuotes));
}
will produce the following output when run in C:\temp on Windows:
Absolute path with quotes:C:\temp\"C:\myFolder"
Absolute path without quotes:C:\myFolder
Equal: false
Empty path with quotes:C:\temp
Empty path without quotes:C:\temp\""
Equal: false
In windows a file name without blanks and the same quoted should refer to the same file (or folder). For instance if we have a folder called c:\uni2 both command lines
dir c:\uni2
dir "c:\uni2"
should give the same result. But in java
String rename;
boolean ya;
File f1 = new File ("C:/UNI2"); // given that exists and it is a directory
ya = f1.exists(); // true
ya = f1.isFile(); // false
ya = f1.isDirectory(); // true
rename = f1.getAbsolutePath(); // "C:\\UNI2"
f1 = new File ("\"C:/UNI2\""); // in windows this should be the same directory!!
ya = f1.exists(); // false
ya = f1.isFile(); // false
ya = f1.isDirectory(); // false
rename = f1.getAbsolutePath(); // "C:\tmp\"C:\UNI2""
which is not the expected behavior (even if it is documented).
I'm trying to link classes from the JDK into the scaladoc-generated doc.
I've used the -doc-external-doc option of scaladoc 2.10.1 but without success.
I'm using -doc-external-doc:/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar#http://docs.oracle.com/javase/7/docs/api/, but I get links such as index.html#java.io.File instead of index.html?java/io/File.html.
Seems like this option only works for scaladoc-generated doc.
Did I miss an option in scaladoc or should I fill a feature request?
I've configured sbt as follows:
scalacOptions in (Compile,doc) += "-doc-external-doc:/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar#http://docs.oracle.com/javase/7/docs/api"
Note: I've seen the Opts.doc.externalAPI util in the upcoming sbt 0.13. I think a nice addition (not sure if it's possible) would be to pass a ModuleID instead of a File. The util would figure out which file corresponds to the ModuleID.
I use sbt 0.13.5.
There's no out-of-the-box way to have the feature of having Javadoc links inside scaladoc. And as my understanding goes, it's not sbt's fault, but the way scaladoc works. As Josh pointed out in his comment You should report to scaladoc.
There's however a workaround I came up with - postprocess the doc-generated scaladoc so the Java URLs get replaced to form proper Javadoc links.
The file scaladoc.sbt should be placed inside a sbt project and whenever doc task gets executed, the postprocessing via fixJavaLinksTask task kicks in.
NOTE There are lots of hardcoded paths so use it with caution (aka do the polishing however you see fit).
import scala.util.matching.Regex.Match
autoAPIMappings := true
// builds -doc-external-doc
apiMappings += (
file("/Library/Java/JavaVirtualMachines/jdk1.8.0_11.jdk/Contents/Home/jre/lib/rt.jar") ->
url("http://docs.oracle.com/javase/8/docs/api")
)
lazy val fixJavaLinksTask = taskKey[Unit](
"Fix Java links - replace #java.io.File with ?java/io/File.html"
)
fixJavaLinksTask := {
println("Fixing Java links")
val t = (target in (Compile, doc)).value
(t ** "*.html").get.filter(hasJavadocApiLink).foreach { f =>
println("fixing " + f)
val newContent = javadocApiLink.replaceAllIn(IO.read(f), fixJavaLinks)
IO.write(f, newContent)
}
}
val fixJavaLinks: Match => String = m =>
m.group(1) + "?" + m.group(2).replace(".", "/") + ".html"
val javadocApiLink = """\"(http://docs\.oracle\.com/javase/8/docs/api/index\.html)#([^"]*)\"""".r
def hasJavadocApiLink(f: File): Boolean = (javadocApiLink findFirstIn IO.read(f)).nonEmpty
fixJavaLinksTask <<= fixJavaLinksTask triggeredBy (doc in Compile)
I took the answer by #jacek-laskowski and modified it so that it avoid hard-coded strings and could be used for any number of Java libraries, not just the standard one.
Edit: the location of rt.jar is now determined from the runtime using sun.boot.class.path and does not have to be hard coded.
The only thing you need to modify is the map, which I have called externalJavadocMap in the following:
import scala.util.matching.Regex
import scala.util.matching.Regex.Match
val externalJavadocMap = Map(
"owlapi" -> "http://owlcs.github.io/owlapi/apidocs_4_0_2/index.html"
)
/*
* The rt.jar file is located in the path stored in the sun.boot.class.path system property.
* See the Oracle documentation at http://docs.oracle.com/javase/6/docs/technotes/tools/findingclasses.html.
*/
val rtJar: String = System.getProperty("sun.boot.class.path").split(java.io.File.pathSeparator).collectFirst {
case str: String if str.endsWith(java.io.File.separator + "rt.jar") => str
}.get // fail hard if not found
val javaApiUrl: String = "http://docs.oracle.com/javase/8/docs/api/index.html"
val allExternalJavadocLinks: Seq[String] = javaApiUrl +: externalJavadocMap.values.toSeq
def javadocLinkRegex(javadocURL: String): Regex = ("""\"(\Q""" + javadocURL + """\E)#([^"]*)\"""").r
def hasJavadocLink(f: File): Boolean = allExternalJavadocLinks exists {
javadocURL: String =>
(javadocLinkRegex(javadocURL) findFirstIn IO.read(f)).nonEmpty
}
val fixJavaLinks: Match => String = m =>
m.group(1) + "?" + m.group(2).replace(".", "/") + ".html"
/* You can print the classpath with `show compile:fullClasspath` in the SBT REPL.
* From that list you can find the name of the jar for the managed dependency.
*/
lazy val documentationSettings = Seq(
apiMappings ++= {
// Lookup the path to jar from the classpath
val classpath = (fullClasspath in Compile).value
def findJar(nameBeginsWith: String): File = {
classpath.find { attributed: Attributed[File] => (attributed.data ** s"$nameBeginsWith*.jar").get.nonEmpty }.get.data // fail hard if not found
}
// Define external documentation paths
(externalJavadocMap map {
case (name, javadocURL) => findJar(name) -> url(javadocURL)
}) + (file(rtJar) -> url(javaApiUrl))
},
// Override the task to fix the links to JavaDoc
doc in Compile <<= (doc in Compile) map {
target: File =>
(target ** "*.html").get.filter(hasJavadocLink).foreach { f =>
//println(s"Fixing $f.")
val newContent: String = allExternalJavadocLinks.foldLeft(IO.read(f)) {
case (oldContent: String, javadocURL: String) =>
javadocLinkRegex(javadocURL).replaceAllIn(oldContent, fixJavaLinks)
}
IO.write(f, newContent)
}
target
}
)
I am using SBT 0.13.8.
I'm finishing a business card production flow (excel > xml > indesign > single page pdfs) and I would like to insert the employees' names in the filenames.
What I have now:
BusinessCard_01_Blue.pdf
BusinessCard_02_Blue.pdf
BusinessCard_03_Blue.pdf (they are gonna go up to the hundreds)
What I need (I can manipulate the name list with regex easily):
BusinessCard_01_CarlosJorgeSantos_Blue.pdf
BusinessCard_02_TaniaMartins_Blue.pdf
BusinessCard_03_MarciaLima_Blue.pdf
I'm a Java and Python toddler. I've read the related questions, tried this in Automator (Mac) and Name Mangler, but couldn't get it to work.
Thanks in advance,
Gus
Granted you have a map where to look at the right name you could do something like this in Java:
List<Files> originalFiles = ...
for( File f : originalFiles ) {
f.renameTo( new File( getNameFor( f ) ) );
}
And define the getNameFor to something like:
public String getNameFor( File f ) {
Map<String,String> namesMap = ...
return namesMap.get( f.getName() );
}
In the map you'll have the associations:
BusinessCard_01_Blue.pdf => BusinessCard_01_CarlosJorgeSantos_Blue.pdf
Does it make sense?
In Python (tested):
#!/usr/bin/python
import sys, os, shutil, re
try:
pdfpath = sys.argv[1]
except IndexError:
pdfpath = os.curdir
employees = {1:'Bob', 2:'Joe', 3:'Sara'} # emp_id:'name'
files = [f for f in os.listdir(pdfpath) if re.match("BusinessCard_[0-9]+_Blue.pdf", f)]
idnumbers = [int(re.search("[0-9]+", f).group(0)) for f in files]
filenamemap = zip(files, [employees[i] for i in idnumbers])
newfiles = [re.sub('Blue.pdf', e + '_Blue.pdf', f) for f, e in filenamemap]
for old, new in zip(files, newfiles):
shutil.move(os.path.join(pdfpath, old), os.path.join(pdfpath, new))
EDIT: This now alters only those files that have not yet been altered.
Let me know if you want something that will build the the employees dictionary automatically.
If you have a list of names in the same order the files are produced, in Python it goes like this untested fragment:
#!/usr/bin/python
import os
f = open('list.txt', 'r')
for n, name in enumerate(f):
original_name = 'BusinessCard_%02d_Blue.pdf' % (n + 1)
new_name = 'BusinessCard_%02d_%s_Blue.pdf' % (
n, ''.join(name.title().split()))
if os.path.isfile(original_name):
print "Renaming %s to %s" % (original_name, new_name),
os.rename(original_name, new_name)
print "OK!"
else:
print "File %s not found." % original_name
Python:
Assuming you have implemented the naming logic already:
for f in os.listdir(<directory>):
try:
os.rename(f, new_name(f.name))
except OSError:
# fail
You will, of course, need to write a function new_name which takes the string "BusinessCard_01_Blue.pdf" and returns the string "BusinessCard_01_CarlosJorgeSantos_Blue.pdf".