<commit_before>module Unison.Editor where

import Debug
import Execute
import Elmz.Json.Request as JR
import Elmz.Layout (Containment(Inside,Outside), Layout, Pt, Region)
import Elmz.Layout as Layout
import Elmz.Moore (Moore(..))
import Elmz.Moore as Moore
import Elmz.Movement as Movement
import Elmz.Selection1D as Selection1D
import Elmz.Signal as Signals
import Graphics.Element (Element)
import Graphics.Element as Element
import Graphics.Input.Field as Field
import Maybe
import Mouse
import Keyboard
import Result
import Signal
import Unison.Action as Action
import Unison.Explorer as Explorer
import Unison.EditableTerm as EditableTerm
import Unison.SearchboxParser as SearchboxParser
import Unison.Hash (Hash)
import Unison.Metadata (Metadata)
import Unison.Metadata as Metadata
import Unison.Node as Node
import Unison.Path (Path)
import Unison.Path as Path
import Unison.Reference (Reference)
import Unison.Reference as Reference
import Unison.Scope as Scope
import Unison.Styles as Styles
import Unison.Term (Term)
import Unison.Term as Term
import Unison.TermExplorer as TermExplorer
import Unison.Terms as Terms
import Unison.Type (Type)
import Unison.Type as Type
import Unison.Var as Var
import Unison.View as View
import Window

type Event
  = Act Action.Action
  | Click (Int,Int)
  | Delete
  | Enter
  | EvaluationResults (List { path : Path, old : Term, new : Term }) -- todo, but can put this off
  | FieldContent Field.Content
  | LocalInfoResults Node.LocalInfo
  | Mouse (Int,Int)
  | Movement Movement.D2
  | Preapply
  | Replace { path : Path, old : Term, new : Term }
  | SearchResults Node.SearchResults
  | MetadataResults (List (Reference.Key, Metadata))
  | ViewToggle

type Request
  = ExplorerRequest TermExplorer.Request
  | EditRequest TermExplorer.LocalFocus Action.Action
  | Declare Term
  | Evaluations (List (Path, Term))
  | Metadatas (List Reference)

type alias In = { event : Maybe Event, availableWidth : Int, topLeft : (Int,Int) }
type alias Out = { term : Term, view : Element, request : Maybe Request }

type alias Model = Moore In Out
type alias Sink a = a -> Signal.Message

moveDown : In -> In
moveDown i = { i | event <- Just (Movement (Movement.D2 Movement.Zero Movement.Negative)) }

