├── .gitignore
├── .idea
├── checkstyle-idea.xml
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── github
│ │ └── gianlucanitti
│ │ └── expreval
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-web.png
│ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── gianlucanitti
│ │ │ └── expreval
│ │ │ ├── ContextDialogFragment.java
│ │ │ ├── EditFunctionDialogFragment.java
│ │ │ ├── EditVariableDialogFragment.java
│ │ │ ├── ExprEval.java
│ │ │ ├── ExprEvalDialog.java
│ │ │ ├── LibraryLocalizer.java
│ │ │ ├── TextViewExpressionContext.java
│ │ │ └── TextViewWriter.java
│ └── res
│ │ ├── layout
│ │ ├── activity_expr_eval.xml
│ │ ├── activity_expr_eval_dialog.xml
│ │ ├── dialog_edit_function.xml
│ │ └── dialog_edit_variable.xml
│ │ ├── menu
│ │ └── mainmenu.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-it
│ │ └── strings.xml
│ │ ├── values-pt-rBR
│ │ └── strings.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── github
│ └── gianlucanitti
│ └── expreval
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── icon.xcf
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Gianluca Nitti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # android-expr-eval
2 | Android application to solve math expressions. Based on [java-expr-eval](https://github.com/gianluca-nitti/java-expr-eval).
3 |
4 | ## New features
5 | Now supports [ACTION_PROCESS_TEXT](https://medium.com/google-developers/custom-text-selection-actions-with-action-process-text-191f792d2999#.ir1ubmtgz) intent on Android 6.0+, i.e. you can evaluate an expression from any application using ExprEval and replace it with the result.
6 | See this animation for an example:
7 |
8 | 
9 |
10 | A custom intent is also available: you can use `startActivityForResult()` with `com.github.gianlucanitti.expreval.ACTION_EVAL` Intent to have an expression evaluated.
11 | You have to `putExtra()` the expression with `"expression"` as the extra name, and the result will be returned in an extra named `"result"`.
12 |
13 | This feature was proposed in [issue #1](https://github.com/gianluca-nitti/android-expr-eval/issues/1).
14 |
15 | ## Download/compile
16 | See the releases page for prebuilt APK.
17 | To build from source, clone the repository, make sure you have the Android SDK installed (and you have the ANDROID_HOME environment variable correctly set), and run
18 | ```
19 | ./gradlew assembleRelease
20 | ```
21 | (you may need to `chmod +x gradlew` it if it's not already executable).
22 |
23 | ## Contributed translations
24 | * [@afmachado](https://github.com/afmachado): Brazilian Portuguese
25 |
26 | ## Screenshots ([Imgur album](http://imgur.com/a/wOJfT))
27 | 
28 | 
29 | 
30 | 
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.github.gianlucanitti.expreval"
9 | minSdkVersion 15
10 | targetSdkVersion 25
11 | versionCode 3
12 | versionName "1.2"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.github.gianluca-nitti:java-expr-eval:v3.1'
26 | compile 'com.android.support:appcompat-v7:25+'
27 | compile 'com.android.support:support-v4:25+'
28 | }
29 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\Gianluca\AppData\Local\Android\android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/github/gianlucanitti/expreval/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gianluca-nitti/android-expr-eval/7270001bd9be435140623515bae2b20e28bc6d63/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/app/src/main/java/com/github/gianlucanitti/expreval/ContextDialogFragment.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import android.app.*;
4 | import android.content.DialogInterface;
5 | import android.os.Bundle;
6 | import android.widget.Toast;
7 | import com.github.gianlucanitti.javaexpreval.*;
8 |
9 | import java.util.*;
10 |
11 | public class ContextDialogFragment extends DialogFragment implements Observer, DialogInterface.OnClickListener{
12 |
13 | private static abstract class ContextItem{
14 | @Override
15 | public abstract String toString();
16 | }
17 |
18 | private static class VariableContextItem extends ContextItem{
19 | private String name;
20 | private ExpressionContext.VariableValue data;
21 |
22 | private VariableContextItem(String name, ExpressionContext.VariableValue data){
23 | this.name = name;
24 | this.data = data;
25 | }
26 |
27 | @Override
28 | public String toString(){
29 | return (data.isReadOnly() ? "readonly " : "") + name + "=" + data.getValue();
30 | }
31 | }
32 |
33 | private static class FunctionContextItem extends ContextItem{
34 | private Function data;
35 |
36 | private FunctionContextItem(Function data){
37 | this.data = data;
38 | }
39 |
40 | @Override
41 | public String toString(){
42 | return (data.isReadOnly() ? "readonly " : "") + data.getName() + "(" + data.getArgCount() + " arguments)";
43 | }
44 | }
45 |
46 | private class ListItems{
47 |
48 | private ArrayList items = new ArrayList<>();
49 | private ExpressionContext ctx;
50 |
51 | private void update(ExpressionContext ctx){
52 | this.ctx = ctx;
53 | items.clear();
54 | for(Map.Entry v: ctx.getVariables().entrySet())
55 | items.add(new VariableContextItem(v.getKey(), v.getValue()));
56 | for(Function f: ctx.getFunctions())
57 | items.add(new FunctionContextItem(f));
58 | }
59 |
60 | private String[] getStrings(){
61 | String[] result = new String[items.size()];
62 | for(int i = 0; i < result.length; i++)
63 | result[i] = items.get(i).toString();
64 | return result;
65 | }
66 |
67 | private ContextItem getItem(int i){
68 | return items.get(i);
69 | }
70 |
71 | private ContextItem removeItem(int i) throws ReadonlyException{
72 | ContextItem item = items.get(i);
73 | if (item instanceof VariableContextItem) {
74 | ctx.delVariable(((VariableContextItem) item).name);
75 | } else {
76 | Function f = ((FunctionContextItem) item).data;
77 | ctx.delFunction(f.getName(), f.getArgCount());
78 | }
79 | update(ctx);
80 | return item;
81 | }
82 | }
83 |
84 | private FragmentManager fm;
85 | private EditVariableDialogFragment editVariable;
86 | private EditFunctionDialogFragment editFunction;
87 |
88 | private ListItems items = new ListItems();
89 |
90 | @Override
91 | public void update(Observable observable, Object data) {
92 | items.update((ExpressionContext)observable);
93 | }
94 |
95 | @Override
96 | public Dialog onCreateDialog(Bundle savedInstanceState){
97 | setRetainInstance(true);
98 | editVariable = new EditVariableDialogFragment();
99 | editFunction = new EditFunctionDialogFragment();
100 | fm = getFragmentManager();
101 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
102 | builder.setItems(items.getStrings(), this);
103 | builder.setPositiveButton(R.string.newContextItem, this);
104 | return builder.create();
105 | }
106 |
107 | @Override
108 | public void onClick(DialogInterface dialog, final int which) {
109 | final ExprEval activity = (ExprEval)getActivity();
110 | AlertDialog.Builder innerDialog = new AlertDialog.Builder(activity);
111 | if (which == DialogInterface.BUTTON_POSITIVE) {
112 | innerDialog.setItems(R.array.addVariableFunction, new DialogInterface.OnClickListener() {
113 | @Override
114 | public void onClick(DialogInterface dialogInterface, int i) {
115 | if(i == 0) {
116 | editVariable.show(fm, "edit_variable");
117 | }else if (i == 1){
118 | editFunction.show(fm, "edit_function");
119 | }
120 | }
121 | });
122 | } else {
123 | innerDialog.setMessage(getString(R.string.contextItemDeletePrompt, items.getItem(which).toString()));
124 | final String deletedMsg = getString(R.string.contextItemDeleted, items.getItem(which).toString());
125 | innerDialog.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener(){
126 | @Override
127 | public void onClick(DialogInterface dialog_inner, int which_inner) {
128 | try{
129 | items.removeItem(which);
130 | activity.writeOutput(deletedMsg);
131 | }catch(ExpressionException ex){
132 | Toast.makeText(activity, ex.getMessage(), Toast.LENGTH_LONG).show();
133 | activity.writeOutput(ex.getMessage());
134 | }
135 | }
136 | });
137 | innerDialog.setNegativeButton(android.R.string.no, null);
138 | }
139 | innerDialog.create().show();
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/gianlucanitti/expreval/EditFunctionDialogFragment.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import android.app.AlertDialog;
4 | import android.app.Dialog;
5 | import android.app.DialogFragment;
6 | import android.content.DialogInterface;
7 | import android.os.Bundle;
8 | import android.view.View;
9 | import android.widget.*;
10 | import com.github.gianlucanitti.javaexpreval.*;
11 |
12 | import java.util.ArrayList;
13 |
14 | public class EditFunctionDialogFragment extends DialogFragment implements DialogInterface.OnClickListener {
15 |
16 | private ExpressionContext ctx;
17 | private ArrayList argNames;
18 |
19 | private EditText nameText;
20 | private EditText exprText;
21 | private EditText newArgText;
22 | private ListView argsList;
23 | private CheckBox readonlyCheckbox;
24 |
25 | private void writeOutput(String s) {
26 | ((ExprEval) getActivity()).writeOutput(s);
27 | }
28 |
29 | @Override
30 | public Dialog onCreateDialog(Bundle savedInstanceState) {
31 | setRetainInstance(true);
32 | ctx = ((ExprEval) getActivity()).getContext();
33 | argNames = new ArrayList<>();
34 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
35 | View rootLayout = getActivity().getLayoutInflater().inflate(R.layout.dialog_edit_function, null);
36 | nameText = (EditText) rootLayout.findViewById(R.id.nameText);
37 | exprText = (EditText) rootLayout.findViewById(R.id.exprText);
38 | newArgText = (EditText) rootLayout.findViewById(R.id.newArgText);
39 | argsList = (ListView) rootLayout.findViewById(R.id.argsList);
40 | readonlyCheckbox = (CheckBox) rootLayout.findViewById(R.id.readonlyCheckbox);
41 | final ArrayAdapter argsArrayAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, argNames);
42 | argsList.setAdapter(argsArrayAdapter);
43 | argsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
44 | @Override
45 | public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
46 | argNames.remove(i);
47 | argsArrayAdapter.notifyDataSetChanged();
48 | }
49 | });
50 | rootLayout.findViewById(R.id.add_argument).setOnClickListener(new View.OnClickListener() {
51 | @Override
52 | public void onClick(View view) {
53 | if (NamedSymbolExpression.isValidSymbolName(newArgText.getText().toString())) {
54 | argNames.add(newArgText.getText().toString());
55 | argsArrayAdapter.notifyDataSetChanged();
56 | newArgText.getText().clear();
57 | } else {
58 | newArgText.setError(getString(R.string.invalidArgName));
59 | }
60 | }
61 | });
62 | builder.setView(rootLayout);
63 | builder.setPositiveButton(android.R.string.ok, this);
64 | builder.setNegativeButton(android.R.string.cancel, this);
65 | return builder.create();
66 | }
67 |
68 | @Override
69 | public void onClick(DialogInterface dialogInterface, int i) {
70 | if (i == DialogInterface.BUTTON_POSITIVE) {
71 | try {
72 | ctx.setFunction(nameText.getText().toString(), Expression.parse(exprText.getText().toString()), readonlyCheckbox.isChecked(), argNames.toArray(new String[argNames.size()]));
73 | writeOutput(getString(R.string.functionNewDef, ctx.getFunction(nameText.getText().toString(), argNames.size()).toString(), exprText.getText().toString()));
74 | } catch (ExpressionException ex) {
75 | writeOutput(ex.getMessage());
76 | Toast.makeText(getActivity(), ex.getMessage(), Toast.LENGTH_LONG).show();
77 | }
78 | }
79 | }
80 |
81 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/gianlucanitti/expreval/EditVariableDialogFragment.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import android.app.AlertDialog;
4 | import android.app.Dialog;
5 | import android.app.DialogFragment;
6 | import android.content.DialogInterface;
7 | import android.os.Bundle;
8 | import android.view.View;
9 | import android.widget.CheckBox;
10 | import android.widget.EditText;
11 | import android.widget.Toast;
12 | import com.github.gianlucanitti.javaexpreval.Expression;
13 | import com.github.gianlucanitti.javaexpreval.ExpressionContext;
14 | import com.github.gianlucanitti.javaexpreval.ExpressionException;
15 |
16 | public class EditVariableDialogFragment extends DialogFragment implements DialogInterface.OnClickListener{
17 |
18 | private ExpressionContext ctx;
19 |
20 | private EditText nameText;
21 | private EditText valueText;
22 | private CheckBox readonlyCheckbox;
23 |
24 | private void writeOutput(String s){
25 | ((ExprEval) getActivity()).writeOutput(s);
26 | }
27 |
28 | @Override
29 | public Dialog onCreateDialog(Bundle savedInstanceState){
30 | setRetainInstance(true);
31 | ctx = ((ExprEval) getActivity()).getContext();
32 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
33 | View rootLayout = getActivity().getLayoutInflater().inflate(R.layout.dialog_edit_variable, null);
34 | nameText = (EditText) rootLayout.findViewById(R.id.nameText);
35 | valueText = (EditText) rootLayout.findViewById(R.id.valueText);
36 | readonlyCheckbox = (CheckBox) rootLayout.findViewById(R.id.readonlyCheckbox);
37 | builder.setView(rootLayout);
38 | builder.setPositiveButton(android.R.string.ok, this);
39 | builder.setNegativeButton(android.R.string.cancel, this);
40 | return builder.create();
41 | }
42 |
43 | @Override
44 | public void onClick(DialogInterface dialogInterface, int which) {
45 | if(which == DialogInterface.BUTTON_POSITIVE){
46 | String varName = nameText.getText().toString();
47 | try {
48 | ctx.setVariable(varName , readonlyCheckbox.isChecked(), Expression.parse(valueText.getText().toString()));
49 | writeOutput(getString(R.string.varNewValue, varName, Double.toString(ctx.getVariable(varName))));
50 | }catch(ExpressionException ex){
51 | writeOutput(ex.getMessage());
52 | Toast.makeText(getActivity(), ex.getMessage(), Toast.LENGTH_LONG).show();
53 | }
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/gianlucanitti/expreval/ExprEval.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.DialogInterface;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.os.Bundle;
7 | import android.support.v7.widget.Toolbar;
8 | import android.text.Html;
9 | import android.text.method.LinkMovementMethod;
10 | import android.text.method.ScrollingMovementMethod;
11 | import android.view.Menu;
12 | import android.view.MenuItem;
13 | import android.view.View;
14 | import android.widget.Button;
15 | import android.widget.EditText;
16 | import android.widget.TextView;
17 | import com.github.gianlucanitti.javaexpreval.ExpressionContext;
18 |
19 | public class ExprEval extends AppCompatActivity implements View.OnClickListener{
20 |
21 | private TextViewExpressionContext ctx;
22 |
23 | private EditText in;
24 | private TextView out;
25 | private Button evalBtn;
26 |
27 | private ContextDialogFragment ctxDialog;
28 |
29 | public ExpressionContext getContext(){
30 | return ctx;
31 | }
32 |
33 | public void writeOutput(String s){
34 | out.append(s + System.getProperty("line.separator"));
35 | }
36 |
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | setContentView(R.layout.activity_expr_eval);
41 | setSupportActionBar((Toolbar)findViewById(R.id.my_toolbar));
42 | LibraryLocalizer.localize(this);
43 | in = (EditText) findViewById(R.id.inputText);
44 | out = (TextView) findViewById(R.id.outputText);
45 | out.setMovementMethod(new ScrollingMovementMethod());
46 | evalBtn = (Button)findViewById(R.id.evalBtn);
47 | evalBtn.setOnClickListener(this);
48 | ctxDialog = new ContextDialogFragment();
49 | ctx = new TextViewExpressionContext(out);
50 | ctx.addObserver(ctxDialog);
51 | ctxDialog.update(ctx, null);
52 | }
53 |
54 | @Override
55 | public boolean onCreateOptionsMenu(Menu menu) {
56 | getMenuInflater().inflate(R.menu.mainmenu, menu);
57 | return true;
58 | }
59 |
60 | @Override
61 | public boolean onOptionsItemSelected(MenuItem item){
62 | switch(item.getItemId()){
63 | case R.id.action_context:
64 | ctxDialog.show(getFragmentManager(), "context_dialog");
65 | return true;
66 | case R.id.action_clearctx:
67 | AlertDialog.Builder prompt = new AlertDialog.Builder(this);
68 | prompt.setMessage(R.string.clearContextPrompt);
69 | prompt.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
70 | @Override
71 | public void onClick(DialogInterface dialogInterface, int i) {
72 | ctx.clear();
73 | ctx.writeOutput(getString(R.string.contextCleared));
74 | }
75 | });
76 | prompt.setNegativeButton(android.R.string.no, null);
77 | prompt.show();
78 | return true;
79 | case R.id.action_clearout:
80 | out.setText("");
81 | return true;
82 | case R.id.action_verbose:
83 | item.setChecked(!item.isChecked());
84 | ctx.setVerbose(item.isChecked());
85 | return true;
86 | case R.id.action_input:
87 | item.setChecked(!item.isChecked());
88 | ctx.setEchoInput(item.isChecked());
89 | return true;
90 | case R.id.action_help:
91 | new AlertDialog.Builder(this).setMessage(Html.fromHtml(getString(R.string.helpMessage))).show();
92 | return true;
93 | case R.id.action_about:
94 | AlertDialog d = new AlertDialog.Builder(this)
95 | .setMessage(Html.fromHtml(getString(R.string.aboutMessage)))
96 | .show();
97 | ((TextView)d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
98 | return true;
99 | default:
100 | return super.onOptionsItemSelected(item);
101 | }
102 | }
103 |
104 | @Override
105 | public void onClick(View view){
106 | if(ctx.update(in.getText().toString()) == TextViewExpressionContext.Status.EXIT)
107 | finish();
108 | in.getText().clear();
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/gianlucanitti/expreval/ExprEvalDialog.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import android.content.Intent;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 | import android.text.method.ScrollingMovementMethod;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.TextView;
10 | import com.github.gianlucanitti.javaexpreval.UndefinedException;
11 |
12 | public class ExprEvalDialog extends AppCompatActivity implements View.OnClickListener{
13 |
14 | private boolean actionIsProcessText;
15 | private String result;
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_expr_eval_dialog);
21 | LibraryLocalizer.localize(this);
22 | View okButton = findViewById(R.id.evalDialogOK);
23 | View cancelButton = findViewById(R.id.evalDialogCancel);
24 | okButton.setOnClickListener(this);
25 | cancelButton.setOnClickListener(this);
26 | actionIsProcessText = getIntent().getAction().equals(Intent.ACTION_PROCESS_TEXT);
27 | String expr = getIntent().getStringExtra(actionIsProcessText ? Intent.EXTRA_PROCESS_TEXT : "expression");
28 | if(actionIsProcessText && getIntent().getBooleanExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, false)){
29 | okButton.setVisibility(View.INVISIBLE);
30 | ((Button)cancelButton).setText(R.string.close);
31 | findViewById(R.id.evalDialogOkToReplace).setVisibility(View.GONE);
32 | }
33 | ((TextView)findViewById(R.id.evalDialogExpr)).append(" " + expr);
34 | TextView evalDialogLog = (TextView)findViewById(R.id.evalDialogLog);
35 | evalDialogLog.setMovementMethod(new ScrollingMovementMethod());
36 | evalDialogLog.append(System.getProperty("line.separator"));
37 | TextViewExpressionContext ctx = new TextViewExpressionContext(evalDialogLog);
38 | ctx.setStopOnError(true);
39 | boolean failed = ctx.update(expr) == TextViewExpressionContext.Status.ERROR;
40 | okButton.setEnabled(!failed);
41 | if(failed)
42 | result = getString(R.string.evalFailed);
43 | else
44 | try {
45 | result = Double.toString(ctx.getVariable("ans"));
46 | }catch(UndefinedException e){
47 | result = getString(R.string.evalFailed);
48 | }
49 | ((TextView)findViewById(R.id.evalDialogResult)).append(" " + result);
50 | }
51 |
52 | @Override
53 | public void onClick(View view) {
54 | if(view.getId() == R.id.evalDialogOK)
55 | setResult(RESULT_OK, new Intent().putExtra(actionIsProcessText ? Intent.EXTRA_PROCESS_TEXT : "result", result));
56 | else
57 | setResult(RESULT_CANCELED);
58 | finish();
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/gianlucanitti/expreval/LibraryLocalizer.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import android.content.Context;
4 | import static com.github.gianlucanitti.javaexpreval.LocalizationHelper.*;
5 |
6 | public class LibraryLocalizer {
7 |
8 | private static void setMessageResource(Context c, Message m, int id){
9 | setMessage(m, c.getString(id));
10 | }
11 |
12 | public static void localize(Context c){
13 | setMessageResource(c, Message.CONTEXT_CLEARED, R.string.contextCleared);
14 | setMessageResource(c, Message.EMPTY_EXPR, R.string.emptyExpr);
15 | setMessageResource(c, Message.EMPTY_SYM_NAME, R.string.emptySymName);
16 | setMessageResource(c, Message.ERROR_PREFIX, R.string.errorPrefix);
17 | setMessageResource(c, Message.EVAL_STEP, R.string.evalStep);
18 | setMessageResource(c, Message.EXPR_END_REACHED, R.string.exprEndReached);
19 | setMessageResource(c, Message.FAILED_STORE_RESULT, R.string.failedStoreResult);
20 | setMessageResource(c, Message.FUNC_ASSIGNED, R.string.functionNewDef);
21 | setMessageResource(c, Message.INCORRECT_DELETE, R.string.incorrectDelete);
22 | setMessageResource(c, Message.INTERACTIVE_HELP, R.string.interactiveHelp);
23 | setMessageResource(c, Message.INVALID_OPERATOR, R.string.invalidOperator);
24 | setMessageResource(c, Message.INVALID_SYM_NAME, R.string.invalidSymName);
25 | setMessageResource(c, Message.ONLY_ONE_EQUALITY, R.string.onlyOneEquality);
26 | setMessageResource(c, Message.OPERATOR_EXPECTED, R.string.operatorExpected);
27 | setMessageResource(c, Message.OPERATOR_FOUND, R.string.operatorFound);
28 | setMessageResource(c, Message.PARENTHESIS_MISMATCH, R.string.parenthesisMismatch);
29 | setMessageResource(c, Message.READONLY_FUNC, R.string.readonlyFunc);
30 | setMessageResource(c, Message.READONLY_VAR, R.string.readonlyVar);
31 | setMessageResource(c, Message.RESERVED_WORD, R.string.reservedWord);
32 | setMessageResource(c, Message.REWRITE_STEP, R.string.rewriteStep);
33 | setMessageResource(c, Message.UNDEFINED_FUNC, R.string.undefinedFunc);
34 | setMessageResource(c, Message.UNDEFINED_VAR, R.string.undefinedVar);
35 | setMessageResource(c, Message.UNKNOWN_CHAR, R.string.unknownChar);
36 | setMessageResource(c, Message.VAR_ASSIGNED, R.string.varNewValue);
37 | setMessageResource(c, Message.VAR_DELETED, R.string.contextItemDeleted);
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/gianlucanitti/expreval/TextViewExpressionContext.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import android.graphics.Color;
4 | import android.widget.TextView;
5 | import com.github.gianlucanitti.javaexpreval.InteractiveExpressionContext;
6 | import com.github.gianlucanitti.javaexpreval.NullOutputStream;
7 |
8 | import java.io.IOException;
9 | import java.io.StringReader;
10 |
11 | public class TextViewExpressionContext extends InteractiveExpressionContext {
12 |
13 | private TextViewWriter inEchoWriter;
14 | private TextViewWriter outWriter;
15 | private TextViewWriter verboseWriter;
16 | private TextViewWriter errorWriter;
17 | boolean echoInput = true;
18 |
19 | public TextViewExpressionContext(TextView out){
20 | super();
21 | inEchoWriter = new TextViewWriter(out, Color.YELLOW);
22 | setOutputWriter(outWriter = new TextViewWriter(out, Color.GREEN), true);
23 | setVerboseOutputWriter(verboseWriter = new TextViewWriter(out, out.getTextColors().getDefaultColor()), true);
24 | setErrorOutputWriter(errorWriter = new TextViewWriter(out, Color.RED), true);
25 | }
26 |
27 | public void writeOutput(String s){
28 | try {
29 | outWriter.write(s);
30 | outWriter.flush();
31 | }catch (IOException e){}
32 | }
33 |
34 | public void setVerbose(boolean b){
35 | if(b)
36 | setVerboseOutputWriter(verboseWriter, true);
37 | else
38 | setVerboseOutputWriter(NullOutputStream.getWriter(), true);
39 | }
40 |
41 | public void setEchoInput(boolean b){
42 | echoInput = b;
43 | }
44 |
45 | public Status update(String s){
46 | setInputReader(new StringReader(s));
47 | InteractiveExpressionContext.Status status = null;
48 | try {
49 | if(echoInput) {
50 | inEchoWriter.write("> " + s + System.getProperty("line.separator"));
51 | inEchoWriter.flush();
52 | }
53 | return update();
54 | }catch(IOException ex){
55 | return Status.ERROR;
56 | }
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/gianlucanitti/expreval/TextViewWriter.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.text.SpannableString;
5 | import android.text.style.ForegroundColorSpan;
6 | import android.widget.TextView;
7 |
8 | import java.io.IOException;
9 | import java.io.Writer;
10 |
11 | public class TextViewWriter extends Writer {
12 |
13 | private StringBuilder buffer;
14 | private TextView v;
15 | private int color;
16 |
17 | public TextViewWriter(TextView target, int c){
18 | v = target;
19 | color = c;
20 | buffer = new StringBuilder();
21 | }
22 |
23 | @Override
24 | public void close() throws IOException {
25 | flush();
26 | }
27 |
28 | @Override
29 | public void flush() throws IOException {
30 | SpannableString s = new SpannableString(buffer.toString());
31 | s.setSpan(new ForegroundColorSpan(color), 0, s.length(), 0);
32 | v.append(s);
33 | buffer = new StringBuilder();
34 | }
35 |
36 | @Override
37 | public void write(@NonNull char[] buf, int offset, int count) throws IOException {
38 | for(int i = offset; i < count; i++)
39 | buffer.append(buf[i]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_expr_eval.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
22 |
23 |
27 |
35 |
41 |
42 |
43 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_expr_eval_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
23 |
24 |
32 |
33 |
39 |
40 |
46 |
47 |
51 |
52 |
58 |
59 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_edit_function.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
14 |
19 |
20 |
21 |
24 |
29 |
34 |
35 |
36 |
39 |
42 |
43 |
44 |
48 |
52 |
53 |
54 |
57 |
65 |
70 |
71 |
72 |
75 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_edit_variable.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
14 |
19 |
20 |
21 |
24 |
29 |
34 |
35 |
36 |
39 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/mainmenu.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gianluca-nitti/android-expr-eval/7270001bd9be435140623515bae2b20e28bc6d63/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gianluca-nitti/android-expr-eval/7270001bd9be435140623515bae2b20e28bc6d63/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gianluca-nitti/android-expr-eval/7270001bd9be435140623515bae2b20e28bc6d63/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gianluca-nitti/android-expr-eval/7270001bd9be435140623515bae2b20e28bc6d63/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gianluca-nitti/android-expr-eval/7270001bd9be435140623515bae2b20e28bc6d63/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ExprEval
5 | Valuta espressione
6 |
7 |
8 | Digita espressione o comando
9 | Valuta
10 | Eliminare tutte le funzioni e variabili non readonly?
11 | Tutte le variabili e funzioni non-readonly sono state eliminate.
12 |
13 | Nella casella di input è possibile digitare expressioni, definizioni di variabili o funzioni (come \"a=5\" o \"log(x,b)=log(x)/log(b)\") e comandi.
14 | I comandi disponibili sono \"help\", \"context\", \"clear\" e \"exit\". Digitare il comando \"help\" per informazioni più dettagliate. Nella casella di output, i risultati sono mostrati in <font color=\"green\">verde</font> e gli errori in <font color=\"red\">rosso</font>.
15 | I passaggi sono mostrati nel colore di default di sistema, e l\'input è riscritto in <font color=\"yellow\">giallo</font> (entrambi possono essere disabilitati dal menu).
16 |
17 |
18 |
19 | Contesto
20 | Svuota contesto
21 | Svuota output
22 | Mostra passaggi
23 | Riscrivi input
24 | Aiuto
25 |
26 |
27 | Nuovo…
28 |
29 | - Aggiungi variabile
30 | - Aggiungi funzione
31 |
32 | Eliminare \"%s\" ?
33 | \"%s\" è stata eliminata.
34 |
35 |
36 | Nome
37 | Sola lettura/readonly (se selezionato, non si potrà modificare o eliminare questo elemento finchè l\'applicazione non viene riavviata)
38 |
39 |
40 | Valore
41 | %1$s vale ora %2$s.
42 |
43 |
44 | Espressione
45 | Argomenti (tap per rimuovere)
46 | Digita nome argomento
47 | Aggiungi argomento
48 | Nome di argomento non valido
49 | %1$s è ora definita come %2$s.
50 |
51 |
52 | Espressione:
53 | Passaggi eseguiti:
54 | Risultato:
55 | Tocca OK per sostituire l\'espressione con il risultato.
56 | Chiudi
57 | impossibile valutare l\'espressione.
58 |
59 |
60 | Un\'espressione vuota è stata trovata.
61 | La stringa vuota non è un identificatore valido.
62 | Errore: %s
63 | %1$s vale %2$s
64 | Una sotto-espressione era attesa, ma è stata raggiunta la fine dell\'espressione.
65 | Attenzione: impossibile memorizzare il risultato. Motivo: %s
66 | Sintassi errata. Per eliminare una funzione, è necessario specificare il numero di argomenti (es. \"fun(2)=\" per eliminare \"fun(x, y)\").
67 |
68 | Le stringhe accettate sono espressioni, assegnamenti e comandi.
69 | Un\'espressione può essere formata da numeri interi o decimali, gli operatori binari +,-,*,/,^, variabili, funzioni e parentesi tonde.
70 | Un nome di variabile è una stringa di una o più lettere e/o underscore. I comandi sono parole riservate e non possono essere usati come nomi di variabili.
71 | Quando un\'espressione viene valutata senza errori, il risultato viene mostrato e memorizzato nella variabile \"ans\".
72 | Un assegnamento di variabile è formato da un nome di variabile seguito dal simbolo = e da un\'espressione il cui risultato verrà assegnato alla variabile.
73 | Un assegnamento vuoto (nella forma \"someVariable=\") elimina la variabile.
74 | Un assegnamento di funzione è formato da un nome di funzione con i relativi parametri, seguito da un = e da un\'espressione, es.\"sum(x,y)=x+y\".
75 | Una funzione può essere eliminata con un assegnamento vuoto; il numero di argomenti deve essere specificato, es. \"sum(2)=\" per eliminare la funzione \"sum\" definita su due argomenti.
76 | Un assegnamento (di variabile o di funzione) può essere preceduto dalla parola \"readonly\" per impedire che venga modificata o eliminata, es. \"readonly x=1\", \"readonly square(a)=a^2\".
77 | I comandi sono: context (stampa tutte le variabili e le funzioni definite), clear (elimina tutte le variabili e le funzioni non-readonly), help (mostra questo messaggio) e exit (chiude l\'applicazione).
78 |
79 | Operatore sconosciuto \'%s\'.
80 | \"%1$s\" non è un\'identificatore valido perché contiene il carattere \'%2$s\'.
81 | Un assegnamento può contenere un solo operatore =.
82 | Un operatore era atteso, ma è stata trovata un\'espressione.
83 | Una sotto-espressione era attesa, ma un\'operatore è stato trovato.
84 | Le parentesi aperte e chiuse non corrispondono.
85 | La funzione \"%1$s\" è definita come read-only per %2$s argomenti.
86 | La variabile \"%s\" è definita come read-only.
87 | %s è una parola riservata e non può essere usata come identificatore.
88 | %1$s può essere riscritto come %2$s
89 | La funzione \"%1$s\" non è definita per %2$s argomenti.
90 | La variabile \"%s\" non è definita.
91 | Carattere non riconosciuto %s.
92 |
--------------------------------------------------------------------------------
/app/src/main/res/values-pt-rBR/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ExprEval
4 | Eval expression
5 |
6 |
7 | Digite a expressão ou comando
8 | Avaliar
9 | Você deseja excluir todas as funçções e variáveis que não são somente leitura?
10 | Todas as variáveis e funções que não são somente leitura foram excluídas.
11 |
12 | Na caixa de entrada você pode digitar expressões, variáveis ou atribuições (como \"a=5\" ou \"log(x,b)=log(x)/log(b)\") e comandos.
13 | Os comandos dispononíveis são \"help\", \"context\", \"clear\" e \"exit\". Digite \"help\" na caixa de entrada para instruções mais detalhadas. Na caixa de saída, os resultados são mostrados em <font color=\"green\">verde</font> e erros em <font color=\"red\">vermelho</font>.
14 | Passos de avaliação são mostrados na cor padrão, e a entrada é repetida em <font color=\"yellow\">amarelo</font> (ambos podem ser desativados pelo menu).
15 |
16 |
17 | <h2>Licença</h2>
18 | Este aplicativo é livre e código aberto lançado sob a licença MIT (<a href="https://github.com/gianluca-nitti/android-expr-eval">click to get the source code</a>).
19 | <h2>Créditos</h2>
20 | <h4>Desenvolvimento</h4>
21 | <a href="https://github.com/gianluca-nitti">@gianluca-nitti</a>
22 | <h4>Traduções</h4>
23 | <ul>
24 | <li><a href="https://github.com/afmachado">@afmachado</a> (<a href="http://bitly.com/1Rwm176">website</a>): Português do Brasil</li>
25 | <li><a href="https://github.com/gianluca-nitti">@gianluca-nitti</a>: Inglês, Italiano</li>
26 | </ul>
27 |
28 | Tenha acesso ao código fonte
29 |
30 |
31 |
32 | Contexto
33 | Limpar contexto
34 | Limpar saída
35 | Mostrar passos
36 | Repetir entrada
37 | Ajuda
38 |
39 |
40 | Novo…
41 |
42 | - Adicionar variável
43 | - Adicionar função
44 |
45 | Você deseja excluir \"%s\" ?
46 | \"%s\" foi excluído.
47 |
48 |
49 | Nome
50 | Apenas leitura (se marcado, você não poderá editar ou excluir isso até que o app seja reiniciado)
51 |
52 |
53 | Valor
54 | %1$s é agora %2$s.
55 |
56 |
57 | Expressão
58 | Argumentos (toque para remover)
59 | Digite o nome do argumento
60 | Adicionar argumento
61 | Nome de argumento inválido
62 | %1$s agora está definido como %2$s.
63 |
64 |
65 | Expressão:
66 | Log de avaliação:
67 | Resultado:
68 | Toque em OK para substituir a expressão pelo resultado.
69 | Fechar
70 | falhou ao avaliar.
71 |
72 |
73 | Uma expressão vazia foi encontrada.
74 | Um nome vazio não é um símbolo identificador válido.
75 | Erro na expressão: %s
76 | %1$s é avaliada para %2$s
77 | Uma subexpresssão era esperada, mas o fim da expressão foi alcançado.
78 | Aviso: falha ao armazenar resultado. Motivo: %s
79 | Sintaxe incorreta. Para excluir uma função, o número de argumentos deve ser especificado (p.e. \"fun(2)=\" para excluir \"fun(x, y)\").
80 |
81 | Declarações aceitas são expressões, atribuições e comandos.
82 | Uma expressão pode ser formada por números inteiros ou decimais, os operadores binários +,-,*,/,^ , variáveis, funções e parênteses.
83 | Um nome de variável é uma frase com uma ou mais letras e/ou sublinhados. Variáveis não podem ser nomeadas com comandos, que são palavras reservadas.
84 | Quando uma expressão é avaliada com sucesso, seu resultado é mostrado e automaticamente atribuído à variável \"ans\", então pode ser acessada pela próxima declaração.
85 | Uma atribuição de variável é formada por um nome de varíavel seguido pelo símbolo = e uma expressão, que é avaliada e vinculada à essa variável.
86 | Uma atribuição vazia (da forma \"algumaVariavel=\") exclui a variável.
87 | Uma atribuição é formada por um nome de função e seus parâmetros, seguido pelo símbolo = e uma expressão, que é vinculada à essa função, p.e.\"soma(x,y)=x+y\".
88 | Uma função pode ser escluída com uma atribuição vazia; o número de argumentos precisa ser especificado, p.e. \"soma(2)=\" para excluir a função \"soma\" definida em dois argumentos.
89 | Uma atribuição (de variável ou função) pode ser preparada com a palavra \"readonly\" para prevenir de ser modificada ou excluída, p.e. \"readonly x=1\", \"readonly square(a)=a^2\".
90 | Os comandos são: context (mostra todas as variáveis e funções definidas), clear (exclui todas as variáveis e funções que não são apenas leitura), help (mostra esta mensagem) e exit (fecha o app).
91 |
92 | Operador desconhecido \'%s\'.
93 | \"%1$s\" não é um símbolo válido para nome pois contém o caractere \'%2$s\'.
94 | Apenas um operador = por comando é permitido.
95 | Um operador era esperado, mas uma expressão foi encontrada.
96 | Uma subexpressão era esperada, mas um operador foi encontrado.
97 | O número de parênteses abertos e fechados não são iguais.
98 | A função \"%1$s\" é definida como apenas leitura para %2$s argumentos.
99 | A variável \"%s\" está definida como apenas leitura.
100 | %s é uma palavra reservada e não pode ser usada como um nome simbólico.
101 | %1$s pode ser reescrito como %2$s
102 | A função \"%1$s\" não está definida para %2$s argumentos.
103 | A variável \"%s\" não está definida.
104 | Caractere não reconhecido %s.
105 |
106 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ExprEval
4 | Eval expression
5 |
6 |
7 | Type expression or command
8 | Evaluate
9 | Do you want to delete all non-readonly functions and variables?
10 | All non-readonly variables and functions have been deleted.
11 |
12 | In the input box you can type expressions, variable or function assignments (like \"a=5\" or \"log(x,b)=log(x)/log(b)\") and commands.
13 | The available commands are \"help\", \"context\", \"clear\" and \"exit\". Type \"help\" in the input box for more detailed instructions. In the output box, results are shown in <font color=\"green\">green</font> and errors in <font color=\"red\">red</font>.
14 | Evaluation steps are shown in default color, and the input is echoed in <font color=\"yellow\">yellow</font> (both can be disabled from the menu).
15 |
16 |
17 | <h2>License</h2>
18 | This application is free and open source software released under the MIT license (<a href="https://github.com/gianluca-nitti/android-expr-eval">click to get the source code</a>).
19 | <h2>Credits</h2>
20 | <h4>Development</h4>
21 | <a href="https://github.com/gianluca-nitti">@gianluca-nitti</a>
22 | <h4>Localization</h4>
23 | <ul>
24 | <li><a href="https://github.com/afmachado">@afmachado</a> (<a href="http://bitly.com/1Rwm176">website</a>): Brazilian Portuguese</li>
25 | <li><a href="https://github.com/gianluca-nitti">@gianluca-nitti</a>: English, Italian</li>
26 | </ul>
27 |
28 | Get the source code
29 |
30 |
31 |
32 | About
33 | Context
34 | Clear context
35 | Clear output
36 | Show steps
37 | Echo input
38 | Help
39 |
40 |
41 | New…
42 |
43 | - Add variable
44 | - Add function
45 |
46 | Do you want to delete \"%s\" ?
47 | \"%s\" has been deleted.
48 |
49 |
50 | Name
51 | Read-only (if checked, you won\'t be able to edit or delete this until the application is restarted)
52 |
53 |
54 | Value
55 | %1$s is now %2$s.
56 |
57 |
58 | Expression
59 | Arguments (tap to remove)
60 | Type argument name
61 | Add argument
62 | Invalid argument name
63 | %1$s is now defined as %2$s.
64 |
65 |
66 | Expression:
67 | Evaluation log:
68 | Result:
69 | Tap OK to replace the expression with the result.
70 | Close
71 | evaluation failed.
72 |
73 |
74 | An empty expression was found.
75 | The empty string isn\'t a valid symbol identifier.
76 | Expression error: %s
77 | %1$s evaluates to %2$s
78 | A sub-expression was expected, but the end of the expression was reached.
79 | Warning: failed to store result. Reason: %s
80 | Incorrect syntax. To delete a function, the number of arguments must be specified (e.g. \"fun(2)=\" to delete \"fun(x, y)\").
81 |
82 | Accepted statements are expressions, assignments and commands.
83 | An expression can be formed by integer or decimal numbers, the +,-,*,/,^ binary operators, variables, functions and parenthesis.
84 | A variable name is a string of one or more letters and/or underscores. Variables can\'t be named as commands, which are reserved words.
85 | When an expression is successfully evaluated, it\'s result is displayed and automatically assigned to the \"ans\" variable, so it can be accessed from the next statement.
86 | A variable assignment is formed by a variable name followed by the = symbol and an expression, which is evaluated and bound to that variable.
87 | An empty assignment (in the form \"someVariable=\") deletes the variable.
88 | A function assignment is formed by a function name and its parameters, followed by the = symbol and an expression, which is bound to that function, e.g.\"sum(x,y)=x+y\".
89 | A function can be deleted with an empty assignment; the number of arguments must be specified, e.g. \"sum(2)=\" to delete the function \"sum\" defined on two arguments.
90 | An assignment (of variable or function) can be prepended with the \"readonly\" word to prevent it to be modified or deleted, e.g. \"readonly x=1\", \"readonly square(a)=a^2\".
91 | The commands are: context (prints all the defined variables and functions), clear (deletes all the non-readonly variables and functions), help (shows this message) and exit (closes the application).
92 |
93 | Unknown operator \'%s\'.
94 | \"%1$s\" isn\'t a valid symbol name because it contains the \'%2$s\' character.
95 | Only one = operator per command is allowed.
96 | An operator was expected, but an expression was found.
97 | A sub-expression was expected, but an operator was found.
98 | The numbers of opened and closed parenthesis don\'t match.
99 | The \"%1$s\" function is defined as read-only for %2$s arguments.
100 | The \"%s\" variable is defined as read-only.
101 | %s is a reserved word and can\'t be used as symbol name.
102 | %1$s can be rewritten as %2$s
103 | The function \"%1$s\" is not defined for %2$s arguments.
104 | The variable \"%s\" is not defined.
105 | Unrecognized character %s.
106 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/github/gianlucanitti/expreval/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.github.gianlucanitti.expreval;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | maven { url "https://jitpack.io" }
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gianluca-nitti/android-expr-eval/7270001bd9be435140623515bae2b20e28bc6d63/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Nov 22 16:31:27 CET 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/icon.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gianluca-nitti/android-expr-eval/7270001bd9be435140623515bae2b20e28bc6d63/icon.xcf
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------