Add test_fonts.aug

Add test_fonts.aug

(*
Module: Test_Fonts
  Provides unit tests and examples for the <Fonts> lens.
*)

module Test_Fonts =

(* Variable: conf *)
let conf = "<?xml version=\"1.0\"?>
<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">
<!-- /etc/fonts/fonts.conf file to configure system font access -->
<fontconfig>

<!--
	DO NOT EDIT THIS FILE.
	IT WILL BE REPLACED WHEN FONTCONFIG IS UPDATED.
	LOCAL CHANGES BELONG IN 'local.conf'.

	The intent of this standard configuration file is to be adequate for
	most environments.  If you have a reasonably normal environment and
	have found problems with this configuration, they are probably
	things that others will also want fixed.  Please submit any
	problems to the fontconfig bugzilla system located at fontconfig.org

	Note that the normal 'make install' procedure for fontconfig is to
	replace any existing fonts.conf file with the new version.  Place
	any local customizations in local.conf which this file references.

	Keith Packard
-->

<!-- Font directory list -->

	<dir>/usr/share/fonts</dir>
	<dir>/usr/X11R6/lib/X11/fonts</dir> <dir>/usr/local/share/fonts</dir>
	<dir>~/.fonts</dir>

<!--
  Accept deprecated 'mono' alias, replacing it with 'monospace'
-->
	<match target=\"pattern\">
		<test qual=\"any\" name=\"family\">
			<string>mono</string>
		</test>
		<edit name=\"family\" mode=\"assign\">
			<string>monospace</string>
		</edit>
	</match>

<!--
  Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
-->
	<match target=\"pattern\">
		<test qual=\"any\" name=\"family\">
			<string>sans serif</string>
		</test>
		<edit name=\"family\" mode=\"assign\">
			<string>sans-serif</string>
		</edit>
	</match>

<!--
  Accept deprecated 'sans' alias, replacing it with 'sans-serif'
-->
	<match target=\"pattern\">
		<test qual=\"any\" name=\"family\">
			<string>sans</string>
		</test>
		<edit name=\"family\" mode=\"assign\">
			<string>sans-serif</string>
		</edit>
	</match>

<!--
  Load local system customization file
-->
	<include ignore_missing=\"yes\">conf.d</include>

<!-- Font cache directory list -->

	<cachedir>/var/cache/fontconfig</cachedir>
	<cachedir>~/.fontconfig</cachedir>

	<config>
<!--
  These are the default Unicode chars that are expected to be blank
  in fonts.  All other blank chars are assumed to be broken and
  won't appear in the resulting charsets
 -->
		<blank>
			<int>0x0020</int>	<!-- SPACE -->
			<int>0x00A0</int>	<!-- NO-BREAK SPACE -->
			<int>0x00AD</int>	<!-- SOFT HYPHEN -->
			<int>0x034F</int>	<!-- COMBINING GRAPHEME JOINER -->
			<int>0x0600</int>	<!-- ARABIC NUMBER SIGN -->
			<int>0x0601</int>	<!-- ARABIC SIGN SANAH -->
			<int>0x0602</int>	<!-- ARABIC FOOTNOTE MARKER -->
			<int>0x0603</int>	<!-- ARABIC SIGN SAFHA -->
			<int>0x06DD</int>	<!-- ARABIC END OF AYAH -->
			<int>0x070F</int>	<!-- SYRIAC ABBREVIATION MARK -->
			<int>0x115F</int>	<!-- HANGUL CHOSEONG FILLER -->
			<int>0x1160</int>	<!-- HANGUL JUNGSEONG FILLER -->
			<int>0x1680</int>	<!-- OGHAM SPACE MARK -->
			<int>0x17B4</int>	<!-- KHMER VOWEL INHERENT AQ -->
			<int>0x17B5</int>	<!-- KHMER VOWEL INHERENT AA -->
			<int>0x180E</int>	<!-- MONGOLIAN VOWEL SEPARATOR -->
			<int>0x2000</int>	<!-- EN QUAD -->
			<int>0x2001</int>	<!-- EM QUAD -->
			<int>0x2002</int>	<!-- EN SPACE -->
			<int>0x2003</int>	<!-- EM SPACE -->
			<int>0x2004</int>	<!-- THREE-PER-EM SPACE -->
			<int>0x2005</int>	<!-- FOUR-PER-EM SPACE -->
			<int>0x2006</int>	<!-- SIX-PER-EM SPACE -->
			<int>0x2007</int>	<!-- FIGURE SPACE -->
			<int>0x2008</int>	<!-- PUNCTUATION SPACE -->
			<int>0x2009</int>	<!-- THIN SPACE -->
			<int>0x200A</int>	<!-- HAIR SPACE -->
			<int>0x200B</int>	<!-- ZERO WIDTH SPACE -->
			<int>0x200C</int>	<!-- ZERO WIDTH NON-JOINER -->
			<int>0x200D</int>	<!-- ZERO WIDTH JOINER -->
			<int>0x200E</int>	<!-- LEFT-TO-RIGHT MARK -->
			<int>0x200F</int>	<!-- RIGHT-TO-LEFT MARK -->
			<int>0x2028</int>	<!-- LINE SEPARATOR -->
			<int>0x2029</int>	<!-- PARAGRAPH SEPARATOR -->
			<int>0x202A</int>	<!-- LEFT-TO-RIGHT EMBEDDING -->
			<int>0x202B</int>	<!-- RIGHT-TO-LEFT EMBEDDING -->
			<int>0x202C</int>	<!-- POP DIRECTIONAL FORMATTING -->
			<int>0x202D</int>	<!-- LEFT-TO-RIGHT OVERRIDE -->
			<int>0x202E</int>	<!-- RIGHT-TO-LEFT OVERRIDE -->
			<int>0x202F</int>	<!-- NARROW NO-BREAK SPACE -->
			<int>0x205F</int>	<!-- MEDIUM MATHEMATICAL SPACE -->
			<int>0x2060</int>	<!-- WORD JOINER -->
			<int>0x2061</int>	<!-- FUNCTION APPLICATION -->
			<int>0x2062</int>	<!-- INVISIBLE TIMES -->
			<int>0x2063</int>	<!-- INVISIBLE SEPARATOR -->
			<int>0x206A</int>	<!-- INHIBIT SYMMETRIC SWAPPING -->
			<int>0x206B</int>	<!-- ACTIVATE SYMMETRIC SWAPPING -->
			<int>0x206C</int>	<!-- INHIBIT ARABIC FORM SHAPING -->
			<int>0x206D</int>	<!-- ACTIVATE ARABIC FORM SHAPING -->
			<int>0x206E</int>	<!-- NATIONAL DIGIT SHAPES -->
			<int>0x206F</int>	<!-- NOMINAL DIGIT SHAPES -->
			<int>0x2800</int>	<!-- BRAILLE PATTERN BLANK -->
			<int>0x3000</int>	<!-- IDEOGRAPHIC SPACE -->
			<int>0x3164</int>	<!-- HANGUL FILLER -->
			<int>0xFEFF</int>	<!-- ZERO WIDTH NO-BREAK SPACE -->
			<int>0xFFA0</int>	<!-- HALFWIDTH HANGUL FILLER -->
			<int>0xFFF9</int>	<!-- INTERLINEAR ANNOTATION ANCHOR -->
			<int>0xFFFA</int>	<!-- INTERLINEAR ANNOTATION SEPARATOR -->
			<int>0xFFFB</int>	<!-- INTERLINEAR ANNOTATION TERMINATOR -->
		</blank>
