Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task/Todo textboxes based on code? #1751

Closed
mristin opened this issue Apr 4, 2021 · 20 comments
Closed

Task/Todo textboxes based on code? #1751

mristin opened this issue Apr 4, 2021 · 20 comments

Comments

@mristin
Copy link
Contributor

mristin commented Apr 4, 2021

Hi @aivarannamaa,
Please apologize if this feature has been already requested or implemented. I couldn't find a relevant issue.

We are looking into how to use contracts for educational purposes (see thonny-icontract-hypothesis and thonny-crosshair). Consider a classroom exercise. I thought that it would be practical if the teacher could write the interfaces of the functions (including the contracts) and mark the blank areas in the code (e.g., a "solution area"), while the pupils would fill out the blanks. To avoid confusion, A thonny plug-in would prevent editing of the non-blank areas.

Do you know if somebody already looked into it? If not, how hard would it be to implement such a plug-in in your opinion? (Would you be perhaps interested to help me implement it if nobody looked into it thus far? I can do the "hard lifting", but I'd need some guidance.)

@aivarannamaa
Copy link
Member

I'm not aware of any attempts to do something similar in Thonny's context, but it shouldn't be too hard to do.

Thonny's editor's superclass has couple of methods which can be helpful here, see thonny.shell.BaseShellText.intercept_insert and intercept_delete for an example. You should be able to use Text's tags (https://tkdocs.com/shipman/text-tag.html) for bringing out the editable parts visually.

Unortunately, there is no clean way for getting the modified behavior into Thonny's editor class. The best way I can think of, is simply patching the class. See the last 2 lines in thonny.plugins.autocomplete for an example.

I'm happy to help when you get stuck.

Out of curiousity, why can't you just tell the students to edit only the marked areas in the code? What kind of confusion do you expect?

@mristin
Copy link
Contributor Author

mristin commented Apr 4, 2021

Unortunately, there is no clean way for getting the modified behavior into Thonny's editor class. The best way I can think of, is simply patching the class. See the last 2 lines in thonny.plugins.autocomplete for an example.

Thanks, I'll see how that works!

Out of curiousity, why can't you just tell the students to edit only the marked areas in the code? What kind of confusion do you expect?

Think high school students in puberty ;-). This is not an issue for the university students, but it makes the life easier for the high school students that they are sure they can not "destroy" the scaffolding code and clearly see what needs to be filled out.

I'll keep you posted how it goes.

@mristin
Copy link
Contributor Author

mristin commented Apr 8, 2021

Hi @aivarannamaa,
I'm about to start to develop the plug-in. Do you have an idea for a good name? thonny-readonly? thonny-unwritable?

@aivarannamaa
Copy link
Member

What about thonny-restricted?

@mristin
Copy link
Contributor Author

mristin commented Apr 9, 2021

What about thonny-restricted?

Hm, "restricted" is a bit too technical and, in my understanding, implies the restriction for the whole file.

What about thonny-restricted-write? Still a bit technical, but it implies that the user can write at least somewhere.

@mristin
Copy link
Contributor Author

mristin commented Apr 9, 2021

Hi @aivarannamaa ,
I tried to hack my way through, but I have to admit it's overwhelming. Let's try to fix one feature at the time.

When a file is opened (or Thonny is loaded or a tab is changed), how could I go through text and set background on all the lines between # restrict-write: on and # restrict-write: off to some color, say lightgray?

How do I hook into the corresponding events? To set the background I assume I need to set the tags appropriately somehow?

@mristin
Copy link
Contributor Author

mristin commented Apr 9, 2021

@aivarannamaa I spent some more time tonight and finally figured out how I can set my one tags. I monkey-patch the method thonny.codeview.CodeView.set_content -- is that appropriate?

I'm still in the dark about how to set the background of the write-restricted text between the markers -- any hints are much appreciated!

@aivarannamaa
Copy link
Member

I monkey-patch the method thonny.codeview.CodeView.set_content -- is that appropriate?

I guess it is pretty good place for this.

I'm still in the dark about how to set the background of the write-restricted text between the markers -- any hints are much appreciated!

If you marked the area with tag, then you need to use tag_config method of tkinter.Text to give it an appearance. See https://tkdocs.com/shipman/text-methods.html. It's optimal to do this once per Text lifetime, but if you already have patched set_content, then it wouldn't hurt to do it each time this method gets invoked.

@mristin
Copy link
Contributor Author

mristin commented Apr 12, 2021

Thanks, @aivarannamaa! I think the work on the plug-in is progressing well. Let me finish the first working version and then it would be great if you could have a brief look?

@aivarannamaa
Copy link
Member

... if you could have a brief look?

Sure!

@mristin
Copy link
Contributor Author

mristin commented Apr 20, 2021

