-
Posts
7,103 -
Joined
-
Days Won
88
Content Type
Forums
Downloads
Forum Articles
Events
Everything posted by TheDcoder
-
Smtp Mailer That Supports Html And Attachments.
TheDcoder replied to Jos's topic in AutoIt Example Scripts
@Jos Awesome, maybe these changes should be merged into the UDF in the first post since AutoIt uses unicode strings anyway, what do you think? -
Smtp Mailer That Supports Html And Attachments.
TheDcoder replied to Jos's topic in AutoIt Example Scripts
@Jos Nice! I will try it out soon. Would the same technique also work for the message body? -
Smtp Mailer That Supports Html And Attachments.
TheDcoder replied to Jos's topic in AutoIt Example Scripts
Awesome UDF But I have a minor issue, can I use unicode characters in the sender name? I tried it but all I see is question marks in the received email. -
@jyotisshetty Yes! Fully agree
-
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
To prevent this topic from turning into a discussion on bitwise operations, I will post an update on the progress In the last updated I showed off the parser I wrote... unfortunately it turns out it isn't capable of handling pretty much anything other than infix binary operators . So I had to go back and start from scratch, I read many articles again to see how they handled expressions, the problem with these articles is that they use object-oriented programming which is hard to follow... so it took me a long time to finally grasp the concept driving all the recursive decent parsers I had been reading about. So I wrote my own parser in JavaScript as a proof of concept, I chose JS because I am familiar with it and it is easier to write high-level code in it, not to mention that it runs in any computer with a browser. Here is the code: /* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ const TokenType = { CONSTANT: Symbol("Constant"), OPERATOR: Symbol("Operator"), BRACKET: Symbol("Bracket"), }; const Operation = { INVERT: Symbol("Invert"), NEGATE: Symbol("Negate"), ADD: Symbol("Add"), SUBTRACT: Symbol("Subtract"), MULTIPLY: Symbol("Multiply"), DIVIDE: Symbol("Divide"), EXPONENTIATE: Symbol("Exponentiate"), ASSIGN: Symbol("Assign"), SINE: Symbol("Sin"), LOG: Symbol("Log"), }; const Precedence = [ [Operation.INVERT], [Operation.NEGATE], [ Operation.SINE, Operation.LOG ], [Operation.EXPONENTIATE], [ Operation.MULTIPLY, Operation.DIVIDE, ], [ Operation.ADD, Operation.SUBTRACT, ], [Operation.ASSIGN], ]; Precedence.reverse(); // IMPORTANT Precedence.next = op => Precedence.find(a => a.includes(op)) + 1; const OP_MAP = new Map([ ['!', Operation.NEGATE], ['+', Operation.ADD], ['-', Operation.SUBTRACT], ['*', Operation.MULTIPLY], ['/', Operation.DIVIDE], ['^', Operation.EXPONENTIATE], ['=', Operation.ASSIGN], ['s', Operation.SINE], ['l', Operation.LOG], ]); if (globalThis.process) main(process.argv); function main(args) { const input = args[2]; if (!input) { console.error("No arguments supplied!"); return; } var tokens = tokenize(input); var expression = parse(tokens); expression.raw = input; var output = JSON.stringify(expression, (key, value) => { if (typeof value == 'symbol') return value.description; return value; }, '\t'); console.log(output); return output; } function tokenize(input) { var tokens = []; var constant; for (let i = 0; i < input.length; ++i) { // Parse constants (numbers) constant = ""; while (true) { if (isNaN(parseInt(input[i], 10))) { if (constant) --i; break; } constant += input[i++]; } if (constant) { tokens.push({type: TokenType.CONSTANT, value: parseInt(constant, 10)}); continue; } // Parse operators if (OP_MAP.has(input[i])) { tokens.push({type: TokenType.OPERATOR, value: OP_MAP.get(input[i])}); continue; } // Parse brackets if (input[i] == '(' || input[i] == ')') { tokens.push({type: TokenType.BRACKET, value: {open: input[i] == '('}}); continue; } // Skip whitespace if (input[i] == ' ') continue; // Unknown token, so break out of the loop break; } return tokens; } function parse(tokens, precedence = 0) { var expression = {op: undefined, args: []}; // Unpack a sub-expression (remove the surrounding brackets) if (tokens[0].type == TokenType.BRACKET && tokens[tokens.length - 1].type == TokenType.BRACKET) tokens = tokens.slice(1, tokens.length - 1); switch (Precedence[precedence] ? Precedence[precedence][0] : undefined) { case Operation.INVERT: if (tokens[0].value == Operation.SUBTRACT) { expression.op = Operation.INVERT; push_sub_exp_as_arg(1); } else return next(); break; case Operation.NEGATE: if (tokens[0].type == (expression.op = Operation.NEGATE)) { push_sub_exp_as_arg(1); } else return next(); break; case Operation.SINE: case Operation.LOG: if ( (tokens[tokens.length - 1].value == (expression.op = Operation.SINE)) || (tokens[tokens.length - 1].value == (expression.op = Operation.LOG)) ) { push_sub_exp_as_arg(0, -1); } else return next(); break; case Operation.EXPONENTIATE: case Operation.MULTIPLY: case Operation.DIVIDE: case Operation.ADD: case Operation.SUBTRACT: case Operation.ASSIGN: parse_infix(Precedence[precedence], Precedence[precedence][0] != Operation.ASSIGN); break; default: return tokens[0].value; } return expression; function parse_infix(ops, left_assoc = true) { var op_pos = find_token_index_by_types(ops, left_assoc ? -1 : +1); if (op_pos < 1) return expression = next(); expression.op = tokens[op_pos].value; push_sub_exp_as_arg(0, op_pos); push_sub_exp_as_arg(op_pos + 1); } function find_token_index_by_types(types, direction = +1) { for (let i = (direction > 0 ? 0 : tokens.length - 1); direction > 0 ? i < tokens.length : i >= 0; i += direction) { // Skip sub-expressions (which are in brackets) if (tokens[i].type == TokenType.BRACKET) { var open = 1; do { if (tokens[i += direction].type == TokenType.BRACKET) { open += (direction > 0 ? tokens[i].value.open : !tokens[i].value.open) ? +1 : -1; continue; } } while (open > 0); } if (types.includes(tokens[i].value)) return i; } return -1; } function push_sub_exp_as_arg(start, end) { var sub_exp = parse(tokens.slice(start, end)); expression.args.push(sub_exp); } function next() { return parse(tokens, precedence + 1); } } I know what you are thinking, it's not easy to follow my code, but the reason I wrote it because I wanted to learn the concept... it will be much harder to write code for the purpose of educating others, and I don't really have time for that at the moment. But I will write a brief explanation of the core concept: This method's key to parsing expressions while keeping operator precedence is to use separate functions for each operation. By "function" I just mean a piece of code which can parse a single operation, this should be trivial because a single operation has a clearly defined structure (e.g the addition operation takes two arguments, which are separated by the + symbol). The second key point is calling these functions in the order of desired precedence, you can have a single main function calling all the individual functions for parsing operations, basically you are blindly calling these functions to see if it work: 1. If it DOES work, then great! Mission successful! 2. If it DOES NOT work, then just simply move onto the next function and hope it works. That's it really, that's the magic, that is what makes operator precedence tick... calling the operation functions in the desired order and doing it until one succeeds. And to finish, what makes this approach "recursive" is that you will be calling the main parse function to parse the arguments for the operation, and this will create a cycle until everything is parsed . Here is an example that I parsed using this code: TheDcoder@arch /v/t/tdop> node parse.js '-((1 + 2) / 3) * 4' { "op": "Multiply", "args": [ { "op": "Invert", "args": [ { "op": "Divide", "args": [ { "op": "Add", "args": [ 1, 2 ] }, 3 ] } ] }, 4 ], "raw": "-((1 + 2) / 3) * 4" } The output is in JSON format and it is hard to visualize, so here is a tree diagram generated from the output: I used NodeJS to run the script, but you can try it in your browser directly! I made a quick and dirty web interface and put the code on GitHub since they offer a free hosting service. Have fun -- Now I have to re-write the parser in C using this concept and hopefully it will be enough for the time being. -
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
Doesn't AutoIt have 64-bit integer support? In any case, I will make sure to add this in EasyCodeIt, perhaps as an optional feature -
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
@rcmaehl Maybe in the future but you will have to settle with the Bitwise functions for now! -
Run a bat file like double click
TheDcoder replied to TheTophatZombie's topic in AutoIt General Help and Support
Not a good idea to create a new thread about the same topic after a mod locks it mate. That being said, you should take a look into the very useful help file, it has what you need -
I was afraid that after M$ drops support for IE and removes it completely from Windows, we won't have any default installed browser which can be scripted, but good to see that they are making Edge usable over WinAPI And since Edge is based on Chromium, it would be awesome if the changes are somehow backported, then we can use the same API to interact with Chrome! Edit: Forgot that Chromium is not a GPL project, so Edge isn't open-source and thus the changes can't be backported... without the help of reverse engineering anyway. Oh well, I guess Edge will do better than IE atleast.
-
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
@JockoDundee Ah I see. You are right that the struct isn't recursively defined (that's impossible in C), what I do is have a pointer for the same struct Technically it is not an array, it is just a pointer to an operand structure, but thanks to pointer arithmetic in C, we can treat it like an array if we allocate enough space to contain multiple structures. The number of elements is supposed to derived from the operation, so for example with OP_ADD (which is binary addition: 1 + 2) the code would assume 2 elements. There can be any number of operands (or arguments) for an operation, but we only use a maximum of 3 (the conditional `?:` operator takes 3 arguments, which is also why it is called the ternary operator). A "Token" represents an individual unit/value in the code, while an "Expression" represents a set of operations that are done on these tokens. In simple English, tokens are the numbers and symbols while the expression is the whole equation -
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
Indeed, that's one of the advantages of strict-typing, less ambiguity and surprises in the future I am not sure, I can think of a way to do this iteratively using goto but not sure if it would be enough to make it work. In any case, a recursive function is simpler in this case, so we can look into non-recursive approaches in the future if needed. -
WebDriver UDF - Help & Support (II)
TheDcoder replied to Danp2's topic in AutoIt General Help and Support
Have you tried the `download.default_directory` Chrome option? You can set a default path for downloads and any downloads will go into that folder. -
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
I am still working on the expression parser, the code is not complete but since it has almost been a week since the last update, so I thought I'd give you guys a sneak peak Here is a screenshot with the graphical representation of an expression's parse tree: The expression is pretty simple: 1 - 2 / 3 * 4 But the final result looks complex and huge because there are multiple layers of nodes for each bit of info... all thanks to C's strict type system, where you can't put anything anywhere like you usually would in a dynamically typed language like AutoIt. Here is a snippet of the code (the expression parsing function) for those are interested: There are no doubt many bugs in there, and a lot of the stuff needs to be completed, but I will try to post weekly updates to show the progress. -
GUI Control Box Text Display
TheDcoder replied to Atrax27's topic in AutoIt General Help and Support
@FrancescoDiMuro Thanks for mentioning my topic, I want to point out that there might be several inaccurate statements in there, especially the section about multi-dimensional arrays. Though all of the essentials should be correct. It has been a few years since I looked back at that topic, I couldn't find the time to revisit it. @Dan_555 You've linked to a great video series, it is very useful for people who aren't familiar with programming... it is the same video series I watched to learn AutoIt, which is kind of the first programming language that I learned . That being said, I do recall a few inaccurate explanations for some of the things, but nothing too harmful, stuff that you will realize as you get more experience. -
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
LOL By the way, I am not actually going to implement the Automation related functions, I want to create a general-purpose language which can be expanded by the user according to their needs (so there could be an UDF with those functions ) Should probably mention this in the first post -
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
@JockoDundee That's a good question! I am not a lawyer obviously but I will write my thoughts about it here. As you have mentioned, I am not using any part of the source or binaries from AutoIt. But what I am doing is making a product which is similar to it... but AutoIt itself also shares similarities with other BASIC language, not to mention that it was open-sourced under GPL at one point, so there is that Even if I am kind of in a gray area, I am acting in good faith and not ripping-off AutoIt for a quick buck, so I hope Jon and rest of the AutoIt team don't have any issue with my endeavor -
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
@JLogan3o13 This is supposed to the the official topic of the project, the other thread was just a discussion that I started before I planned to start work on it. And as I already mentioned, the other thread got too big and it is not very easy to get into for new readers. So I hope to keep this thread cleaner and also offer a good overview in the first posts of this thread -
WebDriver UDF - Help & Support (II)
TheDcoder replied to Danp2's topic in AutoIt General Help and Support
You should be able to use _WD_ExecuteCdpCommand with the Page.setDownloadBehavior command as shown in the python script. I see that this command is deprecated so it may or may not work in the latest version of Chrome. Edit: Did not notice @AttilaP's reply in this page as my notification took me to the previous page. -
You need to get standalone AutoIt, look inside the "Includes" folder for all the include scripts and the constant values inside them
-
Sorry about the lack of updates, I have been busy with life (as usual) and wasn't able to properly formulate a plan on how to proceed forward with parsing statements, I decided that it would be better to tackle expression parsing now, but that threw me into a whole new tangent about various different kinds of techniques for parsing expressions... luckily I have made up my mind with what approach I will use in the initial implementation, I am not 100% sure it will work, but it should. In the mean-while I created an "official" thread for the project: This thread was never really meant to be used for actual technical discussion of the implementation, and it has gotten too big and ugly anyway, it is impossible for new users to get a brief glance about the whole thing without reading through all the pages. So everyone please follow the new thread for updates! I should have an update out soon if all goes according to plan
-
EasyCodeIt - cross-platform AutoIt implementation
TheDcoder replied to TheDcoder's topic in AutoIt Projects and Collaboration
Reserved for future use -
EasyCodeIt A cross-platform implementation of AutoIt Introduction: EasyCodeIt is an attempt at implementing a programming language which is backward compatible with a sub-set of AutoIt which would work across multiple platforms with many aspects being agnostic to the platform-specific differences. Currently the primarily targeted platforms are Linux and Windows, more platforms may be supported in the future as per popular demand. For example it should be easy enough to port to Unix-like platforms such as BSD and Mac with the help of maintainers who are familiar with them. The main motivation behind the creation of this project is the lack of a proper easy-to-use scripting language in Linux, while there are numerous scripting languages which natively support it, none of them are as user-friendly and easy to use as AutoIt. (The "Easy" in "EasyCodeIt" reflects this) There was a previous thread in which the project was originally started, but it got too big and the discussion is too cluttered and hard to follow for any new readers, here is the thread for those who are interested in reading it: Progress: Frontend ✅ Tokenizer 🚧 Parser (work in progress) ✅ Expressions 👷♂️ Statements (current priority) Backend ⏰ Interpreter (scheduled) I am currently working on expression parsing and syntax tree building. -- This section will be updated in the future with new progress. To stay notified 🔔 follow this thread to get update notifications (by using the "Follow" button on the top-right corner of this page) and 👁️ watch the GitHub repository to get any new activity on your feed. Code: The code is available on GitHub, please 🌟 star the project if you like it and would like to show your support, it motivates me a lot! (Also don't forget to 👍 Like this post ) Chat: I created a room in Matrix (an open-source federated chat system) for EasyCodeIt, you can join it to chat with me and others who are in the room, it might be a good way to get the latest status updates from me You can preview the room without joining, and you don't need to be connected to it 24/7 like IRC. It works a bit like Slack for those who are familiar with it. Forum: I have created a dedicated forum to post more frequent updates, possibly in their own threads to better organize the discussion. Please sign-up and follow the blog section to get updates. By the way, you can also post pretty much anything there, both technical and non-technical stuff, it is intended to be a hangout for techies but not only for them. So casual discussions, funny cat videos etc. are allowed!
-
@Jos @GokAy Oops, didn't realize FileReadLine kept track of the last read line by default (it was mentioned in the remarks, which I did not read). In any case, if you are already keeping track of the line no., it is better to explicitly pass it to FileReadLine as well
-
@GokAy Good catch, but you forgot to modify the function call to FileReadLine to include $iLine Global $iLine = 1 While 1 $chars = FileReadLine($journalFile, $iLine) If @error Then ExitLoop ConsoleWrite("Line: " & $iLine & " > " & $chars & @CRLF) ; * See below $iLine += 1 Wend ; * : Replace consolewrite () with what you actually want to do with the read string, as it is you are not doing anything
-
While 1 $chars = FileReadLine($vrFchConf, 1) If @error Then ExitLoop MsgBox(0, "Char read:", $chars) Wend FileClose($vrFchConf) Read the documentation for FileReadLine