<!--
  Rescan configuration every 30 seconds when FcFontSetList is called
 -->
		<rescan>
			<int>30</int>
		</rescan>
	</config>

</fontconfig>
"

(* Test: Fonts.lns *)
test Fonts.lns get conf =
  { "#declaration"
    { "#attribute"
      { "version" = "1.0" }
    }
  }
  { "!DOCTYPE" = "fontconfig"
    { "SYSTEM" = "fonts.dtd" }
  }
  { "#comment" = " /etc/fonts/fonts.conf file to configure system font access " }
  { "fontconfig"
    { "#text" = "

" }
    { "#comment" = "
	DO NOT EDIT THIS FILE.
	IT WILL BE REPLACED WHEN FONTCONFIG IS UPDATED.
	LOCAL CHANGES BELONG IN 'local.conf'.

	The intent of this standard configuration file is to be adequate for
	most environments.  If you have a reasonably normal environment and
	have found problems with this configuration, they are probably
	things that others will also want fixed.  Please submit any
	problems to the fontconfig bugzilla system located at fontconfig.org

	Note that the normal 'make install' procedure for fontconfig is to
	replace any existing fonts.conf file with the new version.  Place
	any local customizations in local.conf which this file references.

	Keith Packard
" }
    { "#text" = "

" }
    { "#comment" = " Font directory list " }
    { "#text" = "

	" }
    { "dir"
      { "#text" = "/usr/share/fonts" }
    }
    { "#text" = "	" }
    { "dir"
      { "#text" = "/usr/X11R6/lib/X11/fonts" }
    }
    { "#text" = " " }
    { "dir"
      { "#text" = "/usr/local/share/fonts" }
    }
    { "#text" = "	" }
    { "dir"
      { "#text" = "~/.fonts" }
    }
    { "#text" = "
" }
    { "#comment" = "
  Accept deprecated 'mono' alias, replacing it with 'monospace'
" }
    { "#text" = "
	" }
    { "match"
      { "#attribute"
        { "target" = "pattern" }
      }
      { "#text" = "
		" }
      { "test"
        { "#attribute"
          { "qual" = "any" }
          { "name" = "family" }
        }
        { "#text" = "
			" }
        { "string"
          { "#text" = "mono" }
        }
        { "#text" = "		" }
      }
      { "#text" = "		" }
      { "edit"
        { "#attribute"
          { "name" = "family" }
          { "mode" = "assign" }
        }
        { "#text" = "
			" }
        { "string"
          { "#text" = "monospace" }
        }
        { "#text" = "		" }
      }
      { "#text" = "	" }
    }
    { "#text" = "
" }
    { "#comment" = "
  Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
" }
    { "#text" = "
	" }
    { "match"
      { "#attribute"
        { "target" = "pattern" }
      }
      { "#text" = "
		" }
      { "test"
        { "#attribute"
          { "qual" = "any" }
          { "name" = "family" }
        }
        { "#text" = "
			" }
        { "string"
          { "#text" = "sans serif" }
        }
        { "#text" = "		" }
      }
      { "#text" = "		" }
      { "edit"
        { "#attribute"
          { "name" = "family" }
          { "mode" = "assign" }
        }
        { "#text" = "
			" }
        { "string"
          { "#text" = "sans-serif" }
        }
        { "#text" = "		" }
      }
      { "#text" = "	" }
    }
    { "#text" = "
" }
    { "#comment" = "
  Accept deprecated 'sans' alias, replacing it with 'sans-serif'
" }
    { "#text" = "
	" }
    { "match"
      { "#attribute"
        { "target" = "pattern" }
      }
      { "#text" = "
		" }
      { "test"
        { "#attribute"
          { "qual" = "any" }
          { "name" = "family" }
        }
        { "#text" = "
			" }
        { "string"
          { "#text" = "sans" }
        }
        { "#text" = "		" }
      }
      { "#text" = "		" }
      { "edit"
        { "#attribute"
          { "name" = "family" }
          { "mode" = "assign" }
        }
        { "#text" = "
			" }
        { "string"
          { "#text" = "sans-serif" }
        }
        { "#text" = "		" }
      }
      { "#text" = "	" }
    }
    { "#text" = "
" }
    { "#comment" = "
  Load local system customization file
" }
    { "#text" = "
	" }
    { "include"
      { "#attribute"
        { "ignore_missing" = "yes" }
      }
      { "#text" = "conf.d" }
    }
    { "#text" = "
" }
    { "#comment" = " Font cache directory list " }
    { "#text" = "

	" }
    { "cachedir"
      { "#text" = "/var/cache/fontconfig" }
    }
    { "#text" = "	" }
    { "cachedir"
      { "#text" = "~/.fontconfig" }
    }
    { "#text" = "
	" }
    { "config"
      { "#text" = "
" }
      { "#comment" = "
  These are the default Unicode chars that are expected to be blank
  in fonts.  All other blank chars are assumed to be broken and
  won't appear in the resulting charsets
 " }
      { "#text" = "
		" }
      { "blank"
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x0020" }
        }
        { "#text" = "	" }
        { "#comment" = " SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x00A0" }
        }
        { "#text" = "	" }
        { "#comment" = " NO-BREAK SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x00AD" }
        }
        { "#text" = "	" }
        { "#comment" = " SOFT HYPHEN " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x034F" }
        }
        { "#text" = "	" }
        { "#comment" = " COMBINING GRAPHEME JOINER " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x0600" }
        }
        { "#text" = "	" }
        { "#comment" = " ARABIC NUMBER SIGN " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x0601" }
        }
        { "#text" = "	" }
        { "#comment" = " ARABIC SIGN SANAH " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x0602" }
        }
        { "#text" = "	" }
        { "#comment" = " ARABIC FOOTNOTE MARKER " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x0603" }
        }
        { "#text" = "	" }
        { "#comment" = " ARABIC SIGN SAFHA " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x06DD" }
        }
        { "#text" = "	" }
        { "#comment" = " ARABIC END OF AYAH " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x070F" }
        }
        { "#text" = "	" }
        { "#comment" = " SYRIAC ABBREVIATION MARK " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x115F" }
        }
        { "#text" = "	" }
        { "#comment" = " HANGUL CHOSEONG FILLER " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x1160" }
        }
        { "#text" = "	" }
        { "#comment" = " HANGUL JUNGSEONG FILLER " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x1680" }
        }
        { "#text" = "	" }
        { "#comment" = " OGHAM SPACE MARK " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x17B4" }
        }
        { "#text" = "	" }
        { "#comment" = " KHMER VOWEL INHERENT AQ " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x17B5" }
        }
        { "#text" = "	" }
        { "#comment" = " KHMER VOWEL INHERENT AA " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x180E" }
        }
        { "#text" = "	" }
        { "#comment" = " MONGOLIAN VOWEL SEPARATOR " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2000" }
        }
        { "#text" = "	" }
        { "#comment" = " EN QUAD " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2001" }
        }
        { "#text" = "	" }
        { "#comment" = " EM QUAD " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2002" }
        }
        { "#text" = "	" }
        { "#comment" = " EN SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2003" }
        }
        { "#text" = "	" }
        { "#comment" = " EM SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2004" }
        }
        { "#text" = "	" }
        { "#comment" = " THREE-PER-EM SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2005" }
        }
        { "#text" = "	" }
        { "#comment" = " FOUR-PER-EM SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2006" }
        }
        { "#text" = "	" }
        { "#comment" = " SIX-PER-EM SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2007" }
        }
        { "#text" = "	" }
        { "#comment" = " FIGURE SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2008" }
        }
        { "#text" = "	" }
        { "#comment" = " PUNCTUATION SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2009" }
        }
        { "#text" = "	" }
        { "#comment" = " THIN SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x200A" }
        }
        { "#text" = "	" }
        { "#comment" = " HAIR SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x200B" }
        }
        { "#text" = "	" }
        { "#comment" = " ZERO WIDTH SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x200C" }
        }
        { "#text" = "	" }
        { "#comment" = " ZERO WIDTH NON-JOINER " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x200D" }
        }
        { "#text" = "	" }
        { "#comment" = " ZERO WIDTH JOINER " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x200E" }
        }
        { "#text" = "	" }
        { "#comment" = " LEFT-TO-RIGHT MARK " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x200F" }
        }
        { "#text" = "	" }
        { "#comment" = " RIGHT-TO-LEFT MARK " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2028" }
        }
        { "#text" = "	" }
        { "#comment" = " LINE SEPARATOR " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2029" }
        }
        { "#text" = "	" }
        { "#comment" = " PARAGRAPH SEPARATOR " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x202A" }
        }
        { "#text" = "	" }
        { "#comment" = " LEFT-TO-RIGHT EMBEDDING " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x202B" }
        }
        { "#text" = "	" }
        { "#comment" = " RIGHT-TO-LEFT EMBEDDING " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x202C" }
        }
        { "#text" = "	" }
        { "#comment" = " POP DIRECTIONAL FORMATTING " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x202D" }
        }
        { "#text" = "	" }
        { "#comment" = " LEFT-TO-RIGHT OVERRIDE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x202E" }
        }
        { "#text" = "	" }
        { "#comment" = " RIGHT-TO-LEFT OVERRIDE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x202F" }
        }
        { "#text" = "	" }
        { "#comment" = " NARROW NO-BREAK SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x205F" }
        }
        { "#text" = "	" }
        { "#comment" = " MEDIUM MATHEMATICAL SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2060" }
        }
        { "#text" = "	" }
        { "#comment" = " WORD JOINER " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2061" }
        }
        { "#text" = "	" }
        { "#comment" = " FUNCTION APPLICATION " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2062" }
        }
        { "#text" = "	" }
        { "#comment" = " INVISIBLE TIMES " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2063" }
        }
        { "#text" = "	" }
        { "#comment" = " INVISIBLE SEPARATOR " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x206A" }
        }
        { "#text" = "	" }
        { "#comment" = " INHIBIT SYMMETRIC SWAPPING " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x206B" }
        }
        { "#text" = "	" }
        { "#comment" = " ACTIVATE SYMMETRIC SWAPPING " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x206C" }
        }
        { "#text" = "	" }
        { "#comment" = " INHIBIT ARABIC FORM SHAPING " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x206D" }
        }
        { "#text" = "	" }
        { "#comment" = " ACTIVATE ARABIC FORM SHAPING " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x206E" }
        }
        { "#text" = "	" }
        { "#comment" = " NATIONAL DIGIT SHAPES " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x206F" }
        }
        { "#text" = "	" }
        { "#comment" = " NOMINAL DIGIT SHAPES " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x2800" }
        }
        { "#text" = "	" }
        { "#comment" = " BRAILLE PATTERN BLANK " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x3000" }
        }
        { "#text" = "	" }
        { "#comment" = " IDEOGRAPHIC SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0x3164" }
        }
        { "#text" = "	" }
        { "#comment" = " HANGUL FILLER " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0xFEFF" }
        }
        { "#text" = "	" }
        { "#comment" = " ZERO WIDTH NO-BREAK SPACE " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0xFFA0" }
        }
        { "#text" = "	" }
        { "#comment" = " HALFWIDTH HANGUL FILLER " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0xFFF9" }
        }
        { "#text" = "	" }
        { "#comment" = " INTERLINEAR ANNOTATION ANCHOR " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0xFFFA" }
        }
        { "#text" = "	" }
        { "#comment" = " INTERLINEAR ANNOTATION SEPARATOR " }
        { "#text" = "
			" }
        { "int"
          { "#text" = "0xFFFB" }
        }
        { "#text" = "	" }
        { "#comment" = " INTERLINEAR ANNOTATION TERMINATOR " }
        { "#text" = "
		" }
      }
      { "#comment" = "
  Rescan configuration every 30 seconds when FcFontSetList is called
 " }
      { "#text" = "
		" }
      { "rescan"
        { "#text" = "
			" }
        { "int"
          { "#text" = "30" }
        }
        { "#text" = "		" }
      }
      { "#text" = "	" }
    }
    { "#text" = "
" }
  }

error: pathspec 'lenses/tests/test_fonts.aug' did not match any file(s) known to git


Php: added default path on redhat

Php: added default path on redhat

(* PHP module for Augeas                      *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(*                                            *)

module PHP =
  autoload xfm

(************************************************************************
 * INI File settings
 *************************************************************************)

let comment  = IniFile.comment IniFile.comment_re IniFile.comment_default
let sep      = IniFile.sep IniFile.sep_re IniFile.sep_default
let empty    = IniFile.empty

(************************************************************************
 *                        ENTRY
 *
 * We have to remove the keyword "section" from possible entry keywords
 * otherwise it would lead to an ambiguity with the "section" label
 * since PHP allows entries outside of sections.
 *************************************************************************)
let entry    = IniFile.entry IniFile.entry_re sep comment

(************************************************************************
 *                         TITLE
 *
 * We use IniFile.title_label because there can be entries
 * outside of sections whose labels would conflict with section names
 *************************************************************************)
let title       = IniFile.title ( IniFile.record_re - ".anon" )
let record      = IniFile.record title entry

let record_anon = [ label ".anon" . ( entry | empty )+ ]

(************************************************************************
 *                         LENS & FILTER
 * There can be entries before any section
 * IniFile.entry includes comment management, so we just pass entry to lns
 *************************************************************************)
let lns    = record_anon? . record*

let filter = (incl "/etc/php*/*/*.ini")
             . (incl "/etc/php.ini")
             . (incl "/etc/php.d/*.ini")
             . Util.stdexcl

let xfm = transform lns filter

(* PHP module for Augeas                      *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(*                                            *)

module PHP =
  autoload xfm

(************************************************************************
 * INI File settings
 *************************************************************************)

let comment  = IniFile.comment IniFile.comment_re IniFile.comment_default
let sep      = IniFile.sep IniFile.sep_re IniFile.sep_default
let empty    = IniFile.empty

(************************************************************************
 *                        ENTRY
 *
 * We have to remove the keyword "section" from possible entry keywords
 * otherwise it would lead to an ambiguity with the "section" label
 * since PHP allows entries outside of sections.
 *************************************************************************)
let entry    = IniFile.entry IniFile.entry_re sep comment

(************************************************************************
 *                         TITLE
 *
 * We use IniFile.title_label because there can be entries
 * outside of sections whose labels would conflict with section names
 *************************************************************************)
let title       = IniFile.title ( IniFile.record_re - ".anon" )
let record      = IniFile.record title entry

let record_anon = [ label ".anon" . ( entry | empty )+ ]

(************************************************************************
 *                         LENS & FILTER
 * There can be entries before any section
 * IniFile.entry includes comment management, so we just pass entry to lns
 *************************************************************************)
let lns    = record_anon? . record*

let filter = (incl "/etc/php*/*/*.ini")
             . Util.stdexcl

let xfm = transform lns filter


Added lenses files to Augeas

Added lenses files to Augeas

(* XML lens for Augeas
   Author: Francis Giraldeau <francis.giraldeau@usherbrooke.ca>

   Reference: http://www.w3.org/TR/2006/REC-xml11-20060816/
*)

module JBXml =

autoload xfm

(************************************************************************
 *                           Utilities lens
 *************************************************************************)

let dels (s:string)   = del s s
let spc               = /[ \t\n]+/
let osp               = /[ \t\n]*/
let sep_spc           = del /[ \t\n]+/ " "
let sep_osp           = del /[ \t\n]*/ ""
let sep_eq            = del /[ \t\n]*=[ \t\n]*/ "="

let nmtoken             = /[a-zA-Z:_][a-zA-Z0-9:_.-]*/
let word                = /[a-zA-Z][a-zA-Z0-9._-]*/
let char                = /.|\n/
(* if we hide the quotes, then we can only accept single or double quotes *)
(* otherwise a put ambiguity is raised *)
let sto_dquote          = dels "\"" . store /[^"]*/ . dels "\""
let sto_squote          = dels "'" . store /[^']*/ . dels "'"

let comment             = [ label "#comment" .
                            dels "<!--" .
                            store /([^-]|-[^-])*/ .
                            dels "-->" ]

let pi_target           = nmtoken - /[Xx][Mm][Ll]/
let empty               = Util.empty
let del_end             = del />[\n]?/ ">\n"
let del_end_simple      = dels ">"

(* This is siplified version of processing instruction
 * pi has to not start or end with a white space and the string
 * must not contain "?>". We restrict too much by not allowing any
 * "?" nor ">" in PI
 *)
let pi                  = /[^ \n\t]|[^ \n\t][^?>]*[^ \n\t]/

(************************************************************************
 *                            Attributes
 *************************************************************************)

let decl          = [ label "#decl" . sep_spc .
                      store /[^> \t\n\r]|[^> \t\n\r][^>\t\n\r]*[^> \t\n\r]/ ]

let decl_def (r:regexp) (b:lens) = [ dels "<" . key r .
                                     sep_spc . store word .
                                     b . sep_osp . del_end_simple ]

let elem_def      = decl_def /!ELEMENT/ decl

let enum          = "(" . osp . nmtoken . ( osp . "|" . osp . nmtoken )* . osp . ")"

let att_type      = /CDATA|ID|IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS/ |
                     enum

let id_def        = [ sep_spc . key /PUBLIC/ .
                      [ label "#literal" . sep_spc . sto_dquote ]* ] |
                    [ sep_spc . key /SYSTEM/ . sep_spc . sto_dquote ]

let notation_def  = decl_def /!NOTATION/ id_def

let att_def       = counter "att_id" .
                    [ sep_spc . seq "att_id" .
                      [ label "#name" . store word . sep_spc ] .
                      [ label "#type" . store att_type . sep_spc ] .
                      ([ key   /#REQUIRED|#IMPLIED/ ] |
                       [ label "#FIXED" . del /#FIXED[ \n\t]*|/ "" . sto_dquote ]) ]*

let att_list_def = decl_def /!ATTLIST/ att_def

let entity_def    = decl_def /!ENTITY/ ([sep_spc . label "#decl" . sto_dquote ])

let decl_def_item = elem_def | entity_def | att_list_def | notation_def

let decl_outer    = sep_osp . del /\[[ \n\t\r]*/ "[\n" .
                    (decl_def_item . sep_osp )* . dels "]"

(* let dtd_def       = [ sep_spc . key "SYSTEM" . sep_spc . sto_dquote ] *)

let doctype       = decl_def /!DOCTYPE/ (decl_outer|id_def)

let attributes    = [ label "#attribute" .
                      [ sep_spc . key nmtoken . sep_eq . sto_dquote ]+ ]
let attributes_sq = [ label "#attribute" .
                      [ sep_spc . key nmtoken . sep_eq . sto_squote ]+ ]

let prolog        = [ label "#declaration" .
                      dels "<?xml" .
                      attributes_sq .
                      sep_osp .
                      dels "?>" ]

(************************************************************************
 *                            Tags
 *************************************************************************)

(* we consider entities as simple text *)
let text_re   = /[^<]+/ - /([^<]*\]\]>[^<]*)/
let text      = [ label "#text" . store text_re ]
let cdata     = [ label "#CDATA" . dels "<![CDATA[" .
                  store (char* - (char* . "]]>" . char*)) . dels "]]>" ]

let element (body:lens) =
    let h = attributes? . sep_osp . dels ">" . body* . dels "</" in
        [ dels "<" . square nmtoken h . sep_osp . del_end ]

let empty_element = [ dels "<" . key nmtoken . value "#empty" .
                      attributes? . sep_osp . del /\/>[\n]?/ "/>\n" ]

let pi_instruction = [ dels "<?" . label "#pi" .
                       [ label "#target" . store pi_target ] .
                       [ sep_spc . label "#instruction" . store pi ]? .
                       sep_osp . del /\?>/ "?>" ]

(* Typecheck is weaker on rec lens, detected by unfolding *)
(*
let content1 = element text
let rec content2 = element (content1|text|comment)
*)

let rec content = element (text|comment|content|empty_element|pi_instruction)

(* Constraints are weaker here, but it's better than being too strict *)
let doc = (sep_osp . (prolog  | comment | doctype | pi_instruction))* .
          ((sep_osp . content) | (sep_osp . empty_element)) .
          (sep_osp . (comment | pi_instruction ))* . sep_osp

let lns = doc

let filter = (excl "*")

let xfm = transform lns filter

error: pathspec 'files/jbxml.aug' did not match any file(s) known to git


Store comments in subtrees so they are restored properly

# Parsing /etc/inittab

map
  grammar pam
  # We really need to be able to exclude some files, like
  # backup files and .rpmsave files
  include '/etc/pam.d/*' '/system/config/pam' $basename
end

grammar pam

  token SEP /[ \t]+/ = '\t'
  token EOL '\n'
  token CONTROL /(\[[^\]]*\]|[^ \t]+)/ = 'none'
  token POUND_TO_EOL /#.*\n/ = '# '

  file: ( comment | record ) *

  comment: [ ( /#.*?\n/ | /[ \t]*\n/ ) ]

  record: [ seq 'record' .
            [ label 'type' . store ... ] .
            SEP .
            [ label 'control' . store CONTROL] .
            SEP .
            [ label 'module' . store ... ] .
            ( [ SEP . label 'opts' . store ... ] )? .
            EOL
          ]
end

# Parsing /etc/inittab

map
  grammar pam
  # We really need to be able to exclude some files, like
  # backup files and .rpmsave files
  include '/etc/pam.d/*' '/system/config/pam' $basename
end

grammar pam

  token SEP /[ \t]+/ = '\t'
  token EOL '\n'
  token CONTROL /(\[[^\]]*\]|[^ \t]+)/ = 'none'
  token POUND_TO_EOL /#.*\n/ = '# '

  file: ( comment | record ) *

  comment: ( /#.*?\n/ | /[ \t]*\n/ )

  record: [ seq 'record' .
            [ label 'type' . store ... ] .
            SEP .
            [ label 'control' . store CONTROL] .
            SEP .
            [ label 'module' . store ... ] .
            ( [ SEP . label 'opts' . store ... ] )? .
            EOL
          ]
end


Add experimental Augeas Lens for Deckard tests

module Deckard =
  autoload xfm

let del_str = Util.del_str

let space = del /[ \t]+/ " "
let tab = del /[ \t]+/ "\t"
let ws = del /[\t ]*/ ""
let word = /[^\t\n\/#; ]+/

let comment = del /[;#]/ ";" . [label "comment" . store /[^\n]+/]

let eol = del /([ \t]*([;#][^\n]*)?\n)+/ "\n" . Util.indent
let comment_or_eol =  ws . comment? . del_str "\n" . del /([ \t]*([;#][^\n]*)?\n)*/ "\n" . Util.indent

(*let comment_or_eol = [ label "#comment" . counter "comment" . (ws . [del /[;#]/ ";" . label "" . store /[^\n]*/ ]? . del_str "\n")]+ . Util.indent
*)

let domain_re = (/[^.\t\n\/#; ]+(\.[^.\t\n\/#; ]+)*\.?/ | ".") - "SECTION" (*quick n dirty, sorry to whoever will ever own SECTION TLD*)
let class_re = /CLASS[0-9]+/ | "IN" | "CH" | "HS" | "NONE" | "ANY"
let domain = [ label "domain" . store domain_re ]
let ttl = [label "ttl" . store /[0-9]+/]
let class = [label "class" . store class_re ]
let type = [label "type" . store ((/[^0-9#;\n \t][^\t\n\/#; ]*/) - class_re) ]
let data = [label "data" . store /[^\n\t ;#][^\n;#]+[^\n\t;# ]/]

let ip_re = /[0-9a-f.:]+/

let match_option = "opcode" | "qtype" | "qcase" | "qname" | "subdomain" | "flags" | "rcode" | "question" | "answer" | "authority" | "additional" | "all" | "TCP" | "ttl"
let adjust_option = "copy_id" | "copy_query"
let reply_option = "QR" | "TC" | "AA" | "AD" | "RD" | "RA" | "CD" | "DO" | "NOERROR" | "FORMERR" | "SERVFAIL" | "NXDOMAIN" | "NOTIMP" | "REFUSED" | "YXDOMAIN" | "YXRRSET" | "NXRRSET" | "NOTAUTH" | "NOTZONE" | "BADVERS"
let step_option = "REPLY" | "QUERY" | "CHECK_ANSWER" | "CHECK_OUT_QUERY" | /TIME_PASSES[ \t]+ELAPSE/

let mandatory = [del_str "MANDATORY" . label "mandatory" . value "true" . comment_or_eol]
let tsig = [del_str "TSIG" . label "tsig" . space . [label "keyname" . store word] . space . [label "secret" . store word] . comment_or_eol]

let match = (mandatory | tsig)* . del_str "MATCH" . [space . label "match" . store match_option ]+ . comment_or_eol
let adjust =  (mandatory | tsig)* . del_str "ADJUST" . [space . label "adjust" . store adjust_option ]+ . comment_or_eol
let reply =  (mandatory | tsig)* . del ("REPLY" | "FLAGS") "REPLY" .  [space . label "reply" . store reply_option ]+ . comment_or_eol

let question = domain . tab . (class . tab)? . type . comment_or_eol
let record = [seq "record" . domain . tab . (ttl . tab)? . (class . tab)? . type . tab . data . comment_or_eol]

let section_question = [ label "question" . del_str "SECTION QUESTION" .
                       comment_or_eol . question? ]
let section_answer = [ label "answer" . counter "record" . del_str "SECTION ANSWER" .
                       comment_or_eol . record* ]
let section_authority = [ label "authority" . counter "record" . del_str "SECTION AUTHORITY" .
                          comment_or_eol . record* ]
let section_additional = [ label "additional" . counter "record" . del_str "SECTION ADDITIONAL" .
                           comment_or_eol . record* ]
let sections = section_question? . section_answer? . section_authority? . section_additional?

let raw = [del_str "RAW" . comment_or_eol . label "raw" . store word  ] . comment_or_eol

let normal = (match . (adjust . reply? | reply . adjust?)? | adjust . (match . reply? | reply . match?)? | reply . (match . adjust? | adjust . match?)?) . (mandatory | tsig)* . sections

(*let normal = ((match | adjust | reply | mandatory | tsig)* . sections)*)

let entry = [label "entry" . del_str "ENTRY_BEGIN" . comment_or_eol . ( normal | raw )? . del_str "ENTRY_END" . eol]

let single_address = [ label "address" . space . store ip_re ]

let addresses = [label "address" . counter "address" . [seq "address" . del_str "ADDRESS" . space . store ip_re . comment_or_eol]+]

let range = [label "range" . del_str "RANGE_BEGIN" . space . [ label "from" . store /[0-9]+/] . space .
            [ label "to" . store /[0-9]+/] . single_address? . comment_or_eol . addresses? . entry* . del_str "RANGE_END" . eol]

let step = [label "step" . del_str "STEP" . space . store /[0-9]+/ . space . [label "type" . store step_option] . [space . label "timestamp" . store /[0-9]+/]? . comment_or_eol .
           entry? ]

let config_record = /[^\n]*/ - ("CONFIG_END" | /STEP.*/ | /SCENARIO.*/ | /RANGE.*/ | /ENTRY.*/)

let config = [ label "config" . counter "config" . [seq "config" . store config_record . del_str "\n"]* . del_str "CONFIG_END" . comment_or_eol ]

let guts = (step | range )*

let scenario = [label "scenario" . del_str "SCENARIO_BEGIN" . (space . store /[^ \t\n#;][^\n#;]+[^\t\n #;]/)? . comment_or_eol . guts . del_str "SCENARIO_END" . eol]

let lns = config? . scenario

(* TODO: REPLAY step *)
(* TODO: store all comments into the tree instead of ignoring them *)

let filter = incl "/home/stepan/nic/deckard/sets/resolver/*.rpl"

let xfm = transform lns filter

error: pathspec 'augeas/deckard.aug' did not match any file(s) known to git


Add more specific entry handlers to xorg.conf

Additionally handle:
* Driver
* Identifier
* VideoRam
* DefaultDepth

This covers all entries in the default configuration.

The advantage of having a specific handler is that it knows more about what
values are valid. For example, with this patch Driver will not accept an
unquoted value, which would cause the X server not to start.

(*
Module: Xorg
 Parses /etc/X11/xorg.conf

Authors: Raphael Pinson <raphink@gmail.com>
         Matthew Booth <mbooth@redhat.com>

About: Reference
 This lens tries to keep as close as possible to `man xorg.conf` where
 possible.

The definitions from `man xorg.conf` are put as commentaries for reference
throughout the file. More information can be found in the manual.

About: License
  This file is licensed under the GPL.

About: Lens Usage
  Sample usage of this lens in augtool

    * Get the identifier of the devices with a "Clone" option:
      > match "/files/etc/X11/xorg.conf/Device[Option = 'Clone']/Identifier"

About: Quotes in values
  In this file, values may or may not be quoted (with double quotes) unless
they contain spaces or tabulations. For this reason, the quotes are
included in the parsed values when present. New values with no spaces will
not have quotes by default, unless you type the quotes yourself around
them. New values with spaces will not be accepted unless they are
explicitely surrounded by double qutoes.

About: Configuration files
  This lens applies to /etc/X11/xorg.conf. See <filter>.
*)

module Xorg =
  autoload xfm

(************************************************************************
 * Group:                 USEFUL PRIMITIVES
 *************************************************************************)

(* Group: Generic primitives *)

(* Variable: eol *)
let eol     = Util.eol

(* Variable: to_eol
 * Match everything from here to eol, cropping whitespace at both ends
 *)
let to_eol  = /[^ \t\n](.*[^ \t\n])?/

(* Variable: indent *)
let indent  = Util.indent

(* Variable: comment *)
let comment = Util.comment

(* Variable: empty *)
let empty   = Util.empty

(* Group: Separators *)

(* Variable: sep_spc *)
let sep_spc = Util.del_ws_spc

(* Variable: sep_dquote *)
let sep_dquote  = Util.del_str "\""

(* Group: Fields and values *)

(* Variable: entries_re
 * This is a list of all patterns which have specific handlers, and should
 * therefore not be matched by the generic handler
 *)
let entries_re  = /([oO]ption|[sS]creen|[iI]nput[dD]evice|[dD]river|[sS]ub[sS]ection|[dD]isplay|[iI]dentifier|[vV]ideo[rR]am|[dD]efault[dD]epth)/

(* Variable: generic_entry_re *)
let generic_entry_re = /[^# \t\n\/]+/ - entries_re

(*
 * Variable: unquoted_word
 *   Words without spaces may have quotes or not
 *   the quotes are then part of the value
 *)
let unquoted_word = /[^" \t\n]+/                   (* " relax Emacs *)

(* Variable: quoted_word *)
let quoted_word = /"[^"\n]+"/                     (* " relax Emacs *)

(* Variable: word_all *)
let word_all = unquoted_word | quoted_word

(* Variable: int *)
let int = /[0-9]+/

(************************************************************************
 * Group:                          ENTRIES AND OPTIONS
 *************************************************************************)

(* View: entry_int
 * This matches an entry which takes a single integer for an argument
 *)
let entry_int (canon:string) (re:regexp) =
        [ indent . del re canon . label canon . sep_spc . store int . eol ]

(* View: entry_rgb
 * This matches an entry which takes 3 integers as arguments representing red,
 * green and blue components
 *)
let entry_rgb (canon:string) (re:regexp) =
        [ indent . del re canon . label canon
          . [ label "red"   . sep_spc . store int ]
          . [ label "green" . sep_spc . store int ]
          . [ label "blue"  . sep_spc . store int ]
          . eol ]

(* View: entry_xy
 * This matches an entry which takes 2 integers as arguments representing X and
 * Y coordinates
 *)
let entry_xy (canon:string) (re:regexp) =
        [ indent . del re canon . label canon
          . [ label "x" . sep_spc . store int ]
          . [ label "y" . sep_spc . store int ]
          . eol ]

(* View: entry_str
 * This matches an entry which takes a single quoted string
 *)
let entry_str (canon:string) (re:regexp) =
        [ indent . del re canon . label canon
          . sep_spc . store quoted_word . eol ]

(* View: entry_generic
 * An entry without a specific handler. Store everything after the keyword,
 * cropping whitespace at both ends.
 *)
let entry_generic  = [ indent . key generic_entry_re
                       . sep_spc . store to_eol . eol ]

(* View: option *)
let option = [ indent . del /[oO]ption/ "Option" . label "Option" . sep_spc
               . store quoted_word
               . [ label "value" . sep_spc . store quoted_word ]*
               . eol ]

(* View: screen
 * The Screen entry of ServerLayout
 *)
let screen = [ indent . del /[sS]creen/ "Screen" . label "Screen" . sep_spc
               . [ label "num" . store int . sep_spc ]?
               . store quoted_word . sep_spc
               . [ label "position" . store to_eol ]
               . eol ]

(* View: input_device *)
let input_device = [ indent . del /[iI]nput[dD]evice/ "InputDevice"
                     . label "InputDevice" . sep_spc . store quoted_word
                     . [ label "option" . sep_spc . store quoted_word ]*
                     . eol ]

(* View: driver *)
let driver = entry_str "Driver" /[dD]river/

(* View: identifier *)
let identifier = entry_str "Identifier" /[iI]dentifier/

(* View: videoram *)
let videoram = entry_int "VideoRam" /[vV]ideo[rR]am/

(* View: default_depth *)
let default_depth = entry_int "DefaultDepth" /[dD]efault[dD]epth/

(************************************************************************
 * Group:                          DISPLAY SUBSECTION
 *************************************************************************)

(* View: display_modes *)
let display_modes = [ indent . del /[mM]odes/ "Modes" . label "Modes"
                      . [ label "mode" . sep_spc . store quoted_word ]+
                      . eol ]

(*************************************************************************
 * View: display_entry
 *   Known values for entries in the Display subsection
 *
 *   Definition:
 *     > Depth    depth
 *     > FbBpp    bpp
 *     > Weight   red-weight green-weight blue-weight
 *     > Virtual  xdim ydim
 *     > ViewPort x0 y0
 *     > Modes    "mode-name" ...
 *     > Visual   "visual-name"
 *     > Black    red green blue
 *     > White    red green blue
 *     > Options
 *)

let display_entry = entry_int "Depth"    /[dD]epth/ |
                    entry_int "FbBpp"    /[fF]b[bB]pp/ |
                    entry_rgb "Weight"   /[wW]eight/ |
                    entry_xy  "Virtual"  /[vV]irtual/ |
                    entry_xy  "ViewPort" /[vV]iew[pP]ort/ |
                    display_modes |
                    entry_str "Visual"   /[vV]isual/ |
                    entry_rgb "Black"    /[bB]lack/ |
                    entry_rgb "White"    /[wW]hite/ |
                    entry_str "Options"  /[oO]ptions/ |
                    empty |
                    comment

(* View: display *)
let display = [ indent . del "SubSection" "SubSection" . sep_spc
                       . sep_dquote . key "Display" . sep_dquote
                       . eol
                       . display_entry*
                       . indent . del "EndSubSection" "EndSubSection" . eol ]

(************************************************************************
 * Group:                       SECTIONS
 *************************************************************************)

(************************************************************************
 * Variable: section_re
 *   Known values for Section names
 *
 *   Definition:
 *     >   The section names are:
 *     >
 *     >   Files          File pathnames
 *     >   ServerFlags    Server flags
 *     >   Module         Dynamic module loading
 *     >   InputDevice    Input device description
 *     >   Device         Graphics device description
 *     >   VideoAdaptor   Xv video adaptor description
 *     >   Monitor        Monitor description
 *     >   Modes          Video modes descriptions
 *     >   Screen         Screen configuration
 *     >   ServerLayout   Overall layout
 *     >   DRI            DRI-specific configuration
 *     >   Vendor         Vendor-specific configuration
 *************************************************************************)
let section_re = /(Files|ServerFlags|Module|InputDevice|Device|VideoAdaptor|Monitor|Modes|Screen|ServerLayout|DRI|Vendor)/

(************************************************************************
 * Variable: secton_re_obsolete
 *   The  following obsolete section names are still recognised for
 *   compatibility purposes.  In new config files, the InputDevice
 *   section should be used instead.
 *
 *   Definition:
 *     >  Keyboard       Keyboard configuration
 *     >  Pointer        Pointer/mouse configuration
 *************************************************************************)
let section_re_obsolete = /(Keyboard|Pointer)/

(* View: section_entry *)
let section_entry = option |
                    screen |
                    display |
                    input_device |
                    driver |
                    identifier |
                    videoram |
                    default_depth |
                    entry_generic |
                    empty | comment

(************************************************************************
 * View: section
 *   A section in xorg.conf
 *
 *   Definition:
 *     > Section  "SectionName"
 *     >    SectionEntry
 *     >    ...
 *     > EndSection
 *************************************************************************)
let section = [ indent . del "Section" "Section"
                       . sep_spc . sep_dquote
                       . key (section_re|section_re_obsolete) . sep_dquote
                       . eol
                .  section_entry*
                . indent . del "EndSection" "EndSection" . eol ]

(*
 * View: lns
 *   The xorg.conf lens
 *)
let lns = ( empty | comment | section )*

(* Variable: filter *)
let filter = (incl "/etc/X11/xorg.conf")

let xfm = transform lns filter

(*
Module: Xorg
 Parses /etc/X11/xorg.conf

Authors: Raphael Pinson <raphink@gmail.com>
         Matthew Booth <mbooth@redhat.com>

About: Reference
 This lens tries to keep as close as possible to `man xorg.conf` where
 possible.

The definitions from `man xorg.conf` are put as commentaries for reference
throughout the file. More information can be found in the manual.

About: License
  This file is licensed under the GPL.

About: Lens Usage
  Sample usage of this lens in augtool

    * Get the identifier of the devices with a "Clone" option:
      > match "/files/etc/X11/xorg.conf/Device[Option = 'Clone']/Identifier"

About: Quotes in values
  In this file, values may or may not be quoted (with double quotes) unless
they contain spaces or tabulations. For this reason, the quotes are
included in the parsed values when present. New values with no spaces will
not have quotes by default, unless you type the quotes yourself around
them. New values with spaces will not be accepted unless they are
explicitely surrounded by double qutoes.

About: Configuration files
  This lens applies to /etc/X11/xorg.conf. See <filter>.
*)

module Xorg =
  autoload xfm

(************************************************************************
 * Group:                 USEFUL PRIMITIVES
 *************************************************************************)

(* Group: Generic primitives *)

(* Variable: eol *)
let eol     = Util.eol

(* Variable: to_eol
 * Match everything from here to eol, cropping whitespace at both ends
 *)
let to_eol  = /[^ \t\n](.*[^ \t\n])?/

(* Variable: indent *)
let indent  = Util.indent

(* Variable: comment *)
let comment = Util.comment

(* Variable: empty *)
let empty   = Util.empty

(* Group: Separators *)

(* Variable: sep_spc *)
let sep_spc = Util.del_ws_spc

(* Variable: sep_dquote *)
let sep_dquote  = Util.del_str "\""

(* Group: Fields and values *)

(* Variable: entries_re *)
let entries_re  = /(Option|Screen|InputDevice|SubSection|Display)/

(* Variable: generic_entry_re *)
let generic_entry_re = /[^# \t\n\/]+/ - entries_re

(*
 * Variable: unquoted_word
 *   Words without spaces may have quotes or not
 *   the quotes are then part of the value
 *)
let unquoted_word = /[^" \t\n]+/                   (* " relax Emacs *)

(* Variable: quoted_word *)
let quoted_word = /"[^"\n]+"/                     (* " relax Emacs *)

(* Variable: word_all *)
let word_all = unquoted_word | quoted_word

(* Variable: int *)
let int = /[0-9]+/

(************************************************************************
 * Group:                          ENTRIES AND OPTIONS
 *************************************************************************)

(* View: entry_int
 * This matches an entry which takes a single integer for an argument
 *)
let entry_int (canon:string) (re:regexp) =
        [ indent . del re canon . label canon . sep_spc . store int . eol ]

(* View: entry_rgb
 * This matches an entry which takes 3 integers as arguments representing red,
 * green and blue components
 *)
let entry_rgb (canon:string) (re:regexp) =
        [ indent . del re canon . label canon
          . [ label "red"   . sep_spc . store int ]
          . [ label "green" . sep_spc . store int ]
          . [ label "blue"  . sep_spc . store int ]
          . eol ]

(* View: entry_xy
 * This matches an entry which takes 2 integers as arguments representing X and
 * Y coordinates
 *)
let entry_xy (canon:string) (re:regexp) =
        [ indent . del re canon . label canon
          . [ label "x" . sep_spc . store int ]
          . [ label "y" . sep_spc . store int ]
          . eol ]

(* View: entry_str
 * This matches an entry which takes a single, possibly quoted, string
 *)
let entry_str (canon:string) (re:regexp) =
        [ indent . del re canon . label canon
          . sep_spc . store word_all . eol ]

(* View: entry_generic
 * An entry without a specific handler. Store everything after the keyword,
 * cropping whitespace at both ends.
 *)
let entry_generic  = [ indent . key generic_entry_re
                       . sep_spc . store to_eol . eol ]

(* View: option *)
let option = [ indent . key "Option" . sep_spc
               . store word_all
               . [ label "value" . sep_spc . store word_all ]*
               . eol ]

(* View: screen
 * The Screen entry of ServerLayout
 *)
let screen = [ indent . key "Screen" . sep_spc
               . [ label "num" . store int . sep_spc ]?
               . store quoted_word . sep_spc
               . [ label "position" . store to_eol ]
               . eol ]

(* View: input_device *)
let input_device = [ indent . key "InputDevice" . sep_spc . store word_all
                     . [ label "option" . sep_spc . store word_all ]*
                     . eol ]

(************************************************************************
 * Group:                          DISPLAY SUBSECTION
 *************************************************************************)

(* View: display_modes *)
let display_modes = [ indent . del /[mM]odes/ "Modes" . label "Modes"
                      . [ label "mode" . sep_spc . store quoted_word ]+
                      . eol ]

(*************************************************************************
 * View: display_entry
 *   Known values for entries in the Display subsection
 *
 *   Definition:
 *     > Depth    depth
 *     > FbBpp    bpp
 *     > Weight   red-weight green-weight blue-weight
 *     > Virtual  xdim ydim
 *     > ViewPort x0 y0
 *     > Modes    "mode-name" ...
 *     > Visual   "visual-name"
 *     > Black    red green blue
 *     > White    red green blue
 *     > Options
 *)

let display_entry = entry_int "Depth"    /[dD]epth/ |
                    entry_int "FbBpp"    /[fF]b[bB]pp/ |
                    entry_rgb "Weight"   /[wW]eight/ |
                    entry_xy  "Virtual"  /[vV]irtual/ |
                    entry_xy  "ViewPort" /[vV]iew[pP]ort/ |
                    display_modes |
                    entry_str "Visual"   /[vV]isual/ |
                    entry_rgb "Black"    /[bB]lack/ |
                    entry_rgb "White"    /[wW]hite/ |
                    entry_str "Options"  /[oO]ptions/ |
                    empty |
                    comment

(* View: display *)
let display = [ indent . del "SubSection" "SubSection" . sep_spc
                       . sep_dquote . key "Display" . sep_dquote
                       . eol
                       . display_entry*
                       . indent . del "EndSubSection" "EndSubSection" . eol ]

(************************************************************************
 * Group:                       SECTIONS
 *************************************************************************)

(************************************************************************
 * Variable: section_re
 *   Known values for Section names
 *
 *   Definition:
 *     >   The section names are:
 *     >
 *     >   Files          File pathnames
 *     >   ServerFlags    Server flags
 *     >   Module         Dynamic module loading
 *     >   InputDevice    Input device description
 *     >   Device         Graphics device description
 *     >   VideoAdaptor   Xv video adaptor description
 *     >   Monitor        Monitor description
 *     >   Modes          Video modes descriptions
 *     >   Screen         Screen configuration
 *     >   ServerLayout   Overall layout
 *     >   DRI            DRI-specific configuration
 *     >   Vendor         Vendor-specific configuration
 *************************************************************************)
let section_re = /(Files|ServerFlags|Module|InputDevice|Device|VideoAdaptor
                        |Monitor|Modes|Screen|ServerLayout|DRI|Vendor)/

(************************************************************************
 * Variable: secton_re_obsolete
 *   The  following obsolete section names are still recognised for
 *   compatibility purposes.  In new config files, the InputDevice
 *   section should be used instead.
 *
 *   Definition:
 *     >  Keyboard       Keyboard configuration
 *     >  Pointer        Pointer/mouse configuration
 *************************************************************************)
let section_re_obsolete = /(Keyboard|Pointer)/

(* View: section_entry *)
let section_entry = empty | comment |
                    option | screen | display | input_device |
                    entry_generic

(************************************************************************
 * View: section
 *   A section in xorg.conf
 *
 *   Definition:
 *     > Section  "SectionName"
 *     >    SectionEntry
 *     >    ...
 *     > EndSection
 *************************************************************************)
let section = [ indent . del "Section" "Section"
                       . sep_spc . sep_dquote
                       . key (section_re|section_re_obsolete) . sep_dquote
                       . eol
                .  section_entry*
                . indent . del "EndSection" "EndSection" . eol ]

(*
 * View: lns
 *   The xorg.conf lens
 *)
let lns = ( empty | comment | section )*

(* Variable: filter *)
let filter = (incl "/etc/X11/xorg.conf")

let xfm = transform lns filter


Check that let expressions work

Check that let expressions work

(* Test let expressions *)
module Pass_let_exp =

  (* This definition is insanely roundabout; it's written that way *)
  (* since we want to exercise LET expressions                     *)
  let lns =
    let lbl = "a" in
    let spc = " " in
    let del_spaces (s:string) = del spc+ s in
    let del_str (s:string) = del s s in
    let store_delim (ldelim:string)
                    (rdelim:string) (val:regexp) =
      del_str ldelim . store val . del_str rdelim in
    [ label lbl . del_spaces " " . store_delim "(" ")" /[a-z]+/ ]

  test lns get "  (abc)" = { "a" = "abc" }

(* Local Variables: *)
(* mode: caml       *)
(* End:             *)

error: pathspec 'tests/modules/pass_let_exp.aug' did not match any file(s) known to git