Giter Site home page Giter Site logo

kacperfkorban / guinep Goto Github PK

View Code? Open in Web Editor NEW
14.0 1.0 0.0 157 KB

Automatic UI forms for Scala 3 functions

Home Page: https://kacperfkorban.github.io/GUInep/

License: Apache License 2.0

Scala 83.87% CSS 2.36% JavaScript 13.77%
code-generation gui scala scala3 frontend

guinep's Introduction

guinep Scala version support

GUInep

Guinep are small tropical fruits from the Caribbean and Central/Southern America. They are described to taste like a cross between Lime and Lychee.

Automatic UI forms for Scala 3 functions

Example

def upperCaseText(text: String): String =
  text.toUpperCase

@main
def run =
  guinep.web(upperCaseText)

This will start a local web server with auto generated endpoints for running all listed functions. And an auto generated front-end with a form for each function.

Usage (with build tools)

sbt

libraryDependencies ++= Seq(
  "io.github.kacperfkorban" %% "guinep-web" % "version_from_releases"
)

scala-cli

//> using lib "io.github.kacperfkorban::guinep-web:version_from_releases"

Usage (in code)

GUInep only exposes one function guinep.web which takes some number of functions as arguments.

def upperCaseText(text: String): String =
  text.toUpperCase

def rollDice(sides: Int): Int =
  scala.util.Random.nextInt(sides) + 1

@main
def run =
  guinep.web(
    upperCaseText,
    rollDice
  )

Demo

GUInep_classes_demo

Current limitations

Currently GUInep doesn't support:

  • Functions with multiple parameter lists (and by extension - extension methods) - #33
  • Fancier GADTs with unobvious inheritance, type bounds and variance - #30
  • Union and intersection types - #44
  • Opaque types - #49

Contributing

If you have any ideas on how to improve GUInep, feel free to open an issue.

All bug reports and feature requests are highly appreciated.

guinep's People

Contributors

kacperfkorban avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

guinep's Issues

Add a config with good DX

It should be possible to pass config options to GUInep. Those can either be front end specific or general GUInep options. e.g.

  • flag that makes all non-nullable inputs as required
  • an option to choose an alternative styling scheme

Some ideas for config:

  • a given instance e.g.
    given GUInepConfig with
      override val useBananas: Boolean = true
    
    guinep.web(someTool)
  • additional parameter list
    guinep.web(someTool)(useBananas = true)
  • builder-ish (change web to be some guinep class instance with an apply method)
    guinep.web
      .withConfig(_.copy(useBananas = true))
      .apply(someTool)

Support multiple parameter lists (and extension methods)

It should be possible to use methods with multiple parameter lists and extension methods with GUInep

e.g.

def addManyParamLists(a: Int)(b: Int): Int =
  a + b

enum IntTree:
  case Leaf
  case Node(left: IntTree, value: Int, right: IntTree)

extension (elem: Int)
  def isInTreeExt(tree: IntTree): Boolean = tree match
  case IntTree.Leaf => false
  case IntTree.Node(left, value, right) =>
    value == elem || elem.isInTreeExt(left) || elem.isInTreeExt(right)
 

Add a "user heap"

For functions for which a huge number of arguments have to be provided or just huge classes have to be constructed, it would be really useful to have a user accessible memory so that the user can save some values inside this memory and then access it multiple times in different forms. We might want to cache this memory so that it stays between reruns.

Add docstrings to exposed functions

Exposed functions should have docstrings, so that the usage instructions will be shown in the IDE popups.
Current exposed functions:

  • guinep.web

More special cased collections

Continuation of #37

Some other collections should also be special cased, those include (but are not limited to):

  • Map
  • Array
  • IArray
  • mutable collections

Support undecidable generics

It should be possible to use undecidable generics types in function definitions.

e.g.

sealed trait WeirdGADT[+A]
case class IntValue(value: Int) extends WeirdGADT[Int]
case class SomeValue[+A](value: A) extends WeirdGADT[A]
case class SomeOtherValue[+A, +B](value: A, value2: B) extends WeirdGADT[A]

// This fails on unknown type params
def printsWeirdGADT(g: WeirdGADT[String]): String = g match
  case SomeValue(value) => s"SomeValue($value)"
  case SomeOtherValue(value, value2) => s"SomeOtherValue($value, $value2)"

This fails, because SomeOtherValue cannot be fully constructed based on parent's type params.

Either some default will have to be used or a new type of form element introduced - one that lets the user pick any supported type.

It should also be possible to use generic functions with GUInep.

e.g.

def showMaybe[A](maybe: Option[A]): String = maybe match
  case None => "None"
  case Some(v) => s"Some(${v.toString})"