model : Sink Field.Content -> Term -> Model
model sink term0 =
  let
    offset term e = case Moore.extract term |> .selection of
      Nothing -> Element.empty
      Just region -> Styles.padNW (region.topLeft.x - Styles.selectionBorderWidth) (region.topLeft.y + region.height) e
    explorerXY term (x,y) = case Moore.extract term |> .selection of
      Nothing -> (x,y)
      Just region -> (x - region.topLeft.x - Styles.selectionBorderWidth, y - (region.topLeft.y + region.height))
    out term explorer =
      { term = Moore.extract term |> .term
      , view = Element.layers [ Moore.extract term |> .layout |> Layout.element
                              , offset term (Moore.extract explorer |> .view) ]
      , request = Maybe.map ExplorerRequest (Moore.extract explorer |> .request) }
    toOpen pt w mds term explorer scope =
      let
        focus = TermExplorer.localFocus scope.focus (Moore.extract term |> .term)
        env = { availableWidth = 500 -- could also compute based on term available width
              , metadata = Moore.extract mds
              , overrides = always Nothing
              , raw = Nothing }
        ex = Moore.feed explorer (TermExplorer.Open env focus Field.noContent)
        term' = Moore.feed term { event = Nothing, explorerOpen = True
                                , availableWidth = w, metadata = env.metadata, topLeft = pt }
        o = let r = out term' ex in { r | request <- Maybe.map ExplorerRequest (Moore.extract ex |> .request) }
      in
        Moore o (exploreropen mds term' ex)

    feedX pt w md m e = Moore.feed m { event = Just e, explorerOpen = False, availableWidth = w, metadata = md, topLeft = pt }
    stepX pt w md m e = Moore.step m { event = Just e, explorerOpen = False, availableWidth = w, metadata = md, topLeft = pt }

    explorerclosed mds term explorer e = case (e.event, e.availableWidth, Moore.extract mds) of
      (Nothing,w,md) -> Maybe.map
        (\term -> Moore (out term explorer) (explorerclosed mds term explorer))
        (Moore.step term { event = Nothing, explorerOpen = False, availableWidth = w, metadata = md, topLeft = e.topLeft })
      (Just event,w,md) -> case event of
        -- these trigger a state change
        Click xy -> case feedX e.topLeft w md term (EditableTerm.Mouse xy) of
          term -> (Moore.extract term |> .scope) `Maybe.andThen` \scope -> Just (toOpen e.topLeft w mds term explorer scope)
        Enter -> (Moore.extract term |> .scope) `Maybe.andThen` \scope -> Just (toOpen e.topLeft w mds term explorer scope)
        -- these dont
        Mouse xy -> stepX e.topLeft w md term (EditableTerm.Mouse xy) `Maybe.andThen` \term ->
          Just <| Moore (out term explorer) (explorerclosed mds term explorer)
        Movement d2 -> stepX e.topLeft w md term (EditableTerm.Movement d2) `Maybe.andThen` \term ->
          Just <| Moore (out term explorer) (explorerclosed mds term explorer)
        Preapply -> stepX e.topLeft w md term (EditableTerm.Modify (Term.App Term.Blank)) `Maybe.andThen` \term ->
          Moore (out term explorer) (explorerclosed mds term explorer)
          `Moore.feed` moveDown e -- moves cursor to point to newly created blank
          |> Just
        Replace r -> stepX e.topLeft w md term (EditableTerm.Replace r) `Maybe.andThen` \term ->
          Just <| Moore (out term explorer) (explorerclosed mds term explorer)
        MetadataResults refs -> case Moore.feed mds refs of
          mds -> Just <| Moore (out term explorer) (explorerclosed mds term explorer)
        Act action -> (Moore.extract term |> .scope) `Maybe.andThen` \scope ->
          let
            focus = TermExplorer.localFocus scope.focus (Moore.extract term |> .term)
            r = out term explorer
            o = { r | request <- Just (EditRequest focus action) }
          in
            Just <| Moore o (explorerclosed mds term explorer)
        _ -> Nothing

    ex0 = TermExplorer.model sink
    tryAccept pt w mds term explorer = explorer `Maybe.andThen`
      \explorer -> case Moore.extract explorer |> .selection of
        Nothing -> Just <| Moore (out term explorer) (exploreropen mds term explorer)
        Just (loc,replacement) ->
          let term' = Moore.feed term { event = Just (EditableTerm.Modify (always replacement))
                                      , explorerOpen = True
                                      , availableWidth = w
                                      , metadata = Moore.extract mds
                                      , topLeft = pt }
          in Just <| Moore (out term' explorer) (explorerclosed mds term' ex0)

    exploreropen mds term explorer e = case (e.event,e.availableWidth) of
      (Nothing,w) -> Maybe.map
        (\term -> Moore (out term explorer) (exploreropen mds term explorer))
        (Moore.step term { event = Nothing, explorerOpen = True
                         , availableWidth = w, metadata = Moore.extract mds, topLeft = e.topLeft })
      (Just event,w) -> case event of
        -- these can trigger a state change
        Click xy ->
          let (x,y) = explorerXY term xy
              eview = Moore.extract explorer |> .view
          in if x < 0 || y < 0 || x > Element.widthOf eview || y > Element.heightOf eview
             then Just <| Moore (out term ex0) (explorerclosed mds term ex0)
             else tryAccept e.topLeft w mds term (Moore.step explorer (TermExplorer.Click (x,y)))
        Enter -> tryAccept e.topLeft w mds term (Moore.step explorer TermExplorer.Enter)
        FieldContent content -> tryAccept e.topLeft w mds term (Moore.step explorer (TermExplorer.FieldContent content))
        -- these cannot
        Mouse xy ->
          let xy' = explorerXY term xy<commit_msg>enter cancels if no valid completions in explorer<commit_after>module Unison.Editor where

