<commit_before>module Main exposing (..)

import Autocomplete
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Html.App as Html
import String
import Json.Decode as Json


main : Program Never
main =
    Html.program
        { init = init ! []
        , update = update
        , view = view
        , subscriptions = subscriptions
        }


subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.map SetAutoState Autocomplete.subscription


type alias Model =
    { people : List Person
    , autoState : Autocomplete.State
    , howManyToShow : Int
    , query : String
    , showMenu : Bool
    }


init : Model
init =
    { people = presidents
    , autoState = Autocomplete.empty
    , howManyToShow = 5
    , query = ""
    , showMenu = True
    }


type Msg
    = SetQuery String
    | SetAutoState Autocomplete.Msg
    | Reset Bool
    | SelectPerson String
    | NoOp


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        SetQuery newQuery ->
            let
                showMenu =
                    not << List.isEmpty <| (acceptablePeople newQuery model.people)
            in
                { model | query = newQuery, showMenu = showMenu } ! []

        SetAutoState autoMsg ->
            let
                ( newState, maybeMsg ) =
                    Autocomplete.update updateConfig autoMsg model.autoState (acceptablePeople model.query model.people) model.howManyToShow

                newModel =
                    { model | autoState = newState }
            in
                case maybeMsg of
                    Nothing ->
                        newModel ! []

                    Just updateMsg ->
                        update updateMsg newModel

        Reset toTop ->
            { model
                | autoState =
                    if toTop then
                        Autocomplete.resetToFirstItem (acceptablePeople model.query model.people) updateConfig model.howManyToShow model.autoState
                    else
                        Autocomplete.resetToLastItem (acceptablePeople model.query model.people) updateConfig model.howManyToShow model.autoState
            }
                ! []

        SelectPerson id ->
            let
                meh =
                    List.filter (\person -> person.name == id) model.people
            in
                { model
                    | query =
                        List.filter (\person -> person.name == id) model.people
                            |> List.head
                            |> Maybe.withDefault (Person "" 0 "" "")
                            |> .name
                    , autoState = Autocomplete.empty
                    , showMenu = False
                }
                    ! []

        NoOp ->
            model ! []


view : Model -> Html Msg
view model =
    let
        options =
            { preventDefault = True, stopPropagation = False }

        dec =
            (Json.customDecoder keyCode
                (\code ->
                    if code == 38 || code == 40 then
                        Ok NoOp
                    else
                        Err "not handling that key"
                )
            )

        menu =
            if model.showMenu then
                [ viewMenu model ]
            else
                []
    in
        div []
            (List.append
                [ h1 [] [ text "U.S. Presidents" ]
                , input
                    [ onInput SetQuery
                    , onWithOptions "keydown" options dec
                    , value model.query
                    ]
                    []
                ]
                menu
            )


acceptablePeople : String -> List Person -> List Person
acceptablePeople query people =
    let
        lowerQuery =
            String.toLower query
    in
        List.filter (String.contains lowerQuery << String.toLower << .name) people


viewMenu : Model -> Html Msg
viewMenu model =
    div [ class "autocomplete-menu" ]
        [ Html.map SetAutoState (Autocomplete.view viewConfig model.howManyToShow model.autoState (acceptablePeople model.query model.people)) ]


