@@ -20,131 +20,4 @@ interface StringNotation {
2020 fun print (word : Word ): String
2121}
2222
23- /* *
24- * Base class for implementing string notations.
25- *
26- * @constructor Creates a string notation that will use the provided regular expression to [split][String.split] parts when parsing.
27- */
28- abstract class BaseStringNotation (private val splitAt : Regex ): StringNotation {
29- /* *
30- * Transforms a parsed part after it has been read. The default implementation is to convert the part to lowercase to discard possibly
31- * wrong case information.
32- */
33- protected open fun transformPartAfterParse (index : Int , part : String ) = part.toLowerCase(Locale .ROOT )
34-
35- override fun parse (sourceString : String ): Word = Word (sourceString.split(splitAt).asSequence().mapIndexed(::transformPartAfterParse))
36-
37- /* *
38- * Allows to transform a part before it is being printed. The default implementation does not modify the part in any way.
39- */
40- protected open fun transformPartToPrint (index : Int , part : String ) = part
41-
42- /* *
43- * Allows to print characters in front of parts. The default implementation will print nothing before the first part and delegate to
44- * [printBeforeInnerPart] for the remaining parts.
45- */
46- protected open fun printBeforePart (index : Int , part : String ) = if (index == 0 ) " " else printBeforeInnerPart(index, part)
47-
48- /* *
49- * Allows to print characters in front of parts that are not the first part. The default implementation prints nothing.
50- */
51- protected open fun printBeforeInnerPart (index : Int , part : String ) = " "
52-
53- override fun print (word : Word ) = word.parts
54- .mapIndexed(::transformPartToPrint)
55- .foldIndexed(StringBuffer ()) { index, left, right -> left.append(printBeforePart(index, right)).append(right) }
56- .toString()
57- }
58-
59- internal fun String.capitalizeOnlyFirst () = if (isNotEmpty()) this [0 ].toUpperCase() + substring(1 ).toLowerCase() else this
60-
61- private val camelCaseSplitRegex = Regex (" (?<=.)(?=\\ p{Lu})" )
62-
63- /* *
64- * The `UpperCamelCase` notation.
65- *
66- * @see JavaTypeName
67- */
68- object UpperCamelCase: BaseStringNotation(camelCaseSplitRegex) {
69- public override fun transformPartToPrint (index : Int , part : String ) = part.capitalizeOnlyFirst()
70- }
71-
72- /* *
73- * The `lowerCamelCase` notation.
74- *
75- * @see JavaMemberName
76- */
77- object LowerCamelCase: BaseStringNotation(camelCaseSplitRegex) {
78- override fun transformPartToPrint (index : Int , part : String ) = if (index == 0 ) part.toLowerCase() else part.capitalizeOnlyFirst()
79- }
80-
81- /* *
82- * The `SCREAMING_SNAKE_CASE` notation.
83- */
84- object ScreamingSnakeCase: BaseStringNotation(Regex ("_ ")) {
85- override fun printBeforeInnerPart (index : Int , part : String ) = " _"
8623
87- override fun transformPartToPrint (index : Int , part : String ) = part.toUpperCase()
88- }
89-
90- /* *
91- * The `snake_case` notation.
92- */
93- object SnakeCase: BaseStringNotation(Regex ("_ ")) {
94- override fun transformPartAfterParse (index : Int , part : String ) = part
95- override fun printBeforeInnerPart (index : Int , part : String ) = " _"
96- }
97-
98- /* *
99- * A notation for java type names. This notation is like [UpperCamelCase], but will drop any character that is not allowed in a Java
100- * identifier when [printing][StringNotation.print].
101- *
102- * Allowed characters are determined using [Character.isJavaIdentifierStart] and [Character.isJavaIdentifierPart].
103- */
104- object JavaTypeName: BaseStringNotation(camelCaseSplitRegex) {
105- override fun transformPartToPrint (index : Int , part : String ) = part.keepOnlyJavaIdentifierChars().capitalizeOnlyFirst()
106- }
107-
108- /* *
109- * A notation for java member names. This notation is like [LowerCamelCase], but will drop any character that is not allowed in a Java
110- * identifier when [printing][StringNotation.print].
111- *
112- * Allowed characters are determined using [Character.isJavaIdentifierStart] and [Character.isJavaIdentifierPart].
113- */
114- object JavaMemberName: BaseStringNotation(camelCaseSplitRegex) {
115- override fun print (word : Word ) = word.parts
116- .foldIndexed(StringBuffer ()) { index, left, right ->
117- val rightPart = right.keepOnlyJavaIdentifierChars().run {
118- if (left.contains(Regex (" [a-zA-Z]" ))) capitalizeOnlyFirst()
119- else this .toLowerCase()
120- }
121- left.append(printBeforePart(index, rightPart)).append(rightPart)
122- }.toString()
123-
124- }
125-
126- /* *
127- * Notation for words written like in normal language. [Parsing][StringNotation.parse] will recognise all substrings that are separated by
128- * one or more characters of whitespace as a [part][Word.parts]. [Printing][StringNotation.print] will print the parts separated by one
129- * space.
130- */
131- object NormalWords: BaseStringNotation(Regex ("[\\s]+")) {
132- override fun transformPartAfterParse (index : Int , part : String ) = part
133- override fun printBeforeInnerPart (index : Int , part : String ) = " "
134- }
135-
136- internal fun String.keepOnlyJavaIdentifierChars () = this .chars()
137- .skipWhile { ! isJavaIdentifierStart(it) }
138- .filter { isJavaIdentifierPart(it) }
139- .collect({ StringBuilder () }, { left, right -> left.appendCodePoint(right) }, { left, right -> left.append(right) })
140- .toString()
141-
142- internal fun IntStream.skipWhile (condition : (Int ) -> Boolean ): IntStream {
143- var found = false
144- return this .filter {
145- if (! found) {
146- found = ! condition(it)
147- }
148- found
149- }
150- }
0 commit comments