Hi @aivarannamaa ,
In the meantime I came up with a shorter name: thonny-sealed thanks to reading Cinderella to my son ;-):
Cinderella receives a letter

I'm pretty much done. Currently, I'm implementing a script that is signing the sealed blocks so that the user can't just type in the comments and have them sealed (or, which is a more probable case, copy/paste them).

The "seals" are defined by a hash (MD5) of the content of a sealed block. The seals are generated using a separate script. An example workflow would be:

  • Teacher writes the program "shell" and indicates the sealed blocks with the comments (# sealed: on and # sealed: off).
  • The teacher runs the script thonny-seal on the program "shell".
  • The teacher distributes the sealed programs to the students who have thonny-sealed installed. They fill out the "shell" and send back the full program to the teacher.

I'd like to warn the user on set_content if one or more seals are broken/invalid. This should however not raise an exception. The user should just be informed so that she knows that somebody tinkered with the seals. What is a preferred way in Thonny to signal errors? (It should just be a dialogue with an "OK" button.)

@aivarannamaa
Copy link
Member

What is a preferred way in Thonny to signal errors? (It should just be a dialogue with an "OK" button.)

I think tkinter.messagebox.showwarning would be the most straightforward solution (https://docs.python.org/3/library/tkinter.messagebox.html#tkinter.messagebox.showwarning)

@mristin
Copy link
Contributor Author

mristin commented Apr 22, 2021

Hi @aivarannamaa ,
The code is now ready for your review:
https://github.com/mristin/thonny-sealed

Thank you a lot in advance! :-)

@mristin
Copy link
Contributor Author

mristin commented Apr 22, 2021

P.S. The readme is not finished yet. I'd like to wait for your feedback in case behavior or appearance needs to change so that I don't have to re-capture the screenshots.

@aivarannamaa
Copy link
Member

aivarannamaa commented Apr 25, 2021

Looks good to me! I'm impressed about your thoroughness -- typings, contracts (of course :) ) , tests...

Some remarks:

  • IMO it would look better if the last line of a sealed block had special background extended till the editor's right edge. You can do this by extending the tag's range till the 0th column of the next line. But I'm not sure how it would affect the main concern of the plug-in. It's possible that Tkinter's marks can be used to forbid the tack "sticking" to the content typed at the next line (https://tkdocs.com/shipman/text-mark.html)
  • You have included __init__.py in the thonnycontrib directory, but this is meant to be a namespace package, so it should be without one.
  • You have used a strange way to load the plug-in -- right when the module is imported. The expected approach is to define a function load_plugin and let Thonny call it at the right moment.

@mristin
Copy link
Contributor Author

mristin commented Apr 25, 2021

Hi @aivarannamaa ,
Thanks a lot for your review! I'm working on it.

While manually testing, I discovered that the coloring comes out a bit weird:

I tried hacking around, and suspect that the issue is in the plugin SyntaxColorer. When I add these lines, the sealed blocks are rendered correctly:

old_raise_tags = thonny.plugins.coloring.SyntaxColorer._raise_tags

def _raise_tags(self: thonny.plugins.coloring.SyntaxColorer):
	"""Raise sealing tags above all the other tags."""
	old_raise_tags(self)
	self.text.tag_raise(TAG_NAME)
	self.text.tag_raise(TAG_END_NAME)

thonny.plugins.coloring.SyntaxColorer._raise_tags = _raise_tags

But is this the expected way to change the coloring? Is there any other way how I can override the tag priority so that the tags of the sealed blocks take precedence over the syntax coloring?

An alternative solution would be to only change the appearance of the two sealing comments. This makes the sealed text much more readable. Here's the screenshot with only the sealing comments highlighted:

The user is not as aware that the sealed blocks are indeed sealed, but the text is easier on the eyes. What do you think?

@mristin
Copy link
Contributor Author

mristin commented Apr 25, 2021

Here's another solution. I allow for arbitrary spaces in the comments as well as unicode characters for the arrows (instead of on and off). When the theme changes, the background coloring becomes problematic. Instead of changing the background, I only change the property "underline" (which I expect to be never affected by the theme).

Here's an example screenshot:

This also looks a bit neater and less distracting than the solutions where the background color was set to light grey.

@aivarannamaa
Copy link
Member

You could also draw a 3d border around the sealed areas, but I'm not sure how good it looks with dark theme.

Regarding raising tags -- I think the solution you found is best there is. Thonny's plug-in system currently isn't prepared for editor tweaking.

@aivarannamaa
Copy link
Member

Closing for now. Please reopen if you have more questions.

@mristin
Copy link
Contributor Author

mristin commented Jun 13, 2021

@aivarannamaa thanks! Sorry, I forgot to close the issue myself. I went with the underline in the end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants