All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.interactive.InteractiveSamples.kt Maven / Gradle / Ivy

There is a newer version: 0.0.88
Show newest version
package pl.mareklangiewicz.interactive

import pl.mareklangiewicz.annotations.DelicateApi
import pl.mareklangiewicz.annotations.NotPortableApi
import pl.mareklangiewicz.bad.bad
import pl.mareklangiewicz.bad.chkEq
import pl.mareklangiewicz.kground.io.UFileSys
import pl.mareklangiewicz.kground.io.implictx
import pl.mareklangiewicz.kground.io.pathToTmpNotes
import pl.mareklangiewicz.kommand.Kommand
import pl.mareklangiewicz.kommand.ReducedScript
import pl.mareklangiewicz.kommand.XClipSelection
import pl.mareklangiewicz.kommand.ax
import pl.mareklangiewicz.kommand.ideOrGVimOpen
import pl.mareklangiewicz.kommand.lineRawOrNull
import pl.mareklangiewicz.kommand.samples.*
import pl.mareklangiewicz.kommand.writeFileWithDD
import pl.mareklangiewicz.kommand.xclipOut
import pl.mareklangiewicz.ulog.ULog
import pl.mareklangiewicz.ulog.i
import pl.mareklangiewicz.ulog.implictx
import pl.mareklangiewicz.ure.*
import pl.mareklangiewicz.ureflect.getReflectCallOrNull
import pl.mareklangiewicz.usubmit.USubmit
import pl.mareklangiewicz.usubmit.implictx
import pl.mareklangiewicz.usubmit.xd.askIf


/**
 * @param reference Either "xclip", or reference in format like from IntelliJ:CopyReference action.
 *   For example, "pl.mareklangiewicz.kommand.demo.MyDemoSamples#getBtop"
 */
@NotPortableApi
@DelicateApi("API for manual interactive experimentation. Conditionally skips")
suspend fun tryInteractivelySomethingRef(reference: String = "xclip") {
  val log = implictx()
  log.i("tryInteractivelySomethingRef(\"$reference\")")
  val ref = if (reference == "xclip")
    xclipOut(XClipSelection.Clipboard).ax().singleOrNull()
      ?: bad { "Clipboard has to have code reference in single line." }
  else reference
  val ure = ure {
    +ure("className") {
      +chWordFirst
      1..MAX of chWordOrDot
      +chWord
    }
    +ch('#')
    +ureIdent().withName("methodName")
  }
  val result = ure.matchEntireOrThrow(ref)
  val className by result.namedValues
  val methodName by result.namedValues
  tryInteractivelyClassMember(className!!, methodName!!)
}

@NotPortableApi
@DelicateApi("API for manual interactive experimentation. Conditionally skips")
suspend fun tryInteractivelyClassMember(className: String, memberName: String) {
  val log = implictx()
  log.i("tryInteractivelyClassMember(\"$className\", \"$memberName\")")
  val call = getReflectCallOrNull(className, memberName) ?: return
  // Note: prepareCallFor fails early if member not found,
  // before we start to interact with the user,
  // but the code is never called without confirmation.
  ifInteractiveCodeEnabled {
    val submit = implictx()
    submit.askIf("Call member $memberName\nfrom class $className?") || return
    val member: Any? = call()
    // Note: call() will either already "do the thing" (when the member is just a fun to call)
    //  or it will only get the property (like ReducedScript/Sample etc.) which will be tried (or not) later.
    member.tryInteractivelyAnything()
  }
}


@DelicateApi("API for manual interactive experimentation. Conditionally skips")
suspend fun Any?.tryInteractivelyAnything() = when (this) {
  is Sample -> tryInteractivelyCheckSample()
  is Kommand -> toInteractiveCheck().ax()
  is ReducedSample<*> -> tryInteractivelyCheckReducedSample() // Note: ReducedSample is also ReducedScript
  is ReducedScript<*> -> tryInteractivelyCheckReducedScript()
  else -> tryOpenDataInIDEOrGVim()
}


@DelicateApi("API for manual interactive experimentation. Conditionally skips")
suspend fun Sample.tryInteractivelyCheckSample() =
  kommand.toInteractiveCheck(expectedLineRaw).ax()

@DelicateApi("API for manual interactive experimentation. Conditionally skips")
suspend fun ReducedSample<*>.tryInteractivelyCheckReducedSample() {
  reducedKommand.lineRawOrNull() chkEq expectedLineRaw // so also if both are nulls it's treated as fine.
  tryInteractivelyCheckReducedScript("Exec ReducedSample ?")
}

@DelicateApi("API for manual interactive experimentation. Conditionally skips")
suspend fun ReducedScript<*>.tryInteractivelyCheckReducedScript(
  question: String = "Exec ReducedScript ?",
) {
  val submit = implictx()
  submit.askIf(question) || return
  val reducedOut = ax()
  reducedOut.tryOpenDataInIDEOrGVim("Open ReducedOut: ${reducedOut.about} in tmp.notes in IDE (if running) or in GVim ?")
}

@DelicateApi("API for manual interactive experimentation. Conditionally skips")
/** @param question null means default question */
suspend fun Any?.tryOpenDataInIDEOrGVim(question: String? = null): Any {
  val log = implictx()
  val fs = implictx()
  val submit = implictx()
  return when {
    this == null -> log.i("It is null. Nothing to open.")
    this is Unit -> log.i("It is Unit. Nothing to open.")
    this is Int && this in 0..10 -> log.i("It is small Int: $this. Nothing to open.")
    this is Long && this in 0..10 -> log.i("It is small Long: $this. Nothing to open.")
    this is Boolean -> log.i("It is Boolean: $this. Nothing to open.")
    this is String && isEmpty() -> log.i("It is empty string. Nothing to open.")
    this is Collection<*> && isEmpty() -> log.i("It is empty collection. Nothing to open.")
    !submit.askIf(question ?: "Open $about in tmp.notes in IDE (if running) or in GVim ?") -> log.i("Not opening.")
    else -> {
      val lines = if (this is Collection<*>) map { it.toString() } else toString().lines()
      val notes = fs.pathToTmpNotes.toString() // FIXME_later: use Path type everywhere
      writeFileWithDD(lines, notes).ax()
      ideOrGVimOpen(notes).ax()
    }
  }
}

private val Any?.about: String
  get() = when (this) {
    null -> "null"
    Unit -> "Unit"
    is Number -> this::class.simpleName + ":$this"
    is Collection<*> -> this::class.simpleName + "(size:$size)"
    is CharSequence ->
      if (length < 20) this::class.simpleName + ": \"$this\""
      else this::class.simpleName + "(length:$length)"
    else -> this::class.simpleName ?: "???"
  }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy