Home > Back-end >  how to handle new line in word count?
how to handle new line in word count?

Time:03-08

i'm referring this answer https://stackoverflow.com/a/42802060/12428090

basically my goal is to handle word count of 100 words the abve solution works fine for typed 100 words and even handles copy paste very well

but it doesnt handles the new line case suppose in entered word or copy pasted word contains new line then the word count is returning incorrect

following is the code please help out

    override fun onTextChanged(s: CharSequence, start: Int, before: Int, 
       count: Int) {
    val wordsLength: Int = countWords(s.toString()) // words.length;
    limitmoderator.text = "$wordsLength/$MAX_WORDS"
    val yourText: String =
        moderator_intro.getText().toString().replace(160.toChar().toString(), " ")
    if (yourText.split("\\s ".toRegex()).size > MAX_WORDS) {
        var space = 0
        var length = 0
        for (i in 0 until yourText.length) {
            if (yourText[i] == ' ') {
                space  
                if (space >= MAX_WORDS) {
                    length = i
                    break
                }
            }
        }
        if (length > 1) {
            moderator_intro.getText()
                .delete(length, yourText.length) // deleting last exceeded words
            setCharLimit(moderator_intro, length - 1) //limit edit text
        }
    } else {
        removeFilter(moderator_intro)
    }}


 private fun countWords(s: String): Int {
 val trim = s.trim()
 return if (trim.isEmpty()) 0 else trim.split("\\s ".toRegex()).size
 // separate string around spaces
    }

    private var filter: InputFilter? = null

    private fun setCharLimit(et: EditText, max: Int) {
filter = LengthFilter(max)
et.filters = arrayOf<InputFilter>(filter as LengthFilter)
     }

    private fun removeFilter(et: EditText) {
    if (filter != null) {
    et.filters = arrayOfNulls(0)
     filter = null
      }
    }
       

so i have tried rplacing the "\n" in the text but it doesnt seems to be handling the case properly

any help will be appreciated

please help

thanks in advance

CodePudding user response:

Here's a different strategy than the one from the question you linked. Notice I'm using afterTextChanged and not onTextChanged!

I'm manually counting words to get the character index of the first whitespace after the last allowable word. That way I don't have to trim and then use Regex, and then try to figure out the index offset of that Regex. Then instead of applying a temporary filter, I directly cut the end of the Editable off.

editText.setSelection is to keep the cursor from jumping to the beginning.

override fun afterTextChanged(s: Editable) {
    var previousWasWhitespace = true
    var i = 0
    var wordCount = 0
    for (c in s) {
        val whitespace = c.isWhitespace()
        if (whitespace && !previousWasWhitespace &&   wordCount == MAX_WORDS) {
            break
        }
        previousWasWhitespace = whitespace
        i  
    }

    if (i < s.length) {
        s.delete(i, s.length)
        editText.setSelection(i)
    }
}

CodePudding user response:

You could write a regular expression to match the text that you want to keep and remove the rest. In this case you want match (non-whitespace )(whitespace*) maximum 100 times.

override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
  val input = moderator_intro.getText().toString()
  val maxWords = 100
  val whiteSpace = "\\p{javaWhitespace}\u00A0\u2007\u202F" //All white space characters
  val keepRegex = Regex("[$whiteSpace]*([^$whiteSpace] [$whiteSpace]*){1,${maxWords.toString()}}")
  val allowedText = keepRegex.find(input)?.value ?: ""
  val wordAmount = allowedText.split(Regex("[$whiteSpace] ")).filter { it.isNotBlank() }.size
  
  val trailingWhiteSpace = Regex("[$whiteSpace] $")
  if(wordAmount == maxWords && allowedText.contains(trailingWhiteSpace)) {
    val newText = allowedText.replace(trailingWhiteSpace, "")
    moderator_intro.getText().delete(allowedText.length, input.length)
    setCharLimit(moderator_intro, newText.length)
  } else {
    removeFilter(moderator_intro)
  }
}
  • Related