# HG changeset patch
# User wenzelm
# Date 1263245487 -3600
# Node ID 502f9096748313427bbd2658bd7da85f038bcba7
# Parent c1509b9d624f56e00a34e24be2a04f1f77e9807f# Parent d5bb188b9f9d18720a4ce7c117a30100eee86ee2
merged with converted/relocated copy of http://isabelle.in.tum.de/repos/isabelle-jedit/rev/93d884afa74b
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/README_BUILD
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/README_BUILD Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,73 @@
+
+Requirements to build from sources
+==================================
+
+* Proper Java JRE/JDK from Sun, e.g. 1.6.0_17
+ http://java.sun.com/javase/downloads/index.jsp
+
+* Netbeans 6.7
+ http://www.netbeans.org/downloads/index.html
+
+* Scala for Netbeans: version 6.7v1 for NB 6.7
+ http://sourceforge.net/project/showfiles.php?group_id=192439&package_id=256544
+ http://blogtrader.net/dcaoyuan/category/NetBeans
+ http://wiki.netbeans.org/Scala
+
+* jEdit 4.3 (final)
+ http://www.jedit.org/
+
+ Netbeans Project "jEdit": install official sources as ./contrib/jEdit/.
+
+* jEdit plugins:
+ Netbeans Library "SideKick" = $HOME/.jedit/jars/SideKick.jar
+ Netbeans Library "ErrorList" = $HOME/.jedit/jars/ErrorList.jar
+ Netbeans Library "Hyperlinks" = $HOME/.jedit/jars/Hyperlinks.jar
+
+* Cobra Renderer 0.98.4
+ http://lobobrowser.org/cobra.jsp
+ Netbeans Library "Cobra-Renderer" = .../cobra.jar
+ Netbenas Library "Rhino-JavaScript" = .../js.jar
+
+* Isabelle/Pure Scala components
+ Netbeans Library "Isabelle-Pure" = ~~/lib/classes/Pure.jar
+
+
+Running the application within Netbeans
+=======================================
+
+* Project properties: add "Run" argument like
+ -noserver -nobackground -settings=/home/makarius/isabelle/isabelle-jedit/dist
+
+* The Isabelle environment is obtained automatically via
+ "$ISABELLE_HOME/bin/isabelle getenv", where ISABELLE_HOME is determined as follows:
+
+ (1) via regular Isabelle settings,
+ e.g. "isabelle env netbeans"
+
+ (2) or via ISABELLE_HOME from raw process environment,
+ e.g. "env ISABELLE_HOME=.../Isabelle netbeans"
+
+ (3) or via JVM system properties (cf. "Run / VM Options")
+ e.g. -Disabelle.home=.../Isabelle
+
+
+Misc notes
+==========
+
+- Netbeans config/Editors/Preferences/...-CustomPreferences.xml
+
+
+
+
+
+-----------------------------------------------------------------------
+To run jedit with remote debugging enabled, I use the following
+command: "java
+-agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address=XXXX
+-jar jedit.jar"
+
+where XXXX is any open port number you wish. The above invocation
+works for Sun's JDK 5.0. There's an alternate incantation for earlier
+releases. (See
+http://java.sun.com/j2se/1.5.0/docs/guide/jpda/conninv.html)
+-----------------------------------------------------------------------
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/build.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/build.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,102 @@
+
+
+
+
+
+ Builds, tests, and runs the project Isabelle-jEdit.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/contrib/jEdit/build-nb.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/contrib/jEdit/build-nb.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This target can only run inside the NetBeans IDE.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/contrib/jEdit/nbproject/project.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/contrib/jEdit/nbproject/project.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,118 @@
+
+
+ org.netbeans.modules.ant.freeform
+
+
+ jEdit
+
+
+
+ jEdit
+
+ build-nb.xml
+
+
+
+
+ .
+ UTF-8
+
+
+
+ java
+ .
+ build/** doc/** icons/** macros/** modes/** package-files/**
+ UTF-8
+
+
+
+
+
+ build
+
+
+
+ clean
+
+
+
+ docs-javadoc
+
+
+
+ run
+
+
+
+ clean
+ build
+
+
+
+ debug-nb
+
+
+
+ jar
+ build/jEdit.jar
+
+ build
+
+
+
+
+
+ .
+ build/** doc/** icons/** macros/** modes/** package-files/**
+
+
+ ${ant.script}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .
+ .
+ build/jEdit.jar
+ 1.5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/dist-template/etc/settings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/dist-template/etc/settings Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,9 @@
+JEDIT_HOME="$COMPONENT"
+
+JEDIT_JAVA_OPTIONS="-Xms128m -Xmx512m -Xss2m"
+#JEDIT_JAVA_OPTIONS="-server -Xms128m -Xmx1024m -Xss4m"
+JEDIT_OPTIONS="-reuseview -noserver -nobackground"
+
+ISABELLE_JEDIT_OPTIONS="-m xsymbols -m no_brackets -m no_type_brackets"
+
+ISABELLE_TOOLS="$ISABELLE_TOOLS:$JEDIT_HOME/lib/Tools"
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/dist-template/lib/Tools/jedit
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/dist-template/lib/Tools/jedit Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,117 @@
+#!/usr/bin/env bash
+#
+# Author: Makarius
+#
+# DESCRIPTION: Isabelle/jEdit interface wrapper
+
+
+## diagnostics
+
+PRG="$(basename "$0")"
+
+usage()
+{
+ echo
+ echo "Usage: isabelle $PRG [OPTIONS] [FILES ...]"
+ echo
+ echo " Options are:"
+ echo " -J OPTION add JVM runtime option"
+ echo " (default JEDIT_JAVA_OPTIONS=$JEDIT_JAVA_OPTIONS)"
+ echo " -d enable debugger"
+ echo " -j OPTION add jEdit runtime option"
+ echo " (default JEDIT_OPTIONS=$JEDIT_OPTIONS)"
+ echo " -l NAME logic image name (default ISABELLE_LOGIC=$ISABELLE_LOGIC)"
+ echo " -m MODE add print mode for output"
+ echo
+ echo "Start jEdit with Isabelle plugin setup and opens theory FILES"
+ echo "(default ~/Scratch.thy)."
+ echo
+ exit 1
+}
+
+fail()
+{
+ echo "$1" >&2
+ exit 2
+}
+
+
+## process command line
+
+# options
+
+JEDIT_LOGIC="$ISABELLE_LOGIC"
+JEDIT_PRINT_MODE=""
+
+getoptions()
+{
+ OPTIND=1
+ while getopts "J:dj:l:m:" OPT
+ do
+ case "$OPT" in
+ J)
+ JAVA_ARGS["${#JAVA_ARGS[@]}"]="$OPTARG"
+ ;;
+ d)
+ JAVA_ARGS["${#JAVA_ARGS[@]}"]="-Xdebug"
+ JAVA_ARGS["${#JAVA_ARGS[@]}"]="-Xrunjdwp:transport=dt_socket,server=y,suspend=n"
+ ;;
+ j)
+ ARGS["${#ARGS[@]}"]="$OPTARG"
+ ;;
+ l)
+ JEDIT_LOGIC="$OPTARG"
+ ;;
+ m)
+ if [ -z "$JEDIT_PRINT_MODE" ]; then
+ JEDIT_PRINT_MODE="$OPTARG"
+ else
+ JEDIT_PRINT_MODE="$JEDIT_PRINT_MODE,$OPTARG"
+ fi
+ ;;
+ \?)
+ usage
+ ;;
+ esac
+ done
+}
+
+declare -a JAVA_ARGS; eval "JAVA_ARGS=($JEDIT_JAVA_OPTIONS)"
+[ -n "$SCALA_HOME" ] && JAVA_ARGS["${#JAVA_ARGS[@]}"]="-Dscala.home=$SCALA_HOME"
+
+declare -a ARGS; eval "ARGS=($JEDIT_OPTIONS)"
+
+declare -a OPTIONS; eval "OPTIONS=($ISABELLE_JEDIT_OPTIONS)"
+getoptions "${OPTIONS[@]}"
+
+getoptions "$@"
+shift $(($OPTIND - 1))
+
+
+# args
+
+if [ "$#" -eq 0 ]; then
+ ARGS["${#ARGS[@]}"]="Scratch.thy"
+else
+ while [ "$#" -gt 0 ]; do
+ ARGS["${#ARGS[@]}"]="$(jvmpath "$1")"
+ shift
+ done
+fi
+
+
+## main
+
+case "$JEDIT_LOGIC" in
+ /*)
+ ;;
+ */*)
+ JEDIT_LOGIC="$(pwd -P)/$JEDIT_LOGIC"
+ ;;
+esac
+
+export JEDIT_LOGIC JEDIT_PRINT_MODE
+
+exec "$ISABELLE_TOOL" java "${JAVA_ARGS[@]}" \
+ -jar "$(jvmpath "$JEDIT_HOME/jedit.jar")" \
+ "-settings=$(jvmpath "$ISABELLE_HOME_USER/jedit")" "${ARGS[@]}"
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/dist-template/modes/isabelle-session.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/dist-template/modes/isabelle-session.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (*
+ *)
+
+
+ {*
+ *}
+
+
+ `
+ `
+
+
+ "
+ "
+
+
+ session
+ parent
+ imports
+ uses
+ options
+ dependencies
+
+
+
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/dist-template/modes/isabelle.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/dist-template/modes/isabelle.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (*
+ *)
+
+
+ {*
+ *}
+
+
+ `
+ `
+
+
+ "
+ "
+
+
+ header
+ theory
+ imports
+ uses
+ begin
+ end
+
+
+
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/dist-template/properties/jedit.props
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/dist-template/properties/jedit.props Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,191 @@
+#jEdit properties
+buffer.deepIndent=false
+buffer.encoding=UTF-8-Isabelle
+buffer.indentSize=2
+buffer.lineSeparator=\n
+buffer.maxLineLen=100
+buffer.noTabs=true
+buffer.sidekick.keystroke-parse=true
+buffer.tabSize=2
+delete-line.shortcut=A+d
+delete.shortcut2=C+d
+encoding.opt-out.Big5-HKSCS=true
+encoding.opt-out.Big5=true
+encoding.opt-out.COMPOUND_TEXT=true
+encoding.opt-out.EUC-JP=true
+encoding.opt-out.EUC-KR=true
+encoding.opt-out.GB18030=true
+encoding.opt-out.GB2312=true
+encoding.opt-out.GBK=true
+encoding.opt-out.IBM-Thai=true
+encoding.opt-out.IBM00858=true
+encoding.opt-out.IBM01140=true
+encoding.opt-out.IBM01141=true
+encoding.opt-out.IBM01142=true
+encoding.opt-out.IBM01143=true
+encoding.opt-out.IBM01144=true
+encoding.opt-out.IBM01145=true
+encoding.opt-out.IBM01146=true
+encoding.opt-out.IBM01147=true
+encoding.opt-out.IBM01148=true
+encoding.opt-out.IBM01149=true
+encoding.opt-out.IBM037=true
+encoding.opt-out.IBM1026=true
+encoding.opt-out.IBM1047=true
+encoding.opt-out.IBM273=true
+encoding.opt-out.IBM277=true
+encoding.opt-out.IBM278=true
+encoding.opt-out.IBM280=true
+encoding.opt-out.IBM284=true
+encoding.opt-out.IBM285=true
+encoding.opt-out.IBM297=true
+encoding.opt-out.IBM420=true
+encoding.opt-out.IBM424=true
+encoding.opt-out.IBM437=true
+encoding.opt-out.IBM500=true
+encoding.opt-out.IBM775=true
+encoding.opt-out.IBM850=true
+encoding.opt-out.IBM852=true
+encoding.opt-out.IBM855=true
+encoding.opt-out.IBM857=true
+encoding.opt-out.IBM860=true
+encoding.opt-out.IBM861=true
+encoding.opt-out.IBM862=true
+encoding.opt-out.IBM863=true
+encoding.opt-out.IBM864=true
+encoding.opt-out.IBM865=true
+encoding.opt-out.IBM866=true
+encoding.opt-out.IBM868=true
+encoding.opt-out.IBM869=true
+encoding.opt-out.IBM870=true
+encoding.opt-out.IBM871=true
+encoding.opt-out.IBM918=true
+encoding.opt-out.ISO-2022-CN=true
+encoding.opt-out.ISO-2022-JP-2=true
+encoding.opt-out.ISO-2022-JP=true
+encoding.opt-out.ISO-2022-KR=true
+encoding.opt-out.ISO-8859-13=true
+encoding.opt-out.ISO-8859-2=true
+encoding.opt-out.ISO-8859-3=true
+encoding.opt-out.ISO-8859-4=true
+encoding.opt-out.ISO-8859-5=true
+encoding.opt-out.ISO-8859-6=true
+encoding.opt-out.ISO-8859-7=true
+encoding.opt-out.ISO-8859-8=true
+encoding.opt-out.ISO-8859-9=true
+encoding.opt-out.JIS_X0201=true
+encoding.opt-out.JIS_X0212-1990=true
+encoding.opt-out.KOI8-R=true
+encoding.opt-out.KOI8-U=true
+encoding.opt-out.Shift_JIS=true
+encoding.opt-out.TIS-620=true
+encoding.opt-out.UTF-16=true
+encoding.opt-out.UTF-16BE=true
+encoding.opt-out.UTF-16LE=true
+encoding.opt-out.UTF-32=true
+encoding.opt-out.UTF-32BE=true
+encoding.opt-out.UTF-32LE=true
+encoding.opt-out.X-UTF-32BE-BOM=true
+encoding.opt-out.X-UTF-32LE-BOM=true
+encoding.opt-out.windows-1250=true
+encoding.opt-out.windows-1251=true
+encoding.opt-out.windows-1253=true
+encoding.opt-out.windows-1254=true
+encoding.opt-out.windows-1255=true
+encoding.opt-out.windows-1256=true
+encoding.opt-out.windows-1257=true
+encoding.opt-out.windows-1258=true
+encoding.opt-out.windows-31j=true
+encoding.opt-out.x-Big5-Solaris=true
+encoding.opt-out.x-EUC-TW=true
+encoding.opt-out.x-IBM1006=true
+encoding.opt-out.x-IBM1025=true
+encoding.opt-out.x-IBM1046=true
+encoding.opt-out.x-IBM1097=true
+encoding.opt-out.x-IBM1098=true
+encoding.opt-out.x-IBM1112=true
+encoding.opt-out.x-IBM1122=true
+encoding.opt-out.x-IBM1123=true
+encoding.opt-out.x-IBM1124=true
+encoding.opt-out.x-IBM1381=true
+encoding.opt-out.x-IBM1383=true
+encoding.opt-out.x-IBM33722=true
+encoding.opt-out.x-IBM737=true
+encoding.opt-out.x-IBM834=true
+encoding.opt-out.x-IBM856=true
+encoding.opt-out.x-IBM874=true
+encoding.opt-out.x-IBM875=true
+encoding.opt-out.x-IBM921=true
+encoding.opt-out.x-IBM922=true
+encoding.opt-out.x-IBM930=true
+encoding.opt-out.x-IBM933=true
+encoding.opt-out.x-IBM935=true
+encoding.opt-out.x-IBM937=true
+encoding.opt-out.x-IBM939=true
+encoding.opt-out.x-IBM942=true
+encoding.opt-out.x-IBM942C=true
+encoding.opt-out.x-IBM943=true
+encoding.opt-out.x-IBM943C=true
+encoding.opt-out.x-IBM948=true
+encoding.opt-out.x-IBM949=true
+encoding.opt-out.x-IBM949C=true
+encoding.opt-out.x-IBM950=true
+encoding.opt-out.x-IBM964=true
+encoding.opt-out.x-IBM970=true
+encoding.opt-out.x-ISCII91=true
+encoding.opt-out.x-ISO-2022-CN-CNS=true
+encoding.opt-out.x-ISO-2022-CN-GB=true
+encoding.opt-out.x-JIS0208=true
+encoding.opt-out.x-JISAutoDetect=true
+encoding.opt-out.x-Johab=true
+encoding.opt-out.x-MS932_0213=true
+encoding.opt-out.x-MS950-HKSCS=true
+encoding.opt-out.x-MacArabic=true
+encoding.opt-out.x-MacCentralEurope=true
+encoding.opt-out.x-MacCroatian=true
+encoding.opt-out.x-MacCyrillic=true
+encoding.opt-out.x-MacDingbat=true
+encoding.opt-out.x-MacGreek=true
+encoding.opt-out.x-MacHebrew=true
+encoding.opt-out.x-MacIceland=true
+encoding.opt-out.x-MacRoman=true
+encoding.opt-out.x-MacRomania=true
+encoding.opt-out.x-MacSymbol=true
+encoding.opt-out.x-MacThai=true
+encoding.opt-out.x-MacTurkish=true
+encoding.opt-out.x-MacUkraine=true
+encoding.opt-out.x-PCK=true
+encoding.opt-out.x-SJIS_0213=true
+encoding.opt-out.x-UTF-16LE-BOM=true
+encoding.opt-out.x-euc-jp-linux=true
+encoding.opt-out.x-eucJP-Open=true
+encoding.opt-out.x-iso-8859-11=true
+encoding.opt-out.x-mswin-936=true
+encoding.opt-out.x-windows-50220=true
+encoding.opt-out.x-windows-50221=true
+encoding.opt-out.x-windows-874=true
+encoding.opt-out.x-windows-949=true
+encoding.opt-out.x-windows-950=true
+encoding.opt-out.x-windows-iso2022jp=true
+encodingDetectors=BOM XML-PI buffer-local-property
+fallbackEncodings=UTF-8 ISO-8859-15 US-ASCII
+firstTime=false
+isabelle-protocol.dock-position=bottom
+isabelle-results.dock-position=bottom
+isabelle.activate.shortcut=CS+ENTER
+mode.isabelle.sidekick.showStatusWindow.label=true
+sidekick-tree.dock-position=right
+sidekick.buffer-save-parse=true
+sidekick.complete-delay=300
+tip.show=false
+view.antiAlias=standard
+view.blockCaret=true
+view.caretBlink=false
+view.eolMarkers=false
+view.extendedState=0
+view.font=IsabelleText
+view.fontsize=18
+view.fracFontMetrics=false
+view.gutter.fontsize=12
+view.middleMousePaste=true
+view.showToolbar=false
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/makedist
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/makedist Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+#
+# makedist -- make Isabelle/jEdit distribution
+
+## self references
+
+PRG=$(basename "$0")
+THIS=$(cd "$(dirname "$0")"; pwd)
+SUPER=$(cd "$THIS/.."; pwd)
+
+
+## diagnostics
+
+JEDIT_HOME="/home/isajedit/jedit-orig/4.3pre17"
+
+function usage()
+{
+ echo
+ echo "Usage: $PRG [OPTIONS]"
+ echo
+ echo " Options are:"
+ echo " -j DIR specify original jEdit distribution"
+ echo " (default: $JEDIT_HOME)"
+ echo
+ echo " Produce Isabelle/jEdit distribution from Netbeans build"
+ echo " in $THIS/dist"
+ echo
+ exit 1
+}
+
+fail()
+{
+ echo "$1" >&2
+ exit 2
+}
+
+
+## process command line
+
+# options
+
+while getopts "j:s:" OPT
+do
+ case "$OPT" in
+ j)
+ JEDIT_HOME="$OPTARG"
+ ;;
+ \?)
+ usage
+ ;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+
+
+# args
+
+[ "$#" -ne 0 ] && usage
+
+
+## main
+
+cd "$THIS/dist" || fail "Bad directory: $THIS/dist"
+
+
+# target name
+
+VERSION=$(basename "$JEDIT_HOME")
+JEDIT="jedit-${VERSION}"
+
+rm -rf "$JEDIT" jedit
+mkdir "$JEDIT"
+ln -s "$JEDIT" jedit
+
+
+# copy stuff
+
+[ "$JEDIT_HOME/jedit.jar" ] || fail "Bad original jEdit directory: $JEDIT_HOME"
+cp -R "$JEDIT_HOME/." "$JEDIT/."
+rm -rf "$JEDIT/jEdit" "$JEDIT/build-support"
+
+mkdir -p "$JEDIT/jars"
+cp -R jars/. "$JEDIT/jars/."
+
+cp -R "$THIS/dist-template/." "$JEDIT/."
+
+perl -i -e 'while (<>) { if (m/NAME="javacc"/) {
+ print qq,\n\n,;
+ print qq,\n\n,; }
+ print; }' "$JEDIT/modes/catalog"
+
+
+# build archive
+
+echo "${JEDIT}.tar.gz"
+tar czf "${JEDIT}.tar.gz" "$JEDIT" jedit
+ln -sf "${JEDIT}.tar.gz" jedit.tar.gz
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/manifest.mf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/manifest.mf Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/nbproject/build-impl.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/nbproject/build-impl.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,709 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+You must set SCALA_HOME or environment property and append "-J-Dscala.home=scalahomepath"
+property to the end of "netbeans_default_options" in NetBeansInstallationPath/etc/netbeans.conf to point to
+Scala installation directory.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set src.dir
+ Must set build.dir
+ Must set dist.dir
+ Must set build.classes.dir
+ Must set dist.javadoc.dir
+ Must set build.test.classes.dir
+ Must set build.test.results.dir
+ Must set build.classes.excludes
+ Must set dist.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+
+
+
+
+
+ java -cp "${run.classpath.with.dist.jar}" ${main.class}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+ java -jar "${dist.jar.resolved}"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must set fix.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+ Must select one file in the IDE or set test.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/nbproject/genfiles.properties
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/nbproject/genfiles.properties Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=d2379ac2
+build.xml.script.CRC32=2db9d955
+build.xml.stylesheet.CRC32=ca9d572e
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=8f41dcce
+nbproject/build-impl.xml.script.CRC32=69f2059c
+nbproject/build-impl.xml.stylesheet.CRC32=bc42a706@1.3.0
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/nbproject/project.properties
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/nbproject/project.properties Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,77 @@
+application.title=Isabelle-jEdit
+application.vendor=makarius
+application.args=-noserver -nobackground
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form,**/*.scala
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+# dist can be used as jEdits settings-directory;
+# jEdit searches for plugins in the 'jars' subdirectory
+# must include something like this to private.properties:
+# application.args=-noserver -nobackground -settings=/absolute/path/to/project/dist
+#
+dist.jar=${dist.dir}/jars/Isabelle-jEdit.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+file.reference.isabelle-jedit-src=src
+file.reference.jedit.jar=/home/makarius/lib/jedit/current/jedit.jar
+includes=**
+jar.compress=false
+java.platform.active=java_default_platform
+javac.classpath=\
+ ${reference.jEdit.build}:\
+ ${libs.Isabelle-Pure.classpath}:\
+ ${libs.Cobra-Renderer.classpath}:\
+ ${libs.Rhino-JavaScript.classpath}:\
+ ${libs.ErrorList.classpath}:\
+ ${libs.Hyperlinks.classpath}:\
+ ${libs.SideKick.classpath}:\
+ ${libs.Console.classpath}:\
+ ${libs.Scala-compiler.classpath}
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}:\
+ ${libs.junit.classpath}:\
+ ${libs.junit_4.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+main.class=org.gjt.sp.jedit.jEdit
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+platform.active=default_platform
+project.jEdit=contrib/jEdit
+reference.jEdit.build=${project.jEdit}/build/jEdit.jar
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+run.jvmargs=-Xms128m -Xmx512m
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=${file.reference.isabelle-jedit-src}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/nbproject/project.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/nbproject/project.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,24 @@
+
+
+ org.netbeans.modules.scala.project
+
+
+ Isabelle-jEdit
+ 1.6.5
+
+
+
+
+
+
+
+ jEdit
+ jar
+
+ build
+ clean
+ build
+
+
+
+
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/plugin/Isabelle.props
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/plugin/Isabelle.props Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,48 @@
+## Isabelle plugin properties
+##
+##:encoding=ISO-8859-1:
+
+#identification
+plugin.isabelle.jedit.Plugin.name=Isabelle
+plugin.isabelle.jedit.Plugin.author=Johannes Hölzl, Fabian Immler, Makarius Wenzel
+plugin.isabelle.jedit.Plugin.version=0.0.1
+plugin.isabelle.jedit.Plugin.description=Isabelle/Isar asynchronous proof processing
+
+#system parameters
+plugin.isabelle.jedit.Plugin.activate=startup
+plugin.isabelle.jedit.Plugin.usePluginHome=false
+
+#dependencies
+plugin.isabelle.jedit.Plugin.depend.0=jdk 1.6
+plugin.isabelle.jedit.Plugin.depend.1=jedit 04.03.17.00
+plugin.isabelle.jedit.Plugin.depend.2=plugin errorlist.ErrorListPlugin 1.7
+plugin.isabelle.jedit.Plugin.depend.3=plugin sidekick.SideKickPlugin 0.7.6
+plugin.isabelle.jedit.Plugin.depend.4=plugin gatchan.jedit.hyperlinks.HyperlinksPlugin 1.0.1
+
+#options
+plugin.isabelle.jedit.Plugin.option-pane=isabelle
+options.isabelle.label=Isabelle
+options.isabelle.code=new isabelle.jedit.Isabelle_Options();
+options.isabelle.logic.title=Logic
+options.isabelle.font-size.title=Font Size
+options.isabelle.font-size=14
+options.isabelle.startup-timeout=10000
+
+#menu actions
+plugin.isabelle.jedit.Plugin.menu.label=Isabelle
+plugin.isabelle.jedit.Plugin.menu=isabelle.activate isabelle.show-output isabelle.show-protocol
+isabelle.activate.label=Activate current buffer
+isabelle.show-output.label=Show Output
+isabelle.show-protocol.label=Show Protocol
+
+#dockables
+isabelle-output.title=Output
+isabelle-protocol.title=Protocol
+
+#SideKick
+sidekick.parser.isabelle.label=Isabelle
+mode.isabelle.sidekick.parser=isabelle
+mode.ml.sidekick.parser=isabelle
+
+#Hyperlinks
+mode.isabelle.hyperlink.source=isabelle
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/plugin/actions.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/plugin/actions.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ isabelle.jedit.Isabelle.switch_active(view);
+
+
+ return isabelle.jedit.Isabelle.is_active(view);
+
+
+
+
+ wm.addDockableWindow("isabelle-output");
+
+
+
+
+ wm.addDockableWindow("isabelle-protocol");
+
+
+
\ No newline at end of file
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/plugin/dockables.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/plugin/dockables.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,11 @@
+
+
+
+
+
+ new isabelle.jedit.Output_Dockable(view, position);
+
+
+ new isabelle.jedit.Protocol_Dockable(view, position);
+
+
\ No newline at end of file
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/plugin/services.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/plugin/services.xml Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,17 @@
+
+
+
+
+
+ new isabelle.jedit.Isabelle_Encoding();
+
+
+ new isabelle.jedit.Isabelle_Sidekick();
+
+
+ new isabelle.jedit.Isabelle_Hyperlinks();
+
+
+ new isabelle.jedit.Scala_Console();
+
+
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/Dummy.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/Dummy.java Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,3 @@
+/* dummy class to make ant javadoc work */
+package isabelle;
+public class Dummy { }
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/document_model.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/document_model.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,145 @@
+/*
+ * Document model connected to jEdit buffer
+ *
+ * @author Fabian Immler, TU Munich
+ * @author Makarius
+ */
+
+package isabelle.jedit
+
+
+import isabelle.proofdocument.{Change, Command, Document, Session}
+
+import scala.actors.Actor, Actor._
+import scala.collection.mutable
+
+import org.gjt.sp.jedit.Buffer
+import org.gjt.sp.jedit.buffer.{BufferAdapter, BufferListener, JEditBuffer}
+import org.gjt.sp.jedit.syntax.{ModeProvider, SyntaxStyle}
+
+
+object Document_Model
+{
+ /* document model of buffer */
+
+ private val key = "isabelle.document_model"
+
+ def init(session: Session, buffer: Buffer): Document_Model =
+ {
+ Swing_Thread.assert()
+ val model = new Document_Model(session, buffer)
+ buffer.setProperty(key, model)
+ model.activate()
+ model
+ }
+
+ def apply(buffer: Buffer): Option[Document_Model] =
+ {
+ Swing_Thread.assert()
+ buffer.getProperty(key) match {
+ case model: Document_Model => Some(model)
+ case _ => None
+ }
+ }
+
+ def exit(buffer: Buffer)
+ {
+ Swing_Thread.assert()
+ apply(buffer) match {
+ case None => error("No document model for buffer: " + buffer)
+ case Some(model) =>
+ model.deactivate()
+ buffer.unsetProperty(key)
+ }
+ }
+}
+
+class Document_Model(val session: Session, val buffer: Buffer)
+{
+ /* history */
+
+ private val document_0 = session.begin_document(buffer.getName)
+
+ @volatile private var history = // owned by Swing thread
+ new Change(document_0.id, None, Nil, Future.value(Nil, document_0))
+
+ def current_change(): Change = history
+ def recent_document(): Document = current_change().ancestors.find(_.is_assigned).get.join_document
+
+
+ /* transforming offsets */
+
+ private def changes_from(doc: Document): List[Text_Edit] =
+ {
+ Swing_Thread.assert()
+ (edits_buffer.toList /:
+ current_change.ancestors.takeWhile(_.id != doc.id))((edits, change) => change.edits ::: edits)
+ }
+
+ def from_current(doc: Document, offset: Int): Int =
+ (offset /: changes_from(doc).reverse) ((i, change) => change before i)
+
+ def to_current(doc: Document, offset: Int): Int =
+ (offset /: changes_from(doc)) ((i, change) => change after i)
+
+ def lines_of_command(doc: Document, cmd: Command): (Int, Int) =
+ {
+ val start = doc.command_start(cmd).get // FIXME total?
+ val stop = start + cmd.length
+ (buffer.getLineOfOffset(to_current(doc, start)),
+ buffer.getLineOfOffset(to_current(doc, stop)))
+ }
+
+
+ /* text edits */
+
+ private val edits_buffer = new mutable.ListBuffer[Text_Edit] // owned by Swing thread
+
+ private val edits_delay = Swing_Thread.delay_last(300) {
+ if (!edits_buffer.isEmpty) {
+ val new_change = current_change().edit(session, edits_buffer.toList)
+ edits_buffer.clear
+ history = new_change
+ new_change.result.map(_ => session.input(new_change))
+ }
+ }
+
+
+ /* buffer listener */
+
+ private val buffer_listener: BufferListener = new BufferAdapter
+ {
+ override def contentInserted(buffer: JEditBuffer,
+ start_line: Int, offset: Int, num_lines: Int, length: Int)
+ {
+ edits_buffer += new Text_Edit(true, offset, buffer.getText(offset, length))
+ edits_delay()
+ }
+
+ override def preContentRemoved(buffer: JEditBuffer,
+ start_line: Int, start: Int, num_lines: Int, removed_length: Int)
+ {
+ edits_buffer += new Text_Edit(false, start, buffer.getText(start, removed_length))
+ edits_delay()
+ }
+ }
+
+
+ /* activation */
+
+ def activate()
+ {
+ buffer.setTokenMarker(new Isabelle_Token_Marker(this))
+ buffer.addBufferListener(buffer_listener)
+ buffer.propertiesChanged()
+
+ edits_buffer += new Text_Edit(true, 0, buffer.getText(0, buffer.getLength))
+ edits_delay()
+ }
+
+ def deactivate()
+ {
+ buffer.setTokenMarker(buffer.getMode.getTokenMarker)
+ buffer.removeBufferListener(buffer_listener)
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/document_view.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/document_view.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,303 @@
+/*
+ * Document view connected to jEdit text area
+ *
+ * @author Fabian Immler, TU Munich
+ * @author Makarius
+ */
+
+package isabelle.jedit
+
+
+import isabelle.proofdocument.{Command, Document, Session}
+
+import scala.actors.Actor._
+
+import java.awt.event.{MouseAdapter, MouseEvent}
+import java.awt.{BorderLayout, Graphics, Dimension, Color, Graphics2D}
+import javax.swing.{JPanel, ToolTipManager}
+import javax.swing.event.{CaretListener, CaretEvent}
+
+import org.gjt.sp.jedit.gui.RolloverButton
+import org.gjt.sp.jedit.textarea.{JEditTextArea, TextArea, TextAreaExtension, TextAreaPainter}
+
+
+object Document_View
+{
+ def choose_color(command: Command, doc: Document): Color =
+ {
+ doc.current_state(command).map(_.status) match {
+ case Some(Command.Status.UNPROCESSED) => new Color(255, 228, 225)
+ case Some(Command.Status.FINISHED) => new Color(234, 248, 255)
+ case Some(Command.Status.FAILED) => new Color(255, 193, 193)
+ case _ => Color.red
+ }
+ }
+
+
+ /* document view of text area */
+
+ private val key = new Object
+
+ def init(model: Document_Model, text_area: TextArea): Document_View =
+ {
+ Swing_Thread.assert()
+ val doc_view = new Document_View(model, text_area)
+ text_area.putClientProperty(key, doc_view)
+ doc_view.activate()
+ doc_view
+ }
+
+ def apply(text_area: TextArea): Option[Document_View] =
+ {
+ Swing_Thread.assert()
+ text_area.getClientProperty(key) match {
+ case doc_view: Document_View => Some(doc_view)
+ case _ => None
+ }
+ }
+
+ def exit(text_area: TextArea)
+ {
+ Swing_Thread.assert()
+ apply(text_area) match {
+ case None => error("No document view for text area: " + text_area)
+ case Some(doc_view) =>
+ doc_view.deactivate()
+ text_area.putClientProperty(key, null)
+ }
+ }
+}
+
+
+class Document_View(model: Document_Model, text_area: TextArea)
+{
+ private val session = model.session
+
+
+ /* visible document -- owned by Swing thread */
+
+ @volatile private var document = model.recent_document()
+
+
+ /* buffer of changed commands -- owned by Swing thread */
+
+ @volatile private var changed_commands: Set[Command] = Set()
+
+ private val changed_delay = Swing_Thread.delay_first(100) {
+ if (!changed_commands.isEmpty) {
+ document = model.recent_document()
+ for (cmd <- changed_commands if document.commands.contains(cmd)) { // FIXME cover doc states as well!!?
+ update_syntax(cmd)
+ invalidate_line(cmd)
+ overview.repaint()
+ }
+ changed_commands = Set()
+ }
+ }
+
+
+ /* command change actor */
+
+ private case object Exit
+
+ private val command_change_actor = actor {
+ loop {
+ react {
+ case command: Command => // FIXME rough filtering according to document family!?
+ Swing_Thread.now {
+ changed_commands += command
+ changed_delay()
+ }
+
+ case Exit => reply(()); exit()
+
+ case bad => System.err.println("command_change_actor: ignoring bad message " + bad)
+ }
+ }
+ }
+
+
+ /* text_area_extension */
+
+ private val text_area_extension = new TextAreaExtension
+ {
+ override def paintValidLine(gfx: Graphics2D,
+ screen_line: Int, physical_line: Int, start: Int, end: Int, y: Int)
+ {
+ def from_current(pos: Int) = model.from_current(document, pos)
+ def to_current(pos: Int) = model.to_current(document, pos)
+ val metrics = text_area.getPainter.getFontMetrics
+ val saved_color = gfx.getColor
+ try {
+ for ((command, command_start) <-
+ document.command_range(from_current(start), from_current(end)))
+ {
+ val begin = start max to_current(command_start)
+ val finish = (end - 1) min to_current(command_start + command.length)
+ encolor(gfx, y, metrics.getHeight, begin, finish,
+ Document_View.choose_color(command, document), true)
+ }
+ }
+ finally { gfx.setColor(saved_color) }
+ }
+
+ override def getToolTipText(x: Int, y: Int): String =
+ {
+ val offset = model.from_current(document, text_area.xyToOffset(x, y))
+ document.command_at(offset) match {
+ case Some((command, command_start)) =>
+ document.current_state(command).get.type_at(offset - command_start).getOrElse(null)
+ case None => null
+ }
+ }
+ }
+
+
+ /* caret_listener */
+
+ private var _selected_command: Command = null
+ private def selected_command = _selected_command
+ private def selected_command_=(cmd: Command)
+ {
+ _selected_command = cmd
+ session.results.event(cmd)
+ }
+
+ private val caret_listener = new CaretListener
+ {
+ override def caretUpdate(e: CaretEvent)
+ {
+ document.command_at(e.getDot) match {
+ case Some((command, command_start)) if (selected_command != command) =>
+ selected_command = command
+ case _ =>
+ }
+ }
+ }
+
+
+ /* (re)painting */
+
+ private val update_delay = Swing_Thread.delay_first(500) { model.buffer.propertiesChanged() }
+
+ private def update_syntax(cmd: Command)
+ {
+ val (line1, line2) = model.lines_of_command(document, cmd)
+ if (line2 >= text_area.getFirstLine &&
+ line1 <= text_area.getFirstLine + text_area.getVisibleLines)
+ update_delay()
+ }
+
+ private def invalidate_line(cmd: Command) =
+ {
+ val (start, stop) = model.lines_of_command(document, cmd)
+ text_area.invalidateLineRange(start, stop)
+
+ if (selected_command == cmd)
+ session.results.event(cmd)
+ }
+
+ private def invalidate_all() =
+ text_area.invalidateLineRange(text_area.getFirstPhysicalLine,
+ text_area.getLastPhysicalLine)
+
+ private def encolor(gfx: Graphics2D,
+ y: Int, height: Int, begin: Int, finish: Int, color: Color, fill: Boolean)
+ {
+ val start = text_area.offsetToXY(begin)
+ val stop =
+ if (finish < model.buffer.getLength) text_area.offsetToXY(finish)
+ else {
+ val p = text_area.offsetToXY(finish - 1)
+ val metrics = text_area.getPainter.getFontMetrics
+ p.x = p.x + (metrics.charWidth(' ') max metrics.getMaxAdvance)
+ p
+ }
+
+ if (start != null && stop != null) {
+ gfx.setColor(color)
+ if (fill) gfx.fillRect(start.x, y, stop.x - start.x, height)
+ else gfx.drawRect(start.x, y, stop.x - start.x, height)
+ }
+ }
+
+
+ /* overview of command status left of scrollbar */
+
+ private val overview = new JPanel(new BorderLayout)
+ {
+ private val WIDTH = 10
+ private val HEIGHT = 2
+
+ setPreferredSize(new Dimension(WIDTH, 0))
+
+ setRequestFocusEnabled(false)
+
+ addMouseListener(new MouseAdapter {
+ override def mousePressed(event: MouseEvent) {
+ val line = y_to_line(event.getY)
+ if (line >= 0 && line < text_area.getLineCount)
+ text_area.setCaretPosition(text_area.getLineStartOffset(line))
+ }
+ })
+
+ override def addNotify() {
+ super.addNotify()
+ ToolTipManager.sharedInstance.registerComponent(this)
+ }
+
+ override def removeNotify() {
+ ToolTipManager.sharedInstance.unregisterComponent(this)
+ super.removeNotify
+ }
+
+ override def getToolTipText(event: MouseEvent): String =
+ {
+ val line = y_to_line(event.getY())
+ if (line >= 0 && line < text_area.getLineCount) "TODO:
Tooltip"
+ else ""
+ }
+
+ override def paintComponent(gfx: Graphics)
+ {
+ super.paintComponent(gfx)
+ val buffer = model.buffer
+
+ for ((command, start) <- document.command_range(0)) {
+ val line1 = buffer.getLineOfOffset(model.to_current(document, start))
+ val line2 = buffer.getLineOfOffset(model.to_current(document, start + command.length)) + 1
+ val y = line_to_y(line1)
+ val height = HEIGHT * (line2 - line1)
+ gfx.setColor(Document_View.choose_color(command, document))
+ gfx.fillRect(0, y, getWidth - 1, height)
+ }
+ }
+
+ private def line_to_y(line: Int): Int =
+ (line * getHeight) / (text_area.getBuffer.getLineCount max text_area.getVisibleLines)
+
+ private def y_to_line(y: Int): Int =
+ (y * (text_area.getBuffer.getLineCount max text_area.getVisibleLines)) / getHeight
+ }
+
+
+ /* activation */
+
+ private def activate()
+ {
+ text_area.getPainter.
+ addExtension(TextAreaPainter.LINE_BACKGROUND_LAYER + 1, text_area_extension)
+ text_area.addCaretListener(caret_listener)
+ text_area.addLeftOfScrollBar(overview)
+ session.command_change += command_change_actor
+ }
+
+ private def deactivate()
+ {
+ session.command_change -= command_change_actor
+ command_change_actor !? Exit
+ text_area.removeLeftOfScrollBar(overview)
+ text_area.removeCaretListener(caret_listener)
+ text_area.getPainter.removeExtension(text_area_extension)
+ }
+}
\ No newline at end of file
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/isabelle_encoding.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/isabelle_encoding.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,64 @@
+/*
+ * Isabelle encoding -- based on utf-8
+ *
+ * @author Makarius
+ */
+
+package isabelle.jedit
+
+
+import org.gjt.sp.jedit.io.Encoding
+import org.gjt.sp.jedit.buffer.JEditBuffer
+
+import java.nio.charset.{Charset, CharsetDecoder, CodingErrorAction}
+import java.io.{InputStream, OutputStream, Reader, Writer, InputStreamReader, OutputStreamWriter,
+ CharArrayReader, ByteArrayOutputStream}
+
+import scala.io.{Source, BufferedSource}
+
+
+object Isabelle_Encoding
+{
+ val NAME = "UTF-8-Isabelle"
+
+ def is_active(buffer: JEditBuffer): Boolean =
+ buffer.getStringProperty(JEditBuffer.ENCODING).asInstanceOf[String] == NAME
+}
+
+class Isabelle_Encoding extends Encoding
+{
+ private val charset = Charset.forName(Standard_System.charset)
+ private val BUFSIZE = 32768
+
+ private def text_reader(in: InputStream, decoder: CharsetDecoder): Reader =
+ {
+ def source(): Source =
+ BufferedSource.fromInputStream(in, decoder, BUFSIZE, { () => source() })
+ new CharArrayReader(Isabelle.system.symbols.decode(source.mkString).toArray)
+ }
+
+ override def getTextReader(in: InputStream): Reader =
+ text_reader(in, charset.newDecoder())
+
+ override def getPermissiveTextReader(in: InputStream): Reader =
+ {
+ val decoder = charset.newDecoder()
+ decoder.onMalformedInput(CodingErrorAction.REPLACE)
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE)
+ text_reader(in, decoder)
+ }
+
+ override def getTextWriter(out: OutputStream): Writer =
+ {
+ val buffer = new ByteArrayOutputStream(BUFSIZE) {
+ override def flush()
+ {
+ val text = Isabelle.system.symbols.encode(toString(Standard_System.charset))
+ out.write(text.getBytes(Standard_System.charset))
+ out.flush()
+ }
+ override def close() { out.close() }
+ }
+ new OutputStreamWriter(buffer, charset.newEncoder())
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/isabelle_hyperlinks.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/isabelle_hyperlinks.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,76 @@
+/*
+ * Hyperlink setup for Isabelle proof documents
+ *
+ * @author Fabian Immler, TU Munich
+ */
+
+package isabelle.jedit
+
+import isabelle.proofdocument.Command
+
+import java.io.File
+
+import gatchan.jedit.hyperlinks.{Hyperlink, HyperlinkSource, AbstractHyperlink}
+
+import org.gjt.sp.jedit.{View, jEdit, Buffer, TextUtilities}
+
+
+private class Internal_Hyperlink(start: Int, end: Int, line: Int, ref_offset: Int)
+ extends AbstractHyperlink(start, end, line, "")
+{
+ override def click(view: View) {
+ view.getTextArea.moveCaretPosition(ref_offset)
+ }
+}
+
+class External_Hyperlink(start: Int, end: Int, line: Int, ref_file: String, ref_line: Int)
+ extends AbstractHyperlink(start, end, line, "")
+{
+ override def click(view: View) = {
+ Isabelle.system.source_file(ref_file) match {
+ case None => System.err.println("Could not find source file " + ref_file) // FIXME ??
+ case Some(file) =>
+ jEdit.openFiles(view, file.getParent, Array(file.getName, "+line:" + ref_line))
+ }
+ }
+}
+
+class Isabelle_Hyperlinks extends HyperlinkSource
+{
+ def getHyperlink(buffer: Buffer, original_offset: Int): Hyperlink =
+ {
+ Document_Model(buffer) match {
+ case Some(model) =>
+ val document = model.recent_document()
+ val offset = model.from_current(document, original_offset)
+ document.command_at(offset) match {
+ case Some((command, command_start)) =>
+ document.current_state(command).get.ref_at(offset - command_start) match {
+ case Some(ref) =>
+ val begin = model.to_current(document, command_start + ref.start)
+ val line = buffer.getLineOfOffset(begin)
+ val end = model.to_current(document, command_start + ref.stop)
+ ref.info match {
+ case Command.RefInfo(Some(ref_file), Some(ref_line), _, _) =>
+ new External_Hyperlink(begin, end, line, ref_file, ref_line)
+ case Command.RefInfo(_, _, Some(id), Some(offset)) =>
+ Isabelle.session.lookup_entity(id) match {
+ case Some(ref_cmd: Command) =>
+ document.command_start(ref_cmd) match {
+ case Some(ref_cmd_start) =>
+ new Internal_Hyperlink(begin, end, line,
+ model.to_current(document, ref_cmd_start + offset - 1))
+ case None => null // FIXME external ref
+ }
+ case _ => null
+ }
+ case _ => null
+ }
+ case None => null
+ }
+ case None => null
+ }
+ case None => null
+ }
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/isabelle_options.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/isabelle_options.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,53 @@
+/*
+ * Editor pane for plugin options
+ *
+ * @author Johannes Hölzl, TU Munich
+ */
+
+package isabelle.jedit
+
+
+import javax.swing.{JComboBox, JSpinner}
+
+import org.gjt.sp.jedit.AbstractOptionPane
+
+
+class Isabelle_Options extends AbstractOptionPane("isabelle")
+{
+ private val logic_name = new JComboBox()
+ private val font_size = new JSpinner()
+
+ private class List_Item(val name: String, val descr: String) {
+ def this(name: String) = this(name, name)
+ override def toString = descr
+ }
+
+ override def _init()
+ {
+ val logic = Isabelle.Property("logic")
+ addComponent(Isabelle.Property("logic.title"), {
+ logic_name.addItem(new List_Item("", "default (" + Isabelle.default_logic() + ")"))
+ for (name <- Isabelle.system.find_logics()) {
+ val item = new List_Item(name)
+ logic_name.addItem(item)
+ if (name == logic)
+ logic_name.setSelectedItem(item)
+ }
+ logic_name
+ })
+
+ addComponent(Isabelle.Property("font-size.title"), {
+ font_size.setValue(Isabelle.Int_Property("font-size"))
+ font_size
+ })
+ }
+
+ override def _save()
+ {
+ val logic = logic_name.getSelectedItem.asInstanceOf[List_Item].name
+ Isabelle.Property("logic") = logic
+
+ val size = font_size.getValue().asInstanceOf[Int]
+ Isabelle.Int_Property("font-size") = size
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/isabelle_sidekick.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/isabelle_sidekick.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,100 @@
+/*
+ * SideKick parser for Isabelle proof documents
+ *
+ * @author Fabian Immler, TU Munich
+ * @author Makarius
+ */
+
+package isabelle.jedit
+
+
+import scala.collection.Set
+import scala.collection.immutable.TreeSet
+
+import javax.swing.tree.DefaultMutableTreeNode
+import javax.swing.text.Position
+import javax.swing.Icon
+
+import org.gjt.sp.jedit.{Buffer, EditPane, TextUtilities, View}
+import errorlist.DefaultErrorSource
+import sidekick.{SideKickParser, SideKickParsedData, SideKickCompletion, IAsset}
+
+import isabelle.proofdocument.{Command, Markup_Node, Document}
+
+
+class Isabelle_Sidekick extends SideKickParser("isabelle")
+{
+ /* parsing */
+
+ @volatile private var stopped = false
+ override def stop() = { stopped = true }
+
+ def parse(buffer: Buffer, error_source: DefaultErrorSource): SideKickParsedData =
+ {
+ implicit def int_to_pos(offset: Int): Position =
+ new Position { def getOffset = offset; override def toString = offset.toString }
+
+ stopped = false
+
+ // FIXME lock buffer !??
+ val data = new SideKickParsedData(buffer.getName)
+ val root = data.root
+ data.getAsset(root).setEnd(buffer.getLength)
+
+ Swing_Thread.now { Document_Model(buffer) } match {
+ case Some(model) =>
+ val document = model.recent_document()
+ for ((command, command_start) <- document.command_range(0) if !stopped) {
+ root.add(document.current_state(command).get.markup_root.swing_tree((node: Markup_Node) =>
+ {
+ val content = command.source(node.start, node.stop)
+ val id = command.id
+
+ new DefaultMutableTreeNode(new IAsset {
+ override def getIcon: Icon = null
+ override def getShortString: String = content
+ override def getLongString: String = node.info.toString
+ override def getName: String = id
+ override def setName(name: String) = ()
+ override def setStart(start: Position) = ()
+ override def getStart: Position = command_start + node.start
+ override def setEnd(end: Position) = ()
+ override def getEnd: Position = command_start + node.stop
+ override def toString = id + ": " + content + "[" + getStart + " - " + getEnd + "]"
+ })
+ }))
+ }
+ if (stopped) root.add(new DefaultMutableTreeNode(""))
+ case None => root.add(new DefaultMutableTreeNode(""))
+ }
+ data
+ }
+
+
+ /* completion */
+
+ override def supportsCompletion = true
+ override def canCompleteAnywhere = true
+
+ override def complete(pane: EditPane, caret: Int): SideKickCompletion =
+ {
+ val buffer = pane.getBuffer
+
+ val line = buffer.getLineOfOffset(caret)
+ val start = buffer.getLineStartOffset(line)
+ val text = buffer.getSegment(start, caret - start)
+
+ val completion = Isabelle.session.current_syntax.completion
+
+ completion.complete(text) match {
+ case None => null
+ case Some((word, cs)) =>
+ val ds =
+ if (Isabelle_Encoding.is_active(buffer))
+ cs.map(Isabelle.system.symbols.decode(_)).sort(_ < _)
+ else cs
+ new SideKickCompletion(pane.getView, word, ds.toArray.asInstanceOf[Array[Object]]) { }
+ }
+ }
+
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/isabelle_token_marker.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/isabelle_token_marker.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,145 @@
+/*
+ * include isabelle's command- and keyword-declarations
+ * live in jEdits syntax-highlighting
+ *
+ * @author Fabian Immler, TU Munich
+ */
+
+package isabelle.jedit
+
+
+import isabelle.Markup
+
+import org.gjt.sp.jedit.buffer.JEditBuffer
+import org.gjt.sp.jedit.syntax.{Token, TokenMarker, TokenHandler, SyntaxStyle, ParserRuleSet}
+
+import java.awt.Color
+import java.awt.Font
+import javax.swing.text.Segment;
+
+
+object Isabelle_Token_Marker
+{
+ /* line context */
+
+ private val rule_set = new ParserRuleSet("isabelle", "MAIN")
+ private class LineContext(val line: Int, prev: LineContext)
+ extends TokenMarker.LineContext(rule_set, prev)
+
+
+ /* mapping to jEdit token types */
+ // TODO: as properties or CSS style sheet
+
+ private val choose_byte: Map[String, Byte] =
+ {
+ import Token._
+ Map[String, Byte](
+ // logical entities
+ Markup.TCLASS -> LABEL,
+ Markup.TYCON -> LABEL,
+ Markup.FIXED_DECL -> LABEL,
+ Markup.FIXED -> LABEL,
+ Markup.CONST_DECL -> LABEL,
+ Markup.CONST -> LABEL,
+ Markup.FACT_DECL -> LABEL,
+ Markup.FACT -> LABEL,
+ Markup.DYNAMIC_FACT -> LABEL,
+ Markup.LOCAL_FACT_DECL -> LABEL,
+ Markup.LOCAL_FACT -> LABEL,
+ // inner syntax
+ Markup.TFREE -> LITERAL2,
+ Markup.FREE -> LITERAL2,
+ Markup.TVAR -> LITERAL3,
+ Markup.SKOLEM -> LITERAL3,
+ Markup.BOUND -> LITERAL3,
+ Markup.VAR -> LITERAL3,
+ Markup.NUM -> DIGIT,
+ Markup.FLOAT -> DIGIT,
+ Markup.XNUM -> DIGIT,
+ Markup.XSTR -> LITERAL4,
+ Markup.LITERAL -> LITERAL4,
+ Markup.INNER_COMMENT -> COMMENT1,
+ Markup.SORT -> FUNCTION,
+ Markup.TYP -> FUNCTION,
+ Markup.TERM -> FUNCTION,
+ Markup.PROP -> FUNCTION,
+ Markup.ATTRIBUTE -> FUNCTION,
+ Markup.METHOD -> FUNCTION,
+ // ML syntax
+ Markup.ML_KEYWORD -> KEYWORD2,
+ Markup.ML_IDENT -> NULL,
+ Markup.ML_TVAR -> LITERAL3,
+ Markup.ML_NUMERAL -> DIGIT,
+ Markup.ML_CHAR -> LITERAL1,
+ Markup.ML_STRING -> LITERAL1,
+ Markup.ML_COMMENT -> COMMENT1,
+ Markup.ML_MALFORMED -> INVALID,
+ // embedded source text
+ Markup.ML_SOURCE -> COMMENT4,
+ Markup.DOC_SOURCE -> COMMENT4,
+ Markup.ANTIQ -> COMMENT4,
+ Markup.ML_ANTIQ -> COMMENT4,
+ Markup.DOC_ANTIQ -> COMMENT4,
+ // outer syntax
+ Markup.IDENT -> NULL,
+ Markup.COMMAND -> OPERATOR,
+ Markup.KEYWORD -> KEYWORD4,
+ Markup.VERBATIM -> COMMENT3,
+ Markup.COMMENT -> COMMENT1,
+ Markup.CONTROL -> COMMENT3,
+ Markup.MALFORMED -> INVALID,
+ Markup.STRING -> LITERAL3,
+ Markup.ALTSTRING -> LITERAL1
+ ).withDefaultValue(NULL)
+ }
+
+ def choose_color(kind: String, styles: Array[SyntaxStyle]): Color =
+ styles(choose_byte(kind)).getForegroundColor
+}
+
+
+class Isabelle_Token_Marker(model: Document_Model) extends TokenMarker
+{
+ override def markTokens(prev: TokenMarker.LineContext,
+ handler: TokenHandler, line_segment: Segment): TokenMarker.LineContext =
+ {
+ val previous = prev.asInstanceOf[Isabelle_Token_Marker.LineContext]
+ val line = if (prev == null) 0 else previous.line + 1
+ val context = new Isabelle_Token_Marker.LineContext(line, previous)
+ val start = model.buffer.getLineStartOffset(line)
+ val stop = start + line_segment.count
+
+ val document = model.recent_document()
+ def to: Int => Int = model.to_current(document, _)
+ def from: Int => Int = model.from_current(document, _)
+
+ var next_x = start
+ for {
+ (command, command_start) <- document.command_range(from(start), from(stop))
+ markup <- document.current_state(command).get.highlight.flatten
+ val abs_start = to(command_start + markup.start)
+ val abs_stop = to(command_start + markup.stop)
+ if (abs_stop > start)
+ if (abs_start < stop)
+ val byte = Isabelle_Token_Marker.choose_byte(markup.info.toString)
+ val token_start = (abs_start - start) max 0
+ val token_length =
+ (abs_stop - abs_start) -
+ ((start - abs_start) max 0) -
+ ((abs_stop - stop) max 0)
+ }
+ {
+ if (start + token_start > next_x)
+ handler.handleToken(line_segment, 1,
+ next_x - start, start + token_start - next_x, context)
+ handler.handleToken(line_segment, byte, token_start, token_length, context)
+ next_x = start + token_start + token_length
+ }
+ if (next_x < stop)
+ handler.handleToken(line_segment, 1, next_x - start, stop - next_x, context)
+
+ handler.handleToken(line_segment, Token.END, line_segment.count, 0, context)
+ handler.setLineContext(context)
+ context
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/output_dockable.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/output_dockable.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,66 @@
+/*
+ * Dockable window with result message output
+ *
+ * @author Makarius
+ */
+
+package isabelle.jedit
+
+
+import isabelle.proofdocument.{Command, HTML_Panel, Session}
+
+import scala.actors.Actor._
+
+import javax.swing.JPanel
+import java.awt.{BorderLayout, Dimension}
+
+import org.gjt.sp.jedit.View
+import org.gjt.sp.jedit.gui.DockableWindowManager
+
+
+
+class Output_Dockable(view: View, position: String) extends JPanel(new BorderLayout)
+{
+ if (position == DockableWindowManager.FLOATING)
+ setPreferredSize(new Dimension(500, 250))
+
+ private val html_panel =
+ new HTML_Panel(Isabelle.system, Isabelle.Int_Property("font-size"), null)
+ add(html_panel, BorderLayout.CENTER)
+
+
+ /* actor wiring */
+
+ private val output_actor = actor {
+ loop {
+ react {
+ case cmd: Command =>
+ Swing_Thread.now { Document_Model(view.getBuffer) } match {
+ case None =>
+ case Some(model) =>
+ val body = model.recent_document.current_state(cmd).map(_.results) getOrElse Nil
+ html_panel.render(body)
+ }
+
+ case Session.Global_Settings =>
+ html_panel.init(Isabelle.Int_Property("font-size"))
+
+ case bad => System.err.println("output_actor: ignoring bad message " + bad)
+ }
+ }
+ }
+
+ override def addNotify()
+ {
+ super.addNotify()
+ Isabelle.session.results += output_actor
+ Isabelle.session.global_settings += output_actor
+ }
+
+ override def removeNotify()
+ {
+ Isabelle.session.results -= output_actor
+ Isabelle.session.global_settings -= output_actor
+ super.removeNotify()
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/plugin.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/plugin.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,197 @@
+/*
+ * Main Isabelle/jEdit plugin setup
+ *
+ * @author Johannes Hölzl, TU Munich
+ * @author Fabian Immler, TU Munich
+ * @author Makarius
+ */
+
+package isabelle.jedit
+
+
+import isabelle.proofdocument.Session
+
+import java.io.{FileInputStream, IOException}
+import java.awt.Font
+import javax.swing.JTextArea
+
+import scala.collection.mutable
+
+import org.gjt.sp.jedit.{jEdit, EBMessage, EBPlugin, Buffer, EditPane, ServiceManager, View}
+import org.gjt.sp.jedit.buffer.JEditBuffer
+import org.gjt.sp.jedit.textarea.JEditTextArea
+import org.gjt.sp.jedit.msg.{EditPaneUpdate, PropertiesChanged}
+
+
+object Isabelle
+{
+ /* plugin instance */
+
+ var system: Isabelle_System = null
+ var session: Session = null
+
+
+ /* name */
+
+ val NAME = "Isabelle"
+
+
+ /* properties */
+
+ val OPTION_PREFIX = "options.isabelle."
+
+ object Property
+ {
+ def apply(name: String): String = jEdit.getProperty(OPTION_PREFIX + name)
+ def update(name: String, value: String) = jEdit.setProperty(OPTION_PREFIX + name, value)
+ }
+
+ object Boolean_Property
+ {
+ def apply(name: String): Boolean = jEdit.getBooleanProperty(OPTION_PREFIX + name)
+ def update(name: String, value: Boolean) = jEdit.setBooleanProperty(OPTION_PREFIX + name, value)
+ }
+
+ object Int_Property
+ {
+ def apply(name: String): Int = jEdit.getIntegerProperty(OPTION_PREFIX + name)
+ def update(name: String, value: Int) = jEdit.setIntegerProperty(OPTION_PREFIX + name, value)
+ }
+
+
+ /* settings */
+
+ def default_logic(): String =
+ {
+ val logic = system.getenv("JEDIT_LOGIC")
+ if (logic != "") logic
+ else system.getenv_strict("ISABELLE_LOGIC")
+ }
+
+ def isabelle_args(): List[String] =
+ {
+ val modes = system.getenv("JEDIT_PRINT_MODE").split(",").toList.map("-m" + _)
+ val logic = {
+ val logic = Property("logic")
+ if (logic != null && logic != "") logic
+ else default_logic()
+ }
+ modes ++ List(logic)
+ }
+
+
+ /* main jEdit components */ // FIXME ownership!?
+
+ def jedit_buffers(): Iterator[Buffer] = Iterator.fromArray(jEdit.getBuffers())
+
+ def jedit_views(): Iterator[View] = Iterator.fromArray(jEdit.getViews())
+
+ def jedit_text_areas(view: View): Iterator[JEditTextArea] =
+ Iterator.fromArray(view.getEditPanes).map(_.getTextArea)
+
+ def jedit_text_areas(): Iterator[JEditTextArea] =
+ jedit_views().flatMap(jedit_text_areas(_))
+
+ def jedit_text_areas(buffer: JEditBuffer): Iterator[JEditTextArea] =
+ jedit_text_areas().filter(_.getBuffer == buffer)
+
+
+ /* manage prover */
+
+ private def prover_started(view: View): Boolean =
+ {
+ val timeout = Int_Property("startup-timeout") max 1000
+ session.start(timeout, Isabelle.isabelle_args()) match {
+ case Some(err) =>
+ val text = new JTextArea(err); text.setEditable(false)
+ Library.error_dialog(view, null, "Failed to start Isabelle process", text)
+ false
+ case None => true
+ }
+ }
+
+
+ /* activation */
+
+ def activate_buffer(view: View, buffer: Buffer)
+ {
+ if (prover_started(view)) {
+ val model = Document_Model.init(session, buffer)
+ for (text_area <- jedit_text_areas(buffer))
+ Document_View.init(model, text_area)
+ }
+ }
+
+ def deactivate_buffer(buffer: Buffer)
+ {
+ session.stop() // FIXME not yet
+
+ for (text_area <- jedit_text_areas(buffer))
+ Document_View.exit(text_area)
+ Document_Model.exit(buffer)
+ }
+
+ def switch_active(view: View) =
+ {
+ val buffer = view.getBuffer
+ if (Document_Model(buffer).isDefined) deactivate_buffer(buffer)
+ else activate_buffer(view, buffer)
+ }
+
+ def is_active(view: View): Boolean =
+ Document_Model(view.getBuffer).isDefined
+}
+
+
+class Plugin extends EBPlugin
+{
+ /* main plugin plumbing */
+
+ override def handleMessage(message: EBMessage)
+ {
+ message match {
+ case msg: EditPaneUpdate =>
+ val edit_pane = msg.getEditPane
+ val buffer = edit_pane.getBuffer
+ val text_area = edit_pane.getTextArea
+
+ def init_view()
+ {
+ Document_Model(buffer) match {
+ case Some(model) => Document_View.init(model, text_area)
+ case None =>
+ }
+ }
+ def exit_view()
+ {
+ if (Document_View(text_area).isDefined)
+ Document_View.exit(text_area)
+ }
+ msg.getWhat match {
+ case EditPaneUpdate.BUFFER_CHANGED => exit_view(); init_view()
+ case EditPaneUpdate.CREATED => init_view()
+ case EditPaneUpdate.DESTROYED => exit_view()
+ case _ =>
+ }
+
+ case msg: PropertiesChanged =>
+ Isabelle.session.global_settings.event(Session.Global_Settings)
+
+ case _ =>
+ }
+ }
+
+ override def start()
+ {
+ Isabelle.system = new Isabelle_System
+ Isabelle.system.install_fonts()
+ Isabelle.session = new Session(Isabelle.system) // FIXME dialog!?
+ }
+
+ override def stop()
+ {
+ Isabelle.session.stop() // FIXME dialog!?
+ Isabelle.session = null
+ Isabelle.system = null
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/protocol_dockable.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/protocol_dockable.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,52 @@
+/*
+ * Dockable window for raw process output
+ *
+ * @author Makarius
+ */
+
+package isabelle.jedit
+
+
+import scala.actors.Actor._
+
+import java.awt.{Dimension, Graphics, BorderLayout}
+import javax.swing.{JPanel, JTextArea, JScrollPane}
+
+import org.gjt.sp.jedit.View
+import org.gjt.sp.jedit.gui.DockableWindowManager
+
+
+class Protocol_Dockable(view: View, position: String) extends JPanel(new BorderLayout)
+{
+ if (position == DockableWindowManager.FLOATING)
+ setPreferredSize(new Dimension(500, 250))
+
+ private val text_area = new JTextArea
+ add(new JScrollPane(text_area), BorderLayout.CENTER)
+
+
+ /* actor wiring */
+
+ private val raw_actor = actor {
+ loop {
+ react {
+ case result: Isabelle_Process.Result =>
+ Swing_Thread.now { text_area.append(result.toString + "\n") }
+
+ case bad => System.err.println("raw_actor: ignoring bad message " + bad)
+ }
+ }
+ }
+
+ override def addNotify()
+ {
+ super.addNotify()
+ Isabelle.session.raw_results += raw_actor
+ }
+
+ override def removeNotify()
+ {
+ Isabelle.session.raw_results -= raw_actor
+ super.removeNotify()
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/jedit/scala_console.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/jedit/scala_console.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,153 @@
+/*
+ * Scala instance of Console plugin
+ *
+ * @author Makarius
+ */
+
+package isabelle.jedit
+
+
+import console.{Console, ConsolePane, Shell, Output}
+
+import org.gjt.sp.jedit.{jEdit, JARClassLoader}
+import org.gjt.sp.jedit.MiscUtilities
+
+import java.io.{File, OutputStream, Writer, PrintWriter}
+
+import scala.tools.nsc.{Interpreter, GenericRunnerSettings, NewLinePrintWriter, ConsoleWriter}
+import scala.collection.mutable
+
+
+class Scala_Console extends Shell("Scala")
+{
+ /* reconstructed jEdit/plugin classpath */
+
+ private def reconstruct_classpath(): String =
+ {
+ def find_jars(start: String): List[String] =
+ if (start != null)
+ Standard_System.find_files(new File(start),
+ entry => entry.isFile && entry.getName.endsWith(".jar")).map(_.getAbsolutePath)
+ else Nil
+ val path = find_jars(jEdit.getSettingsDirectory) ::: find_jars(jEdit.getJEditHome)
+ path.mkString(File.pathSeparator)
+ }
+
+
+ /* global state -- owned by Swing thread */
+
+ private var interpreters = Map[Console, Interpreter]()
+
+ private var global_console: Console = null
+ private var global_out: Output = null
+ private var global_err: Output = null
+
+ private val console_stream = new OutputStream
+ {
+ val buf = new StringBuilder
+ override def flush()
+ {
+ val str = Standard_System.decode_permissive_utf8(buf.toString)
+ buf.clear
+ if (global_out == null) System.out.print(str)
+ else Swing_Thread.now { global_out.writeAttrs(null, str) }
+ }
+ override def close() { flush () }
+ def write(byte: Int) { buf.append(byte.toChar) }
+ }
+
+ private val console_writer = new Writer
+ {
+ def flush() {}
+ def close() {}
+
+ def write(cbuf: Array[Char], off: Int, len: Int)
+ {
+ if (len > 0) write(new String(cbuf.subArray(off, off + len)))
+ }
+
+ override def write(str: String)
+ {
+ if (global_out == null) System.out.println(str)
+ else global_out.print(null, str)
+ }
+ }
+
+ private def with_console[A](console: Console, out: Output, err: Output)(e: => A): A =
+ {
+ global_console = console
+ global_out = out
+ global_err = if (err == null) out else err
+ val res = Exn.capture { scala.Console.withOut(console_stream)(e) }
+ console_stream.flush
+ global_console = null
+ global_out = null
+ global_err = null
+ Exn.release(res)
+ }
+
+ private def report_error(str: String)
+ {
+ if (global_console == null || global_err == null) System.err.println(str)
+ else Swing_Thread.now { global_err.print(global_console.getErrorColor, str) }
+ }
+
+
+ /* jEdit console methods */
+
+ override def openConsole(console: Console)
+ {
+ val settings = new GenericRunnerSettings(report_error)
+ settings.classpath.value = reconstruct_classpath()
+
+ val interp = new Interpreter(settings, new PrintWriter(console_writer, true))
+ {
+ override def parentClassLoader = new JARClassLoader
+ }
+ interp.setContextClassLoader
+ interp.bind("view", "org.gjt.sp.jedit.View", console.getView)
+ interp.bind("console", "console.Console", console)
+ interp.interpret("import isabelle.jedit.Isabelle")
+
+ interpreters += (console -> interp)
+ }
+
+ override def closeConsole(console: Console)
+ {
+ interpreters -= console
+ }
+
+ override def printInfoMessage(out: Output)
+ {
+ out.print(null,
+ "This shell evaluates Isabelle/Scala expressions.\n\n" +
+ "The following special toplevel bindings are provided:\n" +
+ " view -- current jEdit/Swing view (e.g. view.getBuffer, view.getTextArea)\n" +
+ " console -- jEdit Console plugin instance\n" +
+ " Isabelle -- Isabelle plugin instance (e.g. Isabelle.system, Isabelle.session)\n")
+ }
+
+ override def printPrompt(console: Console, out: Output)
+ {
+ out.writeAttrs(ConsolePane.colorAttributes(console.getInfoColor), "scala>")
+ out.writeAttrs(ConsolePane.colorAttributes(console.getPlainColor), " ")
+ }
+
+ override def execute(console: Console, input: String, out: Output, err: Output, command: String)
+ {
+ val interp = interpreters(console)
+ with_console(console, out, err) { interp.interpret(command) }
+ if (err != null) err.commandDone()
+ out.commandDone()
+ }
+
+ override def stop(console: Console)
+ {
+ closeConsole(console)
+ console.clear
+ openConsole(console)
+ val out = console.getOutput
+ out.commandDone
+ printPrompt(console, out)
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/proofdocument/change.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/proofdocument/change.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,42 @@
+/*
+ * Changes of plain text
+ *
+ * @author Fabian Immler, TU Munich
+ * @author Makarius
+ */
+
+package isabelle.proofdocument
+
+
+class Change(
+ val id: Isar_Document.Document_ID,
+ val parent: Option[Change],
+ val edits: List[Text_Edit],
+ val result: Future[(List[Document.Edit], Document)])
+{
+ def ancestors: Iterator[Change] = new Iterator[Change]
+ {
+ private var state: Option[Change] = Some(Change.this)
+ def hasNext = state.isDefined
+ def next =
+ state match {
+ case Some(change) => state = change.parent; change
+ case None => throw new NoSuchElementException("next on empty iterator")
+ }
+ }
+
+ def join_document: Document = result.join._2
+ def is_assigned: Boolean = result.is_finished && join_document.assignment.is_finished
+
+ def edit(session: Session, edits: List[Text_Edit]): Change =
+ {
+ val new_id = session.create_id()
+ val result: Future[(List[Document.Edit], Document)] =
+ Future.fork {
+ val old_doc = join_document
+ old_doc.await_assignment
+ Document.text_edits(session, old_doc, new_id, edits)
+ }
+ new Change(new_id, Some(this), edits, result)
+ }
+}
\ No newline at end of file
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/proofdocument/command.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/proofdocument/command.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,102 @@
+/*
+ * Prover commands with semantic state
+ *
+ * @author Johannes Hölzl, TU Munich
+ * @author Fabian Immler, TU Munich
+ */
+
+package isabelle.proofdocument
+
+
+import scala.actors.Actor, Actor._
+import scala.collection.mutable
+
+import isabelle.jedit.Isabelle
+
+
+object Command
+{
+ object Status extends Enumeration
+ {
+ val UNPROCESSED = Value("UNPROCESSED")
+ val FINISHED = Value("FINISHED")
+ val FAILED = Value("FAILED")
+ }
+
+ case class HighlightInfo(highlight: String) { override def toString = highlight }
+ case class TypeInfo(ty: String)
+ case class RefInfo(file: Option[String], line: Option[Int],
+ command_id: Option[String], offset: Option[Int])
+}
+
+
+class Command(
+ val id: Isar_Document.Command_ID,
+ val span: Thy_Syntax.Span)
+ extends Session.Entity
+{
+ /* classification */
+
+ def is_command: Boolean = !span.isEmpty && span.first.is_command
+ def is_ignored: Boolean = span.forall(_.is_ignored)
+ def is_malformed: Boolean = !is_command && !is_ignored
+
+ def name: String = if (is_command) span.first.content else ""
+ override def toString = if (is_command) name else if (is_ignored) "" else ""
+
+
+ /* source text */
+
+ val source: String = span.map(_.source).mkString
+ def source(i: Int, j: Int): String = source.substring(i, j)
+ def length: Int = source.length
+
+ lazy val symbol_index = new Symbol.Index(source)
+
+
+ /* accumulated messages */
+
+ @volatile protected var state = new State(this)
+ def current_state: State = state
+
+ private case class Consume(session: Session, message: XML.Tree)
+ private case object Assign
+
+ private val accumulator = actor {
+ var assigned = false
+ loop {
+ react {
+ case Consume(session: Session, message: XML.Tree) if !assigned =>
+ state = state.+(session, message)
+
+ case Assign =>
+ assigned = true // single assignment
+ reply(())
+
+ case bad => System.err.println("command accumulator: ignoring bad message " + bad)
+ }
+ }
+ }
+
+ def consume(session: Session, message: XML.Tree) { accumulator ! Consume(session, message) }
+
+ def assign_state(state_id: Isar_Document.State_ID): Command =
+ {
+ val cmd = new Command(state_id, span)
+ accumulator !? Assign
+ cmd.state = current_state
+ cmd
+ }
+
+
+ /* markup */
+
+ lazy val empty_markup = new Markup_Text(Nil, source)
+
+ def markup_node(begin: Int, end: Int, info: Any): Markup_Tree =
+ {
+ val start = symbol_index.decode(begin)
+ val stop = symbol_index.decode(end)
+ new Markup_Tree(new Markup_Node(start, stop, info), Nil)
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/proofdocument/document.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/proofdocument/document.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,197 @@
+/*
+ * Document as editable list of commands
+ *
+ * @author Makarius
+ */
+
+package isabelle.proofdocument
+
+
+object Document
+{
+ /* command start positions */
+
+ def command_starts(commands: Linear_Set[Command]): Iterator[(Command, Int)] =
+ {
+ var offset = 0
+ for (cmd <- commands.elements) yield {
+ val start = offset
+ offset += cmd.length
+ (cmd, start)
+ }
+ }
+
+
+ /* empty document */
+
+ def empty(id: Isar_Document.Document_ID): Document =
+ {
+ val doc = new Document(id, Linear_Set(), Map())
+ doc.assign_states(Nil)
+ doc
+ }
+
+
+ // FIXME
+ var phase0: List[Text_Edit] = null
+ var phase1: Linear_Set[Command] = null
+ var phase2: Linear_Set[Command] = null
+ var phase3: List[Edit] = null
+
+
+
+ /** document edits **/
+
+ type Edit = (Option[Command], Option[Command])
+
+ def text_edits(session: Session, old_doc: Document, new_id: Isar_Document.Document_ID,
+ edits: List[Text_Edit]): (List[Edit], Document) =
+ {
+ require(old_doc.assignment.is_finished)
+
+
+ /* unparsed dummy commands */
+
+ def unparsed(source: String) =
+ new Command(null, List(Outer_Lex.Token(Outer_Lex.Token_Kind.UNPARSED, source)))
+
+ def is_unparsed(command: Command) = command.id == null
+
+ assert(!old_doc.commands.exists(is_unparsed)) // FIXME remove
+
+
+ /* phase 1: edit individual command source */
+
+ def edit_text(eds: List[Text_Edit], commands: Linear_Set[Command]): Linear_Set[Command] =
+ {
+ eds match {
+ case e :: es =>
+ command_starts(commands).find { // FIXME relative search!
+ case (cmd, cmd_start) =>
+ e.can_edit(cmd.source, cmd_start) || e.is_insert && e.start == cmd_start + cmd.length
+ } match {
+ case Some((cmd, cmd_start)) if e.can_edit(cmd.source, cmd_start) =>
+ val (rest, text) = e.edit(cmd.source, cmd_start)
+ val new_commands = commands.insert_after(Some(cmd), unparsed(text)) - cmd
+ edit_text(rest.toList ::: es, new_commands)
+
+ case Some((cmd, cmd_start)) =>
+ edit_text(es, commands.insert_after(Some(cmd), unparsed(e.text)))
+
+ case None =>
+ require(e.is_insert && e.start == 0)
+ edit_text(es, commands.insert_after(None, unparsed(e.text)))
+ }
+ case Nil => commands
+ }
+ }
+
+
+ /* phase 2: recover command spans */
+
+ def parse_spans(commands: Linear_Set[Command]): Linear_Set[Command] =
+ {
+ // FIXME relative search!
+ commands.elements.find(is_unparsed) match {
+ case Some(first_unparsed) =>
+ val prefix = commands.prev(first_unparsed)
+ val body = commands.elements(first_unparsed).takeWhile(is_unparsed).toList
+ val suffix = commands.next(body.last)
+
+ val sources = (prefix.toList ::: body ::: suffix.toList).flatMap(_.span.map(_.source))
+ val spans0 = Thy_Syntax.parse_spans(session.current_syntax.scan(sources.mkString))
+
+ val (before_edit, spans1) =
+ if (!spans0.isEmpty && Some(spans0.first) == prefix.map(_.span))
+ (prefix, spans0.tail)
+ else (if (prefix.isDefined) commands.prev(prefix.get) else None, spans0)
+
+ val (after_edit, spans2) =
+ if (!spans1.isEmpty && Some(spans1.last) == suffix.map(_.span))
+ (suffix, spans1.take(spans1.length - 1))
+ else (if (suffix.isDefined) commands.next(suffix.get) else None, spans1)
+
+ val inserted = spans2.map(span => new Command(session.create_id(), span))
+ val new_commands =
+ commands.delete_between(before_edit, after_edit).append_after(before_edit, inserted)
+ parse_spans(new_commands)
+
+ case None => commands
+ }
+ }
+
+
+ /* phase 3: resulting document edits */
+
+ val result = Library.timeit("text_edits") {
+ val commands0 = old_doc.commands
+ val commands1 = Library.timeit("edit_text") { edit_text(edits, commands0) }
+ val commands2 = Library.timeit("parse_spans") { parse_spans(commands1) }
+
+ val removed_commands = commands0.elements.filter(!commands2.contains(_)).toList
+ val inserted_commands = commands2.elements.filter(!commands0.contains(_)).toList
+
+ val doc_edits =
+ removed_commands.reverse.map(cmd => (commands0.prev(cmd), None)) :::
+ inserted_commands.map(cmd => (commands2.prev(cmd), Some(cmd)))
+
+ val former_states = old_doc.assignment.join -- removed_commands
+
+ phase0 = edits
+ phase1 = commands1
+ phase2 = commands2
+ phase3 = doc_edits
+
+ (doc_edits, new Document(new_id, commands2, former_states))
+ }
+ result
+ }
+}
+
+
+class Document(
+ val id: Isar_Document.Document_ID,
+ val commands: Linear_Set[Command],
+ former_states: Map[Command, Command])
+{
+ /* command ranges */
+
+ def command_starts: Iterator[(Command, Int)] = Document.command_starts(commands)
+
+ def command_start(cmd: Command): Option[Int] =
+ command_starts.find(_._1 == cmd).map(_._2)
+
+ def command_range(i: Int): Iterator[(Command, Int)] =
+ command_starts dropWhile { case (cmd, start) => start + cmd.length <= i }
+
+ def command_range(i: Int, j: Int): Iterator[(Command, Int)] =
+ command_range(i) takeWhile { case (_, start) => start < j }
+
+ def command_at(i: Int): Option[(Command, Int)] =
+ {
+ val range = command_range(i)
+ if (range.hasNext) Some(range.next) else None
+ }
+
+
+ /* command state assignment */
+
+ val assignment = Future.promise[Map[Command, Command]]
+ def await_assignment { assignment.join }
+
+ @volatile private var tmp_states = former_states
+ private val time0 = System.currentTimeMillis
+
+ def assign_states(new_states: List[(Command, Command)])
+ {
+ assignment.fulfill(tmp_states ++ new_states)
+ tmp_states = Map()
+ System.err.println("assign_states: " + (System.currentTimeMillis - time0) + " ms elapsed time")
+ }
+
+ def current_state(cmd: Command): Option[State] =
+ {
+ require(assignment.is_finished)
+ (assignment.join).get(cmd).map(_.current_state)
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/proofdocument/html_panel.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/proofdocument/html_panel.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,140 @@
+/*
+ * HTML panel based on Lobo/Cobra
+ *
+ * @author Makarius
+ */
+
+package isabelle.proofdocument
+
+
+import java.io.StringReader
+import java.awt.{BorderLayout, Dimension}
+import java.awt.event.MouseEvent
+
+import javax.swing.{JButton, JPanel, JScrollPane}
+import java.util.logging.{Logger, Level}
+
+import org.w3c.dom.html2.HTMLElement
+
+import org.lobobrowser.html.parser.{DocumentBuilderImpl, InputSourceImpl}
+import org.lobobrowser.html.gui.HtmlPanel
+import org.lobobrowser.html.domimpl.{HTMLDocumentImpl, HTMLStyleElementImpl, NodeImpl}
+import org.lobobrowser.html.test.{SimpleHtmlRendererContext, SimpleUserAgentContext}
+
+import scala.io.Source
+import scala.actors.Actor._
+
+
+object HTML_Panel
+{
+ sealed abstract class Event { val element: HTMLElement; val mouse: MouseEvent }
+ case class Context_Menu(val element: HTMLElement, mouse: MouseEvent) extends Event
+ case class Mouse_Click(val element: HTMLElement, mouse: MouseEvent) extends Event
+ case class Double_Click(val element: HTMLElement, mouse: MouseEvent) extends Event
+ case class Mouse_Over(val element: HTMLElement, mouse: MouseEvent) extends Event
+ case class Mouse_Out(val element: HTMLElement, mouse: MouseEvent) extends Event
+}
+
+
+class HTML_Panel(
+ sys: Isabelle_System,
+ initial_font_size: Int,
+ handler: PartialFunction[HTML_Panel.Event, Unit]) extends HtmlPanel
+{
+ // global logging
+ Logger.getLogger("org.lobobrowser").setLevel(Level.WARNING)
+
+
+ /* document template */
+
+ private def try_file(name: String): String =
+ {
+ val file = sys.platform_file(name)
+ if (file.isFile) Source.fromFile(file).mkString else ""
+ }
+
+ private def template(font_size: Int): String =
+ """
+
+
+
+
+
+
+
+"""
+
+
+ /* actor with local state */
+
+ private val ucontext = new SimpleUserAgentContext
+
+ private val rcontext = new SimpleHtmlRendererContext(this, ucontext)
+ {
+ private def handle(event: HTML_Panel.Event): Boolean =
+ if (handler != null && handler.isDefinedAt(event)) { handler(event); true }
+ else false
+
+ override def onContextMenu(elem: HTMLElement, event: MouseEvent): Boolean =
+ handle(HTML_Panel.Context_Menu(elem, event))
+ override def onMouseClick(elem: HTMLElement, event: MouseEvent): Boolean =
+ handle(HTML_Panel.Mouse_Click(elem, event))
+ override def onDoubleClick(elem: HTMLElement, event: MouseEvent): Boolean =
+ handle(HTML_Panel.Double_Click(elem, event))
+ override def onMouseOver(elem: HTMLElement, event: MouseEvent)
+ { handle(HTML_Panel.Mouse_Over(elem, event)) }
+ override def onMouseOut(elem: HTMLElement, event: MouseEvent)
+ { handle(HTML_Panel.Mouse_Out(elem, event)) }
+ }
+
+ private val builder = new DocumentBuilderImpl(ucontext, rcontext)
+
+ private case class Init(font_size: Int)
+ private case class Render(body: List[XML.Tree])
+
+ private val main_actor = actor {
+ // crude double buffering
+ var doc1: org.w3c.dom.Document = null
+ var doc2: org.w3c.dom.Document = null
+
+ loop {
+ react {
+ case Init(font_size) =>
+ val src = template(font_size)
+ def parse() =
+ builder.parse(new InputSourceImpl(new StringReader(src), "http://localhost"))
+ doc1 = parse()
+ doc2 = parse()
+ Swing_Thread.now { setDocument(doc1, rcontext) }
+
+ case Render(body) =>
+ val doc = doc2
+ val node =
+ XML.document_node(doc,
+ XML.elem(HTML.BODY, body.map((t: XML.Tree) => XML.elem(HTML.PRE, HTML.spans(t)))))
+ doc.removeChild(doc.getLastChild())
+ doc.appendChild(node)
+ doc2 = doc1
+ doc1 = doc
+ Swing_Thread.now { setDocument(doc1, rcontext) }
+
+ case bad => System.err.println("main_actor: ignoring bad message " + bad)
+ }
+ }
+ }
+
+ main_actor ! Init(initial_font_size)
+
+
+ /* main method wrappers */
+
+ def init(font_size: Int) { main_actor ! Init(font_size) }
+ def render(body: List[XML.Tree]) { main_actor ! Render(body) }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/proofdocument/markup_node.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/proofdocument/markup_node.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,111 @@
+/*
+ * Document markup nodes, with connection to Swing tree model
+ *
+ * @author Fabian Immler, TU Munich
+ * @author Makarius
+ */
+
+package isabelle.proofdocument
+
+
+import javax.swing.tree.DefaultMutableTreeNode
+
+
+
+class Markup_Node(val start: Int, val stop: Int, val info: Any)
+{
+ def fits_into(that: Markup_Node): Boolean =
+ that.start <= this.start && this.stop <= that.stop
+}
+
+
+class Markup_Tree(val node: Markup_Node, val branches: List[Markup_Tree])
+{
+ def set_branches(bs: List[Markup_Tree]): Markup_Tree = new Markup_Tree(node, bs)
+
+ private def add(branch: Markup_Tree) = // FIXME avoid sort
+ set_branches((branch :: branches) sort ((a, b) => a.node.start < b.node.start))
+
+ private def remove(bs: List[Markup_Tree]) = set_branches(branches -- bs)
+
+ def + (new_tree: Markup_Tree): Markup_Tree =
+ {
+ val new_node = new_tree.node
+ if (new_node fits_into node) {
+ var inserted = false
+ val new_branches =
+ branches.map(branch =>
+ if ((new_node fits_into branch.node) && !inserted) {
+ inserted = true
+ branch + new_tree
+ }
+ else branch)
+ if (!inserted) {
+ // new_tree did not fit into children of this
+ // -> insert between this and its branches
+ val fitting = branches filter(_.node fits_into new_node)
+ (this remove fitting) add ((new_tree /: fitting)(_ + _))
+ }
+ else set_branches(new_branches)
+ }
+ else {
+ System.err.println("ignored nonfitting markup: " + new_node)
+ this
+ }
+ }
+
+ def flatten: List[Markup_Node] =
+ {
+ var next_x = node.start
+ if (branches.isEmpty) List(this.node)
+ else {
+ val filled_gaps =
+ for {
+ child <- branches
+ markups =
+ if (next_x < child.node.start)
+ new Markup_Node(next_x, child.node.start, node.info) :: child.flatten
+ else child.flatten
+ update = (next_x = child.node.stop)
+ markup <- markups
+ } yield markup
+ if (next_x < node.stop)
+ filled_gaps + new Markup_Node(next_x, node.stop, node.info)
+ else filled_gaps
+ }
+ }
+}
+
+
+class Markup_Text(val markup: List[Markup_Tree], val content: String)
+{
+ private lazy val root =
+ new Markup_Tree(new Markup_Node(0, content.length, None), markup)
+
+ def + (new_tree: Markup_Tree): Markup_Text =
+ new Markup_Text((root + new_tree).branches, content)
+
+ def filter(pred: Markup_Node => Boolean): Markup_Text =
+ {
+ def filt(tree: Markup_Tree): List[Markup_Tree] =
+ {
+ val branches = tree.branches.flatMap(filt(_))
+ if (pred(tree.node)) List(tree.set_branches(branches))
+ else branches
+ }
+ new Markup_Text(markup.flatMap(filt(_)), content)
+ }
+
+ def flatten: List[Markup_Node] = markup.flatten(_.flatten)
+
+ def swing_tree(swing_node: Markup_Node => DefaultMutableTreeNode): DefaultMutableTreeNode =
+ {
+ def swing(tree: Markup_Tree): DefaultMutableTreeNode =
+ {
+ val node = swing_node(tree.node)
+ tree.branches foreach ((branch: Markup_Tree) => node.add(swing(branch)))
+ node
+ }
+ swing(root)
+ }
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/proofdocument/session.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/proofdocument/session.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,250 @@
+/*
+ * Isabelle session, potentially with running prover
+ *
+ * @author Makarius
+ */
+
+package isabelle.proofdocument
+
+
+import scala.actors.TIMEOUT
+import scala.actors.Actor._
+
+
+object Session
+{
+ /* events */
+
+ case object Global_Settings
+
+
+ /* managed entities */
+
+ type Entity_ID = String
+
+ trait Entity
+ {
+ val id: Entity_ID
+ def consume(session: Session, message: XML.Tree): Unit
+ }
+}
+
+
+class Session(system: Isabelle_System)
+{
+ /* pervasive event buses */
+
+ val global_settings = new Event_Bus[Session.Global_Settings.type]
+ val raw_results = new Event_Bus[Isabelle_Process.Result]
+ val results = new Event_Bus[Command]
+
+ val command_change = new Event_Bus[Command]
+
+
+ /* unique ids */
+
+ private var id_count: BigInt = 0
+ def create_id(): Session.Entity_ID = synchronized { id_count += 1; "j" + id_count }
+
+
+
+ /** main actor **/
+
+ @volatile private var syntax = new Outer_Syntax(system.symbols)
+ def current_syntax: Outer_Syntax = syntax
+
+ @volatile private var entities = Map[Session.Entity_ID, Session.Entity]()
+ def lookup_entity(id: Session.Entity_ID): Option[Session.Entity] = entities.get(id)
+ def lookup_command(id: Session.Entity_ID): Option[Command] =
+ lookup_entity(id) match {
+ case Some(cmd: Command) => Some(cmd)
+ case _ => None
+ }
+
+ private case class Start(timeout: Int, args: List[String])
+ private case object Stop
+ private case class Begin_Document(path: String)
+
+ private val session_actor = actor {
+
+ var prover: Isabelle_Process with Isar_Document = null
+
+ def register(entity: Session.Entity) { entities += (entity.id -> entity) }
+
+ var documents = Map[Isar_Document.Document_ID, Document]()
+ def register_document(doc: Document) { documents += (doc.id -> doc) }
+
+
+ /* document changes */
+
+ def handle_change(change: Change)
+ {
+ require(change.parent.isDefined)
+
+ val (changes, doc) = change.result.join
+ val id_changes = changes map {
+ case (c1, c2) =>
+ (c1.map(_.id).getOrElse(""),
+ c2 match {
+ case None => None
+ case Some(command) =>
+ if (!lookup_command(command.id).isDefined) {
+ register(command)
+ prover.define_command(command.id, system.symbols.encode(command.source))
+ }
+ Some(command.id)
+ })
+ }
+ register_document(doc)
+ prover.edit_document(change.parent.get.id, doc.id, id_changes)
+ }
+
+
+ /* prover results */
+
+ def bad_result(result: Isabelle_Process.Result)
+ {
+ System.err.println("Ignoring prover result: " + result)
+ }
+
+ def handle_result(result: Isabelle_Process.Result)
+ {
+ raw_results.event(result)
+
+ val target_id: Option[Session.Entity_ID] = Position.get_id(result.props)
+ val target: Option[Session.Entity] =
+ target_id match {
+ case None => None
+ case Some(id) => lookup_entity(id)
+ }
+ if (target.isDefined) target.get.consume(this, result.message)
+ else if (result.kind == Isabelle_Process.Kind.STATUS) {
+ // global status message
+ result.body match {
+
+ // document state assigment
+ case List(XML.Elem(Markup.ASSIGN, _, edits)) if target_id.isDefined =>
+ documents.get(target_id.get) match {
+ case Some(doc) =>
+ val states =
+ for {
+ XML.Elem(Markup.EDIT, (Markup.ID, cmd_id) :: (Markup.STATE, state_id) :: _, _)
+ <- edits
+ cmd <- lookup_command(cmd_id)
+ } yield {
+ val st = cmd.assign_state(state_id)
+ register(st)
+ (cmd, st)
+ }
+ doc.assign_states(states)
+ case None => bad_result(result)
+ }
+
+ // command and keyword declarations
+ case List(XML.Elem(Markup.COMMAND_DECL, (Markup.NAME, name) :: (Markup.KIND, kind) :: _, _)) =>
+ syntax += (name, kind)
+ case List(XML.Elem(Markup.KEYWORD_DECL, (Markup.NAME, name) :: _, _)) =>
+ syntax += name
+
+ case _ => if (!result.is_ready) bad_result(result)
+ }
+ }
+ else if (result.kind == Isabelle_Process.Kind.EXIT)
+ prover = null
+ else if (result.kind != Isabelle_Process.Kind.STDIN && !result.is_raw)
+ bad_result(result)
+ }
+
+
+ /* prover startup */
+
+ def startup_error(): String =
+ {
+ val buf = new StringBuilder
+ while (
+ receiveWithin(0) {
+ case result: Isabelle_Process.Result =>
+ if (result.is_raw) {
+ for (text <- XML.content(result.message))
+ buf.append(text)
+ }
+ true
+ case TIMEOUT => false
+ }) {}
+ buf.toString
+ }
+
+ def prover_startup(timeout: Int): Option[String] =
+ {
+ receiveWithin(timeout) {
+ case result: Isabelle_Process.Result
+ if result.kind == Isabelle_Process.Kind.INIT =>
+ while (receive {
+ case result: Isabelle_Process.Result =>
+ handle_result(result); !result.is_ready
+ }) {}
+ None
+
+ case result: Isabelle_Process.Result
+ if result.kind == Isabelle_Process.Kind.EXIT =>
+ Some(startup_error())
+
+ case TIMEOUT => // FIXME clarify
+ prover.kill; Some(startup_error())
+ }
+ }
+
+
+ /* main loop */
+
+ val xml_cache = new XML.Cache(131071)
+
+ loop {
+ react {
+ case Start(timeout, args) =>
+ if (prover == null) {
+ prover = new Isabelle_Process(system, self, args:_*) with Isar_Document
+ val origin = sender
+ val opt_err = prover_startup(timeout)
+ if (opt_err.isDefined) prover = null
+ origin ! opt_err
+ }
+ else reply(None)
+
+ case Stop => // FIXME clarify; synchronous
+ if (prover != null) {
+ prover.kill
+ prover = null
+ }
+
+ case Begin_Document(path: String) if prover != null =>
+ val id = create_id()
+ val doc = Document.empty(id)
+ register_document(doc)
+ prover.begin_document(id, path)
+ reply(doc)
+
+ case change: Change if prover != null =>
+ handle_change(change)
+
+ case result: Isabelle_Process.Result =>
+ handle_result(result.cache(xml_cache))
+
+ case bad if prover != null =>
+ System.err.println("session_actor: ignoring bad message " + bad)
+ }
+ }
+ }
+
+
+ /* main methods */
+
+ def start(timeout: Int, args: List[String]): Option[String] =
+ (session_actor !? Start(timeout, args)).asInstanceOf[Option[String]]
+
+ def stop() { session_actor ! Stop }
+ def input(change: Change) { session_actor ! change }
+
+ def begin_document(path: String): Document =
+ (session_actor !? Begin_Document(path)).asInstanceOf[Document]
+}
diff -r c1509b9d624f -r 502f90967483 src/Tools/jEdit/src/proofdocument/state.scala
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Tools/jEdit/src/proofdocument/state.scala Mon Jan 11 22:31:27 2010 +0100
@@ -0,0 +1,117 @@
+/*
+ * Accumulating results from prover
+ *
+ * @author Fabian Immler, TU Munich
+ * @author Makarius
+ */
+
+package isabelle.proofdocument
+
+
+class State(
+ val command: Command,
+ val status: Command.Status.Value,
+ val rev_results: List[XML.Tree],
+ val markup_root: Markup_Text)
+{
+ def this(command: Command) =
+ this(command, Command.Status.UNPROCESSED, Nil, command.empty_markup)
+
+
+ /* content */
+
+ private def set_status(st: Command.Status.Value): State =
+ new State(command, st, rev_results, markup_root)
+
+ private def add_result(res: XML.Tree): State =
+ new State(command, status, res :: rev_results, markup_root)
+
+ private def add_markup(node: Markup_Tree): State =
+ new State(command, status, rev_results, markup_root + node)
+
+ lazy val results = rev_results.reverse
+
+
+ /* markup */
+
+ lazy val highlight: Markup_Text =
+ {
+ markup_root.filter(_.info match {
+ case Command.HighlightInfo(_) => true
+ case _ => false
+ })
+ }
+
+ private lazy val types: List[Markup_Node] =
+ markup_root.filter(_.info match {
+ case Command.TypeInfo(_) => true
+ case _ => false }).flatten
+
+ def type_at(pos: Int): Option[String] =
+ {
+ types.find(t => t.start <= pos && pos < t.stop) match {
+ case Some(t) =>
+ t.info match {
+ case Command.TypeInfo(ty) => Some(command.source(t.start, t.stop) + ": " + ty)
+ case _ => None
+ }
+ case None => None
+ }
+ }
+
+ private lazy val refs: List[Markup_Node] =
+ markup_root.filter(_.info match {
+ case Command.RefInfo(_, _, _, _) => true
+ case _ => false }).flatten
+
+ def ref_at(pos: Int): Option[Markup_Node] =
+ refs.find(t => t.start <= pos && pos < t.stop)
+
+
+ /* message dispatch */
+
+ def + (session: Session, message: XML.Tree): State =
+ {
+ val changed: State =
+ message match {
+ case XML.Elem(Markup.MESSAGE, (Markup.CLASS, Markup.STATUS) :: _, elems) =>
+ (this /: elems)((state, elem) =>
+ elem match {
+ case XML.Elem(Markup.UNPROCESSED, _, _) => state.set_status(Command.Status.UNPROCESSED)
+ case XML.Elem(Markup.FINISHED, _, _) => state.set_status(Command.Status.FINISHED)
+ case XML.Elem(Markup.FAILED, _, _) => state.set_status(Command.Status.FAILED)
+ case XML.Elem(kind, atts, body) =>
+ val (begin, end) = Position.get_offsets(atts)
+ if (begin.isEmpty || end.isEmpty) state
+ else if (kind == Markup.ML_TYPING) {
+ val info = body.first.asInstanceOf[XML.Text].content // FIXME proper match!?
+ state.add_markup(
+ command.markup_node(begin.get - 1, end.get - 1, Command.TypeInfo(info)))
+ }
+ else if (kind == Markup.ML_REF) {
+ body match {
+ case List(XML.Elem(Markup.ML_DEF, atts, _)) =>
+ state.add_markup(command.markup_node(
+ begin.get - 1, end.get - 1,
+ Command.RefInfo(
+ Position.get_file(atts),
+ Position.get_line(atts),
+ Position.get_id(atts),
+ Position.get_offset(atts))))
+ case _ => state
+ }
+ }
+ else {
+ state.add_markup(
+ command.markup_node(begin.get - 1, end.get - 1, Command.HighlightInfo(kind)))
+ }
+ case _ =>
+ System.err.println("ignored status report: " + elem)
+ state
+ })
+ case _ => add_result(message)
+ }
+ if (!(this eq changed)) session.command_change.event(command)
+ changed
+ }
+}