Multiline text fields and the newline character

60 views
Skip to first unread message

Tim hobbs

unread,
Dec 3, 2013, 3:51:27 PM12/3/13
to elm-d...@googlegroups.com
Hey,
I have a pull request waiting for review https://github.com/evancz/Elm/pull/358 that adds support for multi-line fields.  I have one question though, should it automatically convert "\n\r" to "\n" and back http://stackoverflow.com/questions/10030921/chrome-counts-characters-wrong-in-textarea-with-maxlength-attribute?  It seems to me that it should, but I really don't feel like the worlds expert on this problem so I'm throwing it to the bike shed committee.

Thanks,
Tim

Max Goldstein

unread,
Dec 3, 2013, 5:18:16 PM12/3/13
to elm-d...@googlegroups.com
I vote for automatic conversion. In my experience, '\n' is pretty standard but '\r' is barely mentioned. I think it's a holdover from typewriters - move the paper up and return the carriage - so I see no reason to burden the programmer with it.

A properly abstracted type might be Signal [String], bypassing '\n' as well.

Tim hobbs

unread,
Dec 4, 2013, 4:31:05 AM12/4/13
to elm-d...@googlegroups.com
I think that the [String] abstraction is definitely a good idea, indeed, it would be nice to make the selection start and ends take line and column numbers as well.  I presume if the user set the field text to ["foo\nbar\n\rtag","log baz"] they would end up with a Signal ["foo","bar","tag","log baz"], which would make the fieldMultiline function not work as an 'id' function(making it harder to tell if text had changed).

There is a nice thing about having multiline fields use a FieldState, just like single line ones do.  Which is that switching between the two is really easy.  These two problems lead me to think that providing the user with a single String and then making them preform 'lines' and 'unlines' manually is more reasonable, it is more compatible with single line fields and it provides more guarantees.

I propose that we change FieldState to

type FieldState = {string:String, selectionStart:CursorPosition, selectionEnd:CursorPosition}

data CursorPosition
 = Absolute Int
 |  LineColumn {line:Int,column:Int}

{-| Return the absolute selection start position in the text. -}
absoluteStartPosition: FieldState -> Int

{-| Return the absolute selection end position in the text. -}
absoluteEndPosition: FieldState -> Int

{-| Return the line column selection start position in the text -}
lineColumnStartPosition: FieldState -> {line:Int,column:Int}

{-| Return the line column selection end position in the text -}
lineColumnEndPosition: FieldState -> {line:Int,column:Int}

Tim

Max Goldstein

unread,
Dec 4, 2013, 8:55:53 AM12/4/13
to elm-d...@googlegroups.com
I like using the existing FieldState record, but if single line fields always have Absolute, and multiline fields always have LineColumn, then it's really two different records and you burden the user with information-less pattern matching. Might as well declare {line:Int,column:Int} as a type and use that in both cases. It makes it marginally easier for the single line field users to ignore the still-information-less line, you only define one new container, and the second two functions can be eliminated.
Reply all
Reply to author
Forward
0 new messages