diff options
| author | Jorge Ruesga <jorge@ruesga.com> | 2013-03-25 04:56:38 +0100 |
|---|---|---|
| committer | Jorge Ruesga <jorge@ruesga.com> | 2013-03-27 00:16:04 +0100 |
| commit | 8573124b80d19a9562a6e623022171b41dc4d183 (patch) | |
| tree | 40aa0eca71ca3bd4e09abee5efa046f31cc2f308 /libs/android-syntax-highlight/src | |
| parent | d063637d6110ab2a762268d7ef20afeaa6f482af (diff) | |
CMFM: Editor initial highlight support + props syntax processor + others features
- This change enables support of syntax highlight in editor. Adds also the next syntax processors:
* PropertiesSyntaxHighlightProcessor
- Option for toggle "no suggestion" in editor
- CleanUp
Patchset 2: Theme color scheme support
Patchset 3: Hexdump binary editor preference
No suggestions editor preference
Syntax Highlight color scheme
Add android-syntax-highlight (CMFM) and color-picker-view libraries
ColorPickerDialog and ColorPickerPreference
Separate preference to its own file
Extract themes strings from dark_theme.xml to strings.xml
Rebased
Change-Id: I9df65e6193d46ebafadee5d545dcde1fc5ce20e9
Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
Diffstat (limited to 'libs/android-syntax-highlight/src')
8 files changed, 854 insertions, 0 deletions
diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java new file mode 100644 index 0000000..5e31dab --- /dev/null +++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/HighlightColors.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.filemanager.ash; + +import android.graphics.Color; + +/** + * An enumeration of all the color resources available for syntax highlight processors. + */ +public enum HighlightColors { + + /** + * Text color + */ + TEXT( + "ash_text", //$NON-NLS-1$ + "ash_text_color", //$NON-NLS-1$ + Color.argb(153, 0, 0, 0)), + /** + * Assignment text color + */ + ASSIGNMENT( + "ash_assignment", //$NON-NLS-1$ + "ash_assignment_color", //$NON-NLS-1$ + Color.argb(153, 0, 0, 0)), + /** + * Single line comment color + */ + SINGLE_LINE_COMMENT( + "ash_singleline_comment", //$NON-NLS-1$ + "ash_singleline_comment_color", //$NON-NLS-1$ + Color.argb(255, 63, 127, 95)), + /** + * Multiline line comment color + */ + MULTILINE_LINE_COMMENT( + "ash_multiline_comment", //$NON-NLS-1$ + "ash_multiline_comment_color", //$NON-NLS-1$ + Color.argb(255, 127, 159, 191)), + /** + * Keyword color + */ + KEYWORD( + "ash_keyword", //$NON-NLS-1$ + "ash_keyword_color", //$NON-NLS-1$ + Color.argb(255, 127, 0, 85)), + /** + * Quoted string color + */ + QUOTED_STRING( + "ash_quoted_string", //$NON-NLS-1$ + "ash_quoted_string_color", //$NON-NLS-1$ + Color.argb(255, 42, 0, 255)), + /** + * Variable color + */ + VARIABLE( + "ash_variable", //$NON-NLS-1$ + "ash_variable_color", //$NON-NLS-1$ + Color.argb(153, 0, 0, 192)); + + + private final String mId; + private final String mResId; + private final int mDefault; + + /** + * Constructor of <code>HighlightColors</code> + * + * @param id The id of the object + * @param resid The resource id + * @param def The default value + */ + HighlightColors(String id, String resid, int def) { + this.mId = id; + this.mResId = resid; + this.mDefault = def; + } + + /** + * Returns the identifier + * + * @return String The identifier + */ + public String getId() { + return this.mId; + } + + /** + * Returns the resource identifier + * + * @return String The resource identifier + */ + public String getResId() { + return this.mResId; + } + + /** + * Returns the default value + * + * @return String The default value + */ + public int getDefault() { + return this.mDefault; + } + +} diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java new file mode 100644 index 0000000..11170e7 --- /dev/null +++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/ISyntaxHighlightResourcesResolver.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.filemanager.ash; + +/** + * An interface that should be implemented by the library caller, to + * resolve resources needed by the syntax processors. + * + * @see HighlightColors + */ +public interface ISyntaxHighlightResourcesResolver { + + /** + * Method that returns a string + * + * @param id The color unique id + * @param resid The resource identifier + * @return CharSequence The string + */ + CharSequence getString(String id, String resid); + + /** + * Method that returns an integer + * + * @param id The color unique id + * @param resid The resource identifier + * @param def The default value + * @return int The integer value + */ + int getInteger(String id, String resid, int def); + + /** + * Method that returns a color + * + * @param id The color unique id + * @param resid The resource identifier + * @param def The default value + * @return int The color + */ + int getColor(String id, String resid, int def); +} diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java new file mode 100644 index 0000000..283eba9 --- /dev/null +++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/RegExpUtil.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.filemanager.ash; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +/** + * A helper class for deal with patters + */ +public final class RegExpUtil { + + /** + * A constant that is returned when the no expression matches. + */ + public static final int NO_MATCH = -1; + + /** + * New line pattern + */ + public static final Pattern NEWLINE_PATTERN = Pattern.compile("(\r\n|\n|\r)"); //$NON-NLS-1$ + + /** + * Method that returns the last match position of a regexp, + * + * @param pattern The patter + * @param input The input + * @param withPattern Whether the return position should contains the pattern or not. + * @return int The matched position or -1 + */ + public static int getLastMatch(Pattern pattern, CharSequence input, boolean withPattern) { + Matcher m = pattern.matcher(input); + int p = NO_MATCH; + while (m.find()) { + p = withPattern ? m.start() : m.end(); + } + return p; + } + + /** + * Method that returns the next match position of a regexp, + * + * @param pattern The patter + * @param input The input + * @param withPattern Whether the return position should contains the pattern or not. + * @return int The matched position or -1 + */ + public static int getNextMatch(Pattern pattern, CharSequence input, boolean withPattern) { + Matcher m = pattern.matcher(input); + int p = NO_MATCH; + if (m.find()) { + return withPattern ? m.end() : m.start(); + } + return p; + } +} diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java new file mode 100644 index 0000000..20c85dc --- /dev/null +++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightFactory.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.filemanager.ash; + +import com.cyanogenmod.filemanager.ash.spi.PropertiesSyntaxHighlightProcessor; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * A factory of <code>SyntaxHighlightProcessor</code> classes. + */ +public class SyntaxHighlightFactory { + + private static SyntaxHighlightFactory sFactory; + + private final ArrayList<SyntaxHighlightProcessor> mProcessors; + + /** + * Constructor of <code>SyntaxHighlightFactory</code> + */ + public SyntaxHighlightFactory() { + super(); + this.mProcessors = new ArrayList<SyntaxHighlightProcessor>(); + } + + /** + * Method that returns the default highlight factory instance + * + * @param resolver A class for allow the processor to obtain resources + * @return SyntaxHighlightFactory The default syntax highlight factory + */ + public static final synchronized SyntaxHighlightFactory getDefaultFactory( + ISyntaxHighlightResourcesResolver resolver) { + if (sFactory == null) { + sFactory = createDefaultFactory(resolver); + } + return sFactory; + } + + /** + * Method that returns the syntax highlight processor that can handle the file + * + * @param file The file to process + * @return SyntaxHighlightProcessor The syntax highlight processor + */ + public SyntaxHighlightProcessor getSyntaxHighlightProcessor(File file) { + int cc = this.mProcessors.size(); + for (int i = 0; i < cc; i++) { + SyntaxHighlightProcessor processor = this.mProcessors.get(i); + if (processor.accept(file)) { + return processor; + } + } + return null; + } + + /** + * Method that return all the available syntax highlight processors. + * + * @return List<SyntaxHighlightProcessor> the list available syntax highlight processors. + */ + public List<SyntaxHighlightProcessor> getAvailableSyntaxHighlightProcessors() { + return new ArrayList<SyntaxHighlightProcessor>(this.mProcessors); + } + + /** + * Method that create the default syntax highlight factory. + * + * @param resolver A class for allow the processor to obtain resources + * @return SyntaxHighlightFactory The default factory + */ + private static SyntaxHighlightFactory createDefaultFactory( + ISyntaxHighlightResourcesResolver resolver) { + // TODO Read all processors classes of the SPI package + // For now we add all known syntax highlight processors + SyntaxHighlightFactory factory = new SyntaxHighlightFactory(); + factory.mProcessors.add(new PropertiesSyntaxHighlightProcessor(resolver)); + return factory; + } +} diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java new file mode 100644 index 0000000..2d52034 --- /dev/null +++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/SyntaxHighlightProcessor.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.filemanager.ash; + +import android.text.Spannable; +import android.text.Spanned; +import android.text.style.ForegroundColorSpan; + +import java.io.File; + +/** + * The base class for all the syntax highlight processors.</br> + */ +public abstract class SyntaxHighlightProcessor { + + protected final ISyntaxHighlightResourcesResolver mResourcesResolver; + + /** + * Constructor of <code>SyntaxHighlightProcessor</code> + * + * @param resolver A class for resolve resources + */ + public SyntaxHighlightProcessor(ISyntaxHighlightResourcesResolver resolver) { + super(); + this.mResourcesResolver = resolver; + } + + /** + * Method that request to the syntax highlight processor if it is able to parse + * the file + * + * @param file The file to check + * @return boolean If the syntax highlight processor accepts process the file + */ + protected abstract boolean accept(File file); + + /** + * Method that initializes the processor + */ + public abstract void initialize(); + + /** + * Method that request to the syntax highlight processor to do process and highlight a + * document. This method request a full process. + * + * @param spanable The spannable source to highlight + */ + public abstract void process(Spannable spanable); + + /** + * Method that request to the syntax highlight processor to process and highlight a + * document. This method request a partial process. + * + * @param spanable The spannable source to highlight + * @param start The start of spannable to process + * @param end The end of spannable to process + */ + public abstract void process(Spannable spanable, int start, int end); + + /** + * Method that cancels the active processor + */ + public abstract void cancel(); + + /** + * Method that clear all the existent spans + * + * @param spanable The spannable + */ + @SuppressWarnings("static-method") + public void clear(Spannable spanable) { + ForegroundColorSpan[] spans = + spanable.getSpans(0, spanable.length(), ForegroundColorSpan.class); + int cc = spans.length; + for (int i = 0; i < cc; i++) { + spanable.removeSpan(spans[i]); + } + } + + + /** + * Method that sets a new <code>Spannable</code>. + * + * @param spanable The spannable + * @param color The color of the span + * @param start The start of the span + * @param end The end of the span + */ + @SuppressWarnings("static-method") + protected void setSpan(Spannable spanable, int color, int start, int end) { + if (start == end) return; + spanable.setSpan( + new ForegroundColorSpan(color), + start, + end, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } +} diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java new file mode 100644 index 0000000..5552b8e --- /dev/null +++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/NewLineScanner.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.filemanager.ash.scanners; + +import java.util.regex.Matcher; + +import com.cyanogenmod.filemanager.ash.RegExpUtil; + +/** + * An scanner to process an input, reporting every text into new lines. + */ +public class NewLineScanner extends Scanner { + + private final NewLineScannerListener mListener; + + /** + * The listener for the newline scanner + */ + public interface NewLineScannerListener { + /** + * When a new line is ready + * + * @param newline The newline detected + * @param start The start position of the new line within the input text + * @param end The end position of the new line within the input text + * @param sep The line separator detected + * @return boolean If processor must continue with the next line + */ + boolean onNewLine(CharSequence newline, int start, int end, CharSequence sep); + } + + /** + * Constructor of <code>Scanner</code> + * + * @param input The input + * @param listener The listener where return every new line + */ + public NewLineScanner(CharSequence input, NewLineScannerListener listener) { + super(input); + this.mListener = listener; + } + + /** + * {@inheritDoc} + */ + @Override + public void scan() { + if (this.mInput.length() == 0) return; + Matcher m = RegExpUtil.NEWLINE_PATTERN.matcher(this.mInput); + int next = 0; + while(m.find(next)) { + CharSequence line = this.mInput.subSequence(next, m.start()); + if (!this.mListener.onNewLine(line, next, m.start(), m.group())) { + return; + } + next = m.end(); + } + // The non-matched data + CharSequence line = this.mInput.subSequence(next, this.mInput.length()); + this.mListener.onNewLine(line, next, this.mInput.length(), null); + } +} diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java new file mode 100644 index 0000000..3158345 --- /dev/null +++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/scanners/Scanner.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package com.cyanogenmod.filemanager.ash.scanners; + + +/** + * The base class for all the scanners + */ +public abstract class Scanner { + + CharSequence mInput; + + /** + * Constructor of <code>Scanner</code> + * + * @param input The input + */ + public Scanner(CharSequence input) { + super(); + this.mInput = input; + } + + /** + * Method that starts the scan process + */ + public abstract void scan(); +} diff --git a/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java new file mode 100644 index 0000000..f9fd19a --- /dev/null +++ b/libs/android-syntax-highlight/src/com/cyanogenmod/filemanager/ash/spi/PropertiesSyntaxHighlightProcessor.java @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.filemanager.ash.spi; + +import android.text.Spannable; +import android.text.style.ForegroundColorSpan; + +import com.cyanogenmod.filemanager.ash.HighlightColors; +import com.cyanogenmod.filemanager.ash.ISyntaxHighlightResourcesResolver; +import com.cyanogenmod.filemanager.ash.RegExpUtil; +import com.cyanogenmod.filemanager.ash.SyntaxHighlightProcessor; +import com.cyanogenmod.filemanager.ash.scanners.NewLineScanner; +import com.cyanogenmod.filemanager.ash.scanners.NewLineScanner.NewLineScannerListener; + +import java.io.File; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A <b>properties</b> highlight processor class.</br> + * </br> + * The behaviour of this class is:</br> + * <ul> + * <li>Comments start with # (only spaces are allowed prior to comment)</li> + * <li>Assignment character (=) separates key from value</li> + * <li>Arguments exists only in values, and are composed by {a digit}</li> + * <li>Values can be extended in multiple lines if line ends with the char "\". A + * comment in multiline breaks the multiline and starts a new property.</li> + * </ul> + * </br> + * IMP! This class is not thread safe. Calling "process" methods should be + * done in a synchronous way. + */ +public class PropertiesSyntaxHighlightProcessor extends SyntaxHighlightProcessor { + + private static final String EXT_PROP = "prop"; //$NON-NLS-1$ + private static final String EXT_PROPERTIES = "properties"; //$NON-NLS-1$ + + private static final Pattern COMMENT = Pattern.compile("^\\s*#.*"); //$NON-NLS-1$ + private static final Pattern MULTILINE = Pattern.compile(".*\\\\\\s*$"); //$NON-NLS-1$ + private static final Pattern ASSIGNMENT = Pattern.compile("="); //$NON-NLS-1$ + private static final Pattern ARGUMENT = Pattern.compile("\\{\\d+\\}"); //$NON-NLS-1$ + + protected Spannable mSpannable; + private boolean mMultiLine; + + private int mKeyColor; + private int mAssignmentColor; + private int mCommentColor; + private int mValueColor; + private int mArgumentColor; + + /** + * Constructor of <code>PropertiesSyntaxHighlightProcessor</code> + * + * @param resolver A class for resolve resources + */ + public PropertiesSyntaxHighlightProcessor(ISyntaxHighlightResourcesResolver resolver) { + super(resolver); + initialize(); + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean accept(File file) { + if (file == null) return false; + return file.getName().toLowerCase().endsWith(EXT_PROP) || + file.getName().toLowerCase().endsWith(EXT_PROPERTIES); + } + + /** + * {@inheritDoc} + */ + @Override + public void initialize() { + this.mMultiLine = false; + this.mSpannable = null; + if (this.mResourcesResolver != null) { + this.mKeyColor = this.mResourcesResolver.getColor( + HighlightColors.TEXT.getId(), + HighlightColors.TEXT.getResId(), + HighlightColors.TEXT.getDefault()); + this.mAssignmentColor = this.mResourcesResolver.getColor( + HighlightColors.ASSIGNMENT.getId(), + HighlightColors.ASSIGNMENT.getResId(), + HighlightColors.ASSIGNMENT.getDefault()); + this.mCommentColor = this.mResourcesResolver.getColor( + HighlightColors.SINGLE_LINE_COMMENT.getId(), + HighlightColors.SINGLE_LINE_COMMENT.getResId(), + HighlightColors.SINGLE_LINE_COMMENT.getDefault()); + this.mValueColor = this.mResourcesResolver.getColor( + HighlightColors.VARIABLE.getId(), + HighlightColors.VARIABLE.getResId(), + HighlightColors.VARIABLE.getDefault()); + this.mArgumentColor = this.mResourcesResolver.getColor( + HighlightColors.KEYWORD.getId(), + HighlightColors.KEYWORD.getResId(), + HighlightColors.KEYWORD.getDefault()); + } else { + // By default + this.mKeyColor = HighlightColors.TEXT.getDefault(); + this.mAssignmentColor = HighlightColors.TEXT.getDefault(); + this.mCommentColor = HighlightColors.SINGLE_LINE_COMMENT.getDefault(); + this.mValueColor = HighlightColors.VARIABLE.getDefault(); + this.mArgumentColor = HighlightColors.KEYWORD.getDefault(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void process(final Spannable spanable) { + this.mMultiLine = false; + this.mSpannable = spanable; + clear(spanable); + NewLineScanner scanner = new NewLineScanner(spanable, new NewLineScannerListener() { + @Override + public boolean onNewLine(CharSequence newline, int start, int end, CharSequence sep) { + processNewLine(newline, start, end); + return true; + } + + }); + scanner.scan(); + this.mSpannable = null; + } + + /** + * {@inheritDoc} + */ + @Override + public void process(final Spannable spanable, final int start, final int end) { + // We need a Retrieve the previous line + this.mMultiLine = false; + this.mSpannable = spanable; + CharSequence seqs = spanable.subSequence(0, start); + CharSequence seqe = spanable.subSequence(end, spanable.length()); + int s1 = RegExpUtil.getLastMatch(RegExpUtil.NEWLINE_PATTERN, seqs, false); + if (s1 == RegExpUtil.NO_MATCH) { + s1 = 0; + } + int e1 = RegExpUtil.getNextMatch(RegExpUtil.NEWLINE_PATTERN, seqe, false); + if (e1 == RegExpUtil.NO_MATCH) { + e1 = spanable.length(); + } else { + e1 += end; + } + + // Also, we need to know about if the previous line is multiline + if (s1 > 0) { + int s2 = RegExpUtil.getLastMatch(RegExpUtil.NEWLINE_PATTERN, seqs, true); + CharSequence seqnl = spanable.subSequence(0, s2); + int snl = RegExpUtil.getLastMatch(RegExpUtil.NEWLINE_PATTERN, seqnl, false); + Matcher mlm = MULTILINE.matcher( + spanable.subSequence(snl != RegExpUtil.NO_MATCH ? snl : 0, s2)); + this.mMultiLine = mlm.matches(); + } + + // Process the new line + if (s1 != e1) { + processNewLine(spanable.subSequence(s1, e1), s1, e1); + } + + // Now, multiline again (next line). We check always the next line, because we + // don't know if user delete multiline flag in the current line + e1 = RegExpUtil.getNextMatch(RegExpUtil.NEWLINE_PATTERN, seqe, true); + if (e1 != RegExpUtil.NO_MATCH) { + e1 += end; + seqe = spanable.subSequence(e1, spanable.length()); + int e2 = RegExpUtil.getNextMatch(RegExpUtil.NEWLINE_PATTERN, seqe, false); + if (e2 == RegExpUtil.NO_MATCH) { + e2 = spanable.length(); + } else { + e2 += e1; + } + processNewLine(spanable.subSequence(e1, e2), e1, e2); + } + + this.mSpannable = null; + } + + /** + * {@inheritDoc} + */ + @Override + public void cancel() { + // Not needed by this processor + } + + /** + * A method to process every new line + * + * @param newline The newline + * @param start The start position of the line + * @param end The end position of the line + * @hide + */ + void processNewLine(CharSequence newline, int start, int end) { + // Remove all spannable of the line (this processor doesn't multiline spans and + // only uses ForegroundColorSpan spans) + ForegroundColorSpan[] spans = + this.mSpannable.getSpans(start, end, ForegroundColorSpan.class); + int cc = spans.length; + for (int i = 0; i < cc; i++) { + this.mSpannable.removeSpan(spans[i]); + } + + // Find comment + Matcher cm = COMMENT.matcher(newline); + if (cm.matches()) { + // All the line is a comment + setSpan(this.mSpannable, this.mCommentColor, start, end); + this.mMultiLine = false; + return; + } + + // Has multiline + Matcher mlm = MULTILINE.matcher(newline); + boolean ml = mlm.matches(); + + //Find the assignment + int k = this.mMultiLine ? -1 : start; + int v = start; + int v2 = 0; + int a = -1; + if (!this.mMultiLine) { + Matcher am = ASSIGNMENT.matcher(newline); + if (am.find()) { + // Assignment found + v2 = am.start() + 1; + a = start + am.start(); + v = a + 1; + } + } + + // All the string is a key + if (!this.mMultiLine && a == -1) { + setSpan(this.mSpannable, this.mKeyColor, start, end); + + } else { + // Key + if (!this.mMultiLine) { + setSpan(this.mSpannable, this.mKeyColor, k, a); + } + // Assignment + if (!this.mMultiLine) { + setSpan(this.mSpannable, this.mAssignmentColor, a, a + 1); + } + // Value + setSpan(this.mSpannable, this.mValueColor, v, end); + // Argument + Matcher argm = ARGUMENT.matcher(newline); + while (argm.find(v2)) { + int s = start + argm.start(); + int e = start + argm.end(); + setSpan(this.mSpannable, this.mArgumentColor, s, e); + v2 = argm.end(); + } + } + + // Multiline? + this.mMultiLine = ml; + } +} |
