I have a Java class for which part of the javadoc is actually generated as part of the build process: the return value of a method (a static String value) is inserted into the source file, much like $Revision: $ tags work in some version control software.
While this behaviour may be questionable, such duplication of information is required by the framework I use (WEKA machine learning library). I would like Eclipse's code formatter not to interfere with the generated comments. I am using the Eclipse Indigo release.
I can turn the formatter on/off with special comments //#formatter:on and //#formatter:off. However, the #formatter tags are only functional in 'normal' comments, not in javadoc comments. Obviously, they could be easily confused for javadoc tags. This means I cannot turn off the formatter (for example, automatic line breaking) for the generated part of the javadoc comment, and leave it on for the rest, because the #formatter directives must be placed around the javadoc comment.
It there a workaround to toggle code formatting inside javadoc comments?
Been a while since this was asked/answered and helped me refine the following answer, hopefully additionally useful. I use this alternative as I wanted to run Javascript in Javadocs.
Eclipse provides the #formatter:off and #formatter:on which needs to be enabled via Windows->Preferences->java->code style->formatter:::edit button::: tab "off/on tags".
They may be used in any comments.
Around the doc stuff
// #formatter:off
/**
* javadoc
*/
// #formatter:on
But when you want the formatter off within the javadoc use the
#formatter:xxx within html comments <!-- xxxxx --> to indicate what you
are trying to do. Use the <code>...</code> bloack to ensure no formatting and
the inclusion of code as javascript.
Editted the code statements in the example as I wanted this to work on eclipse
and netbeans. I found the formatter:off work but then stopped working on a different
version of eclipse (yes I use multiple IDE versions).
/**
* <br><!-- #formatter:off -->
* <code>
* <script type="text/javascript">
* // hash structure for holding variable as name and its text
* var hashText = {};
*
* // function causes a hyper-link to be created
* function insertLink(varName, text){
* var link22;
*
* hashText[varName] = text;
*
* link22 = '' + hashText[varName] + '';
*
* document.write(link22);
* }
* function insertLinkA(varName){
* var link22;
*
* link22 = '' + hashText[varName] + '';
*
* document.write(link22);
* }
*
* function setLinkPoint(varName, text){
* hashText[varName] = text;
*
* document.write('<a id="' + varName + '"><U>' + hashText[varName] + '</U></a>');
* }
*
* function setLinkPointA(varName){
* document.write('<a id="' + varName + '"><U>' + hashText[varName] + '</U></a>');
* }
* </script>
* <code>
* <!-- #formatter:on -->
*
*
*/
You can disable formatting for the header, but I don't believe you can selectively disable formatting for nonheader javadoc comments.
I encountered the same problem and changing #formatter:off to FORMATTEROFF did the trick for me.
the idea is to avoid using # in the on/off tag.
Now I can disable the formatter around a part of a javadoc.
Related
I have:
/*
* Search file
*
* #param folderPath - path to search.
* #param resourceResolver - ResourceResolver.
*/
Eclipse format it to:
/*
* Search file
*
* #param folderPath - path to search.
*
* #param resourceResolver - ResourceResolver.
*/
How can I prevent such adding new line before "#param resourceResolver"? Can it be a bug?
"Remove blank lines" feature the line after "Search file", so it's not convenient for me.
Disabling "Enable block comment formating" is also bad choise because of indention.
I'm using Behat to test a registration page.
This page contains a few fields with autocompletion.
User fills in some value in the field, page waits 500 milliseconds, makes an ajax-request and displays some options along with a relevant message (no items found / several items found / one item found).
I'm using a predefined step "I fill in field with value" (tried to use "I fill in value for field" instead).
Next step is custom, similar to one described in documentation - I'm just waiting for message to appear and check that it has correct text.
But after filling the field Mink removes focus from it, causing blur event to be fired on the field.
Jquery-ui clears the field value in response to this blur event, so after 500 milliseconds field is empty and ajax request is aborted.
How can I fix this problem?
Behat v2.5.0
Mink v1.5.0
Mink-extension v1.3.3
Jquery-ui v1.8.21
Selenium v2.44.0
Solution below is specific to my markup code but should be easily adapted to yours. You might need to modify it.
Assuming that selecting auto suggested option in textbox. Autosuggestion options appear as <li> elements after user’s key strokes. <li> element presents in the page however its content is empty at the beginning so there is nothing to be selected by behat. To solve the problem, non existing content between <li> tags is wrapped with <label> tag.
User types in this auto suggestion field:
<input name="brand" type="text" />
Where autosuggestion data appears:
<ul>
<li><label>{{ suggestion }}</label></li>
</ul>
Gherkin:
When I fill in "brand" with "S"
And I wait 1 seconds
Then I select autosuggestion option "Sula"
And I wait 1 seconds
......
FeatureContext:
/**
* #Given /^I wait (\d+) seconds$/
*/
public function iWaitSeconds($seconds)
{
sleep($seconds);
}
/**
* #Then /^I select autosuggestion option "([^"]*)"$/
*
* #param $text Option to be selected from autosuggestion
* #throws \InvalidArgumentException
*/
public function selectAutosuggestionOption($text)
{
$session = $this->getSession();
$element = $session->getPage()->find(
'xpath',
$session->getSelectorsHandler()->selectorToXpath('xpath', '*//*[text()="'. $text .'"]')
);
if (null === $element) {
throw new \InvalidArgumentException(sprintf('Cannot find text: "%s"', $text));
}
$element->click();
}
#Scenario: I'm stuck
Given I use jquery-ui-autocomplete
And I can not test it with behat
Then I trigger keyDown event like this:
"""
/**
* #When I select :entry after filling :value in :field
*/
public function iFillInSelectInputWithAndSelect($entry, $value, $field)
{
$page = $this->getSession()->getPage();
$field = $this->fixStepArgument($field);
$value = $this->fixStepArgument($value);
$page->fillField($field, $value);
$element = $page->findField($field);
$this->getSession()->getDriver()->keyDown($element->getXpath(), '', null);
$this->getSession()->wait(500);
$chosenResults = $page->findAll('css', '.ui-autocomplete a');
foreach ($chosenResults as $result) {
if ($result->getText() == $entry) {
$result->click();
return;
}
}
throw new \Exception(sprintf('Value "%s" not found', $entry));
}
"""
Use this to Fill in the search box: (using the ID selector)
/**
* #Then I type :text into search box
*/
public function iTypeTextIntoSearchBox($text)
{
$element = $this->getSession()->getPage()->findById('searchInput');
$script = "$('#searchInput').keypress();";
$element->setValue($text);
$this->getSession()->evaluateScript($script);
}
I am gonna to use Google App Script to fetch the programme list from the website of radio station.
How can I select the specified elements in the webpage by specifying the id of the element?
Therefore, I can get the programs in the webpage.
Edit, Dec 2013: Google has deprecated the old Xml service, replacing it with XmlService. The script in this answer has been updated to use the new service. The new service requires standard-compliant XML & HTML, while the old one was forgiving of such problems as missing close-tags.
Have a look at the Tutorial: Parsing an XML Document. (As of Dec 2013, this tutorial is still on line, although the Xml service is deprecated.) Starting with that foundation, you can take advantage of the XML parsing in Script Services to navigate the page. Here's a small script operating on your example:
function getProgrammeList() {
txt = '<html> <body> <div> <div> <div id="here">hello world!!</div> </div> </div> </html>'
// Put the receieved xml response into XMLdocument format
var doc = Xml.parse(txt,true);
Logger.log(doc.html.body.div.div.div.id +" = "
+doc.html.body.div.div.div.Text ); /// here = hello world!!
debugger; // Pause in debugger - examine content of doc
}
To get the real page, start with this:
var url = 'http://blah.blah/whatever?querystring=foobar';
var txt = UrlFetchApp.fetch(url).getContentText();
....
If you look at the documentation for getElements you'll see that there is support for retrieving specific tags, for example "div". That finds direct children of a specific element, it doesn't explore the entire XML document. You should be able to write a function that traverses the document examining the id of each div element until it finds your programme list.
var programmeList = findDivById(doc,"here");
Edit - I couldn't help myself...
Here's a utility function that will do just that.
/**
* Find a <div> tag with the given id.
* <pre>
* Example: getDivById( html, 'tagVal' ) will find
*
* <div id="tagVal">
* </pre>
*
* #param {Element|Document}
* element XML document or element to start search at.
* #param {String} id HTML <div> id to find.
*
* #return {XmlElement} First matching element (in doc order) or null.
*/
function getDivById( element, id ) {
// Call utility function to do the work.
return getElementByVal( element, 'div', 'id', id );
}
/**
* !Now updated for XmlService!
*
* Traverse the given Xml Document or Element looking for a match.
* Note: 'class' is stripped during parsing and cannot be used for
* searching, I don't know why.
* <pre>
* Example: getElementByVal( body, 'input', 'value', 'Go' ); will find
*
* <input type="submit" name="btn" value="Go" id="btn" class="submit buttonGradient" />
* </pre>
*
* #param {Element|Document}
* element XML document or element to start search at.
* #param {String} elementType XML element type, e.g. 'div' for <div>
* #param {String} attr Attribute or Property to compare.
* #param {String} val Search value to locate
*
* #return {Element} First matching element (in doc order) or null.
*/
function getElementByVal( element, elementType, attr, val ) {
// Get all descendants, in document order
var descendants = element.getDescendants();
for (var i =0; i < descendants.length; i++) {
var elem = descendants[i];
var type = elem.getType();
// We'll only examine ELEMENTs
if (type == XmlService.ContentTypes.ELEMENT) {
var element = elem.asElement();
var htmlTag = element.getName();
if (htmlTag === elementType) {
if (val === element.getAttribute(attr).getValue()) {
return element;
}
}
}
}
// No matches in document
return null;
}
Applying this to your example, we get this:
function getProgrammeList() {
txt = '<html> <body> <div> <div> <div id="here">hello world!!</div> </div> </div> </html>'
// Get the receieved xml response into an XML document
var doc = XmlService.parse(txt);
var found = getDivById(doc.getElement(),'here');
Logger.log(found.getAttribute(attr).getValue()
+ " = "
+ found.getValue()); /// here = hello world!!
}
Note: See this answer for a practical example of the use of these utilities.
Someone has made an example here where the following custom functions are available for cut & paste use:
getElementById()
getElementsByClassName()
getElementsByTagName()
Then you can do something like this
function doGet() {
var html = UrlFetchApp.fetch('http://en.wikipedia.org/wiki/Document_Object_Model').getContentText();
var doc = XmlService.parse(html);
var html = doc.getRootElement();
var menu = getElementsByClassName(html, 'menu-classname')[0];
return menu;
}
I'm going to assume that you are referring to using UrlFetchApp's fetch() method. In which case, the answer is no, in the context of what you are thinking of.
If you look at the return type for fetch() in the documentation it returns HTTPResponse. There are a few methods for that, but most of them involve getting the returned data as a string. The good news is, you could still use any (well, most) of the traditional JS String methods documented here - so you could use search(), match(), etc. Depending on your project you could use those to find the data you are looking for in the response.
I would like to enter math formulae in Scaladoc documentation of mathematical Scala code. In Java, I found a library called LatexTaglet that can do exactly this for Javadoc, by writing formulae in Latex:
http://latextaglet.sourceforge.net/
And it seems to integrate well with Maven (reporting/plugins section of a POM). Is there an equivalent library for Scaladoc? If not, how could I integrate this library with SBT?
I also considered using MathML (http://www.w3.org/Math/), but looks too verbose. Is there an editor you would recommend? Does MathML integrate well with Scaladoc?
Thank you for your help!
To follow on #mergeconflict answer, here is how I did it
As there is no proper solution, what I did is to implement a crawler that parse all generated html files, and replace any found "import tag" (see code below), by the import of the MathJax script:
lazy val mathFormulaInDoc = taskKey[Unit]("add MathJax script import in doc html to display nice latex formula")
mathFormulaInDoc := {
val apiDir = (doc in Compile).value
val docDir = apiDir // /"some"/"subfolder" // in my case, only api/some/solder is parsed
// will replace this "importTag" by "scriptLine
val importTag = "##import MathJax"
val scriptLine = "<script type=\"text/javascript\" src=\"https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML\"> </script>"
// find all html file and apply patch
if(docDir.isDirectory)
listHtmlFile(docDir).foreach { f =>
val content = Source.fromFile(f).getLines().mkString("\n")
if(content.contains(importTag)) {
val writer = new PrintWriter(f)
writer.write(content.replace(importTag, scriptLine))
writer.close()
}
}
}
// attach this task to doc task
mathFormulaInDoc <<= mathFormulaInDoc triggeredBy (doc in Compile)
// function that find html files recursively
def listHtmlFile(dir: java.io.File): List[java.io.File] = {
dir.listFiles.toList.flatMap { f =>
if(f.getName.endsWith(".html")) List(f)
else if(f.isDirectory) listHtmlFile(f)
else List[File]()
}
}
As you could see, this crawler task is attached to the doc task, to it is done automatically by sbt doc.
Here is an example of doc that will be rendered with formula
/**
* Compute the energy using formula:
*
* ##import MathJax
*
* $$e = m\times c^2$$
*/
def energy(m: Double, c: Double) = m*c*c
Now, it would be possible to improve this code. For example:
add the script import in the html head section
avoid reading the whole files (maybe add a rule that the import tag should be in the first few lines
add the script to the sbt package, and add it to the target/api folder using some suitable task
The short answer is: no. LaTeXTaglet is made possible by the JavaDoc Taglet API. There is no equivalent in Scaladoc, therefore no clean solution.
However, I can think of a hack that might be easy enough to do:
There's a library called MathJax, which looks for LaTeX-style math formulae in an HTML page and dynamically renders it in place. I've used it before, it's pretty nice; all you have to do is include the script. So you could do two things:
Edit and rebuild the Scaladoc source to include MathJax, or...
Write a little post-processor crawl all of Scaladoc's HTML output after it runs, and inject MathJax into each file.
That way, you could just write LaTeX formulae directly in your Scala comments and they should be rendered in the browser. Of course if you wanted a non-hacky solution, I'd suggest you create a taglet-like API for Scaladoc ;)
The forthcoming scala3 aka Dotty has in-built support for markdown which allows rendering simple math formulas using a subset of Latex.
I solved this by using the same approach as Spark did.
Put this JavaScript in a file somewhere in your project:
// From Spark, licensed APL2
// https://github.com/apache/spark/commit/36827ddafeaa7a683362eb8da31065aaff9676d5
function injectMathJax() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.onload = function(){
MathJax.Hub.Config({
displayAlign: "left",
tex2jax: {
inlineMath: [ ["$", "$"], ["\\\\(","\\\\)"] ],
displayMath: [ ["$$","$$"], ["\\[", "\\]"] ],
processEscapes: true,
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'a']
}
});
};
script.src = ('https:' == document.location.protocol ? 'https://' : 'http://') +
'cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML';
document.getElementsByTagName('head')[0].appendChild(script);
}
document.addEventListener('DOMContentLoaded', injectMathJax)
and this little bit into your build.sbt:
lazy val injectMathJax = taskKey[Unit]("Injects MathJax Javascript into Scaladoc template.js")
injectMathJax := {
val docPath = (Compile / doc).value
val templateJsOutput = docPath / "lib" / "template.js"
streams.value.log.info(s"Adding MathJax initialization to $templateJsOutput")
// change this path, obviously
IO.append(templateJsOutput, IO.readBytes(file("doc/static/js/mathjax_init.js")))
},
injectMathJax := (injectMathJax triggeredBy (Compile / doc)).value
I'll eventually get around to building and publicly releasing a plugin for this, as I'm likely going to be using Scala 2.x for a very long time.
Caveats to this approach:
Formulae must be in $ or $$ in Scaladoc comments.
It's best to further enclose them in the comment with another element. I've been using <blockquote>.
For at least the Scaladoc included with Scala 2.11.x, a formula will only show on class, object, and trait top-level symbols. Something in the toggle to show the full comment breaks when MathJax-inject elements are present. I've not figured it out yet, but if I do, I'll submit a patch to Scaladoc directly.
Example:
/**
* A Mean Absolute Scaled Error implementation
*
* Non-seasonal MASE formula:
* <blockquote>
* $$
* \mathrm{MASE} = \mathrm{mean}\left( \frac{\left| e_j \right|}{\frac{1}{T-1}\sum_{t=2}^T \left| Y_t-Y_{t-1}\right|} \right) = \frac{\frac{1}{J}\sum_{j}\left| e_j \right|}{\frac{1}{T-1}\sum_{t=2}^T \left| Y_t-Y_{t-1}\right|}
* $$
* </blockquote>
**/
object MeanAbsoluteScaledError {
I am using Gervill to create a soundbank with instruments. I've recorded a sample for each tone pitch and now I'd like to put these samples into one instrument.
The documentation that I used so far are tests from the openjdk6 source code. Apart from that I found an example by Karl Helgason, that helped greatly. The example loads an audio file into a soundbank however it only uses one sample per instrument. I've modified his example file and when I use the sound bank for replay, it seems that only one sample is used and pitched according to the requested tone pitch. In contrast I want to use a specific sample per tone pitch.
I suspect that my for-loop is constructed around the wrong parts of the method and that an additional sample is overwriting the formerly saved one.
My question is which parts should every sample have separately: The layer? Or the region? Both? Unfortunately Gervill terminology seems to be slightly different from another one that I found, so I am a bit confused.
I've used the following source code (I left the copyright note in the altered source code, I am not a lawyer, so I am not sure if this is the right thing to do.):
/*
* Copyright (c) 2007 by Karl Helgason
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package midiplay;
import com.sun.media.sound.*;
import java.io.File;
import java.io.IOException;
import javax.sound.midi.Patch;
import javax.sound.sampled.*;
public class MakeSoundfont {
public SF2Soundbank CreateSoundbank()
throws UnsupportedAudioFileException, IOException {
SF2Soundbank sf2 = new SF2Soundbank();
String[] fnames = new String[]{"C.wav", "Cs.wav", "D.wav", "Ds.wav"};
SF2Layer layer = new SF2Layer(sf2);
layer.setName("fname Layer");
sf2.addResource(layer);
int i = 0;
for (String fname : fnames) {
File audiofile = new File("./" + fname);
AudioInputStream audiostream = AudioSystem
.getAudioInputStream(audiofile);
AudioFormat format = new AudioFormat(audiostream.getFormat()
.getSampleRate(), 16, 2, true, false);
AudioInputStream convaudiostream = AudioSystem.getAudioInputStream(
format, audiostream);
/*
* Read the content of the file into a byte array.
*/
int datalength = (int) convaudiostream.getFrameLength()
* format.getFrameSize();
byte[] data = new byte[datalength];
convaudiostream.read(data, 0, data.length);
audiostream.close();
/*
* Create SoundFont2 sample.
*/
SF2Sample sample = new SF2Sample(sf2);
sample.setName(fname);
sample.setData(data);
sample.setSampleRate((long) format.getSampleRate());
sample.setOriginalPitch(60 + i);
sf2.addResource(sample);
i++;
/*
* Create region for layer.
*/
SF2LayerRegion region = new SF2LayerRegion();
region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);
region.setSample(sample);
layer.getRegions().add(region);
}
/*
* Create SoundFont2 instrument.
*/
SF2Instrument ins = new SF2Instrument(sf2);
ins.setName("Back Instrument");
ins.setPatch(new Patch(0, 0));
sf2.addInstrument(ins);
/*
* Create region for instrument.
*/
SF2InstrumentRegion insregion = new SF2InstrumentRegion();
insregion.setLayer(layer);
ins.getRegions().add(insregion);
return sf2;
}
}
EDIT: I seem to listen to all the samples at once. They are played at the same time, so I just realized the following: I am only setting the original pitch of the sample, but nowhere do I set the scope, i.e. I do not assign the samples to certain midi keys. Where can I do that?
I found the solution myself after reading some Gervill source code. Using GENERATOR_KEYRANGE one can define the range of tone pitches for a specific sample:
SF2LayerRegion region = new SF2LayerRegion();
region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000);
region.putBytes(SF2Region.GENERATOR_KEYRANGE, new byte[]{(byte)(60+i),(byte)(60+i)});
i++;
region.setSample(sample);
layer.getRegions().add(region);