Python auto-indentation in ScintillaNET - python

i am working on a Winforms application with ScintillaNET. I realized that ScintillaNET itself has no auto-indentation feature. You would have to create one yourself. I have searched online and found a solution to auto-indenting with curly brackets: Auto-indenting with curly brackets.
I decided to make an auto indentation feature for python in ScintillaNET. Since Python's syntax does not use curly brackets, but instead a :, the referenced code does not apply. So to i tried to make use of the InsertChecked feature to check for auto-indenting triggers before a new line. Basically if the user types a : and afterwards adds a new line \n, that is an indication that a condition/class or definition is defined.
To make sure that we don't misinterpret what the user is trying to do, say that in Python, you do string[1:2] to get a substring, then this feature will not apply. We can make sure by doing the following.
if (caretPosition != 0 && caretPosition != ScintillaControl.Text.Length) //if not at the end or start
{
}
But so far, i have a function that just auto indents after : but does not increment that indent by 4 per last line. It's weird because it should be able to get the last line length, then add by 4 (indent). It's very hard to explain, i have provided a GIF image below:
So, anyone have a better implementation of what i'm trying to figure out? Or a function that takes the last line length then adds auto indents once a trigger char appears? Here's my code:
private void textarea_InsertCheck(object sender, InsertCheckEventArgs e)
{
if ((e.Text.EndsWith("\r") || e.Text.EndsWith("\n")))
{
var curLine = TextArea.LineFromPosition(e.Position);
var curLineText = TextArea.Lines[curLine].Text;
var indent = Regex.Match(curLineText, #"");
if (Regex.IsMatch(curLineText, #":"))
e.Text += '\t';
}
}
Help me on this one guys.

Alright, i see that no one has an idea to implement this, but THANK GOD i've been doing some research and found this old thread invisible to search engines that explains what i'm looking for: https://github.com/jacobslusser/ScintillaNET/issues/137
Whew.

Related

Write a custom JSON interpreter for a file that looks like json but isnt using Python

What I need to do is to write a module that can read and write files that use the PDX script language. This language looks alot like json but has enough differences that a custom encoder/decoder is needed to do anything with those files (without a mess of regex substitutions which would make maintenance hell). I originally went with just reading them as txt files, and use regex to find and replace things to convert it to valid json. This lead me to my current point, where any additions to the code requires me to write far more code than I would want to, just to support some small new thing. So using a custom json thing I could write code that shows what valid key:value pairs are, then use that to handle the files. To me that will be alot less code and alot easier to maintain.
So what does this code look like? In general it looks like this (tried to put all possible syntax, this is not an example of a working file):
#key = value # this is the definition for the scripted variable
key = {
# This is a comment. No multiline comments
function # This is a single key, usually optimize_memory
# These are the accepted key:value pairs. The quoted version is being phased out
key = "value"
key = value
key = #key # This key is using a scripted variable, defined either in the file its in or in the `scripted_variables` folder. (see above for example on how these are initially defined)
# type is what the key type is. Like trigger:planet_stability where planet_stability is a trigger
key = type:key
# Variables like this allow for custom names to be set. Mostly used for flags and such things
[[VARIABLE_NAME]
math_key = $VARIABLE_NAME$
]
# this is inline math, I dont actually understand how this works in the script language yet as its new. The "<" can be replaced with any math symbol.
# Valid example: planet_stability < #[ stabilitylevel2 + 10 ]
key < #[ key + 10 ]
# This is used alot to handle code blocks. Valid example:
# potential = {
# exists = owner
# owner = {
# has_country_flag = flag_name
# }
# }
key = {
key = value
}
# This is just a list. Inline brackets are used alot which annoys me...
key = { value value }
}
The major differences between json and PDX script is the nearly complete lack of quotations, using an equals sign instead of a colon for separation and no comma's at the end of the lines. Now before you ask me to change the PDX code, I cant. Its not mine. This is what I have to work with and cant make any changes to the syntax. And no I dont want to convert back and forth as I have already mentioned this would require alot of work. I have attempted to look for examples of this, however all I can find are references to convert already valid json to a python object, which is not what I want. So I cant give any examples of what I have already done, as I cant find anywhere to even start.
Some additional info:
Order of key:value pairs does not technically matter, however it is expected to be in a certain order, and when not in that order causes issues with mods and conflict solvers
bool properties always use yes or no rather than true or false
Lowercase is expected and in some cases required
Math operators are used as separators as well, eg >=, <= ect
The list of syntax is not exhaustive, but should contain most of the syntax used in the language
Past work:
My last attempts at this all revolved around converting it from a text file to a json file. This was alot of work just to get a small piece of this to work.
Example:
potential = {
exists = owner
owner = {
is_regular_empire = yes
is_fallen_empire = no
}
NOR = {
has_modifier = resort_colony
has_modifier = slave_colony
uses_habitat_capitals = yes
}
}
And what i did to get most of the way to json (couldnt find a way to add quotes)
test_string = test_string.replace("\n", ",")
test_string = test_string.replace("{,", "{")
test_string = test_string.replace("{", "{\n")
test_string = test_string.replace(",", ",\n")
test_string = test_string.replace("}, ", "},\n")
test_string = "{\n" + test_string + "\n}"
# Replace the equals sign with a colon
test_string = test_string.replace(" =", ":")
This resulted in this:
{
potential: {
exists: owner,
owner: {
is_regular_empire: yes,
is_fallen_empire: no,
},
NOR: {
has_modifier: resort_colony,
has_modifier: slave_colony,
uses_habitat_capitals: yes,
},
}
}
Very very close yes, but in no way could I find a way to add the quotations to each word (I think I did try a regex sub, but wasnt able to get it to work, since this whole thing is just one unbroken string), making this attempt stuck and also showing just how much work is required just to get a very simple potential block to mostly work. However this is not the method I want anymore, one because its alot of work and two because I couldnt find anything to finish it. So a custom json interpreter is what I want.
The classical approach (potentially leading to more code, but also more "correctness"/elegance) is probably to build a "recursive descent parser", from a bunch of conditionals/checks, loops and (sometimes recursive?) functions/handlers to deal with each of the encountered elements/characters on the input stream. An implicit parse/call tree might be sufficient if you directly output/print the JSON equivalent, or otherwise you could also create a representation/model in memory for later output/conversion.
Related book recommendation could be "Language Implementation Patterns" by Terence Parr, me avoiding to promote my own interpreters and introductory materials :-) In case you need further help, maybe write me?

I do not understand why this function reverses the string

This function requests a string input and reverses it. For some reason, I just cannot wrap my head around the logic behind it.
def reverse(s):
new = ""
for i in s:
print(new)
new = i + new
return new
oldStr = input("String?")
newStr = reverse(oldStr)
print(newStr)
print(reverse("good bye"))
A friend suggested I print the variable new in the string which I added and it helped a little, but I just don't understand it.
It looks to me as if you are in a stage where you want to learn how to debug small programs.
For questions on StackOverflow, you want to provide a minimal reproducible example. What does that mean in your case?
"repoducible" means that you should not depend on user input. Replace user input by hardcoded values.
"minimal" means that you don't call the function twice. Once is enough.
For that reason, I'll not walk you through your original program, but through this one instead:
def reverse(s):
new = ""
for i in s:
print(new)
new = i + new
return new
print(reverse("abcdef"))
I'll use a free program called PyCharm Community Edition. You set a breakpoint where you want to understand how things work. Since you don't understand the reverse() method, put it right at the beginning of that method. You do that by clicking between the line number and the text:
Even if your code has no bug, go to the Run/Debug menu:
Execution will stop at the breakpoint and you'll now be able to see all the variables and step through your code line by line.
Look at all the variables after each single line. Compare the values to what you think the values should be. If there is a mismatch, it's likely a misunderstanding on your side, not by Python. Do that a few times and it'll be obvious why and how the string is reversed.
Let analysis it:
Iteration 1:
new = 'A', i = g
Perform new = i + new : new = gA
Iteration 2:
new = gA, i = o
Perform new = i + new: new = ogA
.
.
.
This happens because we add new i before we add the existing string from previous iteration.
the key is in "new = i + new" note that new is the previous iteration character and is in the right side of the current character, this cause the string to reverse

How to insert a random element on a Anki card?

On Anki, the front of a card have "X+Y?" and the back shows "Z". For example, front "4+7?" and back "11" But I want next time that I see this card the numbers be different, randomizing the X, Y and Z elements. This could be possible picking the values from a pool previously defined by me, I guess.
Searching it on here, I found this code:
import random
foo = ['a', 'b', 'c', 'd', 'e']
print(random.choice(foo))
How can I put it to work on Anki? Because I just tried to copy it and paste in card model editor, but nothing happened. Sorry, I'm not a programmer, so I'd be grateful to know anything that can help me functionalize this random display. Thanks for your time.
Even though it is possible (but convoluted to make it happen), it is usually (very heavily) discouraged to make use of random content on Anki. The reason is the following: if some content has a change of being displayed at the front of a card, then it means you want to memorize it. But then, it means that you are bloating several things that you want to learn into a single card. For several reasons (among which: Anki is optimized to work with the assumption that each card corresponds to a single, atomic thing you want to learn. Breaking that assumption can only make it work worse, which in the end makes you spend more time trying to learn that stuff), it's better to just have a card for each possible thing you want to learn.
Edit having read my words of warning, I'll leave you judge of whether it's really a good decision to do what you want.
The first thing to understand is that even though Anki is mainly written in Rust and Python (which are two programming languages), and even though it supports add-ons written in Python, it's not Python (nor Rust) that should be used for this purpose. I say this because the snippet of code you provided is written in Python.
The reason behind this is that Anki uses webviews to render cards, which means that when you see a card, it's just like if you were seeing a website. Therefore, if you only want execute code when you are reviewing the cards (and not, say, automatically generate cards), the language you have to use is JavaScript. Unfortunately, I am not a JavaScript programmer, so my answer may suck. Fortunately, JavaScript is a rather simple programming language, very well documented, and your request is simple enough for me not to have much room to screw the code (meaning this answer should not suck too much). This being said, let's make it work:
Add a field to your notes that will hold the possible values that will be shown. To make it simple, let's assume none of these values will contain commas, so that we can simply write the values comma-separated. Let's say you called this field Values (rename it as you like). By default, it's going to pick the first of these values if it cannot pick at random. More on this at the end.
Now open the template edit window for this note. If you are in the browser, it should be the Cards... button.
Select Front Template (it should be selected by default). At the top of the template, add the following, which is code that will allow the randomly chosen value to be kept also when you reveal the answer (because by default it would just re-evaluate the whole script, picking at random again).
<script>
// v1.0.0 - https://github.com/SimonLammer/anki-persistence/blob/cd2ca88e019dc3b8f32dad623932c1eabdba7e21/script.js
if(void 0===window.Persistence){var _persistenceKey="github.com/SimonLammer/anki-persistence/",_defaultKey="_default";if(window.Persistence_sessionStorage=function(){var e=!1;try{"object"==typeof window.sessionStorage&&(e=!0,this.clear=function(){for(var e=0;e<sessionStorage.length;e++){var t=sessionStorage.key(e);0==t.indexOf(_persistenceKey)&&(sessionStorage.removeItem(t),e--)}},this.setItem=function(e,t){null==t&&(t=e,e=_defaultKey),sessionStorage.setItem(_persistenceKey+e,JSON.stringify(t))},this.getItem=function(e){return null==e&&(e=_defaultKey),JSON.parse(sessionStorage.getItem(_persistenceKey+e))},this.removeItem=function(e){null==e&&(e=_defaultKey),sessionStorage.removeItem(_persistenceKey+e)})}catch(e){}this.isAvailable=function(){return e}},window.Persistence_windowKey=function(e){var t=window[e],n=!1;"object"==typeof t&&(n=!0,this.clear=function(){t[_persistenceKey]={}},this.setItem=function(e,n){null==n&&(n=e,e=_defaultKey),t[_persistenceKey][e]=n},this.getItem=function(e){return null==e&&(e=_defaultKey),null==t[_persistenceKey][e]?null:t[_persistenceKey][e]},this.removeItem=function(e){null==e&&(e=_defaultKey),delete t[_persistenceKey][e]},null==t[_persistenceKey]&&this.clear()),this.isAvailable=function(){return n}},window.Persistence=new Persistence_sessionStorage,Persistence.isAvailable()||(window.Persistence=new Persistence_windowKey("py")),!Persistence.isAvailable()){var titleStartIndex=window.location.toString().indexOf("title"),titleContentIndex=window.location.toString().indexOf("main",titleStartIndex);titleStartIndex>0&&titleContentIndex>0&&titleContentIndex-titleStartIndex<10&&(window.Persistence=new Persistence_windowKey("qt"))}}
</script>
This code comes from anki persistance. Also, when editing templates, please do not write values above the snippet, always under (it won't change how it renders, but it will ensure all this code is loaded before you do anything else).
Select the Back Template, and add the following snippet at the top of the template (it's the same thing as before):
<script>
// v1.0.0 - https://github.com/SimonLammer/anki-persistence/blob/cd2ca88e019dc3b8f32dad623932c1eabdba7e21/script.js
if(void 0===window.Persistence){var _persistenceKey="github.com/SimonLammer/anki-persistence/",_defaultKey="_default";if(window.Persistence_sessionStorage=function(){var e=!1;try{"object"==typeof window.sessionStorage&&(e=!0,this.clear=function(){for(var e=0;e<sessionStorage.length;e++){var t=sessionStorage.key(e);0==t.indexOf(_persistenceKey)&&(sessionStorage.removeItem(t),e--)}},this.setItem=function(e,t){null==t&&(t=e,e=_defaultKey),sessionStorage.setItem(_persistenceKey+e,JSON.stringify(t))},this.getItem=function(e){return null==e&&(e=_defaultKey),JSON.parse(sessionStorage.getItem(_persistenceKey+e))},this.removeItem=function(e){null==e&&(e=_defaultKey),sessionStorage.removeItem(_persistenceKey+e)})}catch(e){}this.isAvailable=function(){return e}},window.Persistence_windowKey=function(e){var t=window[e],n=!1;"object"==typeof t&&(n=!0,this.clear=function(){t[_persistenceKey]={}},this.setItem=function(e,n){null==n&&(n=e,e=_defaultKey),t[_persistenceKey][e]=n},this.getItem=function(e){return null==e&&(e=_defaultKey),null==t[_persistenceKey][e]?null:t[_persistenceKey][e]},this.removeItem=function(e){null==e&&(e=_defaultKey),delete t[_persistenceKey][e]},null==t[_persistenceKey]&&this.clear()),this.isAvailable=function(){return n}},window.Persistence=new Persistence_sessionStorage,Persistence.isAvailable()||(window.Persistence=new Persistence_windowKey("py")),!Persistence.isAvailable()){var titleStartIndex=window.location.toString().indexOf("title"),titleContentIndex=window.location.toString().indexOf("main",titleStartIndex);titleStartIndex>0&&titleContentIndex>0&&titleContentIndex-titleStartIndex<10&&(window.Persistence=new Persistence_windowKey("qt"))}}
</script>
Go back to Front Template, and add the following where you want the value to be shown. If you don't know, just put it anywhere, check at the end where it renders well, and change it then, so you have visual feedback. Also avoid having other tags with id=values.
<div id="values">{{Values}}</div>
If you renamed the field Values, change the one between double braces too.
6. Add at the bottom of the template the following. This will be responsible for picking a value at random.
<script>
var valuesNode = document.getElementById("values");
var values = valuesNode.innerText.split(',');
var defaultValue = values[0];
var value = defaultValue;
if (Persistence.isAvailable()) {
value = Persistence.getItem();
if (value == null) {
value = values[Math.floor(Math.random() * values.length)];
Persistence.setItem(value);
}
}
valuesNode.innerText = value;
</script>
Go to the Back Template, and add the following where you want the value to be shown (just like in the front template):
<div id="values">{{Values}}</div>
At the bottom of the template, add the following. This will be responsible for showing the randomly picked value when showing the answer.
<script>
var valuesNode = document.getElementById("values");
var values = valuesNode.innerText.split(',');
var defaultValue = values[0];
var value = defaultValue;
if (Persistence.isAvailable()) {
value = Persistence.getItem();
Persistence.clear();
}
valuesNode.innerText = value;
</script>
Here I'm going to explain why there is a default value. This is due to the fact that several Anki clients handle JavaScript differently. anki persistance should work when you are reviewing, but it may not work when you are previewing a card. In these cases, it could still pick a random value, but when you would reveal the answer it could not "remember" which value it picked, so it would pick an other one at random. To prevent that, if it knows it will not remember, it will just pick the default one, so it's consistent when you reveal the answer.

What is equivalent of Perl DB_FILE module in Python?

I was asked by my supervisor to convert some Perl scripts into Python language. I'm baffled by few lines of code and I am also relatively inexperienced with Python as well. I'm an IT intern, so this was something of a challenge.
Here are the lines of code:
my %sybase;
my $S= tie %sybase, "DB_File", $prismfile, O_RDWR|O_CREAT, 0666, $DB_HASH or die "Cannot open: $!\n";
$DB_HASH->{'cachesize' } = $cache;
I'm not sure what is the equivalent of this statement in Python? DB_FILE is a Perl module. DB_HASH is a database type that allows arbitrary keys/values to be stored in data file, at least that's according to Perl documentation.
After that, the next lines of code also got me stumped on how to convert this to the equivalent in Python as well.
$scnt=0;
while(my $row=$msth->fetchrow_arrayref()) {
$scnt++;
$srow++;
#if ($scnt <= 600000) {
$S->put(join('#',#{$row}[0..5]),join('#',#{$row}[6..19]));
perf(500000,'sybase') ;#if $VERBOSE ;
# }
}
I'll probably use fetchall() in Python to store the entire result dataset in it, then work through it row by row. But I'm not sure how to implement join() correctly in Python, especially since these lines use range within the row index elements -- [0..5]. Also it seems to write the output to data file (look at put()). I'm not sure what perf() does, can anyone help me out here?
I'd appreciate any kind of help here. Thank you very much.

Zapier: Code not returning all values expected

I am working with Code by Zapier and having trouble telling if my regex is wrong or some other part is wrong ( I think the latter)
I am pulling a URL, this URL has several 9 digit IDs that get appended to the end of the URL. I was told to try and extract these IDs and rebuild the URLs so we can post API calls for each of them.
I am a Python newb but so far I have this but it only returns the first 9 digit ID, I am hoping for an array so I can rebuild the URLS with each specific ID. This is my code so far:
import re
urls = re.findall(r'\b\d+\b', input_data['input'])
return [
{'url': url} for url in urls
]
The input _data would be "https://api.helpscout.net/v1/conversations/123456789,098765432.json"
As I said, it just returns the first ID. I know I don't have the code to rebuild the URLs or anything just trying to take it one step at a time!
IS my regex incorrect or the way I am returning them? Thanks!
David here, from the Zapier Platform team. I've got good news and bad news.
Good news is, your regex works! So no sweat there. Downside, you're running into a weird corner case with code steps. It's not documented because we don't encourage its use (it's confusing, as you can tell). When you return an array from a code step, it functions like a trigger. That is, subsequent steps run for each item in the array (but the UI only shows the first).
If that's the desired behavior, you can safely ignore the weird test and complete the zap. If you don't want to fan out, you should instead parse out the comma separated string and act on it later.
If you need more direction, let me know a bit about what your other actions are and I can advise from there.
Side note, the reason you're seeing the error message with Willem's function above is that your python code must either set the output variable to a value or return an object. Either of return get_digits(input_data['input']) or output = get_digits(input_data['input']) should work.
The code works correct on my machine:
import re
def get_digits(s):
return [{'url':url} for url in re.findall(r'\b\d+\b',s)]
If I then call this with the sample input, I get:
>>> get_digits("https://api.helpscout.net/v1/conversations/123456789,098765432.json")
[{'url': '123456789'}, {'url': '098765432'}]
So a list with two dictionaries. Each dictionary contains one key, a 'url' that is associated with the string that contains one or more digits.
In case you want to match only nine-digit sequences, you can make the regex more restrictive (but this can only decrease the number of matches):
import re
def get_digits(s):
return [{'url':url} for url in re.findall(r'\b\d{9}\b',s)]
Argh so frustrating, I decided to try JavaScript and multiple methods don't output anything
<script>
var str = "https://api.helpscout.net/v1/conversations/382411278,374879346,374879343.json";
var tickets = str.match(/\d{9}/g);
for(var i = 0; i<tickets.length; i++)
{
document.write("https://api.helpscout.net/v1/conversations/"+tickets[i]+".json</br>")
}
or
<p id="demo"></p>
<script>
function myFunction() {
var str = "https://api.helpscout.net/v1/conversations/382411278,374879346,374879343.json";
var tickets = str.match(/\d{9}/g);
for(var i = 0; i<tickets.length; i++)
{
document.getElementById("demo").innerHTML +="https://api.helpscout.net/v1/conversations/" +tickets[i] + "<br />"
}
}
</script>

Categories