This might require similar mechanisms. Plus the support for this kind of input.

Progress indicator

It would be nice to add a progress spinner for long running queries (to indicate that the frontend is waiting for a response).

Add tests

Figure out how to test the code and a testing framework with some basic tests.

For macros, it should be possible to test the generated Scripts.

For the actual UI generation, it's a bit harder, especially since in the web version almost all the work is done by JS.

Support tuples in addition to functions

The ides is to be able to write code like the following:

def comment(comment: String) = ???

def getImageURL: URL = ???

guinep.web(getImageURL -> comment)

This would generate a form that also includes the non-function parameters in the form as (static) data. So in this case the form would contain an image followed by a text input box and a submit button.

This encoding would also allow for the creation of alternative actions/forms.
e.g.

def good() = ???
def bad() = ???

def getImageURL: URL = ???

guinep.web(getImageURL -> (good, bad))

This example should then generate a form with an image followed by two action buttons - good and bad. This might be useful for automation for data labeling for example - labelling the image as good or bad.

Cleanup the endpoints

The web server should serve the following endpoints:

  • GET / for the main page
  • GET /xxx for the xxx form
  • POST /xxx for running the xxx function with the data possibly from the form

Support missing primitive types

More primitive types should be supported, those include (but are not limited to):

  • Double
  • Float
  • Char
  • Byte
  • Short
  • Long
  • Unit
  • BigInt
  • BigDecimal

Support nullability

It should be possible to use nullable types as inputs. Those should probably be expressed as optional inputs in the web form.

Special case collections

Collections like Seq, List and Vector should be handled in a special way, instead of being supported as recursive data types.

Http server config

Obviously, it should be possible to configure the http server. Maybe it would even be possible to just keep a zio-http config, so that we get all the config options for free.

Support for union types

It should be possible to use union types as inputs in GUInep.

I'm not 100% sure how to show them in the form. Maybe the same way as tagged union types (sum types). Or maybe a radio to distinguish those two.

this is an extension of #38 (which is about supporting only specific union types - with Null)

Make the UI web based

The generated program should be an http server that serves a get endpoint with all the forms and a post endpoint that handles all the form submissions.

Fix the web form to display the result on the same page

It is extremely counterproductive to have the result displayed on a separate page when using guinep.web. The result of a form should be displayed together with the input form after submitting the form. (Below the "submit" button)

Support generics

It should be possible to use generics in GUInep functions, this includes:

  • generic types as input types e.g. Option[Int] (this requires handling in the sum types case in macros)
  • generic functions passed to Guinep

Fix function ordering in the sidebar

Functions in the sidebar are ordered by the hash of their names, since they come out of a hashmap. This shouldn't be the case. The order should be the same as the order of arguments

Use typeclasses for decoding input types

Add decoders for fields, so that we don't have to hardcode generation logic in the macro code

  • This is interesting because it would be nice to be able to add some sort of validation to custom types
  • A default derivation should be provided for the most common use case
  • But what should be the function in the type class? String -> Either[String, A] sounds good, but we want to support more than just text fields ๐Ÿค”
    So the type class should provide both the type of the field and the decoder, but how to make it type safe?

Support recursive structures

It should be possible to use recursive structures in functions, like collections, trees etc.

Currently, this results in StackOverflow in compile time, since the macro unwinds the definition forever.

Support collections as inputs

It should be possible to use collections as inputs.

In the UI those should be possibly extendable sub-forms-ish things i.e. a normal input and a + button that adds a new input.

Support optional arguments

We should distinguish between optional and required fields in the UI.

Right now all fields are optional, so technically "support non-optional arguments" is probably a better issue name.

Support classes as inputs

It should be possible to support class inputs. Those should just require every input from the constructor/apply method.

BONUS here to allow choosing which constructor/apply method to use in the UI (from dropdown maybe)

Support enums as inputs

It should be possible to use enums as input types.

Enums should be shown in the UI as dropdowns.

Support opaque types

It should be possible to use opaque types as function inputs.
e.g.

object HiddenScope {
  opaque type PLN = Int
  object PLN:
    def apply(value: Int): PLN = value
    extension (pln: PLN)
      def toInt: Int = pln
}

def showPLN(pln: HiddenScope.PLN): String =
  s"${pln.toInt} PLN"

Add easy file logging

I think that for many use cases (e.g. simple automation), logging all the operations to a log file will be extremely useful. So it should either be done by default or it should be behind a config flag.

Allow for different style schemes

It should be possible to configure the style of the generated form.

  • 1 point for choosing one of preset style schemes
  • 2 points for also allowing a custom inlined CSS (requires good docs and a spec for the generated HTML :displeasure:)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.