import Debug
import Execute
import Elmz.Json.Request as JR
import Elmz.Layout (Containment(Inside,Outside), Layout, Pt, Region)
import Elmz.Layout as Layout
import Elmz.Moore (Moore(..))
import Elmz.Moore as Moore
import Elmz.Movement as Movement
import Elmz.Selection1D as Selection1D
import Elmz.Signal as Signals
import Graphics.Element (Element)
import Graphics.Element as Element
import Graphics.Input.Field as Field
import Maybe
import Mouse
import Keyboard
import Result
import Signal
import Unison.Action as Action
import Unison.Explorer as Explorer
import Unison.EditableTerm as EditableTerm
import Unison.SearchboxParser as SearchboxParser
import Unison.Hash (Hash)
import Unison.Metadata (Metadata)
import Unison.Metadata as Metadata
import Unison.Node as Node
import Unison.Path (Path)
import Unison.Path as Path
import Unison.Reference (Reference)
import Unison.Reference as Reference
import Unison.Scope as Scope
import Unison.Styles as Styles
import Unison.Term (Term)
import Unison.Term as Term
import Unison.TermExplorer as TermExplorer
import Unison.Terms as Terms
import Unison.Type (Type)
import Unison.Type as Type
import Unison.Var as Var
import Unison.View as View
import Window

type Event
  = Act Action.Action
  | Click (Int,Int)
  | Delete
  | Enter
  | EvaluationResults (List { path : Path, old : Term, new : Term }) -- todo, but can put this off
  | FieldContent Field.Content
  | LocalInfoResults Node.LocalInfo
  | Mouse (Int,Int)
  | Movement Movement.D2
  | Preapply
  | Replace { path : Path, old : Term, new : Term }
  | SearchResults Node.SearchResults
  | MetadataResults (List (Reference.Key, Metadata))
  | ViewToggle

type Request
  = ExplorerRequest TermExplorer.Request
  | EditRequest TermExplorer.LocalFocus Action.Action
  | Declare Term
  | Evaluations (List (Path, Term))
  | Metadatas (List Reference)

type alias In = { event : Maybe Event, availableWidth : Int, topLeft : (Int,Int) }
type alias Out = { term : Term, view : Element, request : Maybe Request }

type alias Model = Moore In Out
type alias Sink a = a -> Signal.Message

moveDown : In -> In
moveDown i = { i | event <- Just (Movement (Movement.D2 Movement.Zero Movement.Negative)) }

