master
branch), it happens from time to time that Emacs crashes after an update – but not often enough that I can remember how to provide enough details for maintainers to investigate.
So here are some notes on how to proceed.
First compile Emacs with enough debugging information: this requires the '-O0 -g3'
flags to be passed to configure
:
CFLAGS="-g3 -O0" CXXFLAGS="-g3 -O0" ./configure --with-cairo --with-modules . . .
make && sudo make install
(You don’t have to make install
, but the following assumes you have.
To execute with gdb
:
gdb emacs
gdb
starts, you can then run Emacs, passing arguments as well by calling run
at the prompt, and appending the args:
(gdb) run -Q --load init-ido.el
This starts emacs with a init file (here init-ido.el
) that you need to create, and which typically would contain the recipe producing the issue. A full backtrace can be obtained by running the following command:
(gdb) bt full
To also get a Lisp backtrace, you need to use src/.gdbinit
, by running gdb in the src
directory. The Lisp backtrace can be obtained by executing:
(gdb) xbacktrace
To set a breakpoint, you can run the following – prior to running Emacs, if needs be:
(gdb) b Factive_minibuffer_window
You can then print the value of various variables, using the p
command:
(gdb) p minibuf_level
$1 = 0
You may need to select the correct frame first to be able to view the relevant variables:
(gdb) select-frame 2
To report the bug you can gather all these details, and add them to a bug report that you can kick off with M-x report-emacs-bug
in Emacs). Hopefully this will help everyone save some time next time another nasty crash occurs!
The ISO standard defines the A series as follows:
Size | Format |
---|---|
0 | 841 × 1189 |
1 | 594 × 841 |
2 | 420 × 594 |
3 | 297 × 420 |
4 | 210 × 297 |
5 | 148 × 210 |
6 | 105 × 148 |
7 | 74 × 105 |
8 | 52 × 74 |
9 | 37 × 52 |
10 | 26 × 37 |
You’ll notice that the height of a given size is the width of the previous size; a paper size is defined by “halving the preceding paper size across the larger dimension.” The base size is A0, whose area is 1m² and ratio 1:√2.
The formula given by Wikipedia gives for size i is:
$$
\alpha_A \times (2^{-\frac{i+1}{2}}) \qquad \mathrm{by} \qquad \alpha_A \times (2^{-\frac{i}{2}})
$$
In Clojure this becomes:
(defn iso-aseries-size [size]
{:size (str "A" size)
:width (* alpha-a (Math/pow 2 (- (/ (inc size) 2))) 1000.0)
:height (* alpha-a (Math/pow 2 (- (/ size 2))) 1000.0)})
with the following:
(defn fourth-root [n] (Math/sqrt (Math/sqrt n)))
(def alpha-a (fourth-root 2))
Trying our formula, we get for the following paper sizes from A0 to A10:
pdfdata.paper> (map #(iso-aseries-size %) (range 11))
;; => ({:size "A0", :width 840.8964152537146, :height 1189.2071150027211}
{:size "A1", :width 594.6035575013606, :height 840.8964152537146}
{:size "A2", :width 420.4482076268573, :height 594.6035575013606}
{:size "A3", :width 297.3017787506803, :height 420.4482076268573}
{:size "A4", :width 210.22410381342866, :height 297.3017787506803}
{:size "A5", :width 148.65088937534014, :height 210.22410381342866}
{:size "A6", :width 105.11205190671433, :height 148.65088937534014}
{:size "A7", :width 74.32544468767007, :height 105.11205190671433}
{:size "A8", :width 52.556025953357164, :height 74.32544468767007}
{:size "A9", :width 37.162722343835036, :height 52.556025953357164}
{:size "A10", :width 26.278012976678582, :height 37.162722343835036})
If we round correctly, we get A5 595 mm × 841 mm, and other sizes also look wrong:
pdfdata.paper> (map #(iso-aseries-size %) (range 11))
;; => ({:size "A0", :width 841, :height 1189}
{:size "A1", :width 595, :height 841}
{:size "A2", :width 420, :height 595}
{:size "A3", :width 297, :height 420}
{:size "A4", :width 210, :height 297}
{:size "A5", :width 149, :height 210}
{:size "A6", :width 105, :height 149}
{:size "A7", :width 74, :height 105}
{:size "A8", :width 53, :height 74}
{:size "A9", :width 37, :height 53}
{:size "A10", :width 26, :height 37})
OK. So digging a bit more, another site gives this other formula
For size n,
It’s not difficult to see this formula is actually identical to the previous one ($2^\{frac{1}{4} = \sqrt4{2}$), but for the fun of writing in Clojure, here it is:
(defn iso-aseries-size [size]
(if (even? size)
{:size (str "A" size)
:width (/ 1000.0 (* (Math/pow 2.0 (/ size 2)) (fourth-root 2)))
:height (/ (* 1000.0 (fourth-root 2)) (Math/pow 2 (/ size 2)))}
{:size (str "A" size)
:width (/ (* 1000.0 (fourth-root 2)) (Math/pow 2 (/ (inc size) 2)))
:height (/ 1000.0 (* (Math/pow 2.0 (/ (dec size) 2)) (fourth-root 2)))}))
So how do we correctly calculate the dimensions? We just go back to the basic principles: set the width of the previous size as the height of the new size, calculate the area of a given size by halving the area of the previous size, round down, and divive by height to get the new width:
(defn iso-aseries-size [size]
(if (= size 0)
{:size (str "A" size)
:height (round (* 1000.0 alpha-a))
:width (round (* 1000.0 (/ 1.0 alpha-a)))}
(let [prev (iso-aseries-size (dec size))
area (* (:width prev) (:height prev))
new-area (floor (/ area 2.0))]
{:size (str "A" size)
:height (:width prev)
:width (floor (/ new-area (:width prev)))})))
which returns the correct dimensions:
pdfdata.paper> (map #(iso-aseries-size %) (range 11))
;; => ({:size "A0", :height 1189, :width 841}
{:size "A1", :height 841, :width 594}
{:size "A2", :height 594, :width 420}
{:size "A3", :height 420, :width 297}
{:size "A4", :height 297, :width 210}
{:size "A5", :height 210, :width 148}
{:size "A6", :height 148, :width 105}
{:size "A7", :height 105, :width 74}
{:size "A8", :height 74, :width 52}
{:size "A9", :height 52, :width 37}
{:size "A10", :height 37, :width 26})
]]>
(Bon, apparemment, il fallait mettre à jour la base de données, parce que comme quoi MySQL 4, c’est plus à la mode, alors je m’y suis mis. Je savais que j’allais me déguster du double-encodage UTF-8, je n’ai pas été déçu…)
]]>I won’t go into too much details (you probably already know about Maven’s dependency management) here, but will quickly describe what I think is important to know before using Maven. Maven helps you build a project. The way it does that is through the build lifecycle and the plugins.
The lifecycle is made of phases that you can call explicitly on the command line, for example:
mvn package
package
is a phase part of the default build lifecycle, like compile
or deploy
. All the phases of the default lifecycle can be found in the reference. At each phase, Maven calls a goal in a plugin that does something for you. For example, the maven-compiler-plugin
has a compile
goal that compiles your java code during the compile
phase of the lifecycle. You can also explicitly call a plugin on the command line, like:
mvn clean:clean
which calls the clean
goal on the maven-clean-plugin
. By default this goal is bound to the clean
phase, so you can call it by executing mvn clean
. You can call any plugin by using its group id, its artifact id, its version and the goal you want to execute, e.g.:
mvn org.codehaus.mojo:versions-maven-plugin:2.1:set -DnewVersion=1.2.3
(A plugin named blah-maven-plugin
can be called by the shortened version of its name, blah
. See also the Guide to Developing Java Plugins)
To “bind” a plugin goal to a phase, you just need to define your plugin in your pom.xml, and define its execution
to a phase of the lifecycle:
<plugin>
<groupId>org.mirah.maven</groupId>
<artifactId>maven-mirah-plugin</artifactId>
<version>1.1-SNAPSHOT</version>
<executions>
<execution>
<phase>compile</phase>
<goals><goal>compile</goal></goals>
</execution>
</executions>
</plugin>
Here we are attaching the mirah compile
goal to the compile
phase of the lifecycle. When Maven executes the compile
phase, it will the compile the Mirah code for us.
That’s pretty much the most important stuff you need to understand to get going with Maven: build lifecycle and plugin goals. Once you understand this, the hardest part is to find the plugin that does what you want, and going through its documentation to see how to configure it.
In no particular order.
Use the help
goal for that plugin, for example:
mvn dependency:help
You can also use the @help@ plugin:
mvn help:describe -Dplugin=de.saumya.mojo:rake-maven-plugin:1.0.0-rc3
Check out this project in GitHub. After a while it becomes impossible to do without.
To list all the dependencies of the project:
mvn dependency:list
To display a tree of the transitive dependencies of the project:
mvn dependency:tree
mvn dependency:sources
Use:
mvn dependency:copy-dependencies -DoutputDirectory=/tmp
This copies all the dependencies into the /tmp
folder. To do this automatically during the package
phase, add the plugin to your pom, as follows:
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
See the maven-dependency-plugin page for more details.
mvn dependency:purge-local-repository
By default, purge-local-repository
will then re-resolve your dependencies. If you don’t want that behaviour, add -DreResolve=false
on the command line.
This is particularly handy when, for some reason, Maven is choking on a dependency that was temporarily unavailable, stubbornly refusing to download it again.
To find the coordinates of a dependency, you can use http://mvnrepository.com. You can also use a ruby gem I have written, called mvnizer. Once installed (gem install mvnizer
), you can easily search for existing artefacts:
$ mvnizer search slf4j-simple
org.slf4j:slf4j-simple:1.7.5:jar
com.googlecode.sli4j:sli4j-slf4j-simple:2.0:jar
You can copy/paste the coordinates from mvnrepository. You can also use mvnizer
:
mvnizer add org.slf4j:slf4j-simple:1.7.5:jar
Beware, mvnizer
applies its own formatting to your pom file.
mvn versions:use-latest-releases
See versions-maven-plugin page for more details.
mvn versions:display-plugin-updates
See versions-maven-plugin page for more details.
Use:
mvn versions:set -DnewVersion=1.2.3
Generally speaking, for anything that deals with the version of your project (and its submodules) or its dependencies, use versions-maven-plugin.
Use build-helper-maven-plugin. Example:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/it/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Use properties-maven-plugin. Example:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>example.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
Properties can then be stored in example.properties
as key/value pairs:
key1=value1
key2=value2
Main-Class
in the MANIFEST file?Use the maven-jar-plugin.
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>org.example.YourMainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Use the maven-shade-plugin. Example:
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.example.YourMainClass</mainClass>
</transformer>
</transformers>
<artifactSet>
<excludes>
<exclude>rubygems:*</exclude>
</excludes>
</artifactSet>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
Use finalName
:
<build>
<finalName>new-name</finalName>
. . .
</build>
Bind the run
goal of the jetty-maven-plugin
to the pre-integration-test
phase, and bind stop
to the post-integration-test
phase:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.14.v20131031</version>
<configuration>
<stopKey>ungeduldig</stopKey>
<stopPort>9995</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
]]>
As part of these plugins, the rake-maven-plugin
allows you to call Rake tasks in a project, which can be useful if the build tool of your comapny is based on Java, but your project is Ruby-based (and you don’t want to use JRuby). To illustrate its use, we’ll use a very straightforward Rakefile:
task :do_that_thing do
puts " *** RAKE RUNNING ***"
end
It has a unique task, do_that_thing
, that we’ll call from Maven. In the pom, you need to add the rake-maven-plugin
:
<plugin>
<groupId>de.saumya.mojo</groupId>
<artifactId>rake-maven-plugin</artifactId>
<version>1.0.0-rc3</version>
We are now going to define its execution, and tie it to the verify
lifecycle step (you can choose what step you want):
<executions>
<execution>
<id>run-spec</id>
<phase>verify</phase>
<goals>
<goal>rake</goal>
</goals>
<configuration>
<args>do_that_thing</args>
</configuration>
</execution>
</executions>
</plugin>
The goal we are calling on the Rake plugin is rake
, and the name of the Rake task is passed in args
. As we are using Rake, we need to define a gem
dependency to rake
. To do so, you first need to add the rubygems
Maven repo provided by TorqueBox:
<repositories>
<repository>
<id>rubygems-releases</id>
<url>http://rubygems-proxy.torquebox.org/releases</url>
</repository>
</repositories>
You can then add the dependency to the rake
gem:
<dependencies>
<dependency>
<groupId>rubygems</groupId>
<artifactId>rake</artifactId>
<version>10.1.0</version>
<type>gem</type>
</dependency>
</dependencies>
Running mvn verify
will then execute the Rake task.
The full example can be found on my GitHub repo, rake-maven-example.
To get more details about the Rake maven plugin (or any plugin at all in general), the help
plugin comes, as usual, quite handy:
mvn help:describe -Dplugin=de.saumya.mojo:rake-maven-plugin:1.0.0-rc3 -Ddetail
]]>
The “heart” of the app is the Spring MVC controller which must be annotated with the Controller
annotation, and its request path defined with the RequestMapping
annotation:
We also put the class in the com.weblogism.myapp
package, we’ll see why in a second.
The Spring MVC configuration is pretty much “standard”:
It defines the component-scan
tag that will look for all the classes annotated with Controller
in the com.weblogism.myapp
; you now see why we used java_package
for our controller.
The compiling and packaging is done by Maven. Again, nothing really extraordinary in the pom.xml
. The only unconventional feature is the use of the jruby-maven-plugin
to compile our JRuby class into a Java class:
It generates its output into target/generate-sources/jruby
, and compiles out class into target/classes
, like any other Java class. The output of the build is a war file that can be deployed in a Java EE container.
To see our amazing app in action, run Jetty:
mvn jetty:run
Once Jetty is up, you can access the app at http://localhost:8080/welcome.html
]]>It started when I decided to upgrade my cucumber-jvm example to the latest version (1.1.3). Quickly after upgrading, I hit that error:
java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.get(ArrayList.java:324)
at gherkin.formatter.JSONFormatter.getFeatureElement(JSONFormatter.java:199)
at gherkin.formatter.JSONFormatter.addHook(JSONFormatter.java:156)
at gherkin.formatter.JSONFormatter.before(JSONFormatter.java:147)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
This is known issue, that has already been fixed in gherkin.
So I rebuilt gherkin locally, thinking it would solve all my problems, and I was still the exact same error, at the same line number. After changing version, deleting the jar from the Maven repository, I was still getting the same error, so it was clear that the class was being pulled from somewhere else.
It turns out the jar was being pulled from cucumber-picocontainer
, which uses shade to create an über-jar with its dependencies, including gherkin. How did I figure that out? Using this piece of code:
URL location = JSONFormatter.class.getProtectionDomain().getCodeSource().getLocation();
System.err.println(location.getPath());
The solution to the problem is therefore to rebuild gherkin, then cucumber-picocontainer, and you’re sorted.
Alternatively you can also just rebuild gherkin, and then make sure it is defined before cucumber-picocontainer
:
]]><dependency> <groupId>info.cukes</groupId> <artifactId>gherkin</artifactId> <version>2.11.8</version> <scope>test</scope> </dependency> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-picocontainer</artifactId> <version>1.1.3</version> <scope>test</scope> </dependency>