├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── build.yml │ └── docs.yaml ├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── compiler.xml ├── dictionaries ├── gradle.xml ├── jarRepositories.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── RELEASING.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── amrdeveloper │ │ └── codeviewlibrary │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_cv_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── amrdeveloper │ │ │ └── codeviewlibrary │ │ │ ├── CustomCodeViewAdapter.java │ │ │ ├── MainActivity.java │ │ │ ├── plugin │ │ │ ├── CommentManager.java │ │ │ ├── SourcePositionListener.java │ │ │ └── UndoRedoManager.java │ │ │ └── syntax │ │ │ ├── GoLanguage.java │ │ │ ├── JavaLanguage.java │ │ │ ├── LanguageManager.java │ │ │ ├── LanguageName.java │ │ │ ├── PythonLanguage.java │ │ │ └── ThemeName.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_cv_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_arrow_downward.xml │ │ ├── ic_arrow_upward.xml │ │ ├── ic_find_in_page.xml │ │ ├── ic_find_replace.xml │ │ ├── ic_go.xml │ │ ├── ic_java.xml │ │ ├── ic_keyword.xml │ │ ├── ic_python.xml │ │ ├── ic_redo.xml │ │ ├── ic_refresh.xml │ │ ├── ic_snippet.xml │ │ └── ic_undo.xml │ │ ├── font │ │ └── jetbrains_mono_medium.ttf │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── bottom_sheet_dialog.xml │ │ ├── list_item_modern_autocomplete.xml │ │ └── list_item_suggestion.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_cv_launcher.xml │ │ └── ic_cv_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_cv_launcher.png │ │ └── ic_cv_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_cv_launcher.png │ │ └── ic_cv_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_cv_launcher.png │ │ └── ic_cv_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_cv_launcher.png │ │ └── ic_cv_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_cv_launcher.png │ │ └── ic_cv_launcher_round.png │ │ └── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── amrdeveloper │ └── codeviewlibrary │ └── ExampleUnitTest.java ├── build.gradle ├── codeview ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── amrdeveloper │ │ └── codeview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── amrdeveloper │ │ └── codeview │ │ ├── Code.java │ │ ├── CodeView.java │ │ ├── CodeViewAdapter.java │ │ ├── Findable.java │ │ ├── Keyword.java │ │ ├── KeywordTokenizer.java │ │ ├── Replaceable.java │ │ ├── Snippet.java │ │ └── Token.java │ └── test │ └── java │ └── com │ └── amrdeveloper │ └── codeview │ └── ExampleUnitTest.java ├── docs ├── add-to-xml.md ├── assets │ └── cv-logo.png ├── auto-complete.md ├── auto-indenting.md ├── config.js ├── contribution │ ├── documentation.md │ ├── report.md │ └── suggestion.md ├── find-and-replace.md ├── highlight.md ├── index.md ├── install.md ├── line-number.md ├── pair-complete.md └── snippets.md ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── media ├── cv-logo.png ├── golang_demo.gif ├── java_demo.gif └── python_demo.gif ├── mkdocs.yml └── settings.gradle /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: amrdeveloper -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Smartphone (please complete the following information):** 27 | - Device: [e.g. iPhone6] 28 | - OS: [e.g. iOS8.1] 29 | - Version [e.g. 22] 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v1 15 | 16 | - uses: actions/cache@v2 17 | with: 18 | path: | 19 | ~/.gradle/caches 20 | ~/.gradle/wrapper 21 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} 22 | restore-keys: | 23 | ${{ runner.os }}-gradle- 24 | 25 | - name: Set Up JDK 26 | uses: actions/setup-java@v1 27 | with: 28 | java-version: '17' 29 | 30 | - name: Run Tests 31 | run: ./gradlew test 32 | 33 | - name: Build Project 34 | run: ./gradlew assemble -------------------------------------------------------------------------------- /.github/workflows/docs.yaml: -------------------------------------------------------------------------------- 1 | name: Build and deploy docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - docs/** 9 | - mkdocs.yml 10 | jobs: 11 | deploy: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-python@v2 16 | with: 17 | python-version: 3.x 18 | - run: pip install mkdocs-material 19 | - run: mkdocs gh-deploy --force 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | site/ 14 | .externalNativeBuild 15 | .cxx 16 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/dictionaries: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Change Log 2 | ========== 3 | 4 | Version 1.3.9 *(2023-12-30)* 5 | ----------------------------- 6 | 7 | * Handle exchanging code lists at the runtime #43 8 | 9 | Version 1.3.8 *(2023-03-27)* 10 | ----------------------------- 11 | 12 | * Improve line number text padding with different text sizes 13 | * Improve the doc for setLineNumberTextSize to be explicit that value is in pixel 14 | 15 | Version 1.3.7 *(2022-10-28)* 16 | ----------------------------- 17 | 18 | * Make highlighting current line number option off by default 19 | 20 | Version 1.3.6 *(2022-10-28)* 21 | ----------------------------- 22 | 23 | * Improve calculating line number padding from 3k ns to 1.5k ns per line. 24 | * Add support for relative line number feature inspired from vim editor 25 | * Add support for highlighting the current line and customize the color 26 | 27 | Version 1.3.5 *(2022-05-13)* 28 | ----------------------------- 29 | 30 | * Fix #28: auto complete on Android 6 and lower 31 | * Remove un used get location call on auto complete 32 | 33 | Version 1.3.4 *(2022-03-20)* 34 | ----------------------------- 35 | 36 | * Feature #18: Add option to bring cursor at the middle of pair 37 | * Feature #11: Add setLineNumberTypeface method to change line number font 38 | 39 | Version 1.3.3 *(2022-02-28)* 40 | ----------------------------- 41 | 42 | * Fix Issue #15: Improve Auto complete drop down position when cursor on the end of the view 43 | 44 | Version 1.3.2 *(2022-02-19)* 45 | ----------------------------- 46 | 47 | * Fix OnDraw not working issue when the line number is disabled 48 | 49 | Version 1.3.1 *(2022-02-06)* 50 | ----------------------------- 51 | 52 | * Fix calculate indentation issue when user insert on the end with no next char 53 | 54 | Version 1.3.0 *(2022-01-27)* 55 | ----------------------------- 56 | 57 | * Improve drawing line number performance 58 | * Improve Auto Complete implementation to fix multi size drop down popup position 59 | * Add setMaxSuggestionsSize to limit the number of suggestions 60 | * Add setAutoCompleteItemHeightInDp take the auto complete list item to change the drop down final size 61 | * Add support for Auto Pair complete 62 | * Improve Auto indenting implementation and be able to support python indentation 63 | 64 | Version 1.2.2 *(2022-01-20)* 65 | ----------------------------- 66 | 67 | * Add the missing Javadoc comments for all the public methods 68 | * Improve highlightSyntax implementation 69 | * Add resetHighlighter method to un highlight all tokens 70 | * Improve the example app 71 | 72 | Version 1.2.1 *(2022-01-07)* 73 | ----------------------------- 74 | 75 | * Improve Auto indenting implementation and make it more customizable 76 | * Add support for find and replacement features and highlight match tokens 77 | 78 | Version 1.1.1 *(2021-11-22)* 79 | ----------------------------- 80 | 81 | * Improve auto-complete drop-down menu position to be directly below the current cursor position 82 | 83 | Version 1.1.0 *(2021-11-19)* 84 | ----------------------------- 85 | 86 | * Support code snippets and change them in runtime 87 | * Support optional line number 88 | * Deploy on MavenCentral 89 | 90 | Version 1.0.1 *(2021-07-21)* 91 | ----------------------------- 92 | 93 | * Added highlightWhileTextChanging option so you can control when the highlighter should to start, default value is true 94 | 95 | Version 1.0.0 *(2020-08-16)* 96 | ----------------------------- 97 | 98 | * Initial release. 99 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | ### Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ### Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ### Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ### Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ### Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at amr96@programmer.net. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ### Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 |

4 | 5 |

6 | 7 | * [Reporting issues](https://amrdeveloper.github.io/CodeView/contribution/report/) 8 | * [Suggesting features](https://amrdeveloper.github.io/CodeView/contribution/suggestion/) 9 | * [Update Documentations](https://amrdeveloper.github.io/CodeView/contribution/documentation/) 10 | 11 | Please provide issue report in the format that we request, EACH DETAIL IS A HUGE HELP. 12 | 13 | Issues that are not following the guidelines, 14 | will be processed as last priority or never or simply closed as invalid. 15 | 16 | ## Contributing Guide 17 | 18 | Please note that PRs are looked only for approved issues. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Amr Hesham 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 | # CodeView 2 |

3 | 4 |

5 | 6 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/343df315aa3b40e09e6e98cf32ff8468)](https://app.codacy.com/gh/AmrDeveloper/CodeView?utm_source=github.com&utm_medium=referral&utm_content=AmrDeveloper/CodeView&utm_campaign=Badge_Grade_Settings) 7 | [![CodeFactor](https://www.codefactor.io/repository/github/amrdeveloper/codeview/badge)](https://www.codefactor.io/repository/github/amrdeveloper/codeview) 8 | ![Build](https://github.com/amrdeveloper/codeview/actions/workflows/build.yml/badge.svg) 9 | [![Min API Level](https://img.shields.io/badge/API-%2B14-brightgreen)]() 10 | ![Maven Central](https://img.shields.io/maven-central/v/io.github.amrdeveloper/codeview?color=green) 11 | [![Jitpack Version](https://jitpack.io/v/AmrDeveloper/CodeView.svg)](https://jitpack.io/#AmrDeveloper/CodeView) 12 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-CodeView-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/8179) 13 | 14 | Android Library to make it easy to create your CodeEditor or IDE for any programming language 15 | even for your programming language, just config the view with your language keywords and other attributes 16 | and you can change the CodeView theme in the runtime so it's made it easy to support any number of themes, 17 | and CodeView has AutoComplete and you can customize it with different keywords and tokenizers. 18 | 19 | ## Demo 20 |

21 | animated 22 | animated 23 | animated 24 |

25 | 26 | - Main Features 27 | - Can support any programming language you want. 28 | - Can support AutoComplete and customize it with different tokenizers and design. 29 | - Can support any theme you want and change it in the runtime. 30 | - Syntax Highlighter depend on your patterns so you can support any features like TODO comment. 31 | - Can support errors and warns with different colors and remove them in the runtime. 32 | - Can change highlighter update delay time. 33 | - Support Code snippets and change it in the runtime. 34 | - Support optional Line Number with customization. 35 | - Support optional highlighting current line number. 36 | - Support optional relative line number inspired from vim editor. 37 | - Support Auto indentation with customization. 38 | - Support highlighting matching tokens. 39 | - Support replace first and replace all matching tokens. 40 | - Support auto pair complete. 41 | 42 | - Documentations: 43 | - [Full Documentation](https://amrdeveloper.github.io/CodeView/) 44 | - [Install Documentation](docs/install.md) 45 | - [Add to XML Documentation](docs/add-to-xml.md) 46 | - [Highlight Documentation](docs/highlight.md) 47 | - [Auto Complete Documentation](docs/auto-complete.md) 48 | - [Pair Complete Documentation](docs/pair-complete.md) 49 | - [Snippets Documentation](docs/snippets.md) 50 | - [Auto Indenting Documentation](docs/auto-indenting.md) 51 | - [Find and Replace Documentation](docs/find-and-replace.md) 52 | - [Line Number Documentation](docs/line-number.md) 53 | 54 | - Articles 55 | - [Android CodeView an Easy way to create Code Editor app](https://itnext.io/android-codeview-an-easy-way-to-create-code-editor-app-5d67c3534f84) 56 | - [Android CodeView the easiest way to highlight text](https://itnext.io/android-codeview-the-easiest-way-to-highlight-patterns-53702e0e2164) 57 | - [Android CodeView Highlight search result in List Items](https://itnext.io/android-codeview-highlight-search-result-in-list-items-b7e4c9fb57d8) 58 | - [Android CodeView Create a code editor with Snippets](https://itnext.io/android-codeview-create-a-code-editor-with-snippets-6733094161e4) 59 | - [Android CodeView Auto Indentation, Find and replace](https://itnext.io/android-codeview-auto-indentation-find-and-replace-3bc91994e214) 60 | 61 | ### License 62 | 63 | ``` 64 | Copyright (c) 2020 - Present Amr Hesham 65 | 66 | Permission is hereby granted, free of charge, to any person obtaining a copy 67 | of this software and associated documentation files (the "Software"), to deal 68 | in the Software without restriction, including without limitation the rights 69 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 70 | copies of the Software, and to permit persons to whom the Software is 71 | furnished to do so, subject to the following conditions: 72 | 73 | The above copyright notice and this permission notice shall be included in all 74 | copies or substantial portions of the Software. 75 | 76 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 77 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 78 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 79 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 80 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 81 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 82 | SOFTWARE. 83 | ``` 84 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | Releasing 2 | ======== 3 | 4 | 1. Update the version in module `build.gradle` file. 5 | 2. Update the `CHANGELOG.md` for the impending release. 6 | 3. Update the `README.md` with the new version if needed. 7 | 4. `git commit -am "Prepare for release X.Y.Z."` (where X.Y.Z is the new version) 8 | 5. `./gradlew publishAllPublicationsToMavenCentral`. 9 | 6. `./gradlew closeAndReleaseRepository`. 10 | 7. `git tag -a X.Y.Z -m "Version X.Y.Z"` (where X.Y.Z is the new version) 11 | 8. Update the `gradle.properties` to the next SNAPSHOT version. 12 | 9. `git commit -am "Prepare next development version."` 13 | 10. `git push && git push --tags` 14 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 33 5 | namespace 'com.amrdeveloper.codeviewlibrary' 6 | 7 | defaultConfig { 8 | applicationId "com.amrdeveloper.codeviewlibrary" 9 | minSdkVersion 15 10 | targetSdkVersion 33 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: "libs", include: ["*.jar"]) 31 | implementation 'androidx.appcompat:appcompat:1.4.0' 32 | implementation 'com.google.android.material:material:1.4.0' 33 | 34 | implementation project(path: ':codeview') 35 | 36 | testImplementation 'junit:junit:4.12' 37 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 39 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/amrdeveloper/codeviewlibrary/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.amrdeveloper.codeviewlibrary", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/ic_cv_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/ic_cv_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/CustomCodeViewAdapter.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import androidx.annotation.NonNull; 11 | 12 | import com.amrdeveloper.codeview.Code; 13 | import com.amrdeveloper.codeview.CodeViewAdapter; 14 | import com.amrdeveloper.codeview.Snippet; 15 | 16 | import java.util.List; 17 | 18 | public class CustomCodeViewAdapter extends CodeViewAdapter { 19 | 20 | private final LayoutInflater layoutInflater; 21 | 22 | public CustomCodeViewAdapter(@NonNull Context context, @NonNull List codes) { 23 | super(context, R.layout.list_item_modern_autocomplete, 0, codes); 24 | this.layoutInflater = LayoutInflater.from(context); 25 | } 26 | 27 | @Override 28 | public View getView(int position, View convertView, ViewGroup parent) { 29 | if (convertView == null) { 30 | convertView = layoutInflater.inflate(R.layout.list_item_modern_autocomplete, parent, false); 31 | } 32 | 33 | ImageView codeType = convertView.findViewById(R.id.code_type); 34 | TextView codeTitle = convertView.findViewById(R.id.code_title); 35 | Code currentCode = (Code) getItem(position); 36 | if (currentCode != null) { 37 | codeTitle.setText(currentCode.getCodeTitle()); 38 | if (currentCode instanceof Snippet) { 39 | codeType.setImageResource(R.drawable.ic_snippet); 40 | } else { 41 | codeType.setImageResource(R.drawable.ic_keyword); 42 | } 43 | } 44 | 45 | return convertView; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | import androidx.core.content.res.ResourcesCompat; 6 | 7 | import android.graphics.Color; 8 | import android.graphics.Typeface; 9 | import android.os.Bundle; 10 | import android.text.Editable; 11 | import android.text.TextWatcher; 12 | import android.view.Menu; 13 | import android.view.MenuItem; 14 | import android.widget.ArrayAdapter; 15 | import android.widget.EditText; 16 | import android.widget.ImageButton; 17 | import android.widget.TextView; 18 | 19 | import com.amrdeveloper.codeview.Code; 20 | import com.amrdeveloper.codeview.CodeView; 21 | import com.amrdeveloper.codeviewlibrary.plugin.CommentManager; 22 | import com.amrdeveloper.codeviewlibrary.plugin.SourcePositionListener; 23 | import com.amrdeveloper.codeviewlibrary.plugin.UndoRedoManager; 24 | import com.amrdeveloper.codeviewlibrary.syntax.ThemeName; 25 | import com.amrdeveloper.codeviewlibrary.syntax.LanguageName; 26 | import com.amrdeveloper.codeviewlibrary.syntax.LanguageManager; 27 | import com.google.android.material.bottomsheet.BottomSheetDialog; 28 | 29 | import java.util.HashMap; 30 | import java.util.List; 31 | import java.util.Map; 32 | import java.util.regex.Pattern; 33 | 34 | public class MainActivity extends AppCompatActivity { 35 | 36 | private CodeView codeView; 37 | private LanguageManager languageManager; 38 | private CommentManager commentManager; 39 | private UndoRedoManager undoRedoManager; 40 | 41 | private TextView languageNameText; 42 | private TextView sourcePositionText; 43 | 44 | private LanguageName currentLanguage = LanguageName.JAVA; 45 | private ThemeName currentTheme = ThemeName.MONOKAI; 46 | 47 | private final boolean useModernAutoCompleteAdapter = true; 48 | 49 | @Override 50 | protected void onCreate(Bundle savedInstanceState) { 51 | super.onCreate(savedInstanceState); 52 | setContentView(R.layout.activity_main); 53 | 54 | configCodeView(); 55 | configCodeViewPlugins(); 56 | } 57 | 58 | private void configCodeView() { 59 | codeView = findViewById(R.id.codeView); 60 | 61 | // Change default font to JetBrains Mono font 62 | Typeface jetBrainsMono = ResourcesCompat.getFont(this, R.font.jetbrains_mono_medium); 63 | codeView.setTypeface(jetBrainsMono); 64 | 65 | // Setup Line number feature 66 | codeView.setEnableLineNumber(true); 67 | codeView.setLineNumberTextColor(Color.GRAY); 68 | codeView.setLineNumberTextSize(25f); 69 | 70 | // Setup highlighting current line 71 | codeView.setEnableHighlightCurrentLine(true); 72 | codeView.setHighlightCurrentLineColor(Color.GRAY); 73 | 74 | // Setup Auto indenting feature 75 | codeView.setTabLength(4); 76 | codeView.setEnableAutoIndentation(true); 77 | 78 | // Setup the language and theme with SyntaxManager helper class 79 | languageManager = new LanguageManager(this, codeView); 80 | languageManager.applyTheme(currentLanguage, currentTheme); 81 | 82 | // Setup auto pair complete 83 | final Map pairCompleteMap = new HashMap<>(); 84 | pairCompleteMap.put('{', '}'); 85 | pairCompleteMap.put('[', ']'); 86 | pairCompleteMap.put('(', ')'); 87 | pairCompleteMap.put('<', '>'); 88 | pairCompleteMap.put('"', '"'); 89 | pairCompleteMap.put('\'', '\''); 90 | 91 | codeView.setPairCompleteMap(pairCompleteMap); 92 | codeView.enablePairComplete(true); 93 | codeView.enablePairCompleteCenterCursor(true); 94 | 95 | // Setup the auto complete and auto indenting for the current language 96 | configLanguageAutoComplete(); 97 | configLanguageAutoIndentation(); 98 | } 99 | 100 | private void configLanguageAutoComplete() { 101 | if (useModernAutoCompleteAdapter) { 102 | // Load the code list (keywords and snippets) for the current language 103 | List codeList = languageManager.getLanguageCodeList(currentLanguage); 104 | 105 | // Use CodeViewAdapter or custom one 106 | CustomCodeViewAdapter adapter = new CustomCodeViewAdapter(this, codeList); 107 | 108 | // Add the odeViewAdapter to the CodeView 109 | codeView.setAdapter(adapter); 110 | } else { 111 | String[] languageKeywords = languageManager.getLanguageKeywords(currentLanguage); 112 | 113 | // Custom list item xml layout 114 | final int layoutId = R.layout.list_item_suggestion; 115 | 116 | // TextView id to put suggestion on it 117 | final int viewId = R.id.suggestItemTextView; 118 | ArrayAdapter adapter = new ArrayAdapter<>(this, layoutId, viewId, languageKeywords); 119 | 120 | // Add the ArrayAdapter to the CodeView 121 | codeView.setAdapter(adapter); 122 | } 123 | } 124 | 125 | private void configLanguageAutoIndentation() { 126 | codeView.setIndentationStarts(languageManager.getLanguageIndentationStarts(currentLanguage)); 127 | codeView.setIndentationEnds(languageManager.getLanguageIndentationEnds(currentLanguage)); 128 | } 129 | 130 | private void configCodeViewPlugins() { 131 | commentManager = new CommentManager(codeView); 132 | configCommentInfo(); 133 | 134 | undoRedoManager = new UndoRedoManager(codeView); 135 | undoRedoManager.connect(); 136 | 137 | languageNameText = findViewById(R.id.language_name_txt); 138 | configLanguageName(); 139 | 140 | sourcePositionText = findViewById(R.id.source_position_txt); 141 | sourcePositionText.setText(getString(R.string.source_position, 0, 0)); 142 | configSourcePositionListener(); 143 | } 144 | 145 | private void configCommentInfo() { 146 | commentManager.setCommentStart(languageManager.getCommentStart(currentLanguage)); 147 | commentManager.setCommendEnd(languageManager.getCommentEnd(currentLanguage)); 148 | } 149 | 150 | private void configLanguageName() { 151 | languageNameText.setText(currentLanguage.name().toLowerCase()); 152 | } 153 | 154 | private void configSourcePositionListener() { 155 | SourcePositionListener sourcePositionListener = new SourcePositionListener(codeView); 156 | sourcePositionListener.setOnPositionChanged((line, column) -> { 157 | sourcePositionText.setText(getString(R.string.source_position, line, column)); 158 | }); 159 | } 160 | 161 | @Override 162 | public boolean onCreateOptionsMenu(Menu menu) { 163 | getMenuInflater().inflate(R.menu.menu_main, menu); 164 | return super.onCreateOptionsMenu(menu); 165 | } 166 | 167 | @Override 168 | public boolean onOptionsItemSelected(@NonNull MenuItem item) { 169 | final int menuItemId = item.getItemId(); 170 | final int menuGroupId = item.getGroupId(); 171 | 172 | if (menuGroupId == R.id.group_languages) changeTheEditorLanguage(menuItemId); 173 | else if (menuGroupId == R.id.group_themes) changeTheEditorTheme(menuItemId); 174 | else if (menuItemId == R.id.findMenu) launchEditorButtonSheet(); 175 | else if (menuItemId == R.id.comment) commentManager.commentSelected(); 176 | else if (menuItemId == R.id.un_comment) commentManager.unCommentSelected(); 177 | else if (menuItemId == R.id.clearText) codeView.setText(""); 178 | else if (menuItemId == R.id.toggle_relative_line_number) toggleRelativeLineNumber(); 179 | else if (menuItemId == R.id.undo) undoRedoManager.undo(); 180 | else if (menuItemId == R.id.redo) undoRedoManager.redo(); 181 | 182 | return super.onOptionsItemSelected(item); 183 | } 184 | 185 | private void changeTheEditorLanguage(int languageId) { 186 | final LanguageName oldLanguage = currentLanguage; 187 | if (languageId == R.id.language_java) currentLanguage = LanguageName.JAVA; 188 | else if (languageId == R.id.language_python) currentLanguage = LanguageName.PYTHON; 189 | else if(languageId == R.id.language_go) currentLanguage = LanguageName.GO_LANG; 190 | 191 | if (currentLanguage != oldLanguage) { 192 | languageManager.applyTheme(currentLanguage, currentTheme); 193 | configLanguageName(); 194 | configLanguageAutoComplete(); 195 | configLanguageAutoIndentation(); 196 | configCommentInfo(); 197 | } 198 | } 199 | 200 | private void changeTheEditorTheme(int themeId) { 201 | final ThemeName oldTheme = currentTheme; 202 | if (themeId == R.id.theme_monokia) currentTheme = ThemeName.MONOKAI; 203 | else if (themeId == R.id.theme_noctics) currentTheme = ThemeName.NOCTIS_WHITE; 204 | else if(themeId == R.id.theme_five_color) currentTheme = ThemeName.FIVE_COLOR; 205 | else if(themeId == R.id.theme_orange_box) currentTheme = ThemeName.ORANGE_BOX; 206 | 207 | if (currentTheme != oldTheme) { 208 | languageManager.applyTheme(currentLanguage, currentTheme); 209 | } 210 | } 211 | 212 | private void toggleRelativeLineNumber() { 213 | boolean isRelativeLineNumberEnabled = codeView.isLineRelativeNumberEnabled(); 214 | isRelativeLineNumberEnabled = !isRelativeLineNumberEnabled; 215 | codeView.setEnableRelativeLineNumber(isRelativeLineNumberEnabled); 216 | } 217 | 218 | private void launchEditorButtonSheet() { 219 | final BottomSheetDialog dialog = new BottomSheetDialog(this); 220 | dialog.setContentView(R.layout.bottom_sheet_dialog); 221 | dialog.getWindow().setDimAmount(0f); 222 | 223 | final EditText searchEdit = dialog.findViewById(R.id.search_edit); 224 | final EditText replacementEdit = dialog.findViewById(R.id.replacement_edit); 225 | 226 | final ImageButton findPrevAction = dialog.findViewById(R.id.find_prev_action); 227 | final ImageButton findNextAction = dialog.findViewById(R.id.find_next_action); 228 | final ImageButton replacementAction = dialog.findViewById(R.id.replace_action); 229 | 230 | searchEdit.addTextChangedListener(new TextWatcher() { 231 | @Override 232 | public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { 233 | 234 | } 235 | 236 | @Override 237 | public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { 238 | 239 | } 240 | 241 | @Override 242 | public void afterTextChanged(Editable editable) { 243 | String text = editable.toString().trim(); 244 | if (text.isEmpty()) codeView.clearMatches(); 245 | codeView.findMatches(Pattern.quote(text)); 246 | } 247 | }); 248 | 249 | findPrevAction.setOnClickListener(v -> { 250 | codeView.findPrevMatch(); 251 | }); 252 | 253 | findNextAction.setOnClickListener(v -> { 254 | codeView.findNextMatch(); 255 | }); 256 | 257 | replacementAction.setOnClickListener(v -> { 258 | String regex = searchEdit.getText().toString(); 259 | String replacement = replacementEdit.getText().toString(); 260 | codeView.replaceAllMatches(regex, replacement); 261 | }); 262 | 263 | dialog.setOnDismissListener(c -> codeView.clearMatches()); 264 | dialog.show(); 265 | } 266 | } -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/plugin/CommentManager.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary.plugin; 2 | 3 | import android.text.Editable; 4 | import android.widget.EditText; 5 | 6 | public class CommentManager { 7 | 8 | private final EditText textView; 9 | private final Editable editable; 10 | 11 | private String commentStart; 12 | private int commentStartLength; 13 | 14 | private String commentEnd; 15 | private int commendEndLength; 16 | 17 | public CommentManager(EditText textView) { 18 | this.textView = textView; 19 | this.editable = textView.getText(); 20 | this.commentStart = ""; 21 | this.commentStartLength = 0; 22 | this.commentEnd = ""; 23 | this.commendEndLength = 0; 24 | } 25 | 26 | public CommentManager(EditText textView, String commentStart, String commentEnd) { 27 | this.textView = textView; 28 | this.editable = textView.getText(); 29 | this.commentStart = commentStart; 30 | this.commentStartLength = commentStart.length(); 31 | this.commentEnd = commentEnd; 32 | this.commendEndLength = commentEnd.length(); 33 | } 34 | 35 | public void commentSelected() { 36 | int start = textView.getSelectionStart(); 37 | int end = textView.getSelectionEnd(); 38 | if (start != end) { 39 | String[] lines = editable.subSequence(start, end).toString().split("\n"); 40 | StringBuilder builder = new StringBuilder(); 41 | int len = lines.length; 42 | for (int i = 0; i < len ; i++) { 43 | String line = lines[i]; 44 | if (!line.startsWith(commentStart)) builder.append(commentStart); 45 | builder.append(line); 46 | if (!line.endsWith(commentEnd)) builder.append(commentEnd); 47 | if (i != len - 1) builder.append("\n"); 48 | } 49 | editable.replace(start, end, builder); 50 | } 51 | } 52 | 53 | public void unCommentSelected() { 54 | int start = textView.getSelectionStart(); 55 | int end = textView.getSelectionEnd(); 56 | if (start != end) { 57 | String[] lines = editable.subSequence(start, end).toString().split("\n"); 58 | StringBuilder builder = new StringBuilder(); 59 | int len = lines.length; 60 | for (int i = 0; i < len ; i++) { 61 | String line = lines[i]; 62 | if (line.startsWith(commentStart) && line.endsWith(commentEnd)) 63 | builder.append(line.substring(commentStartLength, line.length() - commendEndLength)); 64 | else builder.append(line); 65 | if (i != len - 1) builder.append("\n"); 66 | } 67 | editable.replace(start, end, builder); 68 | } 69 | } 70 | 71 | public void setCommentStart(String comment) { 72 | this.commentStart = comment; 73 | this.commentStartLength = comment.length(); 74 | } 75 | 76 | public void setCommendEnd(String comment) { 77 | this.commentEnd = comment; 78 | this.commendEndLength = comment.length(); 79 | } 80 | } -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/plugin/SourcePositionListener.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary.plugin; 2 | 3 | import android.text.Layout; 4 | import android.view.View; 5 | import android.view.accessibility.AccessibilityEvent; 6 | import android.widget.EditText; 7 | 8 | public class SourcePositionListener { 9 | 10 | private final EditText editText; 11 | 12 | @FunctionalInterface 13 | public interface OnPositionChanged { 14 | void onPositionChange(int line, int column); 15 | } 16 | 17 | private OnPositionChanged onPositionChanged; 18 | 19 | public SourcePositionListener(EditText editText) { 20 | this.editText = editText; 21 | editText.setAccessibilityDelegate(viewAccessibility); 22 | } 23 | 24 | public void setOnPositionChanged(OnPositionChanged listener) { 25 | onPositionChanged = listener; 26 | } 27 | 28 | private final View.AccessibilityDelegate viewAccessibility = new View.AccessibilityDelegate() { 29 | 30 | @Override 31 | public void sendAccessibilityEvent(View host, int eventType) { 32 | super.sendAccessibilityEvent(host, eventType); 33 | if (eventType == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED && onPositionChanged != null) { 34 | int selectionStart = editText.getSelectionStart(); 35 | Layout layout = editText.getLayout(); 36 | if (layout == null) return; 37 | int line = editText.getLayout().getLineForOffset(selectionStart); 38 | int column = selectionStart - editText.getLayout().getLineStart(line); 39 | onPositionChanged.onPositionChange(line + 1, column + 1); 40 | } 41 | } 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/plugin/UndoRedoManager.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary.plugin; 2 | 3 | import android.text.Editable; 4 | import android.text.Selection; 5 | import android.text.TextUtils; 6 | import android.text.TextWatcher; 7 | import android.text.style.UnderlineSpan; 8 | import android.widget.TextView; 9 | 10 | import java.util.LinkedList; 11 | 12 | public class UndoRedoManager { 13 | 14 | private final TextView textView; 15 | private final EditHistory editHistory; 16 | private final TextChangeWatcher textChangeWatcher; 17 | 18 | private boolean isUndoOrRedo = false; 19 | 20 | public UndoRedoManager(TextView textView) { 21 | this.textView = textView; 22 | editHistory = new EditHistory(); 23 | textChangeWatcher = new TextChangeWatcher(); 24 | } 25 | 26 | public void undo() { 27 | EditNode edit = editHistory.getPrevious(); 28 | if (edit == null) return; 29 | 30 | Editable text = textView.getEditableText(); 31 | int start = edit.start; 32 | int end = start + (edit.after != null ? edit.after.length() : 0); 33 | 34 | isUndoOrRedo = true; 35 | text.replace(start, end, edit.before); 36 | isUndoOrRedo = false; 37 | 38 | UnderlineSpan[] underlineSpans = text.getSpans(0, text.length(), UnderlineSpan.class); 39 | for (Object span : underlineSpans) text.removeSpan(span); 40 | 41 | Selection.setSelection(text, edit.before == null ? start : (start + edit.before.length())); 42 | } 43 | 44 | public void redo() { 45 | EditNode edit = editHistory.getNext(); 46 | if (edit == null) return; 47 | 48 | Editable text = textView.getEditableText(); 49 | int start = edit.start; 50 | int end = start + (edit.before != null ? edit.before.length() : 0); 51 | 52 | isUndoOrRedo = true; 53 | text.replace(start, end, edit.after); 54 | isUndoOrRedo = false; 55 | 56 | UnderlineSpan[] underlineSpans = text.getSpans(0, text.length(), UnderlineSpan.class); 57 | for (Object span : underlineSpans) text.removeSpan(span); 58 | 59 | Selection.setSelection(text, edit.after == null ? start : (start + edit.after.length())); 60 | } 61 | 62 | public void connect() { 63 | textView.addTextChangedListener(textChangeWatcher); 64 | } 65 | 66 | public void disconnect() { 67 | textView.removeTextChangedListener(textChangeWatcher); 68 | } 69 | 70 | public void setMaxHistorySize(int maxSize) { 71 | editHistory.setMaxHistorySize(maxSize); 72 | } 73 | 74 | public void clearHistory() { 75 | editHistory.clear(); 76 | } 77 | 78 | public boolean canUndo() { 79 | return editHistory.position > 0; 80 | } 81 | 82 | public boolean canRedo() { 83 | return editHistory.position < editHistory.historyList.size(); 84 | } 85 | 86 | private static final class EditHistory { 87 | 88 | private int position = 0; 89 | private int maxHistorySize = -1; 90 | 91 | private final LinkedList historyList = new LinkedList<>(); 92 | 93 | private void clear() { 94 | position = 0; 95 | historyList.clear(); 96 | } 97 | 98 | private void add(EditNode item) { 99 | while (historyList.size() > position) historyList.removeLast(); 100 | historyList.add(item); 101 | position++; 102 | if (maxHistorySize >= 0) trimHistory(); 103 | } 104 | 105 | private void setMaxHistorySize(int maxHistorySize) { 106 | this.maxHistorySize = maxHistorySize; 107 | if (this.maxHistorySize >= 0) trimHistory(); 108 | } 109 | 110 | private void trimHistory() { 111 | while (historyList.size() > maxHistorySize) { 112 | historyList.removeFirst(); 113 | position--; 114 | } 115 | 116 | if (position < 0) position = 0; 117 | } 118 | 119 | private EditNode getCurrent() { 120 | if (position == 0) return null; 121 | return historyList.get(position - 1); 122 | } 123 | 124 | private EditNode getPrevious() { 125 | if (position == 0) return null; 126 | position--; 127 | return historyList.get(position); 128 | } 129 | 130 | private EditNode getNext() { 131 | if (position >= historyList.size()) return null; 132 | EditNode item = historyList.get(position); 133 | position++; 134 | return item; 135 | } 136 | } 137 | 138 | private static final class EditNode { 139 | 140 | private int start; 141 | private CharSequence before; 142 | private CharSequence after; 143 | 144 | public EditNode(int start, CharSequence before, CharSequence after) { 145 | this.start = start; 146 | this.before = before; 147 | this.after = after; 148 | } 149 | } 150 | 151 | private enum ActionType { 152 | INSERT, DELETE, PASTE, NOT_DEF; 153 | } 154 | 155 | private final class TextChangeWatcher implements TextWatcher { 156 | 157 | private CharSequence beforeChange; 158 | private CharSequence afterChange; 159 | private ActionType lastActionType = ActionType.NOT_DEF; 160 | 161 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 162 | if (isUndoOrRedo) return; 163 | beforeChange = s.subSequence(start, start + count); 164 | } 165 | 166 | public void onTextChanged(CharSequence s, int start, int before, int count) { 167 | if (isUndoOrRedo) return; 168 | afterChange = s.subSequence(start, start + count); 169 | makeBatch(start); 170 | } 171 | 172 | private void makeBatch(int start) { 173 | ActionType action = getActionType(); 174 | EditNode currentNode = editHistory.getCurrent(); 175 | if (lastActionType != action || ActionType.PASTE == action || currentNode == null) { 176 | editHistory.add(new EditNode(start, beforeChange, afterChange)); 177 | } else { 178 | if (action == ActionType.DELETE) { 179 | currentNode.start = start; 180 | currentNode.before = TextUtils.concat(beforeChange, currentNode.before); 181 | } else { 182 | currentNode.after = TextUtils.concat(currentNode.after, afterChange); 183 | } 184 | } 185 | lastActionType = action; 186 | } 187 | 188 | private ActionType getActionType() { 189 | if (!TextUtils.isEmpty(beforeChange) && TextUtils.isEmpty(afterChange)) { 190 | return ActionType.DELETE; 191 | } else if (TextUtils.isEmpty(beforeChange) && !TextUtils.isEmpty(afterChange)) { 192 | return ActionType.INSERT; 193 | } else { 194 | return ActionType.PASTE; 195 | } 196 | } 197 | 198 | public void afterTextChanged(Editable s) { 199 | } 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/syntax/GoLanguage.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary.syntax; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | import com.amrdeveloper.codeview.Code; 7 | import com.amrdeveloper.codeview.CodeView; 8 | import com.amrdeveloper.codeview.Keyword; 9 | import com.amrdeveloper.codeviewlibrary.R; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashSet; 13 | import java.util.List; 14 | import java.util.Set; 15 | import java.util.regex.Pattern; 16 | 17 | public class GoLanguage { 18 | 19 | //Language Keywords 20 | private static final Pattern PATTERN_KEYWORDS = Pattern.compile("\\b(break|default|func|interface|case|defer|" + 21 | "go|map|struct|chan|else|goto|package|switch|const" + 22 | "|fallthrough|if|range|type|continue|for|import|return|var|" + 23 | "string|true|false|new|nil|byte|bool|int|int8|int16|int32|int64)\\b"); 24 | 25 | //Brackets and Colons 26 | private static final Pattern PATTERN_BUILTINS = Pattern.compile("[,:;[->]{}()]"); 27 | 28 | //Data 29 | private static final Pattern PATTERN_NUMBERS = Pattern.compile("\\b(\\d*[.]?\\d+)\\b"); 30 | private static final Pattern PATTERN_CHAR = Pattern.compile("['](.*?)[']"); 31 | private static final Pattern PATTERN_STRING = Pattern.compile("[\"](.*?)[\"]"); 32 | private static final Pattern PATTERN_HEX = Pattern.compile("0x[0-9a-fA-F]+"); 33 | private static final Pattern PATTERN_SINGLE_LINE_COMMENT = Pattern.compile("//[^\\n]*"); 34 | private static final Pattern PATTERN_MULTI_LINE_COMMENT = Pattern.compile("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/"); 35 | private static final Pattern PATTERN_ATTRIBUTE = Pattern.compile("\\.[a-zA-Z0-9_]+"); 36 | private static final Pattern PATTERN_OPERATION =Pattern.compile( ":|==|>|<|!=|>=|<=|->|=|>|<|%|-|-=|%=|\\+|\\-|\\-=|\\+=|\\^|\\&|\\|::|\\?|\\*"); 37 | 38 | public static void applyMonokaiTheme(Context context, CodeView codeView) { 39 | codeView.resetSyntaxPatternList(); 40 | codeView.resetHighlighter(); 41 | 42 | Resources resources = context.getResources(); 43 | 44 | //View Background 45 | codeView.setBackgroundColor(resources.getColor(R.color.monokia_pro_black)); 46 | 47 | //Syntax Colors 48 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.monokia_pro_purple)); 49 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.monokia_pro_green)); 50 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.monokia_pro_orange)); 51 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.monokia_pro_purple)); 52 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.monokia_pro_pink)); 53 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.monokia_pro_white)); 54 | codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.monokia_pro_grey)); 55 | codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.monokia_pro_grey)); 56 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.monokia_pro_sky)); 57 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.monokia_pro_pink)); 58 | 59 | //Default Color 60 | codeView.setTextColor(resources.getColor(R.color.monokia_pro_white)); 61 | 62 | codeView.reHighlightSyntax(); 63 | } 64 | 65 | public static void applyNoctisWhiteTheme(Context context, CodeView codeView) { 66 | codeView.resetSyntaxPatternList(); 67 | codeView.resetHighlighter(); 68 | 69 | Resources resources = context.getResources(); 70 | 71 | //View Background 72 | codeView.setBackgroundColor(resources.getColor(R.color.noctis_white)); 73 | 74 | //Syntax Colors 75 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.noctis_purple)); 76 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.noctis_green)); 77 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.noctis_green)); 78 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.noctis_purple)); 79 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.noctis_pink)); 80 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.noctis_dark_blue)); 81 | codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.noctis_grey)); 82 | codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.noctis_grey)); 83 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.noctis_blue)); 84 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.monokia_pro_pink)); 85 | 86 | //Default Color 87 | codeView.setTextColor(resources.getColor(R.color.noctis_orange)); 88 | 89 | codeView.reHighlightSyntax(); 90 | } 91 | 92 | public static void applyFiveColorsDarkTheme(Context context, CodeView codeView) { 93 | codeView.resetSyntaxPatternList(); 94 | codeView.resetHighlighter(); 95 | 96 | Resources resources = context.getResources(); 97 | 98 | //View Background 99 | codeView.setBackgroundColor(resources.getColor(R.color.five_dark_black)); 100 | 101 | //Syntax Colors 102 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.five_dark_purple)); 103 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.five_dark_yellow)); 104 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.five_dark_yellow)); 105 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.five_dark_purple)); 106 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.five_dark_purple)); 107 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.five_dark_white)); 108 | codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.five_dark_grey)); 109 | codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.five_dark_grey)); 110 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.five_dark_blue)); 111 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.five_dark_purple)); 112 | 113 | //Default Color 114 | codeView.setTextColor(resources.getColor(R.color.five_dark_white)); 115 | 116 | codeView.reHighlightSyntax(); 117 | } 118 | 119 | public static void applyOrangeBoxTheme(Context context, CodeView codeView) { 120 | codeView.resetSyntaxPatternList(); 121 | codeView.resetHighlighter(); 122 | 123 | Resources resources = context.getResources(); 124 | 125 | //View Background 126 | codeView.setBackgroundColor(resources.getColor(R.color.orange_box_black)); 127 | 128 | //Syntax Colors 129 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.gold)); 130 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.orange_box_orange2)); 131 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.orange_box_orange2)); 132 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.five_dark_purple)); 133 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.orange_box_orange1)); 134 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.orange_box_grey)); 135 | codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.orange_box_dark_grey)); 136 | codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.orange_box_dark_grey)); 137 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.orange_box_orange3)); 138 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.gold)); 139 | 140 | //Default Color 141 | codeView.setTextColor(resources.getColor(R.color.five_dark_white)); 142 | 143 | codeView.reHighlightSyntax(); 144 | } 145 | 146 | public static String[] getKeywords(Context context) { 147 | return context.getResources().getStringArray(R.array.go_keywords); 148 | } 149 | 150 | public static List getCodeList(Context context) { 151 | List codeList = new ArrayList<>(); 152 | String[] keywords = getKeywords(context); 153 | for (String keyword : keywords) { 154 | codeList.add(new Keyword(keyword)); 155 | } 156 | return codeList; 157 | } 158 | 159 | public static Set getIndentationStarts() { 160 | Set characterSet = new HashSet<>(); 161 | characterSet.add('{'); 162 | return characterSet; 163 | } 164 | 165 | public static Set getIndentationEnds() { 166 | Set characterSet = new HashSet<>(); 167 | characterSet.add('}'); 168 | return characterSet; 169 | } 170 | 171 | public static String getCommentStart() { 172 | return "//"; 173 | } 174 | 175 | public static String getCommentEnd() { 176 | return ""; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/syntax/JavaLanguage.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary.syntax; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | import com.amrdeveloper.codeview.Code; 7 | import com.amrdeveloper.codeview.CodeView; 8 | import com.amrdeveloper.codeview.Keyword; 9 | import com.amrdeveloper.codeviewlibrary.R; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashSet; 13 | import java.util.List; 14 | import java.util.Set; 15 | import java.util.regex.Pattern; 16 | 17 | public class JavaLanguage { 18 | 19 | //Language Keywords 20 | private static final Pattern PATTERN_KEYWORDS = Pattern.compile("\\b(abstract|boolean|break|byte|case|catch" + 21 | "|char|class|continue|default|do|double|else" + 22 | "|enum|extends|final|finally|float|for|if" + 23 | "|implements|import|instanceof|int|interface" + 24 | "|long|native|new|null|package|private|protected" + 25 | "|public|return|short|static|strictfp|super|switch" + 26 | "|synchronized|this|throw|transient|try|void|volatile|while)\\b"); 27 | 28 | private static final Pattern PATTERN_BUILTINS = Pattern.compile("[,:;[->]{}()]"); 29 | private static final Pattern PATTERN_SINGLE_LINE_COMMENT = Pattern.compile("//[^\\n]*"); 30 | private static final Pattern PATTERN_MULTI_LINE_COMMENT = Pattern.compile("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/"); 31 | private static final Pattern PATTERN_ATTRIBUTE = Pattern.compile("\\.[a-zA-Z0-9_]+"); 32 | private static final Pattern PATTERN_OPERATION =Pattern.compile( ":|==|>|<|!=|>=|<=|->|=|>|<|%|-|-=|%=|\\+|\\-|\\-=|\\+=|\\^|\\&|\\|::|\\?|\\*"); 33 | private static final Pattern PATTERN_GENERIC = Pattern.compile("<[a-zA-Z0-9,<>]+>"); 34 | private static final Pattern PATTERN_ANNOTATION = Pattern.compile("@.[a-zA-Z0-9]+"); 35 | private static final Pattern PATTERN_TODO_COMMENT = Pattern.compile("//TODO[^\n]*"); 36 | private static final Pattern PATTERN_NUMBERS = Pattern.compile("\\b(\\d*[.]?\\d+)\\b"); 37 | private static final Pattern PATTERN_CHAR = Pattern.compile("['](.*?)[']"); 38 | private static final Pattern PATTERN_STRING = Pattern.compile("[\"](.*?)[\"]"); 39 | private static final Pattern PATTERN_HEX = Pattern.compile("0x[0-9a-fA-F]+"); 40 | 41 | public static void applyMonokaiTheme(Context context, CodeView codeView) { 42 | codeView.resetSyntaxPatternList(); 43 | codeView.resetHighlighter(); 44 | 45 | Resources resources = context.getResources(); 46 | 47 | //View Background 48 | codeView.setBackgroundColor(resources.getColor(R.color.monokia_pro_black)); 49 | 50 | //Syntax Colors 51 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.monokia_pro_purple)); 52 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.monokia_pro_green)); 53 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.monokia_pro_orange)); 54 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.monokia_pro_purple)); 55 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.monokia_pro_pink)); 56 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.monokia_pro_white)); 57 | codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.monokia_pro_grey)); 58 | codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.monokia_pro_grey)); 59 | codeView.addSyntaxPattern(PATTERN_ANNOTATION, resources.getColor(R.color.monokia_pro_pink)); 60 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.monokia_pro_sky)); 61 | codeView.addSyntaxPattern(PATTERN_GENERIC, resources.getColor(R.color.monokia_pro_pink)); 62 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.monokia_pro_pink)); 63 | //Default Color 64 | codeView.setTextColor( resources.getColor(R.color.monokia_pro_white)); 65 | 66 | codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, resources.getColor(R.color.gold)); 67 | 68 | codeView.reHighlightSyntax(); 69 | } 70 | 71 | public static void applyNoctisWhiteTheme(Context context, CodeView codeView) { 72 | codeView.resetSyntaxPatternList(); 73 | codeView.resetHighlighter(); 74 | 75 | Resources resources = context.getResources(); 76 | 77 | //View Background 78 | codeView.setBackgroundColor(resources.getColor(R.color.noctis_white)); 79 | 80 | //Syntax Colors 81 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.noctis_purple)); 82 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.noctis_green)); 83 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.noctis_green)); 84 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.noctis_purple)); 85 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.noctis_pink)); 86 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.noctis_dark_blue)); 87 | codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.noctis_grey)); 88 | codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.noctis_grey)); 89 | codeView.addSyntaxPattern(PATTERN_ANNOTATION, resources.getColor(R.color.monokia_pro_pink)); 90 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.noctis_blue)); 91 | codeView.addSyntaxPattern(PATTERN_GENERIC, resources.getColor(R.color.monokia_pro_pink)); 92 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.monokia_pro_pink)); 93 | 94 | //Default Color 95 | codeView.setTextColor(resources.getColor(R.color.noctis_orange)); 96 | 97 | codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, resources.getColor(R.color.gold)); 98 | 99 | codeView.reHighlightSyntax(); 100 | } 101 | 102 | public static void applyFiveColorsDarkTheme(Context context, CodeView codeView) { 103 | codeView.resetSyntaxPatternList(); 104 | codeView.resetHighlighter(); 105 | 106 | Resources resources = context.getResources(); 107 | 108 | //View Background 109 | codeView.setBackgroundColor(resources.getColor(R.color.five_dark_black)); 110 | 111 | //Syntax Colors 112 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.five_dark_purple)); 113 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.five_dark_yellow)); 114 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.five_dark_yellow)); 115 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.five_dark_purple)); 116 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.five_dark_purple)); 117 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.five_dark_white)); 118 | codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.five_dark_grey)); 119 | codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.five_dark_grey)); 120 | codeView.addSyntaxPattern(PATTERN_ANNOTATION, resources.getColor(R.color.five_dark_purple)); 121 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.five_dark_blue)); 122 | codeView.addSyntaxPattern(PATTERN_GENERIC, resources.getColor(R.color.five_dark_purple)); 123 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.five_dark_purple)); 124 | 125 | //Default Color 126 | codeView.setTextColor(resources.getColor(R.color.five_dark_white)); 127 | 128 | codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, resources.getColor(R.color.gold)); 129 | 130 | codeView.reHighlightSyntax(); 131 | } 132 | 133 | public static void applyOrangeBoxTheme(Context context, CodeView codeView) { 134 | codeView.resetSyntaxPatternList(); 135 | codeView.resetHighlighter(); 136 | 137 | Resources resources = context.getResources(); 138 | 139 | //View Background 140 | codeView.setBackgroundColor(resources.getColor(R.color.orange_box_black)); 141 | 142 | //Syntax Colors 143 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.gold)); 144 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.orange_box_orange2)); 145 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.orange_box_orange2)); 146 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.five_dark_purple)); 147 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.orange_box_orange1)); 148 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.orange_box_grey)); 149 | codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.orange_box_dark_grey)); 150 | codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.orange_box_dark_grey)); 151 | codeView.addSyntaxPattern(PATTERN_ANNOTATION, resources.getColor(R.color.orange_box_orange1)); 152 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.orange_box_orange3)); 153 | codeView.addSyntaxPattern(PATTERN_GENERIC, resources.getColor(R.color.orange_box_orange1)); 154 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.gold)); 155 | 156 | //Default Color 157 | codeView.setTextColor(resources.getColor(R.color.five_dark_white)); 158 | 159 | codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, resources.getColor(R.color.gold)); 160 | 161 | codeView.reHighlightSyntax(); 162 | } 163 | 164 | public static String[] getKeywords(Context context) { 165 | return context.getResources().getStringArray(R.array.java_keywords); 166 | } 167 | 168 | public static List getCodeList(Context context) { 169 | List codeList = new ArrayList<>(); 170 | String[] keywords = getKeywords(context); 171 | for (String keyword : keywords) { 172 | codeList.add(new Keyword(keyword)); 173 | } 174 | return codeList; 175 | } 176 | 177 | public static Set getIndentationStarts() { 178 | Set characterSet = new HashSet<>(); 179 | characterSet.add('{'); 180 | return characterSet; 181 | } 182 | 183 | public static Set getIndentationEnds() { 184 | Set characterSet = new HashSet<>(); 185 | characterSet.add('}'); 186 | return characterSet; 187 | } 188 | 189 | public static String getCommentStart() { 190 | return "//"; 191 | } 192 | 193 | public static String getCommentEnd() { 194 | return ""; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/syntax/LanguageManager.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary.syntax; 2 | 3 | import android.content.Context; 4 | 5 | import com.amrdeveloper.codeview.Code; 6 | import com.amrdeveloper.codeview.CodeView; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashSet; 10 | import java.util.List; 11 | import java.util.Set; 12 | 13 | public class LanguageManager { 14 | 15 | private final Context context; 16 | private final CodeView codeView; 17 | 18 | public LanguageManager(Context context, CodeView codeView) { 19 | this.context = context; 20 | this.codeView = codeView; 21 | } 22 | 23 | public void applyTheme(LanguageName language, ThemeName theme) { 24 | switch (theme) { 25 | case MONOKAI: 26 | applyMonokaiTheme(language); 27 | break; 28 | case NOCTIS_WHITE: 29 | applyNoctisWhiteTheme(language); 30 | break; 31 | case FIVE_COLOR: 32 | applyFiveColorsDarkTheme(language); 33 | break; 34 | case ORANGE_BOX: 35 | applyOrangeBoxTheme(language); 36 | break; 37 | } 38 | } 39 | 40 | public String[] getLanguageKeywords(LanguageName language) { 41 | switch (language) { 42 | case JAVA: return JavaLanguage.getKeywords(context); 43 | case PYTHON: return PythonLanguage.getKeywords(context); 44 | case GO_LANG: return GoLanguage.getKeywords(context); 45 | default: return new String[]{}; 46 | } 47 | } 48 | 49 | public List getLanguageCodeList(LanguageName language) { 50 | switch (language) { 51 | case JAVA: return JavaLanguage.getCodeList(context); 52 | case PYTHON: return PythonLanguage.getCodeList(context); 53 | case GO_LANG: return GoLanguage.getCodeList(context); 54 | default: return new ArrayList<>(); 55 | } 56 | } 57 | 58 | public Set getLanguageIndentationStarts(LanguageName language) { 59 | switch (language) { 60 | case JAVA: return JavaLanguage.getIndentationStarts(); 61 | case PYTHON: return PythonLanguage.getIndentationStarts(); 62 | case GO_LANG: return GoLanguage.getIndentationStarts(); 63 | default: return new HashSet<>(); 64 | } 65 | } 66 | 67 | public Set getLanguageIndentationEnds(LanguageName language) { 68 | switch (language) { 69 | case JAVA: return JavaLanguage.getIndentationEnds(); 70 | case PYTHON: return PythonLanguage.getIndentationEnds(); 71 | case GO_LANG: return GoLanguage.getIndentationEnds(); 72 | default: return new HashSet<>(); 73 | } 74 | } 75 | 76 | public String getCommentStart(LanguageName language) { 77 | switch (language) { 78 | case JAVA: return JavaLanguage.getCommentStart(); 79 | case PYTHON: return PythonLanguage.getCommentStart(); 80 | case GO_LANG: return GoLanguage.getCommentStart(); 81 | default: return ""; 82 | } 83 | } 84 | 85 | public String getCommentEnd(LanguageName language) { 86 | switch (language) { 87 | case JAVA: return JavaLanguage.getCommentEnd(); 88 | case PYTHON: return PythonLanguage.getCommentEnd(); 89 | case GO_LANG: return GoLanguage.getCommentEnd(); 90 | default: return ""; 91 | } 92 | } 93 | 94 | private void applyMonokaiTheme(LanguageName language) { 95 | switch (language) { 96 | case JAVA: 97 | JavaLanguage.applyMonokaiTheme(context, codeView); 98 | break; 99 | case PYTHON: 100 | PythonLanguage.applyMonokaiTheme(context, codeView); 101 | break; 102 | case GO_LANG: 103 | GoLanguage.applyMonokaiTheme(context, codeView); 104 | break; 105 | } 106 | } 107 | 108 | private void applyNoctisWhiteTheme(LanguageName language) { 109 | switch (language) { 110 | case JAVA: 111 | JavaLanguage.applyNoctisWhiteTheme(context, codeView); 112 | break; 113 | case PYTHON: 114 | PythonLanguage.applyNoctisWhiteTheme(context, codeView); 115 | break; 116 | case GO_LANG: 117 | GoLanguage.applyNoctisWhiteTheme(context, codeView); 118 | break; 119 | } 120 | } 121 | 122 | private void applyFiveColorsDarkTheme(LanguageName language) { 123 | switch (language) { 124 | case JAVA: 125 | JavaLanguage.applyFiveColorsDarkTheme(context, codeView); 126 | break; 127 | case PYTHON: 128 | PythonLanguage.applyFiveColorsDarkTheme(context, codeView); 129 | break; 130 | case GO_LANG: 131 | GoLanguage.applyFiveColorsDarkTheme(context, codeView); 132 | break; 133 | } 134 | } 135 | 136 | private void applyOrangeBoxTheme(LanguageName language) { 137 | switch (language) { 138 | case JAVA: 139 | JavaLanguage.applyOrangeBoxTheme(context, codeView); 140 | break; 141 | case PYTHON: 142 | PythonLanguage.applyOrangeBoxTheme(context, codeView); 143 | break; 144 | case GO_LANG: 145 | GoLanguage.applyOrangeBoxTheme(context, codeView); 146 | break; 147 | } 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/syntax/LanguageName.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary.syntax; 2 | 3 | /** 4 | * List of examples languages for CodeView 5 | */ 6 | public enum LanguageName { 7 | JAVA, 8 | PYTHON, 9 | GO_LANG 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/syntax/PythonLanguage.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary.syntax; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | import com.amrdeveloper.codeview.Code; 7 | import com.amrdeveloper.codeview.CodeView; 8 | import com.amrdeveloper.codeview.Keyword; 9 | import com.amrdeveloper.codeviewlibrary.R; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashSet; 13 | import java.util.List; 14 | import java.util.Set; 15 | import java.util.regex.Pattern; 16 | 17 | public class PythonLanguage { 18 | 19 | //Language Keywords 20 | private static final Pattern PATTERN_KEYWORDS = Pattern.compile("\\b(False|await|else|import|pass|None|break|except|in|raise" + 21 | "|True|class|finally|is|return|and|continue|for|lambda" + 22 | "|try|as|def|from|nonlocal|while|assert|del|global|not" + 23 | "|with|async|elif|if|or|yield)\\b"); 24 | 25 | //Brackets and Colons 26 | private static final Pattern PATTERN_BUILTINS = Pattern.compile("[,:;[->]{}()]"); 27 | 28 | //Data 29 | private static final Pattern PATTERN_NUMBERS = Pattern.compile("\\b(\\d*[.]?\\d+)\\b"); 30 | private static final Pattern PATTERN_CHAR = Pattern.compile("['](.*?)[']"); 31 | private static final Pattern PATTERN_STRING = Pattern.compile("[\"](.*?)[\"]"); 32 | private static final Pattern PATTERN_HEX = Pattern.compile("0x[0-9a-fA-F]+"); 33 | private static final Pattern PATTERN_TODO_COMMENT = Pattern.compile("#TODO[^\n]*"); 34 | private static final Pattern PATTERN_ATTRIBUTE = Pattern.compile("\\.[a-zA-Z0-9_]+"); 35 | private static final Pattern PATTERN_OPERATION =Pattern.compile( ":|==|>|<|!=|>=|<=|->|=|>|<|%|-|-=|%=|\\+|\\-|\\-=|\\+=|\\^|\\&|\\|::|\\?|\\*"); 36 | private static final Pattern PATTERN_HASH_COMMENT = Pattern.compile("#(?!TODO )[^\\n]*"); 37 | 38 | public static void applyMonokaiTheme(Context context, CodeView codeView) { 39 | codeView.resetSyntaxPatternList(); 40 | codeView.resetHighlighter(); 41 | 42 | Resources resources = context.getResources(); 43 | 44 | //View Background 45 | codeView.setBackgroundColor(codeView.getResources().getColor(R.color.monokia_pro_black)); 46 | 47 | //Syntax Colors 48 | codeView.addSyntaxPattern(PATTERN_HEX, context.getResources().getColor(R.color.monokia_pro_purple)); 49 | codeView.addSyntaxPattern(PATTERN_CHAR, context.getResources().getColor(R.color.monokia_pro_green)); 50 | codeView.addSyntaxPattern(PATTERN_STRING, context.getResources().getColor(R.color.monokia_pro_orange)); 51 | codeView.addSyntaxPattern(PATTERN_NUMBERS, context.getResources().getColor(R.color.monokia_pro_purple)); 52 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, context.getResources().getColor(R.color.monokia_pro_pink)); 53 | codeView.addSyntaxPattern(PATTERN_BUILTINS, context.getResources().getColor(R.color.monokia_pro_white)); 54 | codeView.addSyntaxPattern(PATTERN_HASH_COMMENT, context.getResources().getColor(R.color.monokia_pro_grey)); 55 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, context.getResources().getColor(R.color.monokia_pro_sky)); 56 | codeView.addSyntaxPattern(PATTERN_OPERATION, context.getResources().getColor(R.color.monokia_pro_pink)); 57 | //Default Color 58 | codeView.setTextColor(context.getResources().getColor(R.color.monokia_pro_white)); 59 | 60 | codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, context.getResources().getColor(R.color.gold)); 61 | 62 | codeView.reHighlightSyntax(); 63 | } 64 | 65 | public static void applyNoctisWhiteTheme(Context context, CodeView codeView) { 66 | codeView.resetSyntaxPatternList(); 67 | codeView.resetHighlighter(); 68 | 69 | Resources resources = context.getResources(); 70 | 71 | //View Background 72 | codeView.setBackgroundColor(resources.getColor(R.color.noctis_white)); 73 | 74 | //Syntax Colors 75 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.noctis_purple)); 76 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.noctis_green)); 77 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.noctis_green)); 78 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.noctis_purple)); 79 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.noctis_pink)); 80 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.noctis_dark_blue)); 81 | codeView.addSyntaxPattern(PATTERN_HASH_COMMENT, resources.getColor(R.color.noctis_grey)); 82 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.noctis_blue)); 83 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.monokia_pro_pink)); 84 | 85 | //Default Color 86 | codeView.setTextColor(resources.getColor(R.color.noctis_orange)); 87 | 88 | codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, resources.getColor(R.color.gold)); 89 | 90 | codeView.reHighlightSyntax(); 91 | } 92 | 93 | public static void applyFiveColorsDarkTheme(Context context, CodeView codeView) { 94 | codeView.resetSyntaxPatternList(); 95 | codeView.resetHighlighter(); 96 | 97 | Resources resources = context.getResources(); 98 | 99 | //View Background 100 | codeView.setBackgroundColor(resources.getColor(R.color.five_dark_black)); 101 | 102 | //Syntax Colors 103 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.five_dark_purple)); 104 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.five_dark_yellow)); 105 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.five_dark_yellow)); 106 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.five_dark_purple)); 107 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.five_dark_purple)); 108 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.five_dark_white)); 109 | codeView.addSyntaxPattern(PATTERN_HASH_COMMENT, resources.getColor(R.color.five_dark_grey)); 110 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.five_dark_blue)); 111 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.five_dark_purple)); 112 | 113 | //Default Color 114 | codeView.setTextColor(resources.getColor(R.color.five_dark_white)); 115 | 116 | codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, resources.getColor(R.color.gold)); 117 | 118 | codeView.reHighlightSyntax(); 119 | } 120 | 121 | public static void applyOrangeBoxTheme(Context context, CodeView codeView) { 122 | codeView.resetSyntaxPatternList(); 123 | codeView.resetHighlighter(); 124 | 125 | Resources resources = context.getResources(); 126 | 127 | //View Background 128 | codeView.setBackgroundColor(resources.getColor(R.color.orange_box_black)); 129 | 130 | //Syntax Colors 131 | codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.gold)); 132 | codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.orange_box_orange2)); 133 | codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.orange_box_orange2)); 134 | codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.five_dark_purple)); 135 | codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.orange_box_orange1)); 136 | codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.orange_box_grey)); 137 | codeView.addSyntaxPattern(PATTERN_HASH_COMMENT, resources.getColor(R.color.orange_box_dark_grey)); 138 | codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.orange_box_orange3)); 139 | codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.gold)); 140 | 141 | //Default Color 142 | codeView.setTextColor(resources.getColor(R.color.five_dark_white)); 143 | 144 | codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, context.getResources().getColor(R.color.gold)); 145 | 146 | codeView.reHighlightSyntax(); 147 | } 148 | 149 | public static String[] getKeywords(Context context) { 150 | return context.getResources().getStringArray(R.array.python_keywords); 151 | } 152 | 153 | public static List getCodeList(Context context) { 154 | List codeList = new ArrayList<>(); 155 | String[] keywords = getKeywords(context); 156 | for (String keyword : keywords) { 157 | codeList.add(new Keyword(keyword)); 158 | } 159 | return codeList; 160 | } 161 | 162 | public static Set getIndentationStarts() { 163 | Set characterSet = new HashSet<>(); 164 | characterSet.add(':'); 165 | return characterSet; 166 | } 167 | 168 | public static Set getIndentationEnds() { 169 | return new HashSet<>(); 170 | } 171 | 172 | public static String getCommentStart() { 173 | return "#"; 174 | } 175 | 176 | public static String getCommentEnd() { 177 | return ""; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /app/src/main/java/com/amrdeveloper/codeviewlibrary/syntax/ThemeName.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary.syntax; 2 | 3 | public enum ThemeName { 4 | MONOKAI, 5 | NOCTIS_WHITE, 6 | FIVE_COLOR, 7 | ORANGE_BOX 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_cv_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_downward.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_upward.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_find_in_page.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_find_replace.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_go.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_java.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyword.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_python.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_redo.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_refresh.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_snippet.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_undo.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/font/jetbrains_mono_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/font/jetbrains_mono_medium.ttf -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 19 | 20 | 26 | 27 | 38 | 39 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/layout/bottom_sheet_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 19 | 20 | 30 | 31 | 41 | 42 | 54 | 55 | 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_modern_autocomplete.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 24 | 25 | 26 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_suggestion.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 18 | 19 | 23 | 24 | 25 | 29 | 33 | 37 | 38 | 39 | 40 | 41 | 45 | 46 | 47 | 50 | 53 | 56 | 59 | 60 | 61 | 62 | 63 | 64 | 69 | 70 | 74 | 75 | 79 | 80 | 84 | 85 | 89 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_cv_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_cv_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_cv_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-hdpi/ic_cv_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_cv_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-hdpi/ic_cv_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_cv_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-mdpi/ic_cv_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_cv_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-mdpi/ic_cv_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_cv_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-xhdpi/ic_cv_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_cv_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-xhdpi/ic_cv_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_cv_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-xxhdpi/ic_cv_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_cv_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-xxhdpi/ic_cv_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_cv_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-xxxhdpi/ic_cv_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_cv_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/app/src/main/res/mipmap-xxxhdpi/ic_cv_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | public 7 | private 8 | protected 9 | package 10 | abstract 11 | boolean 12 | break 13 | byte 14 | case 15 | catch 16 | char 17 | class 18 | continue 19 | default 20 | do 21 | double 22 | else 23 | enum 24 | extends 25 | final 26 | finally 27 | float 28 | for 29 | if 30 | implements 31 | import 32 | instanceof 33 | int 34 | interface 35 | long 36 | native 37 | new 38 | return 39 | short 40 | static 41 | strictfp 42 | super 43 | switch 44 | synchronized 45 | this 46 | throw 47 | transient 48 | try 49 | void 50 | volatile 51 | while 52 | 53 | 54 | 55 | 56 | break 57 | default 58 | func 59 | interface 60 | select 61 | case 62 | defer 63 | go 64 | map 65 | struct 66 | chan 67 | else 68 | goto 69 | package 70 | switch 71 | const 72 | fallthrough 73 | if 74 | bool 75 | byte 76 | cap 77 | close 78 | complex 79 | complex64 80 | complex128 81 | uint16 82 | copy 83 | false 84 | float32 85 | float64 86 | imag 87 | int 88 | int8 89 | int16 90 | uint32 91 | int32 92 | int64 93 | len 94 | make 95 | new 96 | nil 97 | uint64 98 | range 99 | type 100 | continue 101 | for 102 | import 103 | return 104 | var 105 | 106 | 107 | 108 | 109 | False 110 | await 111 | else 112 | import 113 | pass 114 | None 115 | break 116 | except 117 | in 118 | raise 119 | True 120 | class 121 | finally 122 | is 123 | return 124 | and 125 | continue 126 | for 127 | lambda 128 | try 129 | as 130 | def 131 | from 132 | nonlocal 133 | while 134 | assert 135 | del 136 | global 137 | not 138 | with 139 | async 140 | elif 141 | if 142 | or 143 | yield 144 | 145 | 146 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #19181B 4 | 5 | #272822 6 | #000000 7 | #ffffff 8 | #8C8C8C 9 | #CC7832 10 | #e6b121 11 | 12 | 13 | #9ccc6b 14 | #2d2a2e 15 | #fcfcfa 16 | #ff6188 17 | #78dce8 18 | #ffd866 19 | #ab9df2 20 | #727072 21 | 22 | 23 | #7dd5a9 24 | #2d2a2e 25 | #fef8ec 26 | #ff6b9e 27 | #0094f0 28 | #004d57 29 | #f5a33c 30 | #5842ff 31 | #99b0ae 32 | 33 | 34 | #252526 35 | #267ae9 36 | #fde92f 37 | #eb84f3 38 | #a9b1ae 39 | #ffffff 40 | 41 | 42 | #0c0c0c 43 | #f48400 44 | #ef4200 45 | #ad2a00 46 | #90a9b3 47 | #414d63 48 | #ffffff 49 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5dp 5 | 10dp 6 | 20dp 7 | 25dp 8 | 35dp 9 | 40dp 10 | 45dp 11 | 50dp 12 | 150dp 13 | 14 | 15 | 15sp 16 | 20sp 17 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CodeView 3 | 4 | 5 | Find And Replace 6 | Search keyword 7 | Find previous Match 8 | Find Next Match 9 | Replacement 10 | Replace all 11 | Clear Text 12 | Comment 13 | UnComment 14 | Relative Line Number 15 | Undo 16 | Redo 17 | 18 | 19 | Languages 20 | Java 21 | Python 22 | Go 23 | 24 | 25 | Themes 26 | Monokia 27 | Noctics White 28 | Five Color Dark 29 | Orange Box 30 | 31 | %1$d:%2$d 32 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/test/java/com/amrdeveloper/codeviewlibrary/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeviewlibrary; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' version '8.1.1' apply false 3 | id 'com.android.library' version '8.1.1' apply false 4 | id 'com.vanniktech.maven.publish' version "0.25.3" 5 | } -------------------------------------------------------------------------------- /codeview/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /codeview/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | id 'com.vanniktech.maven.publish' 4 | } 5 | 6 | android { 7 | compileSdkVersion 33 8 | namespace 'com.amrdeveloper.codeview' 9 | 10 | defaultConfig { 11 | minSdkVersion 15 12 | targetSdkVersion 33 13 | versionCode 15 14 | versionName "1.3.9" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | consumerProguardFiles "consumer-rules.pro" 18 | } 19 | 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | 27 | compileOptions { 28 | sourceCompatibility JavaVersion.VERSION_1_8 29 | targetCompatibility JavaVersion.VERSION_1_8 30 | } 31 | 32 | buildFeatures { 33 | buildConfig = false 34 | } 35 | } 36 | 37 | dependencies { 38 | implementation fileTree(dir: "libs", include: ["*.jar"]) 39 | implementation 'androidx.appcompat:appcompat:1.4.0' 40 | testImplementation 'junit:junit:4.12' 41 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 42 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 43 | } -------------------------------------------------------------------------------- /codeview/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/codeview/consumer-rules.pro -------------------------------------------------------------------------------- /codeview/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /codeview/src/androidTest/java/com/amrdeveloper/codeview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeview; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.amrdeveloper.codeview.test", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /codeview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /codeview/src/main/java/com/amrdeveloper/codeview/Code.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.amrdeveloper.codeview; 26 | 27 | /** 28 | * Interface to represent a different types of code such as keywords or snippets 29 | * 30 | * @since 1.1.0 31 | */ 32 | public interface Code { 33 | 34 | /** 35 | * @return The title of code 36 | */ 37 | String getCodeTitle(); 38 | 39 | /** 40 | * @return The prefix value of the code 41 | */ 42 | String getCodePrefix(); 43 | 44 | /** 45 | * @return The body of the code to insert it 46 | */ 47 | String getCodeBody(); 48 | } 49 | -------------------------------------------------------------------------------- /codeview/src/main/java/com/amrdeveloper/codeview/CodeViewAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.amrdeveloper.codeview; 26 | 27 | import android.content.Context; 28 | 29 | import android.view.LayoutInflater; 30 | import android.view.View; 31 | import android.view.ViewGroup; 32 | import android.widget.BaseAdapter; 33 | import android.widget.Filter; 34 | import android.widget.Filterable; 35 | import android.widget.TextView; 36 | 37 | import androidx.annotation.NonNull; 38 | 39 | import java.util.ArrayList; 40 | import java.util.List; 41 | 42 | /** 43 | * Custom base adapter that to use it in CodeView auto complete and snippets feature 44 | *

45 | * CodeViewAdapter supports to take a list of code which can include Keywords and snippets 46 | * 47 | * @since 1.1.0 48 | */ 49 | public class CodeViewAdapter extends BaseAdapter implements Filterable { 50 | 51 | private List originalCodes; 52 | private List currentSuggestions; 53 | private final LayoutInflater layoutInflater; 54 | private final int codeViewLayoutId; 55 | private final int codeViewTextViewId; 56 | 57 | public CodeViewAdapter(@NonNull Context context, int resource, int textViewResourceId, @NonNull List codes) { 58 | this.originalCodes = codes; 59 | this.currentSuggestions = new ArrayList<>(); 60 | this.layoutInflater = LayoutInflater.from(context); 61 | this.codeViewLayoutId = resource; 62 | this.codeViewTextViewId = textViewResourceId; 63 | } 64 | 65 | @Override 66 | public View getView(int position, View convertView, ViewGroup parent) { 67 | if (convertView == null) { 68 | convertView = layoutInflater.inflate(codeViewLayoutId, parent, false); 69 | } 70 | 71 | TextView textViewName = convertView.findViewById(codeViewTextViewId); 72 | Code currentCode = currentSuggestions.get(position); 73 | if (currentCode != null) { 74 | textViewName.setText(currentCode.getCodeTitle()); 75 | } 76 | return convertView; 77 | } 78 | 79 | @Override 80 | public int getCount() { 81 | return currentSuggestions.size(); 82 | } 83 | 84 | @Override 85 | public Object getItem(int position) { 86 | return currentSuggestions.get(position); 87 | } 88 | 89 | @Override 90 | public long getItemId(int position) { 91 | return position; 92 | } 93 | 94 | /** 95 | * Update the current code list with new list 96 | * 97 | * @param newCodeList The new code list 98 | */ 99 | public void updateCodes(List newCodeList) { 100 | currentSuggestions.clear(); 101 | originalCodes.clear(); 102 | originalCodes.addAll(newCodeList); 103 | notifyDataSetChanged(); 104 | } 105 | 106 | /** 107 | * Clear the current code list and notify data set changed 108 | */ 109 | public void clearCodes() { 110 | originalCodes.clear(); 111 | currentSuggestions.clear(); 112 | notifyDataSetChanged(); 113 | } 114 | 115 | @Override 116 | public Filter getFilter() { 117 | return codeFilter; 118 | } 119 | 120 | private final Filter codeFilter = new Filter() { 121 | @Override 122 | protected FilterResults performFiltering(CharSequence constraint) { 123 | FilterResults results = new FilterResults(); 124 | List suggestions = new ArrayList<>(); 125 | 126 | // If no prefix text, show all codes 127 | if (constraint == null || constraint.length() == 0) { 128 | results.values = originalCodes; 129 | results.count = originalCodes.size(); 130 | return results; 131 | } 132 | 133 | // Calculate suggestions based on current text 134 | String filterPattern = constraint.toString().toLowerCase().trim(); 135 | for (Code item : originalCodes) { 136 | if (item.getCodePrefix().toLowerCase().contains(filterPattern)) { 137 | suggestions.add(item); 138 | } 139 | } 140 | 141 | results.values = suggestions; 142 | results.count = suggestions.size(); 143 | return results; 144 | } 145 | 146 | @Override 147 | protected void publishResults(CharSequence constraint, FilterResults results) { 148 | currentSuggestions = (List) results.values; 149 | notifyDataSetChanged(); 150 | } 151 | 152 | @Override 153 | public CharSequence convertResultToString(Object resultValue) { 154 | return ((Code) resultValue).getCodeBody(); 155 | } 156 | }; 157 | 158 | } 159 | -------------------------------------------------------------------------------- /codeview/src/main/java/com/amrdeveloper/codeview/Findable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.amrdeveloper.codeview; 26 | 27 | import java.util.List; 28 | 29 | /** 30 | * Interface used to support find and match features 31 | * 32 | * @since 1.2.1 33 | */ 34 | public interface Findable { 35 | 36 | /** 37 | * Find all the the tokens that matches the regex string and save them on a list 38 | * @param regex The regex used to find tokens 39 | * @return List of the matches Tokens 40 | */ 41 | List findMatches(String regex); 42 | 43 | /** 44 | * Highlight and return the next token 45 | * @return The next matched token, {@code null} if not found 46 | */ 47 | Token findNextMatch(); 48 | 49 | /** 50 | * Highlight and return the previous token 51 | * @return The previous matched token, {@code null} if not found 52 | */ 53 | Token findPrevMatch(); 54 | 55 | /** 56 | * Clear all the matches tokens 57 | */ 58 | void clearMatches(); 59 | } 60 | -------------------------------------------------------------------------------- /codeview/src/main/java/com/amrdeveloper/codeview/Keyword.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.amrdeveloper.codeview; 26 | 27 | /** 28 | * Keyword is used to save information to provide auto complete features 29 | * 30 | * @since 1.1.0 31 | */ 32 | public class Keyword implements Code { 33 | 34 | private final String title; 35 | private final String prefix; 36 | 37 | public Keyword(String title) { 38 | this.title = title; 39 | this.prefix = title; 40 | } 41 | 42 | public Keyword(String title, String prefix) { 43 | this.title = title; 44 | this.prefix = prefix; 45 | } 46 | 47 | @Override 48 | public String getCodeTitle() { 49 | return title; 50 | } 51 | 52 | @Override 53 | public String getCodePrefix() { 54 | return prefix; 55 | } 56 | 57 | @Override 58 | public String getCodeBody() { 59 | return prefix; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /codeview/src/main/java/com/amrdeveloper/codeview/KeywordTokenizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.amrdeveloper.codeview; 26 | 27 | import android.widget.MultiAutoCompleteTextView; 28 | 29 | /** 30 | * The default tokenizer that used for CodeView auto complete feature 31 | */ 32 | public class KeywordTokenizer implements MultiAutoCompleteTextView.Tokenizer { 33 | 34 | @Override 35 | public int findTokenStart(CharSequence charSequence, int cursor) { 36 | // All text until the current cursor position 37 | final String sequenceStr = charSequence.toString().substring(0, cursor); 38 | 39 | // Iterate until find space, newline or (, starting from the current cursor position 40 | for (int i = cursor - 1; i >= 0; i--) { 41 | // Return the next position after the prefix character 42 | final char c = sequenceStr.charAt(i); 43 | if (c == ' ' || c == '\n' || c == '(') return i + 1; 44 | } 45 | 46 | // If no prefix character found then token start is the start of text 47 | return 0; 48 | } 49 | 50 | @Override 51 | public int findTokenEnd(CharSequence charSequence, int cursor) { 52 | return charSequence.length(); 53 | } 54 | 55 | @Override 56 | public CharSequence terminateToken(CharSequence charSequence) { 57 | return charSequence; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /codeview/src/main/java/com/amrdeveloper/codeview/Replaceable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.amrdeveloper.codeview; 26 | 27 | /** 28 | * Interface used to support find and replacement feature 29 | * 30 | * @since 1.2.1 31 | */ 32 | public interface Replaceable { 33 | 34 | /** 35 | * Replace the first string that matched by the regex with new string 36 | * @param regex regex Regex used to find the first target string 37 | * @param replacement Text to replace that matched string by it 38 | */ 39 | void replaceFirstMatch(String regex, String replacement); 40 | 41 | /** 42 | * Replace all strings that matched by the regex with new string 43 | * @param regex Regex used to find the target string 44 | * @param replacement Text to replace that matched string by it 45 | */ 46 | void replaceAllMatches(String regex, String replacement); 47 | } 48 | -------------------------------------------------------------------------------- /codeview/src/main/java/com/amrdeveloper/codeview/Snippet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.amrdeveloper.codeview; 26 | 27 | /** 28 | * Snippet is used to save information to provide snippets features 29 | * 30 | * @since 1.1.0 31 | */ 32 | public class Snippet implements Code { 33 | 34 | private final String title; 35 | private final String prefix; 36 | private final String body; 37 | 38 | public Snippet(String title, String body) { 39 | this.title = title; 40 | this.prefix = title; 41 | this.body = body; 42 | } 43 | 44 | public Snippet(String title, String prefix, String body) { 45 | this.title = title; 46 | this.prefix = prefix; 47 | this.body = body; 48 | } 49 | 50 | @Override 51 | public String getCodeTitle() { 52 | return title; 53 | } 54 | 55 | @Override 56 | public String getCodePrefix() { 57 | return prefix; 58 | } 59 | 60 | @Override 61 | public String getCodeBody() { 62 | return body; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /codeview/src/main/java/com/amrdeveloper/codeview/Token.java: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package com.amrdeveloper.codeview; 26 | 27 | /** 28 | * Token is class to represent a position on the source code 29 | * 30 | * @since 1.2.1 31 | */ 32 | public class Token { 33 | 34 | private final int start; 35 | private final int end; 36 | 37 | public Token(int start, int end) { 38 | this.start = start; 39 | this.end = end; 40 | } 41 | 42 | /** 43 | * @return The start position of the current token in source code 44 | */ 45 | public int getStart() { 46 | return start; 47 | } 48 | 49 | /** 50 | * @return The end position of the current token in source code 51 | */ 52 | public int getEnd() { 53 | return end; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /codeview/src/test/java/com/amrdeveloper/codeview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.amrdeveloper.codeview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /docs/add-to-xml.md: -------------------------------------------------------------------------------- 1 | # Add CodeView to XML layout 2 | 3 | It's easy to add CodeView in your XML layout, notes that CodeView is based on AppCompatMultiAutoCompleteTextView, 4 | so you can easily customize it like any AutoCompleteTextView 5 | 6 | ``` xml 7 | 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/assets/cv-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/docs/assets/cv-logo.png -------------------------------------------------------------------------------- /docs/auto-complete.md: -------------------------------------------------------------------------------- 1 | # Auto Complete 2 | 3 | You have many options to provide an auto complete feature with CodeView 4 | 5 | ### Providing a simple auto complete from an array of strings 6 | 7 | ``` java 8 | // Your language keywords 9 | String[] languageKeywords = ..... 10 | // List item custom layout 11 | int layoutId = ..... 12 | // TextView id on your custom layout to put suggestion on it 13 | int viewId = ..... 14 | // Create ArrayAdapter object that contain all information 15 | ArrayAdapter adapter = new ArrayAdapter<>(context, layoutId, viewId, languageKeywords); 16 | // Set the adapter on CodeView object 17 | codeView.setAdapter(adapter); 18 | ``` 19 | 20 | ### Providing more advanced auto complete from list of Keyword class 21 | 22 | - This option is better if you want to provide title and prefix for your keywords, 23 | also it more easier to use it with snippets feature. 24 | 25 | ``` java 26 | List codes = new ArrayList<>(); 27 | codes.add(new Keyword(..., ..., ...)); 28 | 29 | // Your language keywords 30 | String[] languageKeywords = ..... 31 | // List item custom layout 32 | int layoutId = ..... 33 | // TextView id on your custom layout to put suggestion on it 34 | int viewId = ..... 35 | 36 | CodeViewAdapter codeAdapter = new CodeViewAdapter(context, layoutId, viewId, codes); 37 | codeView.setAdapter(codeAdapter); 38 | ``` 39 | 40 | In both options you can provide custom layout and custom tokenizer if you need that. 41 | 42 | 43 | ``` java 44 | codeView.setAutoCompleteTokenizer(tokenizer); 45 | ``` 46 | 47 | You can limit the number of suggestions result in the auto complete dialog 48 | 49 | ``` java 50 | codeView.setMaxSuggestionsSize(maxSize); 51 | ``` 52 | 53 | Set the auto complete list item size in dp to use it to calculate the full dialog size 54 | 55 | ``` java 56 | codeView.setAutoCompleteItemHeightInDp(50); 57 | ``` 58 | -------------------------------------------------------------------------------- /docs/auto-indenting.md: -------------------------------------------------------------------------------- 1 | # Auto Indenting 2 | 3 | Starting From version 1.2.1 CodeView now have support for customizable Auto indenting. 4 | 5 | ### How auto indenting works in CodeView? 6 | Basically this feature depend on two set of characters which are indentation starts and ends sets, 7 | when user typed character from indentation starts, the indentation level will increased by the tab length, 8 | and if it from indentation ends, indentation level will decreased by the tab length, 9 | 10 | In some cases the user editing the code from the middle so we can't use the global indentation level, and we need to find the level before this code and apply it. 11 | 12 | Now after you understanding how auto indenting works, it's time to know how to config it. 13 | 14 | ### Set Indentations Starts set of characters 15 | 16 | ``` java 17 | codeView.setIndentationStarts(indentationStart); 18 | ``` 19 | 20 | ### Set Indentations Ends set of characters 21 | 22 | ``` java 23 | codeView.setIndentationEnds(indentationEnds); 24 | ``` 25 | 26 | ### Enable/Disable Auto Indentation 27 | 28 | ``` java 29 | codeView.setEnableAutoIndentation(enableIndentation); 30 | ``` 31 | 32 | ### Set Tab length 33 | 34 | ``` java 35 | codeView.setTabLength(tabLength); 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/config.js: -------------------------------------------------------------------------------- 1 | document$.subscribe(() => { 2 | hljs.highlightAll() 3 | }) 4 | -------------------------------------------------------------------------------- /docs/contribution/documentation.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | - All the documentations are written in Mark Down files in docs directory 4 | 5 | - We use Material MkDocs to generate the website 6 | 7 | ### How to edit the docs? 8 | 9 | - Clone the repository 10 | ``` 11 | git clone https://github.com/amrdeveloper/codeview.git 12 | ``` 13 | 14 | - Enter the docs directory 15 | ``` 16 | cd docs 17 | ``` 18 | 19 | - Edit the file, you can see the output live on the website using mkdocs serve, 20 | ``` 21 | mkdocs serve 22 | ``` 23 | 24 | - Open docs website locally to see the output. 25 | ``` 26 | http://127.0.0.1:8000/codeview 27 | ``` 28 | 29 | - After finishing the modification, commit and make Pull request. 30 | -------------------------------------------------------------------------------- /docs/contribution/report.md: -------------------------------------------------------------------------------- 1 | # Report Issue 2 | 3 | - You're most welcome to report any issue or corner case, but first make sure this issue isn't reported before on the issues list on Github Repository. 4 | 5 | - If it unique, that's very good you should report it by creating new issue and explained when exactly this issue appear and it will be amazing if you can add code example. 6 | 7 | - If you want also to work on this issue, tell us in the end that you can do it and we will start discussion about it. 8 | 9 | - Feel free to share your ideas and hints. -------------------------------------------------------------------------------- /docs/contribution/suggestion.md: -------------------------------------------------------------------------------- 1 | # Suggest New Feature 2 | 3 | - I believe that everyone can add new value to CodeView and any contribution will be very helpful. 4 | 5 | - If you see that any part of this tool can be improved, feel free to make new issue with some information for example which part? code, docs...etc and 6 | what is your suggestion to improve it? also do you want to work on this suggestion? 7 | 8 | - After submitting your issue we will have a discussion and brainstorm about this suggestion to see what is the best way to implement it. -------------------------------------------------------------------------------- /docs/find-and-replace.md: -------------------------------------------------------------------------------- 1 | # Find and Replace 2 | 3 | Starting From version 1.2.1 CodeView now have support for find and replace feature easily. 4 | 5 | - To get a list of tokens that matchs your regex, you can use findMatches method. 6 | 7 | ``` java 8 | List tokens = codeView.findMatches(regex); 9 | ``` 10 | 11 | - To highlight and get the next matching token you can use findNextMatch 12 | 13 | ``` java 14 | Token token = codeView.findNextMatch(); 15 | ``` 16 | 17 | - To highlight and get the previous matching token you can use findPrevMatch 18 | 19 | ``` java 20 | Token token = codeView.findPrevMatch(); 21 | ``` 22 | 23 | - You can set differnt color for highlighting matching token depend on your theme 24 | 25 | ``` java 26 | codeView.setMatchingHighlightColor(color); 27 | ``` 28 | 29 | - To clear all the matches tokens 30 | 31 | ``` java 32 | codeView.clearMatches(); 33 | ``` 34 | 35 | - You can replace the first string that matching the regex with other string. 36 | 37 | ``` java 38 | codeView.replaceFirstMatch(regex, replacement); 39 | ``` 40 | 41 | - You can replace all strings that matching the regex with other string. 42 | 43 | ``` java 44 | codeView.replaceAllMatches(regex, replacement); 45 | ``` 46 | 47 | You will find a full example with UI dialog for this feature in the example app 48 | -------------------------------------------------------------------------------- /docs/highlight.md: -------------------------------------------------------------------------------- 1 | # Highlight 2 | 3 | The main goal for creating the CodeView library is to not be limited by a list of highlighters that come with any library but to have the ability to create a highlighter for any set of data, 4 | so you can highlight and provide other features for any programming language or data. 5 | 6 | ### To highlight pattern with color. 7 | 8 | ``` 9 | codeView.addSyntaxPattern(pattern, Color); 10 | ``` 11 | 12 | ### You can add a Map instead of adding patterns one by one 13 | 14 | ``` 15 | codeView.setSyntaxPatternsMap(syntaxPatterns); 16 | ``` 17 | 18 | ### You can also remove pattern in the runtime 19 | 20 | ``` 21 | codeView.removeSyntaxPattern(pattern); 22 | ``` 23 | 24 | ### Highlight the text depend on the new patterns 25 | 26 | ``` 27 | codeView.reHighlightSyntax(); 28 | ``` 29 | 30 | ### Un highlight all tokens 31 | 32 | ``` 33 | codeView.resetHighlighter(); 34 | ``` 35 | 36 | ### Clear all patterns from CodeView 37 | 38 | ``` 39 | codeView.resetSyntaxPatternList(); 40 | ``` 41 | 42 | ### Set highlighter update delay 43 | 44 | ``` 45 | codeView.setUpdateDelayTime(); 46 | ``` 47 | 48 | ### You can control when to highlight the text 49 | 50 | ``` 51 | codeView.highlightWhileTextChanging(highlightWhileTextChanging); 52 | ``` 53 | 54 | ### Add error line with dynamic color to support error, hint, warn...etc 55 | 56 | ``` 57 | codeView.addErrorLine(lineNumber, color); 58 | ``` 59 | 60 | ### Clear all error lines 61 | 62 | ``` 63 | codeView.removeAllErrorLines(); 64 | ``` 65 | 66 | ### Highlight the errors depend on the error lines 67 | 68 | ``` 69 | codeView.reHighlightErrors(); 70 | ``` 71 | 72 | ### Get the number of errors 73 | 74 | ``` 75 | int numberOfErrors = codeView.getErrorsSize(); 76 | ``` -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # CodeView 2 | 3 | Android Library to make it easy to create your CodeEditor or IDE for any programming language 4 | even for your programming language, just config the view with your language keywords and other attributes 5 | and you can change the CodeView theme in the runtime so it's made it easy to support any number of themes, 6 | and CodeView has AutoComplete and you can customize it with different keywords and tokenizers. 7 | 8 | ## Main Features 9 | - Can support any programming language you want. 10 | - Can support AutoComplete and customize it with different tokenizers and design. 11 | - Can support any theme you want and change it in the runtime. 12 | - Syntax Highlighter depend on your patterns so you can support any features like TODO comment. 13 | - Can support errors and warns with different colors and remove them in the runtime. 14 | - Can change highlighter update delay time. 15 | - Support Code snippets and change it in the runtime. 16 | - Support optional Line Number with customization. 17 | - Support optional highlighting current line number. 18 | - Support optional relative line number inspired from vim editor. 19 | - Support Auto indentation with customization. 20 | - Support highlighting matching tokens. 21 | - Support replace first and replace all matching tokens. 22 | - Support auto pair complete. 23 | 24 | We are open to any new feature request, bug fix request, and pull request. -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | # How to install? 2 | 3 | #### Add CodeView from Maven Central 4 | 5 | ``` 6 | dependencies { 7 | implementation 'io.github.amrdeveloper:codeview:1.3.9' 8 | } 9 | ``` 10 | 11 | #### Or Add CodeView from JCentral 12 | 13 | Step 1: Add it to your root build.gradle 14 | ``` 15 | allprojects { 16 | epositories { 17 | maven { url 'https://jitpack.io' } 18 | } 19 | } 20 | ``` 21 | 22 | Step 2: Add the dependency 23 | ``` 24 | dependencies { 25 | implementation 'com.github.AmrDeveloper:CodeView:1.3.9' 26 | } 27 | ``` -------------------------------------------------------------------------------- /docs/line-number.md: -------------------------------------------------------------------------------- 1 | # Line Number 2 | 3 | Starting From version 1.1.1 CodeView now have support for line number. 4 | 5 | ### Enable/Disable line number 6 | 7 | ``` java 8 | codeView.setEnableLineNumber(true and false); 9 | ``` 10 | 11 | ### Check if line number feature is enabled 12 | 13 | ``` java 14 | codeView.isLineNumberEnabled(); 15 | ``` 16 | 17 | ### Enable/Disable relative line number 18 | 19 | ``` java 20 | codeView.setEnableRelativeLineNumber(true and false); 21 | ``` 22 | 23 | ### Check if relative line number feature is enabled 24 | 25 | ``` java 26 | codeView.isLineRelativeNumberEnabled(); 27 | ``` 28 | 29 | ### Enable/Disable highlight current line 30 | 31 | ``` java 32 | codeView.setEnableHighlightCurrentLine(true and false); 33 | ``` 34 | 35 | ### Check if highlight current line feature is enabled 36 | 37 | ``` java 38 | codeView.isHighlightCurrentLineEnabled(); 39 | ``` 40 | 41 | ### Set highlight current line color 42 | 43 | ``` java 44 | codeView.setHighlightCurrentLineColor(Color.GREY); 45 | ``` 46 | 47 | ### Set line number text color 48 | 49 | ``` java 50 | codeView.setLineNumberTextColor(Color.GREY); 51 | ``` 52 | 53 | ### Set line number text size in pixels, it recommended to set it within the range of text size 54 | 55 | ``` java 56 | codeView.setLineNumberTextSize(size like 30f); 57 | ``` 58 | 59 | ### Set line number typeface 60 | 61 | ``` java 62 | codeView.setLineNumberTypeface(typeface); 63 | ``` 64 | -------------------------------------------------------------------------------- /docs/pair-complete.md: -------------------------------------------------------------------------------- 1 | # Pair Complete 2 | 3 | Starting From version 1.3.0 CodeView now has support for auto pair complete, 4 | this feature can help you to implement some features easily such as quote or double quote complete, 5 | or closing braces complete. 6 | 7 | This features is disabled by default to enable or disable it 8 | 9 | ``` java 10 | codeView.enablePairComplete(enableFeature); 11 | ``` 12 | 13 | To enable or disable move the cursor to the center of the pair after inset it 14 | 15 | ``` java 16 | codeView.enablePairCompleteCenterCursor(enableFeature); 17 | ``` 18 | 19 | To use this feature you need to create a Map that contains the pairs keys and values for example 20 | 21 | ``` java 22 | Map pairCompleteMap = new HashMap<>(); 23 | pairCompleteMap.put('{', '}'); 24 | pairCompleteMap.put('[', ']'); 25 | pairCompleteMap.put('(', ')'); 26 | pairCompleteMap.put('<', '>'); 27 | pairCompleteMap.put('"', '"'); 28 | 29 | ``` 30 | 31 | To add your full pairs map 32 | 33 | ``` java 34 | codeView.setPairCompleteMap(pairCompleteMap); 35 | ``` 36 | 37 | To add a single pair 38 | 39 | ``` java 40 | codeView.addPairCompleteItem('[', ']'); 41 | ``` 42 | 43 | To remove a single pair 44 | 45 | ``` java 46 | codeView.removePairCompleteItem('['); 47 | ``` 48 | 49 | To remove all the pairs 50 | 51 | ``` java 52 | codeView.clearPairCompleteMap(); 53 | ``` 54 | -------------------------------------------------------------------------------- /docs/snippets.md: -------------------------------------------------------------------------------- 1 | # Snippets 2 | 3 | Starting From version 1.1.1 CodeView now have support for snippts. 4 | 5 | In the CodeView library keywords and snippets are classes that implementing the Code interface. 6 | 7 | ``` java 8 | public interface Code { 9 | String getCodeTitle(); 10 | String getCodePrefix(); 11 | String getCodeBody(); 12 | } 13 | ``` 14 | 15 | This class has three attributes title, prefix and body, It’s important to know the difference between them 16 | 17 | - The title is that text that you see on the autocomplete dropdown menu so it can be for example "Keyword Package". 18 | 19 | - The prefix is that text that we use it for filtering in the autocomplete adapter for example "package" 20 | 21 | - The body is what we inserted in the code when the user types a string that is a subset of the prefix and then he clicks on the title for example "package main;" 22 | 23 | Add Custom AutoComplete Adapter that support Snippets 24 | 25 | ``` java 26 | List codes = new ArrayList<>(); 27 | codes.add(new Snippet(..., ..., ...)); 28 | 29 | // Your language keywords 30 | String[] languageKeywords = ..... 31 | // List item custom layout 32 | int layoutId = ..... 33 | // TextView id on your custom layout to put suggestion on it R.layout.yourlayout 34 | int viewId = ..... 35 | 36 | CodeViewAdapter codeAdapter = new CodeViewAdapter(context, layoutId, viewId, codes); 37 | codeView.setAdapter(codeAdapter); 38 | ``` 39 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.nonTransitiveRClass=true 2 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | 6 | # Required to publish to Nexus 7 | systemProp.org.gradle.internal.publish.checksums.insecure=true 8 | 9 | # Increase timeout when pushing to Sonatype 10 | systemProp.org.gradle.internal.http.connectionTimeout=120000 11 | systemProp.org.gradle.internal.http.socketTimeout=120000 12 | 13 | GROUP=io.github.amrdeveloper 14 | VERSION_NAME=1.3.9 15 | 16 | POM_DESCRIPTION=Android Library to make it easy to create a code editor 17 | POM_INCEPTION_YEAR=2023 18 | POM_URL=https://github.com/amrdeveloper/codeview/ 19 | 20 | POM_LICENSE_NAME=MIT 21 | POM_LICENSE_URL=https://opensource.org/licenses/MIT 22 | POM_LICENSE_DIST=repo 23 | 24 | POM_SCM_URL=https://github.com/amrdeveloper/codeview/ 25 | POM_SCM_CONNECTION=scm:git:git://github.com/amrdeveloper/codeview.git 26 | POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/amrdeveloper/codeview.git 27 | 28 | POM_DEVELOPER_ID=amrdeveloper 29 | POM_DEVELOPER_NAME=Amr Hesham 30 | POM_DEVELOPER_URL=https://github.com/amrdeveloper/ 31 | 32 | POM_ARTIFACT_ID=codeview 33 | POM_NAME=CodeView 34 | POM_PACKAGING=aar 35 | 36 | SONATYPE_HOST=S01 37 | RELEASE_SIGNING_ENABLED=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 13 01:43:19 EET 2020 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-8.0-bin.zip -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /media/cv-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/media/cv-logo.png -------------------------------------------------------------------------------- /media/golang_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/media/golang_demo.gif -------------------------------------------------------------------------------- /media/java_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/media/java_demo.gif -------------------------------------------------------------------------------- /media/python_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmrDeveloper/CodeView/2370ea6bae2e6711755663760f7e23db52991f7b/media/python_demo.gif -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: CodeView 2 | site_url: https://amrdeveloper.github.io/codeview 3 | site_description: Android Library to make it easy to highlight your data with alot of customization 4 | site_author: AmrDeveloper 5 | 6 | copyright: Copyright © 2022 Amr Heshan 7 | 8 | repo_name: AmrDeveloper/CodeView 9 | repo_url: https://github.com/amrdeveloper/codeview 10 | edit_uri: blob/master/docs/ 11 | 12 | theme: 13 | logo: assets/cv-logo.png 14 | favicon: assets/cv-logo.png 15 | name: material 16 | language: en 17 | icon: 18 | repo: fontawesome/brands/github 19 | font: 20 | text: Roboto 21 | palette: 22 | - scheme: default 23 | primary: deep purple 24 | toggle: 25 | icon: material/toggle-switch-off-outline 26 | name: Switch to dark mode 27 | - scheme: slate 28 | primary: black 29 | toggle: 30 | icon: material/toggle-switch 31 | name: Switch to light mode 32 | features: 33 | - header.autohide 34 | - navigation.instant 35 | - navigation.tracking 36 | - navigation.indexes 37 | - content.code.annotate 38 | - navigation.sections 39 | 40 | nav: 41 | - Home: index.md 42 | - Install: install.md 43 | - Add to XML: add-to-xml.md 44 | - Highlight: highlight.md 45 | - Auto Complete: auto-complete.md 46 | - Pair Complete: pair-complete.md 47 | - Snippets: snippets.md 48 | - Auto Indenting: auto-indenting.md 49 | - Find and Replace: find-and-replace.md 50 | - Line number: line-number.md 51 | - Contribution: 52 | - Documentation: contribution/documentation.md 53 | - Suggest Fetaure: contribution/suggestion.md 54 | - Report Issue: contribution/report.md 55 | 56 | extra: 57 | social: 58 | - icon: fontawesome/brands/github 59 | link: https://github.com/amrdeveloper 60 | name: AmrDeveloper on Github 61 | - icon: fontawesome/brands/twitter 62 | link: https://twitter.com/AmrDeveloper 63 | name: AmrDeveloper on Twitter 64 | - icon: fontawesome/brands/linkedin 65 | link: https://www.linkedin.com/in/amrdeveloper 66 | name: AmrDeveloper on Linkedin 67 | - icon: fontawesome/brands/medium 68 | link: https://amrdeveloper.medium.com 69 | name: AmrDeveloper on Medium 70 | 71 | extra_css: 72 | - https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/github.min.css 73 | extra_javascript: 74 | - https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/highlight.min.js 75 | - config.js 76 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | 16 | rootProject.name = "CodeView" 17 | include ':codeview' 18 | include ':app' 19 | --------------------------------------------------------------------------------