package Ġcom . f red happy face . brain f Ċ Ċ import Ġandroid . text . Editable Ċ import Ġandroid . text . Sp ann able Ċ import Ġandroid . text . Text Watcher Ċ import Ġandroid . text . style . Character Style Ċ import Ġandroid . widget . EditText Ċ import Ġkotlinx . coroutines .* Ċ import Ġjava . util .* Ċ Ċ /** Ċ Ġ* ĠText Highlight Ġprovides Ġconvenience Ġfunctions Ġto Ġapply Ġcolo urs Ġto Ġan Ġedit Ġtext Ċ Ġ* Ċ Ġ* Ġ> Ċ var Ġcolo urs : ĠCo lo urs Ġ= ĠCo lo urs Dark () Ċ var Ġlanguage Rules : ĠLanguage Rules Ġ= ĠLanguage Rules Java () Ċ val Ġcode EditText : ĠEditText Ġ= ĠfindViewById ( R . id . code Highlight ) Ċ val Ġtext Highlight Ġ= ĠText Highlight ( Ċ code EditText , Ċ language Rules , Ċ colo urs Ċ ) Ċ text Highlight . start () Ċ Ġ* Ċ Ġ* Ġ@ constructor Ċ Ġ* Ġ@ param Ġtarget EditText ĠEditText Ċ Ġ* Ġ@ param Ġlanguage Rules ĠLanguage Rules Ċ Ġ* Ġ@ param Ġcolo urs ĠCo lo urs Ċ Ġ* Ġ@ param Ġtime Delay ĠLong Ċ Ġ*/ Ċ open Ġclass ĠText Highlight ( Ċ ĉ target EditText : ĠEditText , Ċ ĉ language Rules : ĠLanguage Rules , Ċ ĉ colo urs : ĠCo lo urs , Ċ ĉ time Delay : ĠLong Ġ= Ġ 1 5 0 Ċ ) Ġ{ Ċ ĉ /** Ċĉ Ġ* ĠUpdate Ġthe Ġtext Ċĉ Ġ*/ Ċ ĉ private Ġval Ġtext Watch Ġ= Ġobject Ġ: ĠText Watcher Ġ{ Ċĉ ĉ override Ġfun Ġafter TextChanged ( s : ĠEdit able ?) Ġ{ Ċĉ ĉ } ĊĊĉ ĉ override Ġfun Ġbefore TextChanged ( s : ĠCharSequence ?, Ġstart : ĠInt , Ġcount : ĠInt , Ġafter : ĠInt ) Ġ{ Ċĉĉ ĉ highlight Task ?. cancel (" Text Ġchanged ") Ċĉĉ ĉ highlight Task Ġ= Ġnull Ċĉ ĉ } ĊĊĉ ĉ override Ġfun Ġon TextChanged ( s : ĠCharSequence ?, Ġstart : ĠInt , Ġbefore : ĠInt , Ġcount : ĠInt ) Ġ{ Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠRefresh Ġthe Ġhighlighting Ġevery Ġdelay Ġif Ġinput Ċĉ Ġ*/ Ċ ĉ private Ġval Ġdelayed Text Watch Ġ= ĠDelay ed Text Watch ( Ċĉ ĉ time Delay , Ċĉ ĉ action Ġ= Ġ{ Ċĉĉ ĉ refresh Highlight () Ċĉ ĉ }) ĊĊ ĉ /** Ċĉ Ġ* Ġtarget EditText . text Ġis Ġthe Ġeditable Ġtext Ċĉ Ġ*/ Ċ ĉ private Ġval Ġeditable : ĠEdit able Ċĉ ĉ get () Ġ= Ġtarget EditText . text ĊĊ ĉ /** Ċĉ Ġ* Ġtarget EditText Ġsetter : Ġclear Applied Styles , Ġset Ġthe Ġvalue Ġto Ġtarget EditText Ġand Ġrefresh Highlight Ċĉ Ġ*/ Ċ ĉ private Ġvar Ġtarget EditText : ĠEditText Ġ= Ġtarget EditText Ċĉ ĉ set ( value ) Ġ{ Ċĉĉ ĉ clear Applied Styles () Ċĉĉ ĉ field Ġ= Ġvalue Ċĉĉ ĉ refresh Highlight () Ċĉ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠSp ann able Highlight er Ġsetter : Ġclear Applied Styles , Ġset Ġthe Ġvalue Ġto Ġtarget EditText Ġand Ġrefresh Highlight Ċĉ Ġ*/ Ċ ĉ private Ġvar Ġsyntax Highlight er Ġ= ĠSp ann able Highlight er ( colo urs ) Ċĉ ĉ set ( value ) Ġ{ Ċĉĉ ĉ clear Applied Styles () Ċĉĉ ĉ field Ġ= Ġvalue Ċĉĉ ĉ refresh Highlight () Ċĉ ĉ } ĊĊ ĉ /** Ċĉ Ġ* Ġcurrent Ġhighlight Task Ċĉ Ġ*/ Ċ ĉ private Ġvar Ġhighlight Task : ĠJob ? Ġ= Ġnull ĊĊ ĉ /** Ċĉ Ġ* ĠLogic Ġfor Ġrefresh Highlight . ĠCancel Ġexisting Ġhighlight Task Ġjobs Ġand Ġcreate Ġa Ġnew ĠCor outine Scope Ċĉ Ġ* Ġfor Ġhighlight Task Ċĉ Ġ* Ċĉ Ġ*/ Ċ ĉ private Ġfun Ġrefresh Highlight () Ġ{ Ċĉ ĉ highlight Task ?. cancel (" Refresh ĠHighlight ") Ċĉ ĉ highlight Task Ġ= Ġnull Ċĉ ĉ highlight Task Ġ= ĠCor outine Scope ( Dispatch ers . Main ). launch Ġ{ Ċĉĉ ĉ val Ġcurrent Text Ġ= Ġeditable . toString () Ċĉĉ ĉ val Ġhighlight Entities Ġ= Ġwith Context ( Dispatch ers . Default ) Ġ{ Ċĉĉĉ ĉ syntax Highlight er . create Highlighting ( current Text ) Ċĉĉ ĉ } Ċĉĉ ĉ val Ġoriginal Ġ= Ġsyntax Highlight er . applied Styles Ċĉĉ ĉ val Ġprevious Styles Ġ= Ġmutable Set Of < Character Style >(). apply Ġ{ Ġadd All ( original ) Ġ} Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ syntax Highlight er . highlight ( editable , Ġhighlight Entities ) Ċĉĉ ĉ } Ġcatch Ġ( e : ĠIndex OutOfBoundsException ) Ġ{ Ċĉĉĉ ĉ clear Applied Styles () Ċĉĉ ĉ } Ċĉĉ ĉ remove Styles ( previous Styles ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠCall Ġto Ġsyntax Highlight er . clear Applied Styles ( editable ) Ċĉ Ġ* Ċĉ Ġ*/ Ċ ĉ private Ġfun Ġclear Applied Styles (): ĠUnit Ġ= Ġsyntax Highlight er . clear Applied Styles ( editable ) ĊĊ ĉ /** Ċĉ Ġ* ĠRemove Ġstyles Ġfrom Ġeditable Ġ( target EditText . text ) Ġand Ġremove Ġstyles Ġfrom Ġsyntax Highlight er . applied Styles Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġstyles Ċĉ Ġ*/ Ċ ĉ private Ġfun Ġremove Styles ( styles : ĠSet < Character Style >) Ġ{ Ċĉ ĉ styles . forEach Ġ{ Ċĉĉ ĉ editable . remove Span ( it ) Ċĉĉ ĉ syntax Highlight er . applied Styles . remove ( it ) Ċĉ ĉ } Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠStart Ġthe ĠText Highlight Ġfunctionality Ġas Ġapplies Ġto Ġtarget EditText Ċĉ Ġ* Ċĉ Ġ*/ Ċ ĉ open Ġfun Ġstart () Ġ{ Ċĉ ĉ target EditText . add TextChanged Listener ( delayed Text Watch ) Ċĉ ĉ target EditText . add TextChanged Listener ( text Watch ) Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠStop / end Ġthe ĠText Highlight Ġfunctionality Ġas Ġapplies Ġto Ġtarget EditText Ċĉ Ġ* Ċĉ Ġ*/ Ċ ĉ open Ġfun Ġend () Ġ{ Ċĉ ĉ target EditText . remove TextChanged Listener ( text Watch ) Ċĉ ĉ target EditText . remove TextChanged Listener ( delayed Text Watch ) Ċ ĉ } Ċ } Ċ Ċ /** Ċ Ġ* ĠDelay ed Text Watch . ĠOverride Ġthe Ġon TextChanged Ġfunction Ġto Ġapply Ġsome Ġaction Ġafter Ġa Ġtimer Ċ Ġ* Ċ Ġ* Ġ> Ġdelayed Text Watch Ġ= ĠDelay ed Text Watch ( Ċ 1 0 0 , Ċ action Ġ= Ġ{ Ċ refresh Highlight () Ċ }) Ċ Ġ* Ċ Ġ* Ġ@ property Ġtime Delay ĠLong . Ġdefault = 1 5 0 Ċ Ġ* Ġ@ property Ġaction Ġ( CharSequence ?) Ġ-> ĠUnit : Ġsome Ġcallable Ċ Ġ*/ Ċ private Ġclass ĠDelay ed Text Watch ( Ċ ĉ private Ġvar Ġtime Delay : ĠLong Ġ= Ġ 1 5 0 , Ċ ĉ val Ġaction : Ġ( CharSequence ?) Ġ-> ĠUnit Ċ ) Ġ: ĠText Watcher Ġ{ Ċ ĉ private Ġvar Ġtimer Ġ= ĠTimer () Ċ ĉ override Ġfun Ġon TextChanged ( s : ĠCharSequence ?, Ġstart : ĠInt , Ġbefore : ĠInt , Ġcount : ĠInt ) Ġ{ Ċĉ ĉ val Ġtext Ġ= Ġs ?. toString () Ġ?: Ġ"" Ċĉ ĉ timer . cancel () Ċĉ ĉ timer Ġ= ĠTimer () Ċĉ ĉ timer . schedule ( object Ġ: ĠTimer Task () Ġ{ Ċĉĉ ĉ override Ġfun Ġrun () Ġ{ Ċĉĉĉ ĉ Coroutine Scope ( Dispatch ers . Main ). launch Ġ{ Ċĉĉĉĉ ĉ action ( text ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ }, Ġtime Delay ) Ċ ĉ } ĊĊ ĉ override Ġfun Ġafter TextChanged ( s : ĠEdit able ?): ĠUnit Ġ= ĠUnit Ċ ĉ override Ġfun Ġbefore TextChanged ( s : ĠCharSequence ?, Ġstart : ĠInt , Ġcount : ĠInt , Ġafter : ĠInt ): ĠUnit Ġ= Ċĉ ĉ Unit Ċ } Ċ Ċ /** Ċ Ġ* ĠSp ann able Highlight er Ġclass Ġused Ġto Ġapply Ġrule Matches : ĠList < Rule Match > Ġto Ġa Ġsp ann able : ĠSp ann able Ċ Ġ* Ġusing Ġspecific Ġlanguage Rules Ġand Ġcolo urs Ċ Ġ*/ Ċ open Ġclass ĠSp ann able Highlight er ( Ċ ĉ private Ġval Ġcolo urs : ĠCo lo urs Ċ ) Ġ: ĠLanguage Rules () Ġ{ Ċ ĉ /** Ċĉ Ġ* Ġapplied Styles : ĠMutable Set < Character Style > Ġtracks Ġstyles Ġfor Ġa ĠSp ann able Ċĉ Ġ*/ Ċ ĉ open Ġval Ġapplied Styles : ĠMutable Set < Character Style > Ġ= Ġmutable Set Of () ĊĊ ĉ /** Ċĉ Ġ* Ġclear Applied Styles . ĠRemove Ġstyles Ġfrom Ġa ĠSp ann able Ġand Ġclear Ġthe Ġapplied Styles Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġsp ann able ĠSp ann able Ċĉ Ġ*/ Ċ ĉ internal Ġfun Ġclear Applied Styles ( span nable : ĠSp ann able ) Ġ{ Ċĉ ĉ applied Styles . forEach Ġ{ Ċĉĉ ĉ span nable . remove Span ( it ) Ċĉ ĉ } Ċĉ ĉ applied Styles . clear () Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠApply Ġsome Ġcharacter Ġstyle Ġ( eg ĠFore ground Color Span ) Ġto Ġa ĠSp ann able Ġfrom Ġa Ġstart Ġindex Ġto Ċĉ Ġ* Ġan Ġend Ġindex Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġcharacter Style ĠCharacter Style Ċĉ Ġ* Ġ@ param Ġsp ann able ĠSp ann able Ċĉ Ġ* Ġ@ param Ġstart ĠInt Ċĉ Ġ* Ġ@ param Ġend ĠInt Ċĉ Ġ*/ Ċ ĉ private Ġfun Ġapply Style ( Ċĉ ĉ character Style : ĠCharacter Style , Ċĉ ĉ span nable : ĠSp ann able , Ċĉ ĉ start : ĠInt , Ċĉ ĉ end : ĠInt Ċ ĉ ) Ġ{ Ċĉ ĉ span nable . set Span ( character Style , Ġstart , Ġend , ĠSp ann able . SPAN _ EXCL USIVE _ EXCL USIVE ) Ċĉ ĉ applied Styles . add ( character Style ) Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* Ġhighlight Ġa ĠSp ann able Ġwith Ġa Ġlist Ġof ĠRule Matches Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġsp ann able ĠSp ann able Ċĉ Ġ* Ġ@ param Ġrule Matches ĠList < Rule Match > Ċĉ Ġ*/ Ċ ĉ internal Ġsuspend Ġfun Ġhighlight ( span nable : ĠSp ann able , Ġrule Matches : ĠList < Rule Match >) Ġ{ Ċĉ ĉ coroutine Scope Ġ{ Ċĉĉ ĉ rule Matches . map Ġ{ Ċĉĉĉ ĉ async Ġ{ Ċĉĉĉĉ ĉ val Ġcharacter Style Ġ= Ġcolo urs . get Colour ( it . rule Name ) Ċĉĉĉĉ ĉ apply Style ( character Style , Ġsp ann able , Ġit . startIndex , Ġit . end Index ) Ċĉĉĉ ĉ } Ċĉĉ ĉ }. await All () Ċĉ ĉ } Ċ ĉ } Ċ } Ċ