Skip to content
This repository has been archived by the owner on Oct 5, 2022. It is now read-only.

Type/info tooltips on selection #133

Closed
schiegl opened this issue Dec 4, 2015 · 14 comments
Closed

Type/info tooltips on selection #133

schiegl opened this issue Dec 4, 2015 · 14 comments

Comments

@schiegl
Copy link

schiegl commented Dec 4, 2015

It would be nice if you could see the type info of the word under the cursor in the completion hint panel as well instead of having to hover it with the mouse.

@lierdakil
Copy link
Contributor

Well, it is possible to assign a keybinding to show type of selected expression. Querying ghc-mod on every cursor movement would be a bad idea on larger projects.

@schiegl
Copy link
Author

schiegl commented Jan 10, 2016

Yes, it might slow things down. But being able to assign a keybinding would be fine as well.

@lierdakil
Copy link
Contributor

Well, you could consult https://github.com/atom-haskell/haskell-ghc-mod#keybindings and https://github.com/atom-haskell/ide-haskell#keyboard-shortcuts. Also possibly https://atom.io/docs/v1.3.3/using-atom-basic-customization#customizing-key-bindings

You might also want to fiddle with haskell-ghc-mod settings (which actually provides show type/show info etc functionality) for more fine-grained control over when to show and when to hide type tooltip.

@rvion
Copy link

rvion commented Jan 11, 2016

@lierdakil on sublime text with stack-ide-sublime plugin, there is an option to redisplay the type popup at each cursor move or selection change, and this is just amazing ☀️ (IMHO). stack-ide-backend handles caching perfectly and it's instant even on quite large projects. (I think that a mix of #62 + improving ghc-mod could be enough to handle large projects correctly)

I'd also like to mention those features in stack-ide-sublime

  1. clickable link opening haddock for types:
    image

  2. an option to remove prefixes ☀️ (this is a must-have too IMHO)
    (with prefixes)
    image

    (without prefixes but with an underscore to tell about hidden prefix: more readable)
    image

  3. realtime closest enclosing expression display (there is the same thing on atom, but it works slighly better on ST):

    capture d ecran 2015-07-28 a 13 39 40 capture d ecran 2015-07-28 a 13 39 32

@lierdakil the clickable links + prefix removal is done this way:

  • 2 new settings:

    // If "show_popup" is true, a popup will remain visible at all time below cursor / selection
    ,"show_popup": false
    
    // if show_popup is true, clicking on types displayed in the popup panel will
    // open a web-browser at specified hoogle_url with the right type query.
    // if you set this to your own hoogle webserver setup for your project,
    // you'll be able to see the documentation for your own type
    // example: "hoogle_url": "https://www.google.fr/search?q=what+is+haskell+"
    ,"hoogle_url": "http://www.stackage.org/lts/hoogle?q="
  • and some (ugly) python code to format types:

    def format_type(raw_type):
    words = raw_type.replace("(", " ( ").replace(")", " ) ").replace("[", " [ ").replace("]", " ] ").replace(",", " , ").split(' ')
    return (" ".join(map(format_subtype, words)).replace(" ( ","(").replace(" ) ",")").replace(" [ ","[").replace(" ] ","]").replace(" , ",","))
    
    def format_subtype(type_string):
    # See documentation about popups here:
    #       http://facelessuser.github.io/sublime-markdown-popups/usage/ (official doc)
    # and   https://www.sublimetext.com/forum/viewtopic.php?f=2&t=17583  (html support announcment)
    
    words = [x for x in type_string.split('.') if x != '']
    # [x for x in type_string.split('.') is necessary to handle the `a.` part of `forall a.` properly
    
    if (len(words) > 1):
        s = ("_"+words[-1])
    else:
        s = type_string
    
    if s == "->":
        return ('<span style="color: blue">{0}</span>'.format("->"))
    elif s == "(" or s == ")" or s == "[" or s == "'" or s == "]" or s=='' or s==',':
        return s
    elif (s[0] != '_' and s[0].islower()):
        return ('<span style="color: #4C4C4C">{0}</span>'.format(s))
    else:
        return ('<a href="{0}" style="color: #333333">{1}</a>'.format(type_string.split(":")[-1], s))

final note about this issue: I think the completion hint panel is not a good place to show expression types, but I'm in favor of having a way to always show types, with refresh at each cursor move / selection change.

I'm used to use selection as a way to understand my code. I really think it speeds up my code understanding.

@lierdakil lierdakil changed the title Show type info in completion hint panel Type/info tooltips on selection Feb 27, 2016
@lierdakil
Copy link
Contributor

@rvion, I think I could manage type/info tooltips on (non-empty) selection. As for prefix removal, I'd ask you to file separate issue if possible (since it's not directly related and I'm still on the fence on that one, because it may get confusing -- consider e.g. Data.ByteString vs Data.ByteString.Lazy)

