diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 03ce0b4..0000000 --- a/.clang-format +++ /dev/null @@ -1,149 +0,0 @@ ---- -Language: Cpp -# BasedOnStyle: LLVM -AccessModifierOffset: -2 -AlignAfterOpenBracket: Align -AlignConsecutiveMacros: false -AlignConsecutiveAssignments: false -AlignConsecutiveBitFields: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlines: Right -AlignOperands: Align -AlignTrailingComments: true -AllowAllArgumentsOnNextLine: true -AllowAllConstructorInitializersOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortEnumsOnASingleLine: true -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: All -AllowShortLambdasOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Never -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: MultiLine -BinPackArguments: true -BinPackParameters: true -BraceWrapping: - AfterCaseLabel: false - AfterClass: false - AfterControlStatement: Never - AfterEnum: false - AfterFunction: false - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - AfterExternBlock: false - BeforeCatch: false - BeforeElse: false - BeforeLambdaBody: false - BeforeWhile: false - IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Attach -BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeColon -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeColon -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: true -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DeriveLineEnding: true -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: true -ForEachMacros: - - foreach - - Q_FOREACH - - BOOST_FOREACH -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - SortPriority: 0 - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - SortPriority: 0 - - Regex: '.*' - Priority: 1 - SortPriority: 0 -IncludeIsMainRegex: '(Test)?$' -IncludeIsMainSourceRegex: '' -IndentCaseLabels: false -IndentCaseBlocks: false -IndentGotoLabels: true -IndentPPDirectives: None -IndentExternBlock: AfterExternBlock -IndentWidth: 2 -IndentWrappedFunctionNames: false -InsertTrailingCommas: None -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 2 -ObjCBreakBeforeNestedBlockParam: true -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInConditionalStatement: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -SpaceBeforeSquareBrackets: false -Standard: Latest -StatementMacros: - - Q_UNUSED - - QT_REQUIRE_VERSION -TabWidth: 8 -UseCRLF: false -UseTab: Never -WhitespaceSensitiveMacros: - - STRINGIZE - - PP_STRINGIZE - - BOOST_PP_STRINGIZE -... - diff --git a/.gitignore b/.gitignore index 82dca52..aa724b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,15 @@ -# Compilied C files -*.o -*.dylib - -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml .DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.gitmodules b/.gitmodules index 1190766..ab4d487 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "cooklang-c"] - path = cooklang-c +[submodule "parser/src/main/cpp/cooklang-c"] + path = parser/src/main/cpp/cooklang-c url = git@github.com:cooklang/cooklang-c.git diff --git a/Test.java b/Test.java deleted file mode 100644 index f47cfaf..0000000 --- a/Test.java +++ /dev/null @@ -1,44 +0,0 @@ -import org.cooklang.Parser; - -public class Test { - public static void main(String[] args) { - String burrito = """ - >> cooking time: 30 min - - Preheat your oven to the lowest setting. Drain the @cannellini beans{2%tins} in a sieve. Place a saucepan on a medium heat. - - Peel and dinely slice the @garlic clove{2}. add the @olive oil{1%tbsp} and sliced garlic to the hot pan. - - Crubmle the @red chilli{1%item} into the pan, then stir and fry until the grlic turns golden. - - Add the @tinned tomatoes{2%tins} and drained cannellini beans to the pan, reduce to a low heat and simmer gently for around 20 minutes, or until reduced and nice and thick. Meanwhile... - - Peel, halve and finely chop the @red onion{1}. Roughly chop the @cherry tomatoes{10}. Finely chop the @coriander{1%bunch} stalks and roughly chop the leaves. - - Coarsely grate the @cheddar cheese{75%g}. Cut @lime{1} in half and the other @lime{1} into six wedges. - - Cut the @avocados{2} in half lengthways, use a spppon to sccoop out and dicard the stone, then scoop the fles into a bowl to make your guacamole. - - Roughly mash the avocado with the back of a fork, then add the onion, cherry tomatoes, coriander stalks and @ground cumin{1%pinch}. Season with @sea salt{} and @black pepper{} and squeeze in the juice from one of the lime halves. - - Mix well then have a taste of your guacoamole and tweak with more salt, pepper and lime jouice until you've got a good balance of flovours and its tasing delicious. Set aside. - - Loosely wrap the @tortillas{6%large} in tin foil then pop in the hot oven to warm through, along with two plates. Finely chop the @fresh red chilli{2} and put it aside for later. - - Make your table look respectable - get the cutlery, salt and pepper and drinks laid out nicely. - - By now your beans should be done, so have a taste and season with salt and pepper. Turn the heat off and pop a lid on th pan sothey stay nice and warm. - - Put a small non-stick saucepan on a low heat. Add the @butter{30%g} and leave to melt. Meanwhile... - - Crack the @eggs{8%large} into a bowl, add a pinch of @salt{} and @black pepper{} and beat with a fork. When the buter has melted, add the eggs to the pan. Stir the eggs slowly with a spatula, getting right into the sides of the pan. Cook gently for 5 to 10 minutes until they just start to scramble then turn the heat off - they'll continute to cook on their own. - - Get two plates and pop a warm tortilla on each one. Divide the scrambled eggs between them then top with a good spoonful of you home-made beans. - - Scatter each portion with grated cheese and as much chilli as youdare, then roll each tortilla up. - - Spoon guacamole and @sour cream{200%ml} on top of each one, scatter with coriander leaves and dust with a little @smoked paprika{1%pinch}. Serve each portion with wedge of lime for squeezing over, and tuck in. - """; - System.out.println(Parser.parseRecipe(burrito)); - } -} diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..3af607e --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,64 @@ +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} + +android { + compileSdk 32 + + defaultConfig { + applicationId "org.cooklang.parser" + minSdk 23 + targetSdk 32 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary true + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + buildFeatures { + compose true + } + composeOptions { + kotlinCompilerExtensionVersion compose_version + } + packagingOptions { + resources { + excludes += '/META-INF/{AL2.0,LGPL2.1}' + } + } +} + +dependencies { + + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.1' + implementation 'com.google.android.material:material:1.6.0' + implementation "androidx.compose.ui:ui:$compose_version" + implementation "androidx.compose.material:material:$compose_version" + implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' + implementation 'androidx.activity:activity-compose:1.3.1' + implementation(project(":parser")) + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" + debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/org/cooklang/parser/ExampleInstrumentedTest.kt b/app/src/androidTest/java/org/cooklang/parser/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..35d6d3a --- /dev/null +++ b/app/src/androidTest/java/org/cooklang/parser/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package org.cooklang.parser + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("org.cooklang.parser", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9d9e1a4 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/org/cooklang/parser/MainActivity.kt b/app/src/main/java/org/cooklang/parser/MainActivity.kt new file mode 100644 index 0000000..15d8ace --- /dev/null +++ b/app/src/main/java/org/cooklang/parser/MainActivity.kt @@ -0,0 +1,80 @@ +package org.cooklang.parser + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.ScrollState +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.Button +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.material.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.google.android.material.textfield.TextInputEditText +import org.cooklang.parser.ui.theme.CooklangParserTheme + +private val testRecipe = "Slice @bacon{1kg} and things" + "\n" + + "Add @bacon{2kg} to @eggs" + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + var rawRecipeText by remember { mutableStateOf(testRecipe) } + + var parsedRecipeString by remember { mutableStateOf("") } + var recipe by remember { mutableStateOf(null)} + + CooklangParserTheme { + // A surface container using the 'background' color from the theme + Column( + modifier = Modifier + .verticalScroll(state = ScrollState(0)) + .fillMaxSize() + .padding(16.dp) + ) { + TextField( + label = { Text(text = "Raw recipe") }, + modifier = Modifier.fillMaxWidth(), + maxLines = 3, + value = rawRecipeText, + onValueChange = { + rawRecipeText = it + }) + Button(onClick = { + recipe = Parser.parseRecipe(rawRecipeText) + + }) { + Text(text = "Parse!") + } + recipe?.let { + Text(text = "Ingredients: ") + it.ingredients.map { + Text(text = "${it.name} ${it.quantityFloat ?: it.quantityString}${it.units}") + } + Spacer(modifier = Modifier.size(8.dp)) + Text(text = "Instructions: ") + Text(text = it.getDisplayString()) + } + + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/cooklang/parser/ui/theme/Color.kt b/app/src/main/java/org/cooklang/parser/ui/theme/Color.kt new file mode 100644 index 0000000..68db7fc --- /dev/null +++ b/app/src/main/java/org/cooklang/parser/ui/theme/Color.kt @@ -0,0 +1,8 @@ +package org.cooklang.parser.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple200 = Color(0xFFBB86FC) +val Purple500 = Color(0xFF6200EE) +val Purple700 = Color(0xFF3700B3) +val Teal200 = Color(0xFF03DAC5) \ No newline at end of file diff --git a/app/src/main/java/org/cooklang/parser/ui/theme/Shape.kt b/app/src/main/java/org/cooklang/parser/ui/theme/Shape.kt new file mode 100644 index 0000000..948d58c --- /dev/null +++ b/app/src/main/java/org/cooklang/parser/ui/theme/Shape.kt @@ -0,0 +1,11 @@ +package org.cooklang.parser.ui.theme + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Shapes +import androidx.compose.ui.unit.dp + +val Shapes = Shapes( + small = RoundedCornerShape(4.dp), + medium = RoundedCornerShape(4.dp), + large = RoundedCornerShape(0.dp) +) \ No newline at end of file diff --git a/app/src/main/java/org/cooklang/parser/ui/theme/Theme.kt b/app/src/main/java/org/cooklang/parser/ui/theme/Theme.kt new file mode 100644 index 0000000..747544b --- /dev/null +++ b/app/src/main/java/org/cooklang/parser/ui/theme/Theme.kt @@ -0,0 +1,44 @@ +package org.cooklang.parser.ui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material.MaterialTheme +import androidx.compose.material.darkColors +import androidx.compose.material.lightColors +import androidx.compose.runtime.Composable + +private val DarkColorPalette = darkColors( + primary = Purple200, + primaryVariant = Purple700, + secondary = Teal200 +) + +private val LightColorPalette = lightColors( + primary = Purple500, + primaryVariant = Purple700, + secondary = Teal200 + + /* Other default colors to override + background = Color.White, + surface = Color.White, + onPrimary = Color.White, + onSecondary = Color.Black, + onBackground = Color.Black, + onSurface = Color.Black, + */ +) + +@Composable +fun CooklangParserTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { + val colors = if (darkTheme) { + DarkColorPalette + } else { + LightColorPalette + } + + MaterialTheme( + colors = colors, + typography = Typography, + shapes = Shapes, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/cooklang/parser/ui/theme/Type.kt b/app/src/main/java/org/cooklang/parser/ui/theme/Type.kt new file mode 100644 index 0000000..c53c0d7 --- /dev/null +++ b/app/src/main/java/org/cooklang/parser/ui/theme/Type.kt @@ -0,0 +1,28 @@ +package org.cooklang.parser.ui.theme + +import androidx.compose.material.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + body1 = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp + ) + /* Other default text styles to override + button = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.W500, + fontSize = 14.sp + ), + caption = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 12.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..4fa21df --- /dev/null +++ b/app/src/main/res/values-night/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..10f3e92 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + CooklangParser + MainActivity + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..8a17357 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/app/src/test/java/org/cooklang/parser/ExampleUnitTest.kt b/app/src/test/java/org/cooklang/parser/ExampleUnitTest.kt new file mode 100644 index 0000000..c71e866 --- /dev/null +++ b/app/src/test/java/org/cooklang/parser/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package org.cooklang.parser + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..ed02a6f --- /dev/null +++ b/build.gradle @@ -0,0 +1,14 @@ +buildscript { + ext { + compose_version = '1.1.1' + } +}// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id 'com.android.application' version '7.1.2' apply false + id 'com.android.library' version '7.1.2' apply false + id 'org.jetbrains.kotlin.android' version '1.6.10' apply false +} + +task clean(type: Delete) { + delete rootProject.buildDir +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..cd0519b --- /dev/null +++ b/gradle.properties @@ -0,0 +1,23 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..f1c7897 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat May 14 15:49:12 CEST 2022 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/org/cooklang/Cookware.java b/org/cooklang/Cookware.java deleted file mode 100644 index 118ecc9..0000000 --- a/org/cooklang/Cookware.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.cooklang; - -public class Cookware implements DirectionItem { - public String name; - - private Float quantityFloat; - private String quantityString; - - public void setQuantityFloat(Float newQuantity) { - this.quantityFloat = newQuantity; - } - - public void setQuantityString(String newQuantity) { - this.quantityString = newQuantity; - } - - public void setName(String newName) { - this.name = newName; - } - - public String toString() { - return name; - } -} diff --git a/org/cooklang/DirectionItem.java b/org/cooklang/DirectionItem.java deleted file mode 100644 index acaaab2..0000000 --- a/org/cooklang/DirectionItem.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.cooklang; - -public interface DirectionItem { -} diff --git a/org/cooklang/Ingredient.java b/org/cooklang/Ingredient.java deleted file mode 100644 index 9f049c0..0000000 --- a/org/cooklang/Ingredient.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cooklang; - -public class Ingredient implements DirectionItem { - public String name; - - private Float quantityFloat; - private String quantityString; - public String units; - - public void setName(String newName) { - this.name = newName; - } - - public void setQuantityFloat(Float newQuantity) { - this.quantityFloat = newQuantity; - } - - public void setQuantityString(String newQuantity) { - this.quantityString = newQuantity; - } - - public void setUnits(String newUnits) { - this.units = newUnits; - } - - public String toString() { - return String.format("%s %s %s %s", name, quantityFloat, quantityString, units); - } -} diff --git a/org/cooklang/Parser.java b/org/cooklang/Parser.java deleted file mode 100644 index 68f7ba8..0000000 --- a/org/cooklang/Parser.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cooklang; - -public class Parser { - static { System.loadLibrary("cooklang"); } - public static native Recipe parseRecipe(String text); -} diff --git a/org/cooklang/Quantity.java b/org/cooklang/Quantity.java deleted file mode 100644 index 9df30b2..0000000 --- a/org/cooklang/Quantity.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.cooklang; - -public interface Quantity {} - - -// public class String implements Quantity {} diff --git a/org/cooklang/Recipe.java b/org/cooklang/Recipe.java deleted file mode 100644 index 273a48b..0000000 --- a/org/cooklang/Recipe.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.cooklang; - -import java.util.*; - -public class Recipe { - public List steps = new ArrayList<>(); - public Hashtable metadata = new Hashtable(); - - public void addStep(Step step) { - steps.add(step); - } - - public void addMetadata(String key, String value) { - metadata.put(key, value); - } - - public String toString() { - if (steps == null || steps.size() <= 0) return ""; - - StringBuilder sb = new StringBuilder(); - - for (Map.Entry entry : metadata.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - - sb.append(String.format(">> %s: %s\n", key, value)); - } - - for (int i = 0; i < steps.size(); i++) { - - sb.append(steps.get(i).toString()); - - // if not the last item - if (i != steps.size() - 1) { - sb.append("\n"); - } - - } - - return sb.toString(); - - } -} diff --git a/org/cooklang/Step.java b/org/cooklang/Step.java deleted file mode 100644 index 9b7b080..0000000 --- a/org/cooklang/Step.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.cooklang; - -import java.util.*; - -public class Step { - public List directions = new ArrayList<>(); - - public void addTextItem(TextItem texItem) { - directions.add(texItem); - } - - public void addIngredient(Ingredient ingredient) { - directions.add(ingredient); - } - - public void addCookware(Cookware cookware) { - directions.add(cookware); - } - - public void addTimer(Timer timer) { - directions.add(timer); - } - - public String toString() { - if (directions == null || directions.size() <= 0) return ""; - - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < directions.size(); i++) { - sb.append(directions.get(i).toString()); - } - - return sb.toString(); - } -} diff --git a/org/cooklang/TextItem.java b/org/cooklang/TextItem.java deleted file mode 100644 index ad470dd..0000000 --- a/org/cooklang/TextItem.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.cooklang; - -public class TextItem implements DirectionItem { - public String value; - - public void setValue(String newValue) { - this.value = newValue; - } - - public String toString() { - return value; - } -} diff --git a/org/cooklang/Timer.java b/org/cooklang/Timer.java deleted file mode 100644 index f181bb4..0000000 --- a/org/cooklang/Timer.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cooklang; - -public class Timer implements DirectionItem { - public String units; - public String name; - - private Float quantityFloat; - private String quantityString; - - public void setQuantityFloat(Float newQuantity) { - this.quantityFloat = newQuantity; - } - - public void setQuantityString(String newQuantity) { - this.quantityString = newQuantity; - } - - public void setUnits(String newUnits) { - this.units = newUnits; - } - - public void setName(String newName) { - this.name = newName; - } - - public String toString() { - return String.format("%s %s %s %s", name, quantityFloat, quantityString, units); - } -} diff --git a/parser/.gitignore b/parser/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/parser/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/parser/build.gradle b/parser/build.gradle new file mode 100644 index 0000000..c97a6a1 --- /dev/null +++ b/parser/build.gradle @@ -0,0 +1,51 @@ +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' +} + +android { + compileSdk 32 + + defaultConfig { + minSdk 23 + targetSdk 32 + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + externalNativeBuild { + cmake { + cppFlags "" + } + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + externalNativeBuild { + cmake { + path "src/main/cpp/CMakeLists.txt" + version "3.18.1" + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } +} + +dependencies { + + implementation 'androidx.core:core-ktx:1.7.0' + implementation 'androidx.appcompat:appcompat:1.4.1' + implementation 'com.google.android.material:material:1.6.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' +} \ No newline at end of file diff --git a/parser/consumer-rules.pro b/parser/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/parser/proguard-rules.pro b/parser/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/parser/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/parser/src/androidTest/java/org/cooklang/parser/ExampleInstrumentedTest.kt b/parser/src/androidTest/java/org/cooklang/parser/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..2b07dea --- /dev/null +++ b/parser/src/androidTest/java/org/cooklang/parser/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package org.cooklang.parser + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("org.cooklang.parser.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/parser/src/main/AndroidManifest.xml b/parser/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7c6d058 --- /dev/null +++ b/parser/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/parser/src/main/cpp/CMakeLists.txt b/parser/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000..63552b7 --- /dev/null +++ b/parser/src/main/cpp/CMakeLists.txt @@ -0,0 +1,51 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.18.1) + +# Declares and names the project. + +project("cooklang") + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. + +add_library( # Sets the name of the library. + cooklang + + # Sets the library as a shared library. + SHARED + # Provides a relative path to your source file(s). + cooklang-c/src/CooklangParser.c + cooklang-c/src/CooklangRecipe.c + cooklang-c/src/LinkedListLib.c + cooklang-c/parserFiles/Cooklang.tab.c + parser.c) + +# Searches for a specified prebuilt library and stores the path as a +# variable. Because CMake includes system libraries in the search path by +# default, you only need to specify the name of the public NDK library +# you want to add. CMake verifies that the library exists before +# completing its build. + +find_library( # Sets the name of the path variable. + log-lib + + # Specifies the name of the NDK library that + # you want CMake to locate. + log) + +# Specifies libraries CMake should link to your target library. You +# can link multiple libraries, such as libraries you define in this +# build script, prebuilt third-party libraries, or system libraries. + +target_link_libraries( # Specifies the target library. + cooklang + + # Links the target library to the log library + # included in the NDK. + ${log-lib}) \ No newline at end of file diff --git a/cooklang-c b/parser/src/main/cpp/cooklang-c similarity index 100% rename from cooklang-c rename to parser/src/main/cpp/cooklang-c diff --git a/org_cooklang_Parser.c b/parser/src/main/cpp/parser.c similarity index 92% rename from org_cooklang_Parser.c rename to parser/src/main/cpp/parser.c index 1bdef14..3a849dc 100644 --- a/org_cooklang_Parser.c +++ b/parser/src/main/cpp/parser.c @@ -1,36 +1,36 @@ #include "cooklang-c/include/CooklangParser.h" #include "cooklang-c/parserFiles/Cooklang.tab.h" -#include "org_cooklang_Parser.h" +#include "parser.h" JNIEXPORT jobject JNICALL -Java_org_cooklang_Parser_parseRecipe(JNIEnv *env, jclass, jstring content) { - jclass recipeClass = (*env)->FindClass(env, "org/cooklang/Recipe"); +Java_org_cooklang_parser_Parser_parseRecipe(JNIEnv *env, jclass clazz, jstring content) { + jclass recipeClass = (*env)->FindClass(env, "org/cooklang/parser/Recipe"); jmethodID recipeConstructor = (*env)->GetMethodID(env, recipeClass, "", "()V");; - jclass stepClass = (*env)->FindClass(env, "org/cooklang/Step"); + jclass stepClass = (*env)->FindClass(env, "org/cooklang/parser/Step"); jmethodID stepConstructor = (*env)->GetMethodID(env, stepClass, "", "()V"); - jclass textItemClass = (*env)->FindClass(env, "org/cooklang/TextItem"); + jclass textItemClass = (*env)->FindClass(env, "org/cooklang/parser/TextItem"); jmethodID textItemConstructor = (*env)->GetMethodID(env, textItemClass, "", "()V"); - jclass ingredientClass = (*env)->FindClass(env, "org/cooklang/Ingredient"); + jclass ingredientClass = (*env)->FindClass(env, "org/cooklang/parser/Ingredient"); jmethodID ingredientConstructor = (*env)->GetMethodID(env, ingredientClass, "", "()V"); - jclass cookwareClass = (*env)->FindClass(env, "org/cooklang/Cookware"); + jclass cookwareClass = (*env)->FindClass(env, "org/cooklang/parser/Cookware"); jmethodID cookwareConstructor = (*env)->GetMethodID(env, cookwareClass, "", "()V"); - jclass timerClass = (*env)->FindClass(env, "org/cooklang/Timer"); + jclass timerClass = (*env)->FindClass(env, "org/cooklang/parser/Timer"); jmethodID timerConstructor = (*env)->GetMethodID(env, timerClass, "", "()V"); - jmethodID addStep = (*env)->GetMethodID(env, recipeClass, "addStep", "(Lorg/cooklang/Step;)V"); + jmethodID addStep = (*env)->GetMethodID(env, recipeClass, "addStep", "(Lorg/cooklang/parser/Step;)V"); jmethodID addMetadata = (*env)->GetMethodID(env, recipeClass, "addMetadata", "(Ljava/lang/String;Ljava/lang/String;)V"); - jmethodID addTextItem = (*env)->GetMethodID(env, stepClass, "addTextItem", "(Lorg/cooklang/TextItem;)V"); - jmethodID addIngredient = (*env)->GetMethodID(env, stepClass, "addIngredient", "(Lorg/cooklang/Ingredient;)V"); - jmethodID addTimer = (*env)->GetMethodID(env, stepClass, "addTimer", "(Lorg/cooklang/Timer;)V"); - jmethodID addCookware = (*env)->GetMethodID(env, stepClass, "addCookware", "(Lorg/cooklang/Cookware;)V"); + jmethodID addTextItem = (*env)->GetMethodID(env, stepClass, "addTextItem", "(Lorg/cooklang/parser/TextItem;)V"); + jmethodID addIngredient = (*env)->GetMethodID(env, stepClass, "addIngredient", "(Lorg/cooklang/parser/Ingredient;)V"); + jmethodID addTimer = (*env)->GetMethodID(env, stepClass, "addTimer", "(Lorg/cooklang/parser/Timer;)V"); + jmethodID addCookware = (*env)->GetMethodID(env, stepClass, "addCookware", "(Lorg/cooklang/parser/Cookware;)V"); jmethodID setTextItemValue = (*env)->GetMethodID(env, textItemClass, "setValue", "(Ljava/lang/String;)V"); diff --git a/org_cooklang_Parser.h b/parser/src/main/cpp/parser.h similarity index 85% rename from org_cooklang_Parser.h rename to parser/src/main/cpp/parser.h index a75177a..6c3c2a1 100644 --- a/org_cooklang_Parser.h +++ b/parser/src/main/cpp/parser.h @@ -12,7 +12,7 @@ extern "C" { * Method: parseRecipe * Signature: (Ljava/lang/String;)Lorg/cooklang/Recipe; */ -JNIEXPORT jobject JNICALL Java_org_cooklang_Parser_parseRecipe +JNIEXPORT jobject JNICALL Java_org_cooklang_parser_Parser_parseRecipe (JNIEnv *, jclass, jstring); #ifdef __cplusplus diff --git a/parser/src/main/java/org/cooklang/parser/Cookware.kt b/parser/src/main/java/org/cooklang/parser/Cookware.kt new file mode 100644 index 0000000..0184533 --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/Cookware.kt @@ -0,0 +1,13 @@ +package org.cooklang.parser + +import org.cooklang.parser.DirectionItem + +data class Cookware( + var name: String? = null, + var quantityFloat: Float? = null, + var quantityString: String? = null +) : DirectionItem { + override fun getDisplayString(): String { + return "${quantityFloat ?: quantityString ?: ""} $name" + } +} \ No newline at end of file diff --git a/parser/src/main/java/org/cooklang/parser/DirectionItem.kt b/parser/src/main/java/org/cooklang/parser/DirectionItem.kt new file mode 100644 index 0000000..8b271e5 --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/DirectionItem.kt @@ -0,0 +1,5 @@ +package org.cooklang.parser + +interface DirectionItem : Displayable { + +} \ No newline at end of file diff --git a/parser/src/main/java/org/cooklang/parser/Displayable.kt b/parser/src/main/java/org/cooklang/parser/Displayable.kt new file mode 100644 index 0000000..a3c919a --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/Displayable.kt @@ -0,0 +1,5 @@ +package org.cooklang.parser + +interface Displayable { + fun getDisplayString(): String +} \ No newline at end of file diff --git a/parser/src/main/java/org/cooklang/parser/Ingredient.kt b/parser/src/main/java/org/cooklang/parser/Ingredient.kt new file mode 100644 index 0000000..288d703 --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/Ingredient.kt @@ -0,0 +1,14 @@ +package org.cooklang.parser + +import org.cooklang.parser.DirectionItem + +data class Ingredient( + var name: String? = null, + var quantityFloat: Float? = null, + var quantityString: String? = null, + var units: String? = null //maybe should be enum? +) : DirectionItem{ + override fun getDisplayString(): String { + return "$name" + } +} \ No newline at end of file diff --git a/parser/src/main/java/org/cooklang/parser/Parser.kt b/parser/src/main/java/org/cooklang/parser/Parser.kt new file mode 100644 index 0000000..b13d606 --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/Parser.kt @@ -0,0 +1,11 @@ +package org.cooklang.parser + +import org.cooklang.parser.Recipe + +object Parser { + external fun parseRecipe(text: String?): Recipe? + + init { + System.loadLibrary("cooklang") + } +} \ No newline at end of file diff --git a/parser/src/main/java/org/cooklang/parser/Quantity.kt b/parser/src/main/java/org/cooklang/parser/Quantity.kt new file mode 100644 index 0000000..38048c6 --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/Quantity.kt @@ -0,0 +1,3 @@ +package org.cooklang.parser + +interface Quantity \ No newline at end of file diff --git a/parser/src/main/java/org/cooklang/parser/Recipe.kt b/parser/src/main/java/org/cooklang/parser/Recipe.kt new file mode 100644 index 0000000..1afce38 --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/Recipe.kt @@ -0,0 +1,34 @@ +package org.cooklang.parser + +import java.lang.StringBuilder +import java.util.* + +class Recipe : Displayable { + val steps: MutableList = mutableListOf() + var metadata = Hashtable() + fun addStep(step: Step) { + steps.add(step) + } + + val ingredients: List get() = steps.map { it.ingredients }.reduce { acc, list -> acc + list } + val cookware: List get() = steps.map { it.cookware }.reduce { acc, list -> acc + list } + + fun addMetadata(key: String, value: String) { + metadata[key] = value + } + + override fun getDisplayString(): String { + if (steps.size <= 0) return "" + val sb = StringBuilder() + for ((key, value) in metadata) { + sb.append(">> $key: $value\n") + } + steps.forEachIndexed { index, step -> + sb.append("${index + 1}. ${step.getDisplayString()}") + if (index != steps.lastIndex) { + sb.append("\n") + } + } + return sb.toString() + } +} \ No newline at end of file diff --git a/parser/src/main/java/org/cooklang/parser/Step.kt b/parser/src/main/java/org/cooklang/parser/Step.kt new file mode 100644 index 0000000..8df13e7 --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/Step.kt @@ -0,0 +1,38 @@ +package org.cooklang.parser + +import org.cooklang.parser.DirectionItem +import org.cooklang.parser.TextItem +import org.cooklang.parser.Ingredient +import org.cooklang.parser.Cookware +import java.lang.StringBuilder +import java.util.ArrayList + +class Step: Displayable { + val directions: MutableList = mutableListOf() + fun addTextItem(texItem: TextItem) { + directions.add(texItem) + } + + fun addIngredient(ingredient: Ingredient) { + directions.add(ingredient) + } + + fun addCookware(cookware: Cookware) { + directions.add(cookware) + } + + fun addTimer(timer: Timer) { + directions.add(timer) + } + val ingredients: List get() = directions.filterIsInstance(Ingredient::class.java) + val cookware: List get() = directions.filterIsInstance(Cookware::class.java) + + override fun getDisplayString(): String { + if (directions.size <= 0) return "" + val sb = StringBuilder() + directions.forEach { + sb.append(it.getDisplayString()) + } + return sb.toString() + } +} \ No newline at end of file diff --git a/parser/src/main/java/org/cooklang/parser/TextItem.kt b/parser/src/main/java/org/cooklang/parser/TextItem.kt new file mode 100644 index 0000000..838f1bc --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/TextItem.kt @@ -0,0 +1,9 @@ +package org.cooklang.parser + +import org.cooklang.parser.DirectionItem + +data class TextItem(var value: String? = null) : DirectionItem{ + override fun getDisplayString(): String { + return value ?: "" + } +} \ No newline at end of file diff --git a/parser/src/main/java/org/cooklang/parser/Timer.kt b/parser/src/main/java/org/cooklang/parser/Timer.kt new file mode 100644 index 0000000..a3fbdac --- /dev/null +++ b/parser/src/main/java/org/cooklang/parser/Timer.kt @@ -0,0 +1,14 @@ +package org.cooklang.parser + +import org.cooklang.parser.DirectionItem + +data class Timer( + var units: String? = null, + var name: String? = null, + var quantityFloat: Float? = null, + var quantityString: String? = null +) : DirectionItem { + override fun getDisplayString(): String { + return "$name ${quantityFloat?: quantityString?: ""} ${units ?: ""}" + } +} \ No newline at end of file diff --git a/parser/src/test/java/org/cooklang/parser/ParserTest.kt b/parser/src/test/java/org/cooklang/parser/ParserTest.kt new file mode 100644 index 0000000..e9d60c7 --- /dev/null +++ b/parser/src/test/java/org/cooklang/parser/ParserTest.kt @@ -0,0 +1,19 @@ +package org.cooklang.parser + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ParserTest { + + @Test + fun testParser() { + val recipe = Parser.parseRecipe("Slice @bacon{1} and things") + assert(recipe!!.metadata!!.isNotEmpty()) + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..68ec702 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} +rootProject.name = "CooklangParser" +include ':app' +include ':parser' diff --git a/shell.nix b/shell.nix deleted file mode 100644 index d937139..0000000 --- a/shell.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ }: - -let - # get a normalized set of packages, from which - # we will install all the needed dependencies - pkgs = import (fetchTarball { - name = "nixos-unstable-2022-05-08"; - url = "https://github.com/NixOS/nixpkgs/archive/52f31d531b68d92f901310ea3a48999ac182df73.tar.gz"; - sha256 = "1kfvidyc0ipq1f89xgz8i22czss2iry74fwbz5z8rabzzpfzywqr"; - }) {}; -in - pkgs.mkShell { - buildInputs = [ - pkgs.openjdk - pkgs.gcc - pkgs.clang-tools - ]; - shellHook = '' - export NIX_ENV=dev - ''; - }