-
Notifications
You must be signed in to change notification settings - Fork 757
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
History cleanups #3267
History cleanups #3267
Conversation
I really think we ought to restrict updates to 3.9 to fixes from the beta. It's a slippery slope that we can afford not to walk on for the next few weeks IMO. Something gets merged that has accidental bugs, we have to wait for a patch, etc. What do you think @snappizz ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have preferred to have this in 3.9.0, but I agree that it could be done now, too, if we are not overly strict. The fixes were really needed.
Either is fine, and I don't want to be a pest - sorry for getting around to it so late ! |
mixed feelings on this one. i don't see the harm in this particular case since History is not a critical SC feature, but we don't want any more of these between now and 3.9.0. |
yes, agreed: trick or treat! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've added a lot of material to this, thank you! I'm wondering if we could make the style less informal, because in its current form the terse, capitalization-free style seems a little unfriendly to newbies.
Having explicit descriptions of the return types/argument types could go a long way. Most of the time, the general function is clear from the name, but the type is not. For example, the lines
argument of History.new
.
I think this could definitely go into 3.9.0, I agree that none of this is a dangerous change, but IMO it still needs a fair bit of work on the documentation side.
HelpSource/Classes/History.schelp
Outdated
@@ -5,11 +5,66 @@ categories:: Streams-Patterns-Events | |||
|
|||
description:: | |||
|
|||
History keeps track of all code lines that are being executed, in order to forward them to other players, to easily reuse earlier versions, or to store and reproduce a performance. Since it records everything that is interpreted, there is only one privileged instance of History - code::History.current::. | |||
(adc 2006/7) | |||
History stores all code strings as they are being evaluated, in order to reuse code written earlier, to forward code to other players, or to store, reproduce, edit and analyse live-coded performances. It records every evaluated code string into a privileged instance of History - code::History.current::. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we replace usage of "privileged" with "singleton"? it's a more accurate term and will make the pattern usage apparent to people who know it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, done
HelpSource/Classes/History.schelp
Outdated
|
||
method:: keepsLog | ||
subsection:: configuring what to record and post |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could this be shortened to "configuration"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, to match style, the first word of each subsection should be capitalized
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
HelpSource/Classes/History.schelp
Outdated
remove last line from history | ||
|
||
subsection:: repeating history | ||
method::evaluateLineAt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method is missing a description
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
HelpSource/Classes/History.schelp
Outdated
add an entry to (current) history by hand. | ||
|
||
method::drop | ||
drop the newest n lines from history. if n is negative, drop the oldest n lines. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name in the description should match the name of the argument in the method, which is num
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
HelpSource/Classes/History.schelp
Outdated
|
||
subsection::More internal methods: | ||
method::new | ||
create a new instance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does the lines
arg to new
do? that needs to be documented
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
HelpSource/Classes/HistoryGui.schelp
Outdated
method::setDocStr | ||
set string of current doc | ||
method::rip | ||
create a new doc with currently selected line |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would really appreciate it if you could put some newlines between methods. it's hard to read in the current state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, done
@@ -167,25 +147,20 @@ HistoryGui : JITGui { | |||
.action_({ |lview| | |||
var index = lview.value; | |||
if (lview.items.isEmpty) { | |||
"no entries yet.".postln; | |||
// "no entries yet.".postln; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mixed whitespace after this comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually the commented-out post can just be removed, so I did that.
//.path_(docTitle); // don't lose title. | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing newline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
"// result: ".postln; | ||
result.postln; | ||
} { | ||
"// History code evaluation FAILED for line: ".postln; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think you need to capitalize "failed" here. also, it might be a good idea to post the error message in addition to the line that failed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The scenario is that you play back a history, possibly in edited form, so the current state is not exactly the same, and some lines may fail.
Then I want to know when a line went wrong, and which one, so this should warn visibly.
So I would prefer changing this to:
warn("History code evaluation failed for line: ...")
As there may be multiple lines that fail, they should not spam the post window with long error posts every 2 seconds. Maybe we want a flag whether to post errors on playback?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As there may be multiple lines that fail, they should not spam the post window with long error posts every 2 seconds.
Wouldn't it be a good idea to stop at the first line that fails? And you can just take the error message, not the whole stack trace. Also, isn't this method also putting out quite a lot of extra information itself anyway? (4 lines per line evaluated)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, seems we need two error modes for two use cases of History.play:
- historian mode - reconstruct History to replay as accurately as possible
-> on error, stop and throw, so one can edit history to fix it - showtime mode - replay history in segments, maybe in modified orders
-> on error, keep playing, just post short info - next line might work again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused, sorry... I'm just talking about evaluateAtLine
, not play. Are they related in some way? It doesn't seem that History.play
would ever result in calling this method.
But, I agree that's a good distinction to make. Would you rather do it as two functions or one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, you are right,
History.play does it differently, and should actually also protect against errors.
evaluateLineAt gets used from HistoryGui, and there it is not guaranteed that every line will work - state may not be as needed for the line, esp. if the line is code shared from other players by network.
ok, will consider what is best here.
HelpSource/Classes/HistoryGui.schelp
Outdated
method::filteredShorts | ||
the filtered short lines for gui display | ||
method:.setKeyFilter | ||
set the key(s) to filter for, and filter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this mean "and then perform the filter"? i think that would be hard to understand for a non-native English speaker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it does, added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for the quick edits :) much appreciated
factored evaluateLineAt into .eval which allows throwing errors or not, |
thanks for these comments, they helped clear up the ideas for this: |
ping @brianlheim - did I catch all of your requested changes? |
@@ -5,6 +5,7 @@ History { // adc 2006, Birmingham; rewrite 2007. | |||
|
|||
classvar <>saveFolder = "~/Desktop/", <logFolder, <logFile, <logPath, <>keepsLog = true; | |||
classvar <>current, <>maxShortLength=65; | |||
classvar <>ignoreErrors = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a code smell IMO. but if there's no way to just pass it directly to a method call, I guess it works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally it would be, yes :-) specifically here, it server two purposes:
when recording code experiments, you always write code that does not compile
or stops with errors, forgotten semicolons, etc etc.
all these broken lines would clutter recorded history, so it is useful to have th option to just forget them.
when performing with history playback, such as (First Rule of the Avantgarde:) Try it Backwards. in that case, any lines that depend on historically previous ones will produce errors.
a = [1, 2, 3]; // line 1
a.scramble; // line 2
// playing back line2 before line1 will produce 30 lines of Error post:
-> ERROR: Message 'scramble' not understood.
RECEIVER:
nil
ARGS:
CALL STACK:
DoesNotUnderstandError:reportError
arg this = <instance of DoesNotUnderstandError>
Nil:handleError
arg this = nil
arg error = <instance of DoesNotUnderstandError>
Thread:handleError
arg this = <instance of Thread>
arg error = <instance of DoesNotUnderstandError>
Object:throw
arg this = <instance of DoesNotUnderstandError>
Object:doesNotUnderstand
arg this = nil
arg selector = 'scramble'
arg args = [*0]
Interpreter:interpretPrintCmdLine
arg this = <instance of Interpreter>
var res = nil
var func = <instance of Function>
var code = "a.scramble"
var doc = nil
var ideClass = <instance of Meta_ScIDE>
Process:interpretPrintCmdLine
arg this = <instance of Main>
^^ The preceding error dump is for ERROR: Message 'scramble' not understood.
RECEIVER: nil
having your post window flooded with error messages in a show is annoying, and can slow down the IDE responses, so you want the option to suppress error posting - if you ever try turning it off, you will know exactly why you want it on ;-)
makes sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, not sure if that answers your comment - did it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my question was more about it having class scope as opposed to function scope, but I get what you're saying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The recording functions of History
(and the related variables) are all class methods (class variables), because there is only one instance of Interpreter
which we can add it to. I suppose instances could be useful for other kinds of logs, but this is not what the class is intended for currently.
The playback functions of History
are all instance methods, because there are multple recordings that could be played back. So in such a way, it assumes that history happens only once, but leaves many traces.
I suspect that for clarity these could be two classes, or the recorder could have a single instance it redirects to. But for now, this looks good and has always worked rather well.
@@ -325,6 +335,34 @@ History { // adc 2006, Birmingham; rewrite 2007. | |||
^str.clumps(indices.differentiate) | |||
} | |||
|
|||
*evaluateLineAt { |index| current.evaluateLineAt(index) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to abbreviate 'eval' below, you should do it here too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -151,6 +158,10 @@ History { // adc 2006, Birmingham; rewrite 2007. | |||
|
|||
play { |start=0, end, verbose=true| // line numbers; | |||
// starting from past 0 may not work. | |||
if (lines.isEmpty) { | |||
"History.current is empty, cannot play.".postln; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this isn't strictly true, right? not sure why this check was added in preference to just doing a no-op.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, when users play a history (current or recorded) and nothing happens, they may be surprised. Next thing they would check is probably whether this history is empty - so why not tell them? History is used in live coding performances, and anything that helps and speeds up orientation live is desirable I think.
Maybe the line should be "History:play - the history is empty, so there is nothing play yet.".postln;
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed it be more accurate, informative, and less worry-inducing:
if (lines.isEmpty) {
"% - % is empty, so there is nothing to play.".postf(
thisMethod,
if (this == History.current) { "History.current" } { "this history" }
);
var docTitle = title ++ Date.getDate.format("%Y-%m-%d-%Hh%M-History"); | ||
Document.new(docTitle, this.storyString) | ||
// path not working yet | ||
//.path_(docTitle); // don't lose title. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these comments stil relevant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess yes - Document:path_ still gives a NotYetImplemented error. would be noce to be able to set a path where this document would be saved when you hit save, rather than having to navigate and type in the path.
hm, could write it as a file first, and then read in the file...
I'll think about that some more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried again, setting path still does not work,
and IDE save dialog does not take the document title...
so I would keep the comment like this:
//.path_(docTitle); // path not working yet in Qt
// - would be nice to set and show a path
// where the doc can be saved later, by hand or automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! in the future, would be good to mark that with TODO
or FIXME
so it can be easily found in the codebase
HistoryGui.methods.detect { |m| m.name == \showLineAt } | ||
); | ||
this.showLineAt(index); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please move this method to the deprecated folder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
@adcxyz a few more questions/thoughts, but other than that looks good. Thanks for all the work on this, and sorry it took me awhile to get to it! |
@brianlheim - done. |
... and committed |
For future reference - "address all requested changes from review" and "make changes as requested by X" are not very helpful commit messages. It would be better in the future if you broke those up into more logical units - in this case, "History: deprecate postInlined", "History: rename evaluateLineAt -> evalLineAt", "History: update comment", and so on. It really does make a huge difference when using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am going to (reluctantly) say I am ok with this being in the next beta. There are some things here that seem dangerous but the documentation is very good and I trust that enough people use History that any bugs will be spotted relatively quickly.
Thanks @adcxyz ! |
yes, right, will pay more attention to that. |
it's up to you really. i don't mind if you leave it as-is--that's why i said "in the future". :) |
ok - I tried to get this with amend, but seems a mess, |
|
This PR cleans up a number of little problems in History and HistoryGui.
Because History is quite independent of the rest of SC,
I think this could still be included in 3.9 without any risk.
History:
HistoryGui