Permalink
Browse files

Properties: improve handling of whitespace, empty props, and undersco…

…res in keys

This brings the lens closer to the Java specification

With help from Carlos Sanchez <csanchez@maestrodev.com> and Dominic Cleal
<dcleal@redhat.com>
  • Loading branch information...
1 parent c177f81 commit 6ffc07ef9717a8878d554a24997d0d89ed42148c @brettporter brettporter committed with Apr 7, 2012
Showing with 153 additions and 15 deletions.
  1. +2 −0 AUTHORS
  2. +36 −14 lenses/properties.aug
  3. +115 −1 lenses/tests/test_properties.aug
View
@@ -47,10 +47,12 @@ Contributions by:
Matt Palmer <matt@anchor.net.au>
Bill Pemberton <wfp5p@virginia.edu>
Alan Pevec <apevec@redhat.com>
+ Brett Porter <brett@apache.org>
Robin Lee Powell <rlpowell@digitalkingdom.org>
Andrew Replogle <areplogl@redhat.com>
Lubomir Rintel <lubo.rintel@gooddata.com>
Roman Rakus <rrakus@redhat.com>
+ Carlos Sanchez <csanchez@maestrodev.com>
Satoru SATOH <satoru.satoh@gmail.com>
Nicolas Valcárcel Scerpella <nvalcarcel@ubuntu.com>
Nahum Shalman <nshalman elys com>
View
@@ -1,25 +1,47 @@
-(* Augeas module for editing tomcat properties files
+(* Augeas module for editing Java properties files
Author: Craig Dunn <craig@craigdunn.org>
- FIXME: Doesn't cover everything that's legal in Java properties yet
- - multiline
- - "!" comments
- - key:value syntax
+ Limitations:
+ - doesn't support \ alone on a line
+ - values are not unescaped
+ - multi-line properties are broken down by line, and can't be replaced with a single line
+
+ See format info: http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html#load(java.io.Reader)
*)
module Properties =
(* Define some basic primitives *)
- let empty = Util.empty
- let eol = Util.eol
- let sepch = del /[ \t]*=[ \t]*/ "="
- let value_to_eol = /[^ \t\n](.*[^ \t\n])?/
- let indent = Util.indent
- let entry = /[A-Za-z][A-Za-z0-9.]+/
+ let empty = Util.empty
+ let eol = Util.eol
+ let hard_eol = del "\n" "\n"
+ let sepch = del /([ \t]*(=|:)|[ \t])/ "="
+ let sepspc = del /[ \t]/ " "
+ let sepch_ns = del /[ \t]*(=|:)/ "="
+ let sepch_opt = del /[ \t]*(=|:)?[ \t]*/ "="
+ let value_to_eol_ws = store /(:|=)[^\n]*[^ \t\n\\]/
+ let value_to_bs_ws = store /(:|=)[^\n]*[^\\\n]/
+ let value_to_eol = store /([^ \t\n:=][^\n]*[^ \t\n\\]|[^ \t\n\\:=])/
+ let value_to_bs = store /([^ \t\n:=][^\n]*[^\\\n]|[^ \t\n\\:=])/
+ let indent = Util.indent
+ let backslash = del /[\\][ \t]*\n/ "\\\n"
+ let entry = /([^ \t\n:=\/!#\\]|[\\]:|[\\]=|[\\][\t ]|[\\][^\/\n])+/
+
+ let multi_line_entry =
+ [ indent . value_to_bs . backslash ] + .
+ [ indent . value_to_eol . eol ] . value " < multi > "
+
+ let multi_line_entry_ws =
+ [ indent . value_to_bs_ws . backslash ] + .
+ [ indent . value_to_eol . eol ] . value " < multi_ws > "
(* define comments and properties*)
- let comment = Util.comment
- let property = [ indent . key entry . sepch . store value_to_eol . eol ]
+ let bang_comment = [ label "!comment" . del /[ \t]*![ \t]*/ "! " . store /([^ \t\n].*[^ \t\n]|[^ \t\n])/ . eol ]
+ let comment = ( Util.comment | bang_comment )
+ let property = [ indent . key entry . sepch . ( multi_line_entry | indent . value_to_eol . eol ) ]
+ let property_ws = [ indent . key entry . sepch_ns . ( multi_line_entry_ws | indent . value_to_eol_ws . eol ) ]
+ let empty_property = [ indent . key entry . sepch_opt . hard_eol ]
+ let empty_key = [ sepch_ns . ( multi_line_entry | indent . value_to_eol . eol ) ]
(* setup our lens and filter*)
- let lns = ( property | empty | comment ) *
+ let lns = ( empty | comment | property_ws | property | empty_property | empty_key ) *
@@ -6,8 +6,47 @@ module Test_properties =
tomcat.port = 8080
tomcat.application.name=testapp
tomcat.application.description=my test application
+property.with_underscore=works
+empty.property=
+empty.property.withtrailingspaces= \n! more comments
+key: value
+key2:value2
+key3 :value3
+key4:=value4
+
+long.description=this is a description that happens to span \
+ more than one line with a combination of tabs and \
+ spaces \ \nor not
+
+# comment break
+
+short.break = a\
+ b
+
+=empty_key
+ =empty_key
+
+cheeses
+
+spaces only
+multi spaces
+ indented spaces
+
+\= =A
+space and = equals
+space with \
+ multiline
+
+escaped\:colon=value
+escaped\=equals=value
+escaped\ space=value
"
+(* Other tests that aren't supported yet
+overflow.description=\
+ just wanted to indent it
+*)
+
let lns = Properties.lns
test lns get conf =
@@ -18,7 +57,48 @@ test lns get conf =
{ "tomcat.port" = "8080" }
{ "tomcat.application.name" = "testapp" }
{ "tomcat.application.description" = "my test application" }
-
+ { "property.with_underscore" = "works" }
+ { "empty.property" }
+ { "empty.property.withtrailingspaces" }
+ { "!comment" = "more comments" }
+ { "key" = "value" }
+ { "key2" = "value2" }
+ { "key3" = "value3" }
+ { "key4" = "=value4" }
+ {}
+ { "long.description" = " < multi > "
+ { = "this is a description that happens to span " }
+ { = "more than one line with a combination of tabs and " }
+ { = "spaces " }
+ { = "or not" }
+ }
+ {}
+ { "#comment" = "comment break" }
+ {}
+ { "short.break" = " < multi > "
+ { = "a" }
+ { = "b" }
+ }
+ {}
+ { = "empty_key" }
+ { = "empty_key" }
+ {}
+ { "cheeses" }
+ {}
+ { "spaces" = "only" }
+ { "multi" = "spaces" }
+ { "indented" = "spaces" }
+ {}
+ { "\\=" = "A" }
+ { "space" = "and = equals" }
+ { "space" = " < multi > "
+ { = "with " }
+ { = "multiline" }
+ }
+ {}
+ { "escaped\:colon" = "value" }
+ { "escaped\=equals" = "value" }
+ { "escaped\ space" = "value" }
test lns put conf after
set "tomcat.port" "99";
set "tomcat.application.host" "foo.network.com"
@@ -29,5 +109,39 @@ test lns put conf after
tomcat.port = 99
tomcat.application.name=testapp
tomcat.application.description=my test application
+property.with_underscore=works
+empty.property=
+empty.property.withtrailingspaces= \n! more comments
+key: value
+key2:value2
+key3 :value3
+key4:=value4
+
+long.description=this is a description that happens to span \
+ more than one line with a combination of tabs and \
+ spaces \ \nor not
+
+# comment break
+
+short.break = a\
+ b
+
+=empty_key
+ =empty_key
+
+cheeses
+
+spaces only
+multi spaces
+ indented spaces
+
+\= =A
+space and = equals
+space with \
+ multiline
+
+escaped\:colon=value
+escaped\=equals=value
+escaped\ space=value
tomcat.application.host=foo.network.com
"

0 comments on commit 6ffc07e

Please sign in to comment.