-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Leaf Projectors #1218
Leaf Projectors #1218
Conversation
…rily disabled scroll to caret
… disabled for now
…was used only by backpark targets. new 'segment' is now what was previously called 'unselected'
…ind of nasty though may need an alternate approach
/* Projector model and action are serialized so that | ||
* they may be used by the Editor without it having | ||
* specialized knowledge of projector internals */ | ||
type serialized_model = string; | ||
type serialized_action = string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the Cook functor solution and am weighing up whether it might have applications to UI
@@ -12,3 +16,115 @@ let div_if = (p, ats, ns) => p ? div(~attrs=[ats], ns) : div_empty; | |||
let span_if = (p, ats, ns) => p ? span(~attrs=[ats], ns) : span([]); | |||
|
|||
let unless = (p, a) => p ? Effect.Many([]) : a; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
personally these feel like view/Widgets.re
things to me instead of util/Web.re
things
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, i forgot about Widgets. maybe we should just combine these modules? do you see a distinction between them? right now i can't just move things to Widgets as it's in web (renegotiating what goes where is likely going to be an ongoing process now that the core/web division is changing)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me web is just like wrappers around html things and widgets has more hazel-specific logic and styles etc - maybe we move widgets to util/Widgets.re if it can't be in web? (I still find it a little concerning that we need an html definition of a slider in core)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had some similar issues on my livelits branch. I struggle to see how the projectors can be web (platform) agnostic. So unless they're entirely configured in web I don't know how you'd excise the dependency from core.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Negabinary i started to move widgets but looking at it the current arrangement makes sense to me. the range and TextArea components i defined in web are intended to be completely independent from hazel logic. all of the textarea logic is just to get and set text area ui state; it could all be in vdom in-principle. otoh current widgets are all related to hazel UI chrome outside the syntax-editor as such. so these modules are disjoint along two different dimensions. admittedly thats not well-reflected in the naming
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@7h3kk1d contemplating this resulted in a tweet: https://twitter.com/disconcision/status/1818812875411968085
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(via the tangent "what does it mean to be truly view independent?" => "let's take string out of Core" => "let's string out")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TextArea has some weird behaviour when you type a speech mark into it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just to confirm that you're seeing the same weirdness: quote characters get inserted fine in the textarea, but these actions are not reflected in the underlying syntax? (this also means the shape of the textarea doesn't expand for quotes) or are you seeing something above and beyond that?
i knew about this one but was ignoring it as i don't totally understand how to address it in a principled way. the way regular string literals work in the underyling syntax model is a bit ad-hoc; quotes have special-case behavior relative to all other characters. briefly: inserting a quote must automatically insert a closing quote; otherwise the text serialization of that code state has an ambiguous lexing. but we don't want to prevent someone from just typing an empty string normally. the solution we ended up with is that typing a quote inside a string simply moves the caret to the end of the string. not pretty but in practice seems to work fine. of course ultimately we want escaped characters in strings, but ideally this will all be handled at the core syntax layer.
could add some textarea-projector-specific code that catches keystrokes, suppresses quotes, and the refires the event to the textarea i guess. implementing the string livelit with the DOM textarea is likely more trouble than it's worth, but i wanted to do this as a trial run for embedding non-hazel-native components...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah same weirdness! Hazel afaik doesn't have any quote escape mechanism so in terms of the underlying syntax the best thing is probably just to suppress quotes for now if that's straightforward enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, suppressing quotes for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks and feels great overall.
Only bug I can find is that when the projectors panel is disabled you can still click the grayed out button (and it seems to do some sort of folding):
Other notes in addition to a few inline comments in the code:
- The copy-and-paste and undo issues you indicate as a wontfix for this PR, which I am okay with for now, but that I don't want to leave hanging too long. What is your plan for those?
- The first scratch slide now has a bunch of projectors stuff in it, which should instead be under Documentation.
- I was expecting to be able to fold when my cursor was on something like an ap, e.g. in the example above, where it would fold the entire highlighted term, but I guess that's related to the parenthesization issue that we're going to fix later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: module naming in util is inconsistent, some end in Util and others don't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the pattern matt has now established of importing util modules in Util so you can just refer to them as e.g. Util.Web; I think going forward we should migrate away from Util in the filename.
src/haz3lweb/dune
Outdated
(write-file js-of-ocaml-flags-dev "(:standard)")) | ||
(write-file | ||
js-of-ocaml-flags-dev | ||
"(:standard --debug-info --no-inline --pretty --source-map)")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this change the dev experience meaningfully?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not afaict. but it does make the flags the same across all our build targets, and the same as david's setup, so at least it eliminates that potential source of confusion
@@ -2,8 +2,8 @@ open Util; | |||
|
|||
[@deriving (show({with_path: false}), sexp, yojson)] | |||
type buffer = | |||
| Unparsed | |||
| Parsed; | |||
//| Parsed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's going on here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an artefact of separating the original TyDi implementation from the llm completion stuff. The parsed buffer option is currently meaningless so I just removed it until the LLM stuff is reimplemented
commenting to remind myself about the slider keyboard input focus issue |
I've been hoping inspiration will strike for a simple approach to copy/paste. The options seem to be: Implement some kind of synchronization between an internal (segment) buffer and the browser copy/paste actions. This is probably not too bad, but I'm also just not totally sure if it's going to work seamlessly syntax-wise. Reinserting a segment as a selection should work (it's how pickup/putdown used to work), but i'm wary against since-then baked in assumptions around adding incomplete syntax. At the very least paste has to be able to replace UUIDs. Hopefully not that bad but it's not something I want to get bogged down in atm. The other option is implementing some kind of attributes system, and use those to represent projectors in the text representation. This requires some more planning, and would be natural to implement at the same time as text-based livelit invocation (not currently on my agenda, but would likely do at some point). Ofc this latter option doesnt have the advantage. |
…on keyboard actions. supress textarea DOM undo/redo for now. don't record projector focus etc actions in history.
@cyrus- et al: all issues addressed I think. function applications don't try to project now (greyed-out toggle should be in-sync).
|
@disconcision tab-completing let/if/etc. doesn't work still, what's the issue there? Also we talked about connecting error marks with the lines so it doesn't look like there are multiple errors, did you decide against that or just not done? |
planning to fix both just taking longer than id like |
@cyrus- all issues addressed. in particular, tab completions of definitions is fixed, and error holes now have child lines. |
@cyrus- technically that's already there for the term decorations, you just can't see if because the term shards are opaque. I looked briefly but I don't really know how to address it in the current approach to line drawing |
@disconcision maybe make the error shards opaque as well to avoid the issue for now and @dm0n3y can take a look in the next revision of the decorations? |
@cyrus- i've addressed the error hole thing in summer-refresh; tedious to replicate here as the css is completely different. i've made the background color of the error holes the same color as the code background + the red overlay, so it looks the same. the cost is that this means we need to either move the error holes behind selections or it looks super funky. but that's not a huge issue i think |
Overview
This PR is intended to start (but not finish) a system for flexible projectional code-editing UI. Right now, the system should be sufficient to serve as the basis for non-splicing livelits, type hold inference UI, hiding parts of code in live views (e.g. function bodies), and at least a basic form of module collapsing. Both inline and block (multiline) GUIs are supported, though there is only a single reference implementation for the latter (
TextAreaCore
), so some details might not have ended up on the right side of the projector server / projector client divide. I want to support a range of use cases so I'm solicited feedback on the flexibility of the interface.Getting Started
Documentation/Projectors
slide in the editor for a functional overviewProjectorBase.Projector
ProjectorBase
,Projector
,ProjectorPerform
, andProjectorView
Zipper
intoZipperBase
Action.t
FoldCore
,InfoCore
,CheckboxCore
,SliderCore
,SliderFCore
, andTextAreaCore
.How the projector system interacts with the parent editor
Piece.t
type,Projector(Base.projector_kind)
, which stores a record entry specifying the kind of projector, the syntax itself, and an optional serialized model for internal projector state. Projectors have an associated UUID which is set to that of their wrapped syntax. When their wrapped syntax is transformed, the id for that syntax is reset to the projector id to retain sync. (This is mostly an implementation detail; a convenience to retain an association between a projector and the id-tracked semantic information if its wrapped syntax)kind
is hydrated into a first class projector module of type ProjectorBase.Projector, whose various methods determine all projector-specific logic. Projector views have access to certain information fed to them by their parent editor, including their underlying syntax and staticInfo
entry (later: dynamic info). Views are also provided with callbacks for both local (kind-specific) actions and parent editor requests.Caveats and Wontfixes
Adding a new kind of projector
ProjectorBase.Projector
(or copy e.g.FoldCore
)Base.projector_kind
(used for adding/removing/updating)Projector.to_module
Fold
inKeyboard
ProjectorView.name
,ProjectorView.of_name
, andProjectorView.Panel.applicable_projectors
SetIndicated
andRemove
actions inProjectorPerform
for how to manually add/remove projectors from an editorOther changes made in this PR
TODO(andrews)