Shoes3 / ebook

An interactive eBook written in Shoes.
2 stars 0 forks source link

Codeblocks not working #10

Open ccoupe opened 7 years ago

IanTrudel commented 7 years ago

Below is a sample Markdown file for codespan and codeblock. It yields the following output with a modified Kramdown001.rb.

<kd:codespan "code" nil {:location=>5}>
<kd:codespan "back-ticks around" nil {:location=>5}>
<kd:codespan "javascript\nvar s = \"JavaScript syntax highlighting\";\nalert(s);\n" nil {:location=>7}>
<kd:codeblock "This is a code block.\n" nil {:location=>16}>

Kramdown001.rb modifications:

def convert_codespan(el)
   pp el
end

def convert_codeblock(el)
   pp el
end

Markdown file: codespan_block.zip

ccoupe commented 7 years ago

That's s a hint. Maybe you could add the code in kd_render.rb and show_ebook.rb that makes it into something that Shoes will eval into a rounded rect with run and copy buttons?

IanTrudel commented 7 years ago

The existing code should be reusable with little or no modifications. The following from former help.rb is necessary: dewikify_code, run_code and CODE_STYLE.

ccoupe commented 7 years ago

Think like a compiler: code gen and runtime support. kd_render.rb is the compiler and show_ebook.rb is the runtime support routine dewikify_code, run_code and CODE_STYLE would be runtime support. What does kd_render.rb(convert_codeblock) return (to be eval-ed) by the runtime and how to get get a handle on that

IanTrudel commented 7 years ago

The approach you suggested does work but it emits the whole dewikify_code alike for each codespan and codeblock. I however successfully embedded methods in the generated code, which are called in the resulting Shoes app. Need some clean up and then post it here.

IanTrudel commented 7 years ago

There you go @ccoupe. You should be able to do something with md_run_code.zip. Take note that it seems to only work with the custom GfmLink parser. GFM as input doesn't seem to catch codeblocks. Needs a little visual adjustment but it might be due to global settings in the original Shoes Manual. Happy New Year!

image

IanTrudel commented 7 years ago

Alright, it works with GFM as input. It had to be between quotes.

ccoupe commented 7 years ago

What had to be in quotes?

IanTrudel commented 7 years ago

It was input: 'GFM'. No worries, you already use GFM input correctly.

ccoupe commented 7 years ago

And we have: codespan-block-almost-good

There is subtle line spacing issues for codespan vs code/block (and an odd shoes.log message) but it's looking really good. IMO