updateConfig : Autocomplete.UpdateConfig Msg Person
updateConfig =
    Autocomplete.updateConfig
        { toId = .name
        , onKeyDown =
            \code maybeId ->
                if code == 38 || code == 40 then
                    Nothing
                else if code == 13 then
                    Maybe.map SelectPerson maybeId
                else
                    Just <| Reset False<commit_msg>working on mentions<commit_after>port module Main exposing (..)

import Autocomplete
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Html.App as Html
import String
import Json.Decode as Json


main : Program Never
main =
    Html.program
        { init = init ! []
        , update = update
        , view = view
        , subscriptions = subscriptions
        }


port caretPosition : (CaretPosition -> msg) -> Sub msg


subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.batch
        [ Sub.map SetAutoState Autocomplete.subscription
        , caretPosition SetCaretPosition
        ]


type alias Model =
    { people : List Person
    , autoState : Autocomplete.State
    , howManyToShow : Int
    , value : String
    , position : Position
    , query : String
    , showMenu : Bool
    , caretPos : CaretPosition
    }


type alias CaretPosition =
    { top : Int
    , left : Int
    }


type alias Position =
    Int


init : Model
init =
    { people = presidents
    , autoState = Autocomplete.empty
    , howManyToShow = 5
    , value = ""
    , position = 0
    , query = ""
    , showMenu = False
    , caretPos = { top = 0, left = 0 }
    }


type Msg
    = SetValue String
    | SetAutoState Autocomplete.Msg
    | Reset Bool
    | SelectPerson String
    | SetCaretPosition CaretPosition
    | NoOp


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        SetValue value ->
            let
                stringToPos =
                    String.slice 0 model.position model.value

                mention =
                    String.dropLeft model.position model.value

                query =
                    if String.endsWith "@" stringToPos then
                        mention
                    else
                        value

                showMenu =
                    not << List.isEmpty <| (acceptablePeople query model.people)
            in
                { model | value = value, showMenu = showMenu, query = query } ! []

        SetAutoState autoMsg ->
            let
                ( newState, maybeMsg ) =
                    Autocomplete.update updateConfig autoMsg model.autoState (acceptablePeople model.query model.people) model.howManyToShow

                newModel =
                    { model | autoState = newState }
            in
                case maybeMsg of
                    Nothing ->
                        newModel ! []

                    Just updateMsg ->
                        update updateMsg newModel

        Reset toTop ->
            { model
                | autoState =
                    if toTop then
                        Autocomplete.resetToFirstItem (acceptablePeople model.query model.people) updateConfig model.howManyToShow model.autoState
                    else
                        Autocomplete.resetToLastItem (acceptablePeople model.query model.people) updateConfig model.howManyToShow model.autoState
            }
                ! []

        SelectPerson id ->
            let
                meh =
                    List.filter (\person -> person.name == id) model.people
            in
                { model
                    | query =
                        List.filter (\person -> person.name == id) model.people
                            |> List.head
                            |> Maybe.withDefault (Person "" 0 "" "")
                            |> .name
                    , autoState = Autocomplete.empty
                    , showMenu = False
                }
                    ! []

        SetCaretPosition pos ->
            { model | caretPos = pos } ! []

        NoOp ->
            model ! []


view : Model -> Html Msg
view model =
    let
        options =
            { preventDefault = True, stopPropagation = False }

        dec =
            (Json.customDecoder keyCode
                (\code ->
                    if code == 38 || code == 40 then
                        Ok NoOp
                    else
                        Err "not handling that key"
                )
            )

        menu =
            if model.showMenu then
                [ viewMenu model ]
            else
                []
    in
        div []
            (List.append
                [ h1 [] [ text "U.S. Presidents" ]
                , viewEditor model
                ]
                menu
            )


viewEditor model =
    textarea
        [ onInput SetValue
          -- , onWithOptions "keydown" options dec
        , value model.value
        ]
        []


acceptablePeople : String -> List Person -> List Person
acceptablePeople query people =
    let
        lowerQuery =
            String.toLower query
    in
        List.filter (String.contains lowerQuery << String.toLower << .name) people


viewMenu : Model -> Html Msg
viewMenu model =
    div [ class "autocomplete-menu" ]
        [ Html.map SetAutoState (Autocomplete.view viewConfig model.howManyToShow model.autoState (acceptablePeople model.query model.people)) ]


updateConfig : Autocomplete.UpdateConfig Msg Person
updateConfig =
    Autocomplete.updateConfig
        { toId = .name
        , onKeyDown =
            \code maybeId ->
                if code == 38 || code == 40 then
                    Nothing
                else if code == 13 then
                    Maybe.map SelectPerson maybeId
                else
                    Just <| Reset False
{'fraction_non_alphanumeric': 0.07233326736592123, 'fraction_numerical': 0.002968533544429052, 'mean_word_length': 1.2242517605633803, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7298038', 'n_tokens_mistral': 2594, 'n_tokens_neox': 2354, 'n_words': 686}