There are several things that need to be addressed in Simple Script that will affect the direction it will go in the future.
1) Docking form
I recently switched from a modal window to a docking form for Simple Script, and so far it's been a semi-disaster. It works great as long as you leave it exactly as-is when you start it up. If you undock it, it freezes as soon as you click any buttons in the window. I can't seem to figure out what might cause this problem. I really haven't tried anything to fix it, because I don't even know what to try.
I can handle this in one of three ways:
a) Leave it as it is, and just warn the users not to undock it. This is the least preferable solution.
b) Someone who's familiar with programming in Delphi can help me find the problems and fix them. This is my preferred solution, but I can't do it on my own.
c) I can simply make the window non-dockable. It will still be non-modal, which means you can work with the document underneath while the Script Writer window is active, like the way the Find dialog works.
How disappointed would everyone be if I went with option (c)? Unless someone can help me fix the bugs, it looks like this is what I'll have to do.
2) Using Simple Script to work with templates
As discussed in this thread:
Some people have suggested a modification to Simple Script that would allow it to automatically load templates. There have been several ideas about how to do this, but I thought perhaps the simplest solution would be to add a "Run in new document" button on the Script Writer window. By adding a single-line "appendfile" script to the .ini file, the user could store the templates as external documents and select them from the favorites list. Clicking the button would create a new document and then run the active script, which in this case would simply append the contents of the template file to the current (new) document.
I'm more than happy to hear other suggestions of how to do this. Keep in mind that I want to stay away from program control in the scripts themselves because that opens up a lot of issues that I'm not ready to deal with right now. So having a "New" function, for instance, is out of the question.
I think a lot of new possibilities open up by adding variables to scripts. I could add a bunch of functions that would set variables either directly or based upon the content of the document (i.e. the number of lines as an integer variable, or a certain portion of the text as a string variable). You could then use these variables in any function that requres a parameter of that type.
To set the variables, I could have functions such as:
You could then use variables in functions like this:
I could even let you put variables in the middle of a string, maybe with an escape sequence, like this:
Are there any other ideas of what you would like to see with variables?
4) Anything else?
As always, I'm more than happy to take suggestions on improving Simple Script. While I can't guarantee I'll make everyone happy, I want to make it as useful as possible to the most people.
I'm really a fan of your plug-in, and I think it will be really useful when it is done, here is my input:
1) Docking form
I can see that many programmers are helping you in fixing the docking problem, yet if you can not fix it then just go to option C.
2) Using Simple Script to work with templates
very good Idea ,I know it is not what you wanted simple script for, but it is a needed functionality, quickText is there which give you some kind of a template, but it is not docking form, and not that smart, being able to have smart template will give us (NotePad++ users) endless possibilities.
My suggestion in here is to have the templates linked to the supported languages some how (probably when you change the ini file to xml) so that when i open sql document i can see sql templates in language pull down and general template in a second pull down, and may be you can all in a third one.
the "open in new window" button is fine with me, yet if you can default the new document language to the template language, that would be great. so if i chose "alter table add column" template, and click "open in new window", it will show the "ALTER TABLE..." in a new document with the language set to SQL, so all the key words are colored
you suggested somthing like:
of course; what any programmer would perfare is something like:
MyString = "Hello, World."
MyInt = 3
WordCount = getwordcount()
yet I think this is not possible for you as you only deal with functions, so my suggestions to you are:
* Avoid puting a variable in the get functions, so instead of getwordcount("WordCount") use setint("WordCount",getwordcount()) this will make it more stander
* use capital letters as needed so instead of setint("WordCount",getwordcount()) say setInt("wordCount",getWordCount())
also, you need to provide a way to convert strings to numbers some how and handle exceptions, so for example:
setInt("myInt",ToInt("3")) will work, yet setInt("myInt",ToInt("H")) will not, so in the second case either you stop the script with an error or set myInt to 0, and I think the first option is better
4) anything else
well if you want to introduce variables, i think it is time to add conditions (if function), thats for now; and may loops to follow, so here is what I suggest:
that will make it easy to add some loop handling later like
and may be link IFs
lines between the if() and endIf() will run/not run depending on the condition
> My suggestion in here is to have the templates linked to the supported languages some how
I'm planning to eventually allow you to categorize your favorite scripts, and I'm considering allowing you to group scripts by language and have them only available for certain languages. There's no reason I couldn't do the same with templates.
> if you can default the new document language to the template language, that would be great.
I'll keep this in mind when I get to that point.
> MyString = "Hello, World."
I agree that it would be nicer to do it that way, but introducing the concept of operators in Simple Script would require a major rewrite.
> * Avoid puting a variable in the get functions, so instead of getwordcount("WordCount") use setint("WordCount",getwordcount()) this will make it more stander
Nested functions aren't planned until I start working on a more robust scripting language, which may be a different plugin entirely.
However, I came up with a great idea last night. I could add auto-updating, read-only variables. For example, Wordcount could be a variable that each time you read it, runs a function to count the number of words in the document. For performance reasons, I would recommend storing it as a regular variable if you need to use it more than once, so that you don't have to keep calling it. i.e. setint("Mywordcount","Wordcount")
> also, you need to provide a way to convert strings to numbers
Your method uses nested functions again, but there's no reason I couldn't have a function that takes a string value and stores it in an integer variable. For example:
(Of course, the name of the function is still open for debate)
Since StringToBeConverted could itself be a variable, this should handle the conversion fine.
I hadn't thought of using an operator as a parameter to a function. That's an interesting idea.
I had a different idea about If statements that I was planning to do when I create a more robust scripting language in the future, but now I'll have to go back and re-think it.
Thanks for your suggestions.
In this thread:
there's a discussion of code snippets, and how Simple Script can almost, but not quite, do this.
I think the idea of code snippets is very similar to the idea of templates. However I end up deciding to implement templates, I need to add two things to Simple Script in order to provide the functionality desired by the original poster in the above thread:
1) An option to run a script on blank text and insert the result into the document at the cursor position.
2) A function to append two pieces of text, one to the front and one to the back. For example:
surround(fronttext,backtext): Places fronttext at the beginning of the document and backtext at the end of the document.
("Document" in the above means either the selected text if there is text selected, the full document if there isn't, or blank text if the option to insert text into the cursor position is selected)
I have some more thoughts on templates, but it's getting late and I need to sleep on it. Hopefully in the morning I'll have a clearer idea of what I'm thinking of.
Okay, I think I've mostly figured out how I want to implement templates.
Because I want to keep to the original goal of a scripting plugin, templates will still be stored as scripts. However, there's nothing wrong with including an interface to automatically generate the script from a document. I can do this all behind the scenes, but still provide an interface to edit the script itself.
For instance, I could have a "Templates" tab on the Script Writer window that stores all of the templates. To add a new one, you create your template in Notepad++ then click a button on the Templates tab, which basically runs a script that does some processing on each line of the text, including wrapping it in an "add" function, but instead of putting the result back out to the document, it stores the result internally as a script on the Templates tab. You can then run this particular script by double-clicking on it.
There would also be a way to design scripts by hand and add them as a template.
Any script stored as a template would automatically open a new document before running it.
There would be something similar for code snippets, although this is a little trickier because there are actually two pieces of text that need to be stored (beginning and ending tags), so you can't just design them in Notepad++. I'll have to think about this a little more.
Code snippets, though still technically scripts, would replace the selection if there is text selected or insert at the cursor position if there isn't.
In summary, there would be three different ways scripts could run:
1) Standard. Replaces the entire document if no text is selected.
2) Template. Always opens a new document.
3) Code Snippet. Inserts if no text is selected.
I could provide options to run any of the three types of scripts as any of the others, e.g. open a new document when you double-click on a code snippet.
What do you think of this idea?
> templates will still be stored as scripts.
> click a button on the Templates tab, which basically runs a script that does some
> processing on each line of the text...
This isn't like your original idea, which I guess would treat templates like in my opinion they are (meant to be):
> Hello, <<%Name%>>. You are <<%Name%>>, are you not? My name is <<%Name2%>>.
If you store these pseudo-templates as scripts, where will the templates themselves be left? Does a user have to store them himself? It's not very convenient to have to edit the pseudo-template script, as being able to store and edit the template itself would be.
I could see three ways of doing this.
1) One would be to generate the script based upon adding the lines from the document one by one.
As long as I add "GetVariables()" and "ReplaceVariables()" onto the end of each template script, it should still work just fine.
Hello, <<%Name%>>. You are <<%Name%>>, are you not? My name is <<%Name2%>>.
would be converted into the following template script:
add("Hello, <<%Name%>>. You are <<%Name%>>, are you not? My name is <<%Name2%>>.")
2) The second way would be to store the text itself, and generate the script only when you want to open the template. The advantage of this would be that I could provide an interface to edit the text, but the disadvantage would be that you couldn't edit the script that opens the template. This wouldn't allow the possibility of creating template scripts manually.
The third way would be a compromise between the two: You store templates as both text and a script. I could add a function appendtemplatetext(templatetextname). You could still edit the script that opens the template in a new document, and I would still provide an interface to edit the text itself.
For example, you might store the "Hello" text in example 1 above as a template text called "Hello".
When you save it, it automatically creates a template script, also called "Hello" which is simply the following:
That would just be a default, however. You're free to modify the script however you want. You could also modify the text behind the script. I would try to make both of these features simple to get to (e.g. a button for each on the Template window)
You could still create template scripts manually in case you don't want to work from stored text.
In fact, by modifying the scripts, you could even string multiple template texts together. e.g.
This method solves most of the problems; however, it seems to be a little more complicated than I would like, and perhaps confusing for the user. The most important thing would be to work out some kind of terminology to distinguish between the stored text and the script that loads it.
3b) A variation of option (3), I could store the template texts externally as files on the hard drive. Templates then would be similar to Favorites, in that they load a file when you run them. The actual templates would still be scripts underneath, but they would have an "appendfile" function instead of an "appendtemplatetext" function by default.
> This wouldn't allow the possibility of creating template scripts manually.
I don't see how this would be. I think it should always be possible to create (and edit) template scripts manually. They are just the same as normal scripts, right? This also explains why loading two templatetexts, as in the example, is no special case. A template script will just be a standard translation for a template.
I suggest to create a list of templates similar to Favorite scripts. You could add a third list, which would simply contain Template Scripts, automatically generated if a Template is applied/executed. A simple option could be used to either execute immediately, or just generate the Template Script and stop then, to allow manual editing.
> some kind of terminology to distinguish between the stored text and the script that
> loads it
Why is some terminology needed? If you store Templates and Template Scripts in different locations, I don't see the problem.
> surround(fronttext,backtext): Places fronttext at the beginning of the document and
> backtext at the end of the document.
Just to extend this, which may lead to a more simple implementation, it could be made possible to refer to the selected text, being either the complete document, a selection, or no selection at all, as a variable. This would allow using it more than once in a template. For example, to create a link the template could look something like:
I'm not sure I understand what you're saying. Could you explain in a little more detail please?
Using a template to create an HTML link from a selected text, like this:
This is the selected text
The template would look something like this:
When you select the text and execute the template the result would be:
<a href="This is the selected text">This is the selected text</a>
This would require to be able to refer to the text selection by some kind of variable.
(1) Tiny changes:
+ make the description area and the tree view resizable
+ if we could somehow parse the source code (even as simply as the function-list plugin does) your simple script GUI controls are a way of displaying class methods and variables with a documentation snippet as well!
(2) Major feature:
+ is there some way for it to trap keyboard entries of characters like '.' or phrases like '->'? This will ensure that we can write simple-script to make custom "intellisense" or intelligent auto-complete help pop-up etc.
I would have written the code, but for the fact that I am not well-versed with C++
If anything like this is already there, kindly point it out.
A BIG Thanks !!
(to both Don and you)
> make the description area and the tree view resizable
I suppose I could do that.
> if we could somehow parse the source code (even as simply as the function-list plugin does) your simple script GUI controls are a way of displaying class methods and variables with a documentation snippet as well!
I'm not sure I understand what you're asking for here.
> is there some way for it to trap keyboard entries of characters like '.' or phrases like '->'?
I wish I knew how to do it, because I had some other ideas for plugins that would use this.
> I would have written the code, but for the fact that I am not well-versed with C++
It's actually written in Delphi rather than C++, but if you don't know Delphi either, that's a moot point.
Thanks for the suggestions.
Here is my contribution again, now in this thread:
Perhaps creating a new document could be done by using a list similar to the favorites, but without each template having to be activated or formed by some kind of script. I think it would work best if the Simple Script would simply create the document from its own list of favorite( template)s, when an item is double clicked, for example. Creating would mean performing the steps descibed above: creating a new document, copying the template into it, leaving the user with the need to name his file as soon as he wants to save it, but allowing him to directly edit it.
This way, it wouldn't be necessary to create both a template _and_ a script to use that template in order to create a file with those contents. Having to write a standard script for each template (possibly by using a template for that...) is just one more step to make it less convenient.
Perhaps the Simple Script Plug-In could be extended somehow to support both scripts and templates, allowing code to be generated from some kind of "standardized" input.
I am thinking of simple SQL scripts I write for adding columns to a table. Perhaps this could be automated in some way, based on a simple template containing some default code or possibly multiple (parts of a) template(s). The user-made code generate script could then contain function calls to create the full script by (combining the parts of the template and) replacing some identifier words like #TableName# by the correct tablename read from another template, file or list. The same goes for columns to be added, including their types etc. I believe the Simple Script Plug-In currently doesn't have loop functionality to read items from a list and/or repeat actions, but adding this would enable this kind of extended "automated" code scripting. How do you feel about this?
This could possibly also be done by storing information from a file (or) list in variables, something like ReadLine/ReadVariable( FromFile, VariableToStoreLineIn ).
The file could possibly be read into a (new) document first to avoid have to double code some steps, so the lines could simply be read from the document, but of course the document will have to be created then.
I agree that having it be able to load a template without requiring a script would be easier. My main concern is that this is entirely separate from the purpose of Simple Script in the first place. While using a script to generate a new document makes sense, you're talking about having a separate section that has nothing to do with scripts. That might be getting a little too far from the original purpose of the plugin. I'll consider it, but I don't know if I'm willing to go that far.
Your example of SQL scripts to add columns to a table sounds like something that the merge function could handle, although not in its current state. Once I start introducing variables, I plan to change the behavior of the merge function so that it doesn't work from the clipboard, but directly from a text parameter (usually a variable). I could definitely add functions to read in variables from a file. If you read the entire file into a single variable, you could then use the merge function to generate the script.
This is another bonus of using scripts to generate the document; so that you could do things like that.
The other thing I was thinking was a way to let the user input data directly when it loads the template. In essence, there would be a syntax for defining variables in the document, and a function to look up all of these variables, prompt the user for their values, and then replace them all in the document. Or maybe two functions: one to read in the variables from the document, and one to replace them. That way you could read the variables to use them later without having to replace them immediately.
For example, if the document is:
Hello, <<%Name%>>. You are <<%Name%>>, are you not? My name is <<%Name2%>>.
and you run the functions:
GetVariables(): Prompts the user for the values of all of the variables in the document.
ReplaceVariables(): Replaces all variables in the document with their respective values.
It would recognize <<Name>> and <<Name2>> as variables. It would prompt the user for the values of these two variables, then replace them, resulting in something like:
Hello, John. You are John, are you not? My name is Larry.
It would be sort of a "Mad Libs" style of replacing variables with user-entered data.
I finally have the time to take a look at your Simple Script (after struggling with releases v4.7.x).
It's quite impressive!
One remark : the message box may confuse user while there's a parsing error in the script.
The title should be "Simple Script" instead of "Notepad++" IMO.
Regarding the crash issue, beyond the delphi, I may be helpful.
Otherwise, my opinion is : it's always better to not provide a buggy feature, especially if it contains the critical bug.
I post your plugin on Notepad++ download page :
Let me know if you want to modify any information.
> The title should be "Simple Script" instead of "Notepad++" IMO.
Good call. I hadn't even noticed that before. Unfortunately, I'm just using the standard Delphi ShowMessage function for that, which means I don't have any control over the title. I could create a new form for it and program it directly, but it's a little too much work for just a cosmetic change. I think I'll leave it how it is unless it becomes a more serious problem.
> it's always better to not provide a buggy feature, especially if it contains the critical bug.
I agree. Assuming I can't get the issue resolved, my latest thought on the crash issue is to leave the form undocked by default, but allow you to manually set an option in the .ini file that overrides this default behavior. If you set this option, the form will be docked when you start it up, otherwise it won't. I will document it in the Readme file with a warning. That way, the only people who can potentially encounter the bug are those who have already been warned about it.
> I post your plugin on Notepad++ download page
Thanks. Since all of the other plugins on the n++ plugins project page are also on the download page, I figured Simple Script would get there eventually, but I didn't want to bug you about it, especially since you've been working so hard on the 4.7.x recently. As my work on the docking form issue will attest, I know what it feels like to have problems appear in newly written code that require an emergency effort to fix.
> Unfortunately, I'm just using the standard Delphi ShowMessage function for that, which means I don't have any control over the title.
You can use
with CreateMessageDialog(Msg, DlgType, Buttons) do
Caption := 'Simple Script';
Position := poScreenCenter;
Result := ShowModal;
I haven't checked at your current code to see whether you're using the return result of ShowMessage. If not, then you can just call ShowModal as a procedure rather than a function.
Thanks. I'll try that.
I'm not using any return value, so I'll just do it as a procedure, like you said.
Where can I get ahold of your source? I'll take a look at it, as I had similar problems with Dbgp. Can't guarantie a solution tho.
You can download the source from the same place that you download the binary:
Just to point you in the right direction, here's what I did:
I inherited the TScriptWriter form from TNppDockingForm, and set a variable in it that points to the Tsimplescriptplugin object that creates the form, so that I can call the Tsimplescriptplugin methods from the form itself.
After I show the form for the first time (in TSimpleScriptPlugin.RunScript function in simplescriptplugin module) I call the RegisterDockingForm function. The "DoOnce" variable is to make sure it only happens once. That was the only change between the 1.07 and 1.08 versions.
I also made a slight modification to TNppPlugin.RegisterDockingForm function in nppplugin.pas. Now it takes a parameter telling it where to dock the form (left, right, etc). It defaults to Left if you leave out the parameter.
Thanks for any help you can give me.
I finally had time to look at your code. One thing I see is that you create ScriptWriterForm to soon.
You do this in the SimpleScriptPlugin constructor. At that time SetInfo callback is not yet called (by notepad) and the parent handle (NppHandle) is not yet known.
Try to move the creation of this form to FuncRunScript. At that time all needed resources are already set up.
I changed this and it seems that things work, but when I exit notepad all shit crashes. You'll have to move the needed destructos to the right places. q:)
I hope this helps for now. I'll give it another look when I can.
And thanks for the patch to the framewrok.
I tried your suggestion, but unfortunately it didn't seem to help. I moved the line to FuncRunScript (and wrapped it in an "If ScriptWriterForm=nil" to make sure it wasn't already created) but when I undock the form and then click the Validate button, Notepad++ still freezes.
In fact, doing it this way introduces a new, seemingly unrelated, problem. Now I can't make a new line in the script because ENTER seems to be disabled in the Script Writer window. Changing it back so that the form is created in the simplescriptplugin constructor fixes this problem.
I wonder if it's a difference in our compilers. I've tried it on Delphi 6 and Delphi 7 and both seem to do the same thing. What version of Delphi are you using?
I use Delphi 6.
I'll give it another go. Perhaps I just didn't trigger the bug.
But as I said, freezes are usual for "window parent problem". It might even be, that this is not fixable. Delphi is a complex wrap arround Windows API and god knows what goes on in there. q:)
This is not directly related to Simple Script but GExperts which can be obtained from http://www.gexperts.org/ provides some enhancements to the Delphi IDE one of which is a message box wizard. It also has a directory cleaner to purge junk files after a programming session. The code librarian is also a nice tool.
Sign up for the SourceForge newsletter:
You seem to have CSS turned off.
Please don't fill out this field.