Frege / frege-repl

Frege REPL
78 stars 17 forks source link

Documentation command #3

Closed Ingo60 closed 9 years ago

Ingo60 commented 10 years ago

The following would be nice to have:

:help name

(where name could be a qualified name) which should print the html-ized doc comment for that item. Most of the needed functionality should already be there in compiler/DocUtils.fr and compiler/EclipseUtils.fr The only difficulty should be to keep track of the namespaces in scope according to the imports done by the user. This you need to resolve the name and get the corresponding symbol table entry, which could then be handed down to the documentation functions.

Also nice (but not really important) would be to have a command like

:java

to see the generated java code, maybe in an extra tab or page. I sometimes wanted this for answering "how would I write this Haskell code in Java" type questions on stackoverflow quickly. :)

mmhelloworld commented 10 years ago

:help name would be really useful. I am myself very much interested to see this feature integrated. I will look into this more.

:java - Thanks for bringing this up. I keep forgetting about this one which is actually very easy to implement since we already keep the generated Java source in memory. So we just need to expose the generated source with this new command.

mmhelloworld commented 10 years ago

In the online REPL, now :java command would display the generated Java source for the last successful compilation in a separate dialog (which can be closed by either pressing ESC or clicking "close" button on the top right).

Ingo60 commented 10 years ago

This is extra cool!

mmhelloworld commented 10 years ago

Frege documentation is also available now in online REPL.

Few examples:

frege> :help flip This should display the documentation for flip function in a dialog window which can be closed by pressing ESC or clicking the 'close' button on the top right of the dialog.

frege> :help frege.data.List This should display the package documentation for frege.data.List. (It would be better if we can provide the link to the module's complete documentation.)

frege> :help >>= This would display the documentation for >>=. In the documentation dialog, Bind has a link which on clicking should open frege.prelude.PreludeMonad module and link Bind in a new tab.

We can also import another module and then look up the documentation for the functions in that module.

frege> import Data.List

frege> :help intercalate

This should display the documentation for intercalate from Data.List module.

Ingo60 commented 10 years ago

Magnificent!

It doesn't seem to work for class or type names, though?

mmhelloworld commented 10 years ago

Ah! yes, I will look into it.

mmhelloworld commented 10 years ago

Now types and classes are working in online REPL.

There is still one problem: Items with explicit namespaces are not working.

My current approach is to create a QName and from QName, find the symbol and then invoke symbolDocumentation. I create QName in the following ways and return the documentation from the successful one:

  1. TName{pack=global.thisPack, base=source}
  2. VName{pack=global.thisPack, base=source}

Here source is the name that we pass from the REPL.

Items with explicit namespaces do not fall in either of these cases or I think I am not creating QName correctly. For example,

This works:

frege> import Java.Net
frege> :help URL

But the following is not working:

frege> import Java.Net as JNet()
frege> :help JNet.URL
JNet.URL cannot be resolved!

Any ideas?

Ingo60 commented 10 years ago

Some observations:

Same for List.unique after importing Data.List.

I recommend not to construct a QName, but rather an SName and to use Utilities.resolve, so you don't reinvent the name resolution logic. Note that resolve requires a default function to make a QName from a string, you can pass (VName g.thisPack) here (it will nevertheless also find types).

In order to make this work with name spaces, it is required that you have a Global state that has the name spaces actually imported. You may run the import pass for every import definition (and keep that state) to achieve this.

Since obviously the :t command does find the correct things, you must already have something you can reuse. Note however that you would need to do an extra check in case we have just a namespace name.

mmhelloworld commented 10 years ago

Thanks Ingo for the great explanation. I fixed the implementation as per your suggestion and it seems to be working now. Just want to make sure if I am creating SNames correctly, could you please verify the code below? (Complete code for this feature is here)

createSName s
  | Just m <- s =~ #(.*)\.(.*)\.([A-Z].*)# = with2con m
  | Just m <- s =~ #(.*)\.(.*)\.(.*)#      = with2var m
  | Just m <- s =~ #(.*)\.([A-Z].*)#       = with1con m
  | Just m <- s =~ #(.*)\.(.*)#            = with1var m
  | Just m <- s =~ #[A-Z].*#               = Simple (Token CONID s 1 0 0 [])
  | otherwise                              = Simple (Token VARID s 1 0 0 []) where
                                               with2con m = With2 (ns m) (ty 2 m) (conid 3 m)
                                               with2var m = With2 (ns m) (ty 2 m) (varid 3 m)
                                               with1con m = With1 (ty 1 m) (conid 2 m)
                                               with1var m = With1 (ty 1 m) (varid 2 m)
                                               ns m     = Token QUALIFIER (maybe "" id $ (m :: Matcher).group 1) 1 0 0 []
                                               ty pos m = Token QUALIFIER (maybe "" id $ (m :: Matcher).group pos) 1 0 0 []
                                               conid pos m = Token CONID (maybe "" id $ (m :: Matcher).group pos) 1 0 0 []
                                               varid pos m = Token VARID (maybe "" id $ (m :: Matcher).group pos) 1 0 0 []
Ingo60 commented 10 years ago

Looks good so far. I see two enhancements:

mmhelloworld commented 10 years ago

I thought about the anchors but completely missed \p{Lu}, thanks!

I guess this enhancement is now complete for online REPL unless there are some bugs or things that can be improved still.

Now I am thinking of implementing this feature for console REPL. Do we need to write a similar function like emitHtml so that the documentation can be displayed in console without Html formatting?

Ingo60 commented 10 years ago

I've thought about that, too. Would it be acceptable to fire up some Swing window?

mmhelloworld commented 10 years ago

It seems Java Swing has some support to render HTML contents but JavaFX WebView looks promising (an example).

mmhelloworld commented 10 years ago

These commands are now supported in console REPL (New version available in releases page here). A Swing window will be launched to display the Java code or to display the Frege documentation.

In the Swing window displaying Frege documentation, clicking any links would trigger the user browser to display the link contents.