Error in line 0 | 2016-12-31 23:54:48 -0700 undefined method l' for (Shoes::Types::App "Shoes") /home/ccoupe/Projects/ebook/kd-render.rb:203:ineval' (eval):2:in rendering' /home/ccoupe/Projects/ebook/kd-render.rb:203:ineval' /home/ccoupe/Projects/ebook/kd-render.rb:203:in rendering' /home/ccoupe/Projects/ebook/show_ebook.rb:92:inblock in draw_ruby' /home/ccoupe/Projects/ebook/show_ebook.rb:92:in each' /home/ccoupe/Projects/ebook/show_ebook.rb:92:indraw_ruby' /home/ccoupe/Projects/ebook/show_ebook.rb:107:in block in show_doc' /home/ccoupe/Projects/ebook/show_ebook.rb:106:incall' /home/ccoupe/Projects/ebook/show_ebook.rb:106:in clear' /home/ccoupe/Projects/ebook/show_ebook.rb:106:inshow_doc' /home/ccoupe/Projects/ebook/show_ebook.rb:98:in open_entry' /home/ccoupe/Projects/ebook/show_ebook.rb:271:inblock (7 levels) in make_ebook' -e:1:in `call'

Examples with run this buttons work. Very good progress!

ccoupe commented 7 years ago

It looks like this code in Plot-Widget.md line 54 w/o line wrapping in your editor is causing the error above.

   chart: "timeseries",
   default: "skip", click: proc {|btn, l, t| puts "click on #{@grf.near_x(l)}" }

I have no idea why it's failing or when the '1' comes from.

Added later: Does the run-this/copy-this method take the place of syntax highlighting ? They seem incompatible to me.

IanTrudel commented 7 years ago

I have no idea why it's failing or when the '1' comes from.

The convoluted code in convert_codespan and convert_codeblock is likely to be the culprit. The problem is to properly escape the code to be then eval'ed. So it turned out %[render_code(%{#{el.value}})]. As you can see, there is already a #{} and the second one in Plot-Widget.md is likely to mess things up. It needs some work.

I'd like to suggest a way to be able to turn on/off display of the generated code. Normally just a simple puts e in rendering method, combined with cshoes, will allow you to see the code generated in the console.

Does the run-this/copy-this method take the place of syntax highlighting ? They seem incompatible to me.

It's possible to mix both. The syntax highlighter will allow us to generate custom Shoes code that will colorize, bold, and so on. However, it will likely superside the use of Shoes own code, i.e. para code(str).

ccoupe commented 7 years ago

What I've done, for the moment, is to add a a syntax_highlight: true to the yaml which calls the older methods (renamed) which for now, just output to the console via el.inspect. If set to false it attempts to do your conversion.

Perhaps codespan should behave more like github codespan and not get the copy/run treatment. Just a mono font applied to the text.

IanTrudel commented 7 years ago

The best would be to get both but we can settle for Shoes own code rendering for now and next version add syntax highlighting. A bit difficult to focus on syntax highlighting where there are many other things to get right first. Use Shoes para code will at least allow us to match the Shoes Manual as far as visual goes.

ccoupe commented 7 years ago

I greatly prefer the appearance and readability of using

      def highlight_codespan(el)
        # need to escape some things in the string like "
        str = el.value
        str.gsub!(/\"/, '\"')
        %[para "#{str}", :font => 'monospace']
      end

That should also simplify render_code method since it doesn't serve two masters. No doubt there, are other special chars that may need escaping.

ccoupe commented 7 years ago

Since render_code() only has to do codeblocks , it would be possible for it to have two arguments, the pretty string from syntax highlighting and the executable string (currently named 'str') that is attached to the copy and run buttons. render_code could also detect that it doesn't have an optional 'pretty_string' arg and fall back to the executable 'str' arg.

IanTrudel commented 7 years ago

The following seems to be working rather well. What do you think?

%Q[render_code(#{el.value.inspect})]

Don't forget that you can style Shoes code however you want, including monospace text. style(Shoes::Code, :stroke => "#C30")

ccoupe commented 7 years ago

After some debugging, one problem is the snippet author - aka me, didn't have a Shoe.app {} or do end. around some codeblocks. In that case, we want syntax highlighting (when working) but we don't want "run this" buttons, just "copy_this". Many ways to cope. Much to learn and do.

IanTrudel commented 7 years ago

There are cases where run this is relevant without Shoes.app { }. For example, alert("This ain't no Shoes.app, or is it?") will most certainly work with a run this.

As a side note, Kramdown and Rouge are able to determine the language to highlight on its own. It means we will be able to support, in the future, run this for various languages where command line may be defined in our YAML configuration file.

ccoupe commented 7 years ago

Yes, there are cases when alert/confirm...would be viable 'run this' (the Shoes manual does that) and there are ebook cases when when they should not be runnable because 'alert' is inside a block of example code that wasn't intended to be run. Alert and dialog friends outside of app block is not good Shoes practice and a source of errors and confusion because of the binding issues. My thinking is to not accommodate date and currently if there is no Shoes.app it will call the render_copy instead of render_code at runtime/display-time.

%Q[render_code(#{el.value.inspect})]

That does help. Wish I knew why.

ccoupe commented 7 years ago

Better, but still wrong. more-better

The copy button actually runs example. Still, it does not toss up errors, so it's better.

IanTrudel commented 7 years ago

%Q[render_code(#{el.value.inspect})]

That does help. Wish I knew why.

%Q[] is used for interpolated strings. We would otherwise run out of ways to properly escape strings before eval.

ccoupe commented 7 years ago

It's the inspect that does all the escaping so that %Q will undo some of them. Clever.

The copy button actually runs example

Actually, it does both, runs it and copies to the clipboard which could mean the copy this button is visually overwriting the 'run time' link and both are firing on a click. Other than some argument names and wrangling the code looks identical to help.rb, _help_picky.rb, &template.rb . Any clues?

IanTrudel commented 7 years ago

Any clues?

I have rendering() method output generated code running on cshoes for debugging purpose. The clue would be to look at the code generated and see why run button and copy button are merged together. The suspect would be a missing brace, bracket and/or quote.

IanTrudel commented 7 years ago

Additionally, the dsp_str logic seems wrong. It should first and foremost default to empty string rather than nil. The if !display_str means if the variable is not nil, it will set dsp_str to exe_str. Shouldn't it be set to display_str? It might be better to use ternary operator or something.

ccoupe commented 7 years ago

current the dsp_str logic looks like this

    dsp_str = display_str
    dsp_str = exe_str if !display_str
    dsp_str.strip!

display_str is something from the syntax_highlighter and we don't know what that looks like, so it's nil from kd_render.rb/convert_codeblock until we do know, so ! nil is true and we just use the exe_str in two different places (display and the eval in the button.

I was correct about layout problems on the pseudo buttons. Commenting out the copy_this stack reveals run_this which only runs the code. Missing punctuation drives the ruby parser crazy.

There are pseudo button layout problem with the render_copy and back when one method was being used for both run and copy there was a layout issue. One possibility: ebook does not extend Shoes::Manual - because there is no help.rb in merge packaged app.

IanTrudel commented 7 years ago

How does Shoes Manual behave when there are issues with codeblock? My recollection is that the Shoes Manual is rather unforgiving.

We may check syntax in future version of the Shoes eBook but it doesn't seem reasonable for the first version. It comes to the author to check for now.

I don't understand the last paragraph you wrote. o_O

ccoupe commented 7 years ago

I don't understand the last paragraph you wrote.

It means the code taken from Shoes for run/copy has and had layout problems when used in ebook. Why? Because it depends on something in Shoes::Manual?

IanTrudel commented 7 years ago

How would that be? My tests were all without Shoes::Manual. No dependencies. Do you think something interfere?

ccoupe commented 7 years ago

help_picky.rb and help.rb:

def Shoes.make_help_page(book_title = "The Shoes Manual")
  font "fonts/Coolvetica.ttf" unless Shoes::FONTS.include? "Coolvetica"
  proc do
    extend Shoes::Manual

and your code is in defined to be in Shoes::Manual. Should be an easy test for me to see if it makes any difference.... It does not. The problem is elsewhere

IanTrudel commented 7 years ago

Oh, I was referring to render_code tests. Shoes eBook has its own module. It shouldn't make any difference what the module name is. Perhaps some styles are colliding?