diff --git a/app/src/main/java/io/legado/app/ui/widget/code/CodeView.kt b/app/src/main/java/io/legado/app/ui/widget/code/CodeView.kt index ee0da2ce3..82bd4a53d 100644 --- a/app/src/main/java/io/legado/app/ui/widget/code/CodeView.kt +++ b/app/src/main/java/io/legado/app/ui/widget/code/CodeView.kt @@ -1,449 +1,422 @@ -package io.legado.app.ui.widget.code; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.os.Handler; -import android.text.Editable; -import android.text.InputFilter; -import android.text.Layout; -import android.text.Spannable; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextWatcher; -import android.text.style.BackgroundColorSpan; -import android.text.style.ForegroundColorSpan; -import android.text.style.ReplacementSpan; -import android.util.AttributeSet; - -import androidx.annotation.ColorInt; -import androidx.annotation.NonNull; -import androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@SuppressWarnings("unused") -public class CodeView extends AppCompatMultiAutoCompleteTextView { - - private int tabWidth; - private int tabWidthInCharacters; - private int mUpdateDelayTime = 500; - - private boolean modified = true; - private boolean highlightWhileTextChanging = true; - - private boolean hasErrors = false; - private boolean mRemoveErrorsWhenTextChanged = true; - - private final Handler mUpdateHandler = new Handler(); - private Tokenizer mAutoCompleteTokenizer; - private final float displayDensity = getResources().getDisplayMetrics().density; - - private static final Pattern PATTERN_LINE = Pattern.compile("(^.+$)+", Pattern.MULTILINE); - private static final Pattern PATTERN_TRAILING_WHITE_SPACE = Pattern.compile("[\\t ]+$", Pattern.MULTILINE); - - private final SortedMap mErrorHashSet = new TreeMap<>(); - private final Map mSyntaxPatternMap = new HashMap<>(); - private List mIndentCharacterList = Arrays.asList('{', '+', '-', '*', '/', '='); - - public CodeView(Context context) { - super(context); - initEditorView(); - } - - public CodeView(Context context, AttributeSet attrs) { - super(context, attrs); - initEditorView(); - } - - public CodeView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initEditorView(); - } - - private void initEditorView() { +package io.legado.app.ui.widget.code + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Paint.FontMetricsInt +import android.graphics.Rect +import android.os.Handler +import android.os.Looper +import android.text.* +import android.text.style.BackgroundColorSpan +import android.text.style.ForegroundColorSpan +import android.text.style.ReplacementSpan +import android.util.AttributeSet +import androidx.annotation.ColorInt +import androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView +import java.util.* +import java.util.regex.Matcher +import java.util.regex.Pattern +import kotlin.math.roundToInt + +@Suppress("unused") +class CodeView : AppCompatMultiAutoCompleteTextView { + private var tabWidth = 0 + private var tabWidthInCharacters = 0 + private var mUpdateDelayTime = 500 + private var modified = true + private var highlightWhileTextChanging = true + private var hasErrors = false + private var mRemoveErrorsWhenTextChanged = true + private val mUpdateHandler = Handler(Looper.getMainLooper()) + private var mAutoCompleteTokenizer: Tokenizer? = null + private val displayDensity = resources.displayMetrics.density + private val mErrorHashSet: SortedMap = TreeMap() + private val mSyntaxPatternMap: MutableMap = HashMap() + private var mIndentCharacterList = mutableListOf('{', '+', '-', '*', '/', '=') + + constructor(context: Context?) : super(context!!) { + initEditorView() + } + + constructor(context: Context?, attrs: AttributeSet?) : super( + context!!, attrs + ) { + initEditorView() + } + + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super( + context!!, attrs, defStyleAttr + ) { + initEditorView() + } + + private fun initEditorView() { if (mAutoCompleteTokenizer == null) { - mAutoCompleteTokenizer = new KeywordTokenizer(); + mAutoCompleteTokenizer = KeywordTokenizer() } - - setTokenizer(mAutoCompleteTokenizer); - - setFilters(new InputFilter[]{ - new InputFilter() { - @Override - public CharSequence filter(CharSequence source, int start, int end, - Spanned dest, int dstart, int dend) { - if (modified && - end - start == 1 && - start < source.length() && - dstart < dest.length()) { - char c = source.charAt(start); - - if (c == '\n') { - return autoIndent(source, dest, dstart, dend); - } - } - return source; + setTokenizer(mAutoCompleteTokenizer) + filters = arrayOf( + InputFilter { source, start, end, dest, dStart, dEnd -> + if (modified && end - start == 1 && start < source.length && dStart < dest.length) { + val c = source[start] + if (c == '\n') { + return@InputFilter autoIndent(source, dest, dStart, dEnd) } } - }); - addTextChangedListener(mEditorTextWatcher); - } - - private CharSequence autoIndent(CharSequence source, Spanned dest, int dstart, int dend) { - String indent = ""; - int istart = dstart - 1; - - boolean dataBefore = false; - int pt = 0; - - for (; istart > -1; --istart) { - char c = dest.charAt(istart); - - if (c == '\n') break; - + source + } + ) + addTextChangedListener(mEditorTextWatcher) + } + + private fun autoIndent( + source: CharSequence, + dest: Spanned, + dStart: Int, + dEnd: Int + ): CharSequence { + var indent = "" + var iStart = dStart - 1 + var dataBefore = false + var pt = 0 + while (iStart > -1) { + val c = dest[iStart] + if (c == '\n') break if (c != ' ' && c != '\t') { if (!dataBefore) { - if (mIndentCharacterList.contains(c)) --pt; - dataBefore = true; + if (mIndentCharacterList.contains(c)) --pt + dataBefore = true } - if (c == '(') { - --pt; + --pt } else if (c == ')') { - ++pt; + ++pt } } + --iStart } - - if (istart > -1) { - char charAtCursor = dest.charAt(dstart); - int iend; - - for (iend = ++istart; iend < dend; ++iend) { - char c = dest.charAt(iend); - - if (charAtCursor != '\n' && - c == '/' && - iend + 1 < dend && - dest.charAt(iend) == c) { - iend += 2; - break; + if (iStart > -1) { + val charAtCursor = dest[dStart] + var iEnd: Int = ++iStart + while (iEnd < dEnd) { + val c = dest[iEnd] + if (charAtCursor != '\n' && c == '/' && iEnd + 1 < dEnd && dest[iEnd] == c) { + iEnd += 2 + break } - if (c != ' ' && c != '\t') { - break; + break } + ++iEnd } - - indent += dest.subSequence(istart, iend); + indent += dest.subSequence(iStart, iEnd) } - if (pt < 0) { - indent += "\t"; + indent += "\t" } - - return source + indent; + return source.toString() + indent } - private void highlightSyntax(Editable editable) { - if (mSyntaxPatternMap.isEmpty()) return; - - for (Pattern pattern : mSyntaxPatternMap.keySet()) { - int color = mSyntaxPatternMap.get(pattern); - for (Matcher m = pattern.matcher(editable); m.find(); ) { - createForegroundColorSpan(editable, m, color); + private fun highlightSyntax(editable: Editable) { + if (mSyntaxPatternMap.isEmpty()) return + for (pattern in mSyntaxPatternMap.keys) { + val color = mSyntaxPatternMap[pattern]!! + val m = pattern.matcher(editable) + while (m.find()) { + createForegroundColorSpan(editable, m, color) } } } - private void highlightErrorLines(Editable editable) { - if (mErrorHashSet.isEmpty()) return; - int maxErrorLineValue = mErrorHashSet.lastKey(); - - int lineNumber = 0; - Matcher matcher = PATTERN_LINE.matcher(editable); + private fun highlightErrorLines(editable: Editable) { + if (mErrorHashSet.isEmpty()) return + val maxErrorLineValue = mErrorHashSet.lastKey() + var lineNumber = 0 + val matcher = PATTERN_LINE.matcher(editable) while (matcher.find()) { if (mErrorHashSet.containsKey(lineNumber)) { - int color = mErrorHashSet.get(lineNumber); - createBackgroundColorSpan(editable, matcher, color); + val color = mErrorHashSet[lineNumber]!! + createBackgroundColorSpan(editable, matcher, color) } - lineNumber = lineNumber + 1; - if (lineNumber > maxErrorLineValue) break; + lineNumber += 1 + if (lineNumber > maxErrorLineValue) break } } - private void createForegroundColorSpan(Editable editable, Matcher matcher, @ColorInt int color) { - editable.setSpan(new ForegroundColorSpan(color), - matcher.start(), matcher.end(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - - private void createBackgroundColorSpan(Editable editable, Matcher matcher, @ColorInt int color) { - editable.setSpan(new BackgroundColorSpan(color), - matcher.start(), matcher.end(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - - private Editable highlight(Editable editable) { - if (editable.length() == 0) return editable; - + private fun createForegroundColorSpan( + editable: Editable, + matcher: Matcher, + @ColorInt color: Int + ) { + editable.setSpan( + ForegroundColorSpan(color), + matcher.start(), matcher.end(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + } + + private fun createBackgroundColorSpan( + editable: Editable, + matcher: Matcher, + @ColorInt color: Int + ) { + editable.setSpan( + BackgroundColorSpan(color), + matcher.start(), matcher.end(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + } + + private fun highlight(editable: Editable): Editable { + if (editable.isEmpty()) return editable try { - clearSpans(editable); - highlightErrorLines(editable); - highlightSyntax(editable); - } catch (IllegalStateException e) { - e.printStackTrace(); + clearSpans(editable) + highlightErrorLines(editable) + highlightSyntax(editable) + } catch (e: IllegalStateException) { + e.printStackTrace() } - return editable; + return editable } - private void highlightWithoutChange(Editable editable) { - modified = false; - highlight(editable); - modified = true; + private fun highlightWithoutChange(editable: Editable) { + modified = false + highlight(editable) + modified = true } - public void setTextHighlighted(CharSequence text) { - if (text == null || text.length() == 0) return; - - cancelHighlighterRender(); - - removeAllErrorLines(); - - modified = false; - setText(highlight(new SpannableStringBuilder(text))); - modified = true; + fun setTextHighlighted(text: CharSequence?) { + if (text.isNullOrEmpty()) return + cancelHighlighterRender() + removeAllErrorLines() + modified = false + setText(highlight(SpannableStringBuilder(text))) + modified = true } - public void setTabWidth(int characters) { - if (tabWidthInCharacters == characters) return; - tabWidthInCharacters = characters; - tabWidth = Math.round(getPaint().measureText("m") * characters); + fun setTabWidth(characters: Int) { + if (tabWidthInCharacters == characters) return + tabWidthInCharacters = characters + tabWidth = (paint.measureText("m") * characters).roundToInt() } - private void clearSpans(Editable editable) { - int length = editable.length(); - ForegroundColorSpan[] foregroundSpans = editable.getSpans( - 0, length, ForegroundColorSpan.class); - - for (int i = foregroundSpans.length; i-- > 0; ) - editable.removeSpan(foregroundSpans[i]); - - BackgroundColorSpan[] backgroundSpans = editable.getSpans( - 0, length, BackgroundColorSpan.class); - - for (int i = backgroundSpans.length; i-- > 0; ) - editable.removeSpan(backgroundSpans[i]); + private fun clearSpans(editable: Editable) { + val length = editable.length + val foregroundSpans = editable.getSpans( + 0, length, ForegroundColorSpan::class.java + ) + run { + var i = foregroundSpans.size + while (i-- > 0) { + editable.removeSpan(foregroundSpans[i]) + } + } + val backgroundSpans = editable.getSpans( + 0, length, BackgroundColorSpan::class.java + ) + var i = backgroundSpans.size + while (i-- > 0) { + editable.removeSpan(backgroundSpans[i]) + } } - public void cancelHighlighterRender() { - mUpdateHandler.removeCallbacks(mUpdateRunnable); + fun cancelHighlighterRender() { + mUpdateHandler.removeCallbacks(mUpdateRunnable) } - private void convertTabs(Editable editable, int start, int count) { - if (tabWidth < 1) return; - - String s = editable.toString(); - - for (int stop = start + count; - (start = s.indexOf("\t", start)) > -1 && start < stop; - ++start) { - editable.setSpan(new TabWidthSpan(), - start, - start + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + private fun convertTabs(editable: Editable, start: Int, count: Int) { + var startIndex = start + if (tabWidth < 1) return + val s = editable.toString() + val stop = startIndex + count + while (s.indexOf("\t", startIndex).also { startIndex = it } > -1 && startIndex < stop) { + editable.setSpan( + TabWidthSpan(), + startIndex, + startIndex + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ) + ++startIndex } } - public void setSyntaxPatternsMap(Map syntaxPatterns) { - if (!mSyntaxPatternMap.isEmpty()) mSyntaxPatternMap.clear(); - mSyntaxPatternMap.putAll(syntaxPatterns); + fun setSyntaxPatternsMap(syntaxPatterns: Map?) { + if (mSyntaxPatternMap.isNotEmpty()) mSyntaxPatternMap.clear() + mSyntaxPatternMap.putAll(syntaxPatterns!!) } - public void addSyntaxPattern(Pattern pattern, @ColorInt int Color) { - mSyntaxPatternMap.put(pattern, Color); + fun addSyntaxPattern(pattern: Pattern, @ColorInt Color: Int) { + mSyntaxPatternMap[pattern] = Color } - public void removeSyntaxPattern(Pattern pattern) { - mSyntaxPatternMap.remove(pattern); + fun removeSyntaxPattern(pattern: Pattern) { + mSyntaxPatternMap.remove(pattern) } - public int getSyntaxPatternsSize() { - return mSyntaxPatternMap.size(); + fun getSyntaxPatternsSize(): Int { + return mSyntaxPatternMap.size } - public void resetSyntaxPatternList() { - mSyntaxPatternMap.clear(); + fun resetSyntaxPatternList() { + mSyntaxPatternMap.clear() } - public void setAutoIndentCharacterList(List characterList) { - mIndentCharacterList = characterList; + fun setAutoIndentCharacterList(characterList: MutableList) { + mIndentCharacterList = characterList } - public void clearAutoIndentCharacterList() { - mIndentCharacterList.clear(); + fun clearAutoIndentCharacterList() { + mIndentCharacterList.clear() } - public List getAutoIndentCharacterList() { - return mIndentCharacterList; + fun getAutoIndentCharacterList(): List { + return mIndentCharacterList } - public void addErrorLine(int lineNum, int color) { - mErrorHashSet.put(lineNum, color); - hasErrors = true; + fun addErrorLine(lineNum: Int, color: Int) { + mErrorHashSet[lineNum] = color + hasErrors = true } - public void removeErrorLine(int lineNum) { - mErrorHashSet.remove(lineNum); - hasErrors = mErrorHashSet.size() > 0; + fun removeErrorLine(lineNum: Int) { + mErrorHashSet.remove(lineNum) + hasErrors = mErrorHashSet.size > 0 } - public void removeAllErrorLines() { - mErrorHashSet.clear(); - hasErrors = false; + fun removeAllErrorLines() { + mErrorHashSet.clear() + hasErrors = false } - public int getErrorsSize() { - return mErrorHashSet.size(); + fun getErrorsSize(): Int { + return mErrorHashSet.size } - public String getTextWithoutTrailingSpace() { + fun getTextWithoutTrailingSpace(): String { return PATTERN_TRAILING_WHITE_SPACE - .matcher(getText()) - .replaceAll(""); + .matcher(text) + .replaceAll("") } - public void setAutoCompleteTokenizer(Tokenizer tokenizer) { - mAutoCompleteTokenizer = tokenizer; + fun setAutoCompleteTokenizer(tokenizer: Tokenizer?) { + mAutoCompleteTokenizer = tokenizer } - public void setRemoveErrorsWhenTextChanged(boolean removeErrors) { - mRemoveErrorsWhenTextChanged = removeErrors; + fun setRemoveErrorsWhenTextChanged(removeErrors: Boolean) { + mRemoveErrorsWhenTextChanged = removeErrors } - public void reHighlightSyntax() { - highlightSyntax(getEditableText()); + fun reHighlightSyntax() { + highlightSyntax(editableText) } - public void reHighlightErrors() { - highlightErrorLines(getEditableText()); + fun reHighlightErrors() { + highlightErrorLines(editableText) } - public boolean isHasError() { - return hasErrors; + fun isHasError(): Boolean { + return hasErrors } - public void setUpdateDelayTime(int time) { - mUpdateDelayTime = time; + fun setUpdateDelayTime(time: Int) { + mUpdateDelayTime = time } - public int getUpdateDelayTime() { - return mUpdateDelayTime; + fun getUpdateDelayTime(): Int { + return mUpdateDelayTime } - public void setHighlightWhileTextChanging(boolean updateWhileTextChanging) { - this.highlightWhileTextChanging = updateWhileTextChanging; + fun setHighlightWhileTextChanging(updateWhileTextChanging: Boolean) { + highlightWhileTextChanging = updateWhileTextChanging } - @Override - public void showDropDown() { - int[] screenPoint = new int[2]; - getLocationOnScreen(screenPoint); - - final Rect displayFrame = new Rect(); - getWindowVisibleDisplayFrame(displayFrame); - - int position = getSelectionStart(); - Layout layout = getLayout(); - int line = layout.getLineForOffset(position); - - float verticalDistanceInDp = (750 + 140 * line) / displayDensity; - setDropDownVerticalOffset((int) verticalDistanceInDp); - - float horizontalDistanceInDp = layout.getPrimaryHorizontal(position) / displayDensity; - setDropDownHorizontalOffset((int) horizontalDistanceInDp); - super.showDropDown(); + override fun showDropDown() { + val screenPoint = IntArray(2) + getLocationOnScreen(screenPoint) + val displayFrame = Rect() + getWindowVisibleDisplayFrame(displayFrame) + val position = selectionStart + val layout = layout + val line = layout.getLineForOffset(position) + val verticalDistanceInDp = (750 + 140 * line) / displayDensity + dropDownVerticalOffset = verticalDistanceInDp.toInt() + val horizontalDistanceInDp = layout.getPrimaryHorizontal(position) / displayDensity + dropDownHorizontalOffset = horizontalDistanceInDp.toInt() + super.showDropDown() } - private final Runnable mUpdateRunnable = new Runnable() { - @Override - public void run() { - Editable source = getText(); - highlightWithoutChange(source); - } - }; - - private final TextWatcher mEditorTextWatcher = new TextWatcher() { - - private int start; - private int count; - - @Override - public void beforeTextChanged(CharSequence charSequence, int start, int before, int count) { - this.start = start; - this.count = count; + private val mUpdateRunnable = Runnable { + val source = text + highlightWithoutChange(source) + } + private val mEditorTextWatcher: TextWatcher = object : TextWatcher { + private var start = 0 + private var count = 0 + override fun beforeTextChanged( + charSequence: CharSequence, + start: Int, + before: Int, + count: Int + ) { + this.start = start + this.count = count } - @Override - public void onTextChanged(CharSequence charSequence, int start, int before, int count) { - if (!modified) return; - + override fun onTextChanged( + charSequence: CharSequence, + start: Int, + before: Int, + count: Int + ) { + if (!modified) return if (highlightWhileTextChanging) { - if (mSyntaxPatternMap.size() > 0) { - convertTabs(getEditableText(), start, count); - mUpdateHandler.postDelayed(mUpdateRunnable, mUpdateDelayTime); + if (mSyntaxPatternMap.isNotEmpty()) { + convertTabs(editableText, start, count) + mUpdateHandler.postDelayed(mUpdateRunnable, mUpdateDelayTime.toLong()) } } - - if (mRemoveErrorsWhenTextChanged) removeAllErrorLines(); + if (mRemoveErrorsWhenTextChanged) removeAllErrorLines() } - @Override - public void afterTextChanged(Editable editable) { + override fun afterTextChanged(editable: Editable) { if (!highlightWhileTextChanging) { - if (!modified) return; - - cancelHighlighterRender(); - - if (mSyntaxPatternMap.size() > 0) { - convertTabs(getEditableText(), start, count); - mUpdateHandler.postDelayed(mUpdateRunnable, mUpdateDelayTime); + if (!modified) return + cancelHighlighterRender() + if (mSyntaxPatternMap.isNotEmpty()) { + convertTabs(editableText, start, count) + mUpdateHandler.postDelayed(mUpdateRunnable, mUpdateDelayTime.toLong()) } } } - }; - - private final class TabWidthSpan extends ReplacementSpan { - - @Override - public int getSize( - @NonNull Paint paint, - CharSequence text, - int start, - int end, - Paint.FontMetricsInt fm) { - return tabWidth; + } + + private inner class TabWidthSpan : ReplacementSpan() { + override fun getSize( + paint: Paint, + text: CharSequence, + start: Int, + end: Int, + fm: FontMetricsInt? + ): Int { + return tabWidth } - @Override - public void draw( - @NonNull Canvas canvas, - CharSequence text, - int start, - int end, - float x, - int top, - int y, - int bottom, - @NonNull Paint paint) { + override fun draw( + canvas: Canvas, + text: CharSequence, + start: Int, + end: Int, + x: Float, + top: Int, + y: Int, + bottom: Int, + paint: Paint + ) { } } -} + + companion object { + private val PATTERN_LINE = Pattern.compile("(^.+$)+", Pattern.MULTILINE) + private val PATTERN_TRAILING_WHITE_SPACE = Pattern.compile("[\\t ]+$", Pattern.MULTILINE) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/code/KeywordTokenizer.kt b/app/src/main/java/io/legado/app/ui/widget/code/KeywordTokenizer.kt index 938e2e124..607fc9b9c 100644 --- a/app/src/main/java/io/legado/app/ui/widget/code/KeywordTokenizer.kt +++ b/app/src/main/java/io/legado/app/ui/widget/code/KeywordTokenizer.kt @@ -1,31 +1,25 @@ -package io.legado.app.ui.widget.code; - -import android.widget.MultiAutoCompleteTextView; - -public class KeywordTokenizer implements MultiAutoCompleteTextView.Tokenizer { - - @Override - public int findTokenStart(CharSequence charSequence, int cursor) { - String sequenceStr = charSequence.toString(); - sequenceStr = sequenceStr.substring(0, cursor); - - int spaceIndex = sequenceStr.lastIndexOf(" "); - int lineIndex = sequenceStr.lastIndexOf("\n"); - int bracketIndex = sequenceStr.lastIndexOf("("); - - int index = Math.max(0, Math.max(spaceIndex, Math.max(lineIndex, bracketIndex))); - if (index == 0) return 0; - return (index + 1 < charSequence.length()) ? index + 1 : index; +package io.legado.app.ui.widget.code + +import android.widget.MultiAutoCompleteTextView +import kotlin.math.max + +class KeywordTokenizer : MultiAutoCompleteTextView.Tokenizer { + override fun findTokenStart(charSequence: CharSequence, cursor: Int): Int { + var sequenceStr = charSequence.toString() + sequenceStr = sequenceStr.substring(0, cursor) + val spaceIndex = sequenceStr.lastIndexOf(" ") + val lineIndex = sequenceStr.lastIndexOf("\n") + val bracketIndex = sequenceStr.lastIndexOf("(") + val index = max(0, max(spaceIndex, max(lineIndex, bracketIndex))) + if (index == 0) return 0 + return if (index + 1 < charSequence.length) index + 1 else index } - @Override - public int findTokenEnd(CharSequence charSequence, int cursor) { - return charSequence.length(); + override fun findTokenEnd(charSequence: CharSequence, cursor: Int): Int { + return charSequence.length } - @Override - public CharSequence terminateToken(CharSequence charSequence) { - return charSequence; + override fun terminateToken(charSequence: CharSequence): CharSequence { + return charSequence } - -} +} \ No newline at end of file