model : Sink Field.Content -> Term -> Model
model sink term0 =
  let
    offset term e = case Moore.extract term |> .selection of
      Nothing -> Element.empty
      Just region -> Styles.padNW (region.topLeft.x - Styles.selectionBorderWidth) (region.topLeft.y + region.height) e
    explorerXY term (x,y) = case Moore.extract term |> .selection of
      Nothing -> (x,y)
      Just region -> (x - region.topLeft.x - Styles.selectionBorderWidth, y - (region.topLeft.y + region.height))
    out term explorer =
      { term = Moore.extract term |> .term
      , view = Element.layers [ Moore.extract term |> .layout |> Layout.element
                              , offset term (Moore.extract explorer |> .view) ]
      , request = Maybe.map ExplorerRequest (Moore.extract explorer |> .request) }
    toOpen pt w mds term explorer scope =
      let
        focus = TermExplorer.localFocus scope.focus (Moore.extract term |> .term)
        env = { availableWidth = 500 -- could also compute based on term available width
              , metadata = Moore.extract mds
              , overrides = always Nothing
              , raw = Nothing }
        ex = Moore.feed explorer (TermExplorer.Open env focus Field.noContent)
        term' = Moore.feed term { event = Nothing, explorerOpen = True
                                , availableWidth = w, metadata = env.metadata, topLeft = pt }
        o = let r = out term' ex in { r | request <- Maybe.map ExplorerRequest (Moore.extract ex |> .request) }
      in
        Moore o (exploreropen mds term' ex)

    feedX pt w md m e = Moore.feed m { event = Just e, explorerOpen = False, availableWidth = w, metadata = md, topLeft = pt }
    stepX pt w md m e = Moore.step m { event = Just e, explorerOpen = False, availableWidth = w, metadata = md, topLeft = pt }

    explorerclosed mds term explorer e = case (e.event, e.availableWidth, Moore.extract mds) of
      (Nothing,w,md) -> Maybe.map
        (\term -> Moore (out term explorer) (explorerclosed mds term explorer))
        (Moore.step term { event = Nothing, explorerOpen = False, availableWidth = w, metadata = md, topLeft = e.topLeft })
      (Just event,w,md) -> case event of
        -- these trigger a state change
        Click xy -> case feedX e.topLeft w md term (EditableTerm.Mouse xy) of
          term -> (Moore.extract term |> .scope) `Maybe.andThen` \scope -> Just (toOpen e.topLeft w mds term explorer scope)
        Enter -> (Moore.extract term |> .scope) `Maybe.andThen` \scope -> Just (toOpen e.topLeft w mds term explorer scope)
        -- these dont
        Mouse xy -> stepX e.topLeft w md term (EditableTerm.Mouse xy) `Maybe.andThen` \term ->
          Just <| Moore (out term explorer) (explorerclosed mds term explorer)
        Movement d2 -> stepX e.topLeft w md term (EditableTerm.Movement d2) `Maybe.andThen` \term ->
          Just <| Moore (out term explorer) (explorerclosed mds term explorer)
        Preapply -> stepX e.topLeft w md term (EditableTerm.Modify (Term.App Term.Blank)) `Maybe.andThen` \term ->
          Moore (out term explorer) (explorerclosed mds term explorer)
          `Moore.feed` moveDown e -- moves cursor to point to newly created blank
          |> Just
        Replace r -> stepX e.topLeft w md term (EditableTerm.Replace r) `Maybe.andThen` \term ->
          Just <| Moore (out term explorer) (explorerclosed mds term explorer)
        MetadataResults refs -> case Moore.feed mds refs of
          mds -> Just <| Moore (out term explorer) (explorerclosed mds term explorer)
        Act action -> (Moore.extract term |> .scope) `Maybe.andThen` \scope ->
          let
            focus = TermExplorer.localFocus scope.focus (Moore.extract term |> .term)
            r = out term explorer
            o = { r | request <- Just (EditRequest focus action) }
          in
            Just <| Moore o (explorerclosed mds term explorer)
        _ -> Nothing

    ex0 = TermExplorer.model sink
    tryAccept pt w mds term explorer = explorer `Maybe.andThen`
      \explorer -> case Moore.extract explorer |> .selection of
        Nothing -> Just <| Moore (out term explorer) (exploreropen mds term explorer)
        Just (loc,replacement) ->
          let term' = Moore.feed term { event = Just (EditableTerm.Modify (always replacement))
                                      , explorerOpen = True
                                      , availableWidth = w
                                      , metadata = Moore.extract mds
                                      , topLeft = pt }
          in Just <| Moore (out term' explorer) (explorerclosed mds term' ex0)

    exploreropen mds term explorer e = case (e.event,e.availableWidth) of
      (Nothing,w) -> Maybe.map
        (\term -> Moore (out term explorer) (exploreropen mds term explorer))
        (Moore.step term { event = Nothing, explorerOpen = True
                         , availableWidth = w, metadata = Moore.extract mds, topLeft = e.topLeft })
      (Just event,w) -> case event of
        -- these can trigger a state change
        Click xy ->
          let (x,y) = explorerXY term xy
              eview = Moore.extract explorer |> .view
          in if x < 0 || y < 0 || x > Element.widthOf eview || y > Element.heightOf eview
             then Just <| Moore (out term ex0) (explorerclosed mds term ex0)
             else tryAccept e.topLeft w mds term (Moore.step explorer (TermExplorer.Click (x,y)))
        Enter -> case Moore.feed explorer TermExplorer.Enter of
          explorer -> case Moore.extract explorer |> .selection of
            -- treat Enter as a cancel event if no valid selection
            Nothing -> Just <| Moore (out term ex0) (explorerclosed mds term ex0)
            Just _ -> tryAccept e.topLeft w mds term (Just explorer)
        FieldContent content ->
          tryAccept e.topLeft w mds term (Moore.step explorer (TermExplorer.FieldContent content))
        -- these cannot
        Mouse xy ->
          let xy' = explorerXY term xy
{'fraction_non_alphanumeric': 0.09155884165126309, 'fraction_numerical': 0.0020948860135551447, 'mean_word_length': 2.569606333846492, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 121, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6931989', 'n_tokens_mistral': 4750, 'n_tokens_neox': 4573, 'n_words': 1699}