@lierdakil
Copy link
Contributor

@rvion, I've added experimental support for 'show type on selection'. It's disabled by default. To enable, see 'showTypeOnSelection' option in haskell-ghc-mod. Feel free to file new issues if something doesn't work right.

@rvion
Copy link

rvion commented Feb 27, 2016

@lierdakil big thanks !!

@lierdakil
Copy link
Contributor

For anyone interested, prefix hiding can be achieved with recent language-haskell using something like this in your stylesheet (provided syntax highlighting in tooltips is enabled):

ide-haskell-tooltip .hint.haskell .module {
      display: inline-block;
      white-space: nowrap;
      width: 1ex;
      overflow-x: hidden;
      vertical-align: bottom;
      position: relative;
      &::before {
        content: "_";
      }
}

You can also make it show prefix on mouseover with something like

ide-haskell-tooltip .hint.haskell .module {
      display: inline-block;
      white-space: nowrap;
      width: 1ex;
      overflow-x: hidden;
      vertical-align: bottom;
      position: relative;
      &::before {
        content: "_";
      }
      //show on hover
      pointer-events: auto;
      &:hover {
        &::before {
          content: none;
        }
        width: initial;
      }
}

@nrolland
Copy link

Is there a way to reuse that in a static HTML system for litterate haskell stuff ? what would be the entry point to process haskell litterate source and get the HTML representation with tooltips classes ?

@lierdakil
Copy link
Contributor

@nrolland, I'm sorry, but I'm not sure what exactly you are trying to do. Could you maybe explain in more detail?

@nrolland
Copy link

Sure, I have some literate haskell files, which I compile down to HTML with pandoc via hakyll.
Nothing fancy, it's really your standard haskell bloggy blog. it gives a nice you have syntax highlighting via a css style sheet. But no tooltips, like what you seem to have !

It would be nice to be able to generate the type info along the way, very much the same way you can do with say fsharp here

@lierdakil
Copy link
Contributor

Ah, ok, I get it now. Regrettably, ide-haskell uses ghc-mod to dynamically query type information (via node's spawnProcess), so it's not really suitable to use in static HTML. Besides, you will have to run your lhs through some part of GHC pipeline to get type information, so it has to, at minimum, typecheck (which it may or may not for your blog posts, I have no idea)

But if you're willing to invest some time and effort into this, you could use ghc-mod as a library from hakyll. One caveat is that ghc-mod gets type information for a single point in input source, so you'll likely have to reimplement some of the logic in types(https://github.com/DanielG/ghc-mod/blob/v5.6.0.0/Language/Haskell/GhcMod/Info.hs#L54), or, more specifically, remove filter in collectSpansTypes (https://github.com/DanielG/ghc-mod/blob/v5.6.0.0/Language/Haskell/GhcMod/SrcUtils.hs#L50). That said, this could be a good starting point into GHC API.

You would also have to insert annotations into lhs source 'manually', i.e. there would be no direct mapping to Pandoc's AST (unless you do this via a pandoc filter, which is possible).

Overall, this would be relatively complicated and time-consuming, and ide-haskell can't help you there much, if at all, but ghc-mod could at least simplify things.

If you decide to do that and have any questions/difficulties, you can try asking for help on ghc-mod repo or on #ghc-mod @ freenode IRC channel.

P.S. Note that ghc-mod is currently undergoing a huge code reorganization. We're aiming to split the code that deals with GHC API directly into a separate library (currently named ghc-mod-core), so master branch is sorta out of whack right now, and you may need to update your code when we actually release that.

@nrolland
Copy link

nrolland commented Jan 31, 2017

They do typecheck, that's the point of this litterate file : the same source is both the program and the documentation.

The question would be what's the best way to retrieve the typing information at each point, then store that type information (in the output file, not to the lhs itself)

The entry point you provided for ghc-mod seems well suited for that.
It would be a very good thing to have that use case in mind in your GHC-mod reorg.
A good architecture should make that kind of application a no-brainer, and there are many contexts into which the typing information is to be consumed. I unfortunately have little time to invest in such endeavour, I can just extend things.

An alternative to this might be to load the litterate haskell file in a context akin to atom-haskell, and upon client hover, to issue a request with the hovered location info to that context, retrieving the same info as you do from within atom-haskell, and forward the HTML answer to the client.

Upon glancing quickly .. maybe that's what stack-ide does :)
It seems that https://github.com/haskell-tools/haskell-tools can also generate signature.
but not sure what's the scope of that project VS ghc-mod VS others..

I wish there was more modularity in those developper tools : everything is already there, there is already a mapping from source to types in HTML, but that seems amazingly hard to reuse !

@lierdakil
Copy link
Contributor

lierdakil commented Jan 31, 2017 via email

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants