Skip to content

Commit

Permalink
Merge branch 'main' into update/minor_major
Browse files Browse the repository at this point in the history
  • Loading branch information
rochala authored Jul 27, 2023
2 parents 79b1ae2 + 86b8bd1 commit 8693496
Show file tree
Hide file tree
Showing 32 changed files with 812 additions and 587 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ name: Build Status
on:
pull_request:
push:

env:
MUNIT_FLAKY_OK: true

jobs:
tests:
runs-on: ubuntu-latest
Expand Down
14 changes: 12 additions & 2 deletions api/src/main/scala/com.olegych.scastie.api/ApiModels.scala
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,11 @@ object CompletionInfoRequest {
implicit val completionInfoRequestFormat: OFormat[CompletionInfoRequest] = Json.format[CompletionInfoRequest]
}

case class InsertInstructions(text: String, cursorMove: Int)
case class AdditionalInsertInstructions(text: String, startLine: Int, startChar: Int, endLine: Int, endChar: Int)
case class InsertInstructions(text: String, editRange: EditRange)
case class AdditionalInsertInstructions(text: String, editRange: EditRange)
case class EditRange(startLine: Int, startChar: Int, endLine: Int, endChar: Int)

case class ScalaCompletionList(items: Set[CompletionItemDTO], isIncomplete: Boolean)

case class CompletionItemDTO(
label: String,
Expand All @@ -183,6 +186,9 @@ case class HoverDTO(from: Int, to: Int, content: String)

case class CompletionsDTO(items: Set[CompletionItemDTO])

object EditRange {
implicit val editRangeFormat: OFormat[EditRange] = Json.format[EditRange]
}

object InsertInstructions {
implicit val insertInstructionsFormat: OFormat[InsertInstructions] = Json.format[InsertInstructions]
Expand All @@ -192,6 +198,10 @@ object AdditionalInsertInstructions {
implicit val additionalInsertInstructionsFormat: OFormat[AdditionalInsertInstructions] = Json.format[AdditionalInsertInstructions]
}

object ScalaCompletionList {
implicit val completionListFormat: OFormat[ScalaCompletionList] = Json.format[ScalaCompletionList]
}

object CompletionItemDTO {
implicit val completionItemDTOFormat: OFormat[CompletionItemDTO] = Json.format[CompletionItemDTO]
}
Expand Down
2 changes: 2 additions & 0 deletions api/src/main/scala/com.olegych.scastie.api/ScalaTarget.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ sealed trait ScalaTarget {
if (digits.head == "2") digits.init.mkString(".")
else digits.head
}

def isJVMTarget = targetType == ScalaTargetType.Scala3 || targetType == ScalaTargetType.Scala2
}

object ScalaTarget {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class LoadBalancerRecoveryTest()
with BeforeAndAfterAll {

// import system.dispatcher
implicit val timeout = Timeout(10.seconds)
implicit val timeout: Timeout = Timeout(25.seconds)

test("recover from crash") {
val crash =
Expand Down Expand Up @@ -126,7 +126,7 @@ class LoadBalancerRecoveryTest()

Await.result(
(dispatchActor.ask(task)).mapTo[SnippetId],
10.seconds
15.seconds
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.olegych.scastie.client.components

import com.olegych.scastie.api._
import com.olegych.scastie.client.View
import japgolly.scalajs.react._
import org.scalajs.dom
import vdom.all._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package components

import japgolly.scalajs.react._
import org.scalajs.dom
import org.scalajs.dom.document
import org.scalajs.dom.html
import org.scalajs.dom.window

import vdom.all._


Expand Down Expand Up @@ -43,7 +41,7 @@ object LoginModal {
),
p(
"By signing in, you agree to our ",
a(href := "javascript:;", onClick ==> (e => e.stopPropagationCB >> props.openPrivacyPolicyModal))("privacy policy"),
a(href := "#", onClick ==> (e => e.preventDefaultCB >> e.stopPropagationCB >> props.openPrivacyPolicyModal))("privacy policy"),
"."
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import com.olegych.scastie.client.components.editor.EditorKeymaps
import japgolly.scalajs.react._

import vdom.all._
import extra._

final case class NewButton(
isDarkTheme: Boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.olegych.scastie.client.components
import japgolly.scalajs.react._
import scalajs.js
import vdom.all._
import com.olegych.scastie.client.components.editor.EditorKeymaps
import scala.scalajs.js.annotation.JSImport

final case class PrivacyPolicyModal(isDarkTheme: Boolean, isClosed: Boolean, close: Reusable[Callback]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package com.olegych.scastie.client
package components


import com.olegych.scastie.client.components.editor.EditorKeymaps
import japgolly.scalajs.react._
import org.scalajs.dom

import vdom.all._
import extra._


// scheduled for removal 2023-04-30
Expand Down Expand Up @@ -46,7 +44,7 @@ object PrivacyPolicyPrompt {
| whether you want to keep your existing code snippets, or remove them all from our database.
| By keeping the snippets, you acknowledge that you have read and agreed
| to the privacy policy terms available """.stripMargin.stripLineEnd,
a(href := "javascript:;", onClick ==> (e => e.stopPropagationCB >> props.openPrivacyPolicyModal))(
a(href := "#", onClick ==> (e => e.preventDefaultCB >> e.stopPropagationCB >> props.openPrivacyPolicyModal))(
"here"
),
"."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ object TopBar {
openInNewTab("https://gitter.im/scalacenter/scastie")

def issue: Callback =
openInNewTab("https://github.com/scalacenter/scastie/issues/new")
openInNewTab("https://github.com/scalacenter/scastie/issues/new/choose")

val logoutUrl = "/logout"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ object CodeEditor {
val errors = props.compilationInfos
.filter(prob => prob.line.isDefined && prob.line.get <= doc.lines)
.map(problem => {
val line = problem.line.get
val line = problem.line.get max 1
val lineInfo = doc.line(line)

Diagnostic(lineInfo.from, HTMLFormatter.format(problem.message), parseSeverity(problem.severity), lineInfo.to)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.olegych.scastie.client.components.editor

import typings.codemirrorState.mod._
import typings.codemirrorView.mod._

import scala.concurrent.duration._
import scala.scalajs.js.timers._

import scalajs.js
import EditorTextOps._


trait DebouncingCapabilities {
type OnChange = (String, EditorView) => Unit

private val onChangeFacet: Facet[OnChange, OnChange] = Facet.define[OnChange, OnChange] {
FacetConfig[OnChange, OnChange]().setCombine(input => over(input.toSeq))
}

private def debounce(fn: OnChange): OnChange = {
var timeout: js.UndefOr[js.timers.SetTimeoutHandle] = js.undefined

(code: String, view: EditorView) => {
val tokenLength = view
.lineBeforeCursor
.reverseIterator
.takeWhile(c => !c.isWhitespace || c == '.')
.length

tokenLength match {
case 0 => fn(code, view)
case _ =>
timeout.foreach(clearTimeout)
timeout = setTimeout(250.millis) {
fn(code, view)
}
}
}
}

private def over(functions: Seq[OnChange]): OnChange = {
(code: String, view: EditorView) => functions.foreach(f => f(code, view))
}

protected def onChangeCallback(onChange: OnChange): Extension = {
val debouncedOnChange = debounce(onChange)

js.Array[Any](
onChangeFacet.of(debouncedOnChange),
EditorView.updateListener.of(viewUpdate => {
if (viewUpdate.docChanged) {
val content = viewUpdate.state.sliceDoc()
val onChange = viewUpdate.state.facet[OnChange](onChangeFacet.asInstanceOf[Facet[Any, OnChange]])
onChange(content, viewUpdate.view)
}
})
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import org.scalajs.dom
import typings.codemirrorState.anon
import typings.codemirrorView.mod.EditorView
import typings.codemirrorView.mod.{KeyBinding => JSKeyBinding}
import typings.codemirrorCommands.mod._
import typings.codemirrorAutocomplete.mod.acceptCompletion
import com.olegych.scastie.client

import scalajs.js

object EditorKeymaps {
import typings.codemirrorCommands.mod._

private def presentationMode(editor: CodeEditor): Unit = {
if (!editor.isEmbedded) {
Expand All @@ -33,7 +34,7 @@ object EditorKeymaps {
def keymapping(e: CodeEditor) =
typings.codemirrorView.mod.keymap.of(
js.Array(
KeyBinding.fromCommand(insertTab, new Key("Tab")),
KeyBinding.tabKeybind,
KeyBinding(_ => e.saveOrUpdate.runNow(), saveOrUpdate, true),
KeyBinding(_ => e.saveOrUpdate.runNow(), saveOrUpdateAlt, true),
KeyBinding(_ => e.openNewSnippetModal.runNow(), openNewSnippetModal, true),
Expand Down Expand Up @@ -63,14 +64,20 @@ case class Key(default: String, linux: String, mac: String, win: String) {
}

object KeyBinding {
def fromCommand(action: typings.codemirrorState.mod.StateCommand, key: Key, preventDefault: Boolean = false): JSKeyBinding = {
val tabKeybind: JSKeyBinding = {
val key = new Key("Tab")
JSKeyBinding()
.setRun(x => action(x.asInstanceOf[anon.Dispatch]))
.setRun(dispatch =>
if (!acceptCompletion(dispatch))
insertTab(dispatch.asInstanceOf[anon.Dispatch])
else
false
)
.setKey(key.default)
.setLinux(key.linux)
.setMac(key.mac)
.setWin(key.win)
.setPreventDefault(preventDefault)
.setPreventDefault(true)
}

def apply(action: EditorView => Unit, key: Key, preventDefault: Boolean = false): JSKeyBinding = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.olegych.scastie.client.components.editor

import typings.codemirrorView.mod._


object EditorTextOps {
val regex = """\.?\w+""".r

implicit class EditorTextOpsOps(view: EditorView) {
def lineBeforeCursor: String = {
val pos = view.state.selection.main.from
val line = view.state.doc.lineAt(pos)
val start = Math.max(line.from, pos - 250)
line.text.slice(start.toInt - line.from.toInt, pos.toInt - line.from.toInt)
}

def matchesPreviousToken(previousToken: String): Boolean = {
val matchedString = regex.findAllIn(lineBeforeCursor).iterator.toSeq
matchedString.lastOption.exists(_.startsWith(previousToken))
}

}
}
Loading

0 comments on commit 8693496

Please sign in to comment.