Is this utility useful enough to bother putting into CodePlex? - c#

It was my second C# project, undertaken years ago, and it has lived on, because (imho) it is Genuinely Useful Software. It's also badly designed and the code is embarrassing.
It runs C# code. You write a method, the method name appears in a listbox, you double-click the method name to execute it. That's it.
Examples:
When I open up my C# web project at work, a method runs a couple command-window apps my project needs, and checks to confirm that the requisite service is up. I never have to remember that stuff.
I hate UPPERCASE, so I have a method that lower-cases SQL, but preserves the case of quoted strings. Another method calls a web service to beautify SQL. Those both operate on the clipboard.
One method fixes the names of MP3 files: title casing, replacing underscores and hyphens, optionally removing/inserting text or prepending numbers. Creates a playlist!
I double-click to harvest all of my Twitter links, turning them into an HTML page with hyperlinks and a jQuery-powered search.
A method searches the specified log4net.log for every operation that took longer than the specified number of milliseconds.
I can create a restore point by double-clicking a method (and open up the corresponding dialog with another method).
When my wife had to write some sorting algorithms for school, the utility was an ideal testbed. I use it to test bits of code all the time.
None of these methods is in any way impressive. No large brain stuff. Most of it is just string manipulation, file system operations -- mundane stuff. Handy though!
This morning, I wanted to format some SQL output as rows in an Excel table. I wrote a method to read the output and format it as tab-delimited columns, for import into Excel. I have no idea how else I could have done that. It took about 8 minutes to write.
I have 300 methods, perhaps 50 of which are often useful, the rest there if the occasion arises. Occasionally I move the real cruft into the Zaps group, so it's out of the way.
The utility has lots of ease-of-use features. I prefer the keyboard to the mouse, so methods are tagged into groups that are accessible from a dropdown: control-T selects a different group. Don't remember the group? You enter control-F to find all the methods matching a string. Arrow down and press to run the method. The parameters window always remembers its state: if you entered Hoytster last time, it's there this time. You can right-click a method to see its tooltip; double-right-click to see its source.
I tried to make it easy to create new methods quickly.
A method generates your new function's prototype: you enter the method's name, group tag, tooltip, etc, and the new method is created with the requisite attribute decorations. The prototype is placed in the clipboard so you can paste it into one of the utility's source files.
It's easy to prompt for parameters:
...GetParameters("*Target File", "#Report File", "Open Report [No, Yes]");
opens a window with textboxes labeled Target File and Report File, and an Open Report checkbox with text that toggles Yes and No. Strings in curly-braces become radiobuttons. The Target File must exist, because of the initial asterisk; the parameters window will not close if an invalid target file is entered. The Report File must be valid (it CAN be created) because of the #-sign.
When you run the method and the parameters window appears, it has a [Capture] button you click to generate the code needed to capture the returned parameters, putting it into the clipboard again:
string targetFile = parameters["Target File"];
...
boolean openReport = parameters["Open Report"] == "Yes";
Ach, I go on too long.
So, how ambitious should I be? CodePlex? Maybe a dedicated web site, where people can upload their methods?
Getting the utility publish-ready would be a lot of work. I have to clean up the code; remove the really dumb methods and the never-finished methods; create a screen cast of the "make a new method" process, document the teeny "meta-language" (tongue-in-cheek) that drives the parameters window.
I like the idea of y'all using my utility to be a bit more productive. I love the idea of seeing what methods you invent and share. No doubt it's out there, but I'm not aware of places on the net where people share code as simple as a method "Fix the names of my MP3s".
Would you like to have this utility?
Besides being overworked and lazy, I have never put up a web site (!) -- and y'all might mock me because my GetParameters() method has about 200 lines (my poor excuse: I started out with FORTRAN). This utility was never designed; it accreted. :)
So let me know: Do you think this utility is useful enough to put up on CodePlex (or somplace)?
Thanks in advance! - Hoytster

Put it out on CodePlex and gage the usefulness of it. If it is very useful to many people start moving forward by creating a community around it like the website you talked about. If it is going to be a lot of work and you don't know if it will be useful to people, start small with your effort level and keep moving it up.
I did this exact same thing with my URL Rewriter that I developed, that was based off of Apache mod_rewrite, for the .NET framework.
http://urlrewriter.codeplex.com
I started small and as people requested new feature and started using it more and more, the effort became easy to justify.

Related

Is there something better than preprocessor directives (#if, etc) in C#?

Most questions of this type are seeking to alter the program behavior (things that could be decided at run time) or want to deal directly with debug printing. This is a bit different.
I have code that depends on a peripheral (like a card reader). Sometimes I don't use it, which means the library isn't present. (And I'm being nice, because "library" turns out to mean installing a 2GB software suite). When I remove the library, I can't open the device. If I can't open the device, I can't create the class member that uses it. With the class inoperative, I can't call its methods from within the code. Therefore, I can't just choose not to execute it; I need it to go away since it will not compile without the library.
Preprocessor directives like #if and all that are ok, maybe; but these things appear in more than one file, which means independently maintaining a #define at the top of each. I come from a simpler place (meaning, C) where one header file can be used to control this. I note that C# is rather hostile about #define (either the label exists, or not; no constants or calculations allowed), and that makes me think there's another way.
How do you handle this?
---Follow-up(s)---
I did read the "duplicate" Q/A's, and have a fairly good picture of what I'm dealing with. I didn't find those questions in my original search, but sometimes that's just how it is.
#Amy suggests that #define at the top is "not how it's done" but rather "put it on the command line". So, (if I realize we are sticking with this mechanism) the discussion might go to examining ways to have that happen . One does not simply drop to a terminal and do that. It happens as "IDE features" or "IDE hacks".
#Alexei Levenkov asks what I really want. I really want to (a) not get compile errors, and (b) do it by selectively leaving out the code. And, find the C# equivalent to the way I proposed.
Some more constraints are addressed by the fact that I haven't been using VS or C# for all that long. So I know a lot less than you all do. Considering I got the code from the last person and have to deal with what I see, I don't want to set up the person after me to have to figure out what "interesting" thing I might have done to make it work. Thus, things like hand-editing a project file may work but will also cause consternation down the line.
# Eric Lippert suggests "hostile" is really "sensible". I may have had my tongue too far into my cheek on that one. VS seems to be telling me I'm doing it wrong, so I sensed there's a "right way" I simply don't know about. As for the 2GB supporting application, I will go to various computers and pull down the repository and try out something, and so this "overhead" wants to propagate with it. It's worse if I'm linked through my phone to do the download. And if I build the application with everything included, the end user is then required to install that software suite before the program will run. In theory, they could be required to buy the software. If I sent you a tic-tac-toe game, and told you it wouldn't run until you installed Oracle, you'd probably pass on the whole thing.
I considered the "stub out the interface" idea, but there seemed to be more hooks into the class than I wanted to deal with. Plus, I don't know what these things do, so I have to know something about them in order to "fake" them.
In the end I decided that we're still largely using the #if scheme to get this done, and the replacement feature I imagined might exist, doesn't. And I'm using the provision in the project file(s) as cited by #Jim G. as it gets the job done and is only a little imperfect. It's good enough.
As #BJ Safdie said here:
Set them in your Compilation Properties or Build options.
You get to the build options by right-clicking the project and selecting
properties from the menu.

C# Resources: display resource string names instead of localized values

Having rather large project using Resources for internationalization (following this guide: ASP.NET MVC 2 Localization complete guide, using things like data attributes, and so on) we run into the need of translating the resource files. In the beggining of project I selected approach to have lot of small resource files - for each view, viewmodel, controller, ... So I ended up having hundreds of resources. During the translations (which is done by our partners using ResXManager tool we run into trouble identifying the context of the string (where is it displayed, to find out the correct form of translation to make sense when displayed).
So I was asked to make the mutation of application which do not display the localized values, but the keys (or string names). E.g. having string in resources TBL_NAME used somewhere in the view like #ResX.TBL_NAME and translated into english as "Name", I would like to show it in this special mutation as "TBL_NAME", so the translator may see the context - where exactly this string is used.
The best would be, if this is not special build of application, but rather the another "language" of the application available for translators, so he can switch between english and this "unlocalized" languages.
I'm looking some easy ideas of doing this. So far I was thinking of these approaches:
Override ResourceManager.GetString - cannot use, because we use generated Designer classes to access strings massively and so far I haven't find a way to change created ResourceManager (see this answer). Did I miss something?
Create resources for some unused language, which will contain pairs string name/translated value as TBL_NAME/TBL_NAME - viable, but very exhausting since we have hundreds of resources. Also the addition of new resource will require us to remeber that we need to add also this unused language resource will exact same strings name. You also have to do twice much work when adding single string to application.
At the moment, it seems for me, that using resources and current approach it is impossible to solve this task, so I decided to ask this as question (and I'm aware it is rather discussion than question) here, hoping, someone will give me some hint about other approach to solve this problem.
My preferred option would be to give the translators an environment where they can see what they are translating. Rigi requires a bit of setup (basically you need to add an additional UI language), but once you have done that translators can work within the live website - or in a test instance, which is what we did.
They can also work in screenshots, which is convenient when translators would have to access admin or other role specific pages but you do not want to bother giving them all kinds of user rights. These screenshots can be generated as part of automated UI tests or during manual UI testing.
I am afraid I can't say anything about the cost of the solution, but our translators are really happy with it. I am not sure if this is what you are looking for since you asked for an easy solution, but it definitely solves the issue of giving translators the context they need to do their job - better than displaying resource IDs.

Implement Language Auto-Completion based on ANTLR4 Grammar

I am wondering if are there any examples (googling I haven't found any) of TAB auto-complete solutions for Command Line Interface (console), that use ANTLR4 grammars for predicting the next term (like in a REPL model).
I've written a PL/SQL grammar for an open source database, and now I would like to implement a command line interface to the database that provides the user the feature of completing the statements according to the grammar, or eventually discover the proper database object name to use (eg. a table name, a trigger name, the name of a column, etc.).
Thanks for pointing me to the right direction.
Actually it is possible! (Of course, based on the complexity of your grammar.) Problem with auto-completion and ANTLR is that you do not have complete expression and you want to parse it. If you would have complete expression, it wont be any big problem to know what kind of element is at what place and to know what can be used at such a place. But you do not have complete expression and you cannot parse the incomplete one. So what you need to do is to wrap the input into some wrapper/helper that will complete the expression to create a parse-able one. Notice that nothing that is added only to complete the expression is important to you - you will only ask for members up to last really written character.
So:
A) Create the wrapper that will change this (excel formula) '=If(' into '=If()'
B) Parse the wrapped input
C) Realize that you are in the IF function at the first parameter
D) Return all that can go into that place.
It actually works, I have completed intellisense editor for several simple languages. There is much more infrastructure than this, but the basic idea is as I wrote it. Only be careful, writing the wrapper is not easy if not impossible if the grammar is really complex. In that case look at Papa Carlo project. http://lakhin.com/projects/papa-carlo/
As already mentioned auto completion is based on the follow set at a given position, simply because this is what we defined in the grammar to be valid language. But that's only a small part of the task. What you need is context (as Sam Harwell wrote: it's a semantic process, not a syntactic one). And this information is independent of the parser. And since a parser is made to parse valid input (and during auto completion you have most of the time invalid input), it's not the right tool for this task.
Knowing what token can follow at a given position is useful to control the entire process (e.g. you don't want to show suggestions if only a string can appear), but is most of the time not what you actually want to suggest (except for keywords). If an ID is possible at the current position, it doesn't tell you what ID is actually allowed (a variable name? a namespace? etc.). So what you need is essentially 3 things:
A symbol table that provides you with all possible names sorted by scope. Creating this depends heavily on the parsed language. But this is a task where a parser is very helpful. You may want to cache this info as it is time consuming to run this analysis step.
Determine in which scope you are when invoking auto completion. You could use a parser as well here (maybe in conjunction with step 1).
Determine what type of symbol(s) you want to show. Many people think this is where a parser can give you all necessary information (the follow set). But as mentioned above that's not true (keywords aside).
In my blog post Universal Code Completion using ANTLR3 I especially addressed the 3rd step. There I don't use a parser, but simulate one, only that I don't stop when a parser would, but when the caret position is reached (so it is essential that the input must be valid syntax up to that point). After reaching the caret the collection process starts, which not only collects terminal nodes (for keywords) but looks at the rule names to learn what needs to be collected too. Using specific rule names is my way there to put context into the grammar, so when the collection code finds a rule table_ref it knows that it doesn't need to go further down the rule chain (to the ultimate ID token), but instead can use this information to provide a list of tables as suggestion.
With ANTLR4 things might become even simpler. I haven't used it myself yet, but the parser interpreter could be a big help here, as it essentially doing what I do manually in my implementation (with the ANTLR3 backend).
This is probably pretty hard to do.
Fundamentally you want to use some parser to predict "what comes next" to display as auto-completion. This has to at least predict what the FIRST token is at the point where the user's input stops.
For ANTLR, I think this will be very difficult. The reason is that ANTLR generates essentially procedural, recursive descent parsers. So at runtime, when you need to figure out what FIRST tokens are, you have to inspect the procedural source code of the generated parser. That way lies madness.
This blog entry claims to achieve autocompletion by collecting error reports rather than inspecting the parser code. Its sort of an interesting idea, but I do not understand how his method really works, and I cannot see how it would offer all possible FIRST tokens; it might acquire some of them. This SO answer confirms my intuition.
Sam Harwell discusses how he has tackled this; he is one of the ANTLR4 implementers and if anybody can make this work, he can. It wouldn't surprise me if he reached inside ANTLR to extract the information he needs; as an ANTLR implementer he would certainly know where to tap in. You are not likely to be so well positioned. Even so, he doesn't really describe what he did in detail. Good luck replicating. You might ask him what he really did.
What you want is a parsing engine for which that FIRST token information is either directly available (the parser generator could produce it) or computable based on the parser state. This is actually possible to do with bottom up parsers such as LALR(k); you can build an algorithm that walks the state tables and computes this information. (We do this with our DMS Software Reengineering Toolkit for its GLR parser precisely to produce syntax error reports that say "missing token, could be any of these [set]")

Deploying a C# application - user form (novice)

I'm virtually a complete novice, I've tried Googling for answers and become totally confused.
Using Visual Studio 2010, I have a C# application which is an email notifier for a friend. The external (Arduino) hardware works, the main code (from a website) works but I'm sending it to her on the other side of the world to use and she is very 'non-technical' - hence the need for a 'setup form'.
I have created a form where she can enter comm port (selected from a list), username and password (all to be used by the main code), but that form should run only when the application is first installed on the PC.
At the moment it runs in VS-2010 (though I need to iron out a couple of snags), validates and hides - but I don't know how to a) store the data and make it available to the main code, b) ensure that the form only runs at setup, or c) exactly what I need to do or include to create an installable application.
Could somebody either help or direct me to some tutorials that don't assume I understand all the terminology?
I just want to create something that she can instal from a memory stick. I know it can be done and it's proababy quite simple for those who understand - I'm trying to learn but I'm no longer young and it's a struggle.
Thanks
a) store the data and make it available to the main code,
write the data on a file!
you have millions of possibilities, for isntance reading and writing a plain text file can be done with few lines of code, but if you want to encrypt your file (it may be the case if you want to store the password) you can use System.Security.Cryptography as shown in this guide
b) ensure that the form only runs at setup,
once you have written the file, then it means that the program has run already at least once, so you don't need to ask the user again (just read the data from the file)
c) exactly what I need to do or include to create an installable application.
Visual Studio already comes with the Setup project for this task. See this good guide.
From your comment and link to the code project for the Arduino, I gather that this is your first venture into writing code in C#, or very close to it. And ideally you'd like to make this as easy for your friend as possible. The best advice I can give you is not to try to run before you learn to walk. If you try to create a custom setup project and use a configuration file, which is what you are talking about doing, you may hit so many barriers that you never get to a successful end of the project. That kind of experience is discouraging and I'd hate for you to lose the drive to ever want to try another software project.
Make this initial project easy on yourself. This is not good programming practice for most situations, but if you only have one user, hard-code her configruation information for this first version. In other words, put her username, password, com port, etc directly into the main program. This eliminates the need for both the configuration, and any custom setup form. If you still want to make the whole thing configurable and versatile, do that in your next version. Custom setup is not a beginner task. It will be a lot easier to take on with the encouragement of your friend's excitement and compliments over a first version that works.

Localizing data that is generated dynamically

This was a hard question for me to summarize so we may need to edit this a bit.
Background
About four years ago, we had to translate our asp.net application for our clients in Mexico. Extensibility and scalability were not that much of a concern at the time (oh yes, I just said those dreadful words) because we only have U.S. and Mexican customers.
Rather than use resource files, we replaced every single piece of static text in our application with some type of server control (asp.net label for example). We store each and every English word in a SQL database. We have added the ability to translate the English text into another language and also can add cultural overrides. For example, hello can be translated to ¡hola! in one language and overridden to ¡bueno! in a different culture. The business has full control over these translations because will built management utilities for them to control everything. The translation kicks in when we detect that the user has a browser culture other than en-us. Every form descends from a base form that iterates through each server control and executes a translation (translation data is stored as a datatable in an application variable for a culture). I'm still amazed at how fast the control iteration is.
The problem
The business is very happy with how the translations work. In addition to the static content that I mentioned above, the business now wants to have certain data translated as well. System notes are a good example of a translation they want. Example "Sent Letter #XXXX to Customer" - the business wants the "Sent Letter to Customer" text translated based on their browser culture.
I have read a couple of other posts on SO that talk about localization but they don't address my problem. How do you translate a phrase that is dynamically generated? I could easily read the English text and translate "Sent", "Letter", "to" and "Customer", but I guarantee that it will look stupid to the end user because it's a phrase. The dynamic part of the system-generated note would screw up any look-ups that we perform on the phrase if we stored the phrase in English, less the dynamic text.
One thought I had... We don't have a table of system generated note types. I suppose we could create one that had placeholders for dynamic data and the translation engine would ignore the placeholder markers. The problem with this approach is that our SQL server database is a replication of an old pick database and we don't really know all the types of system generated phrases (They are deep in the pic code base, in subroutines, control files, etc.). Things like notes, ticklers, and payment rejection reasons are all stored differently. Trying to normalize this data has proven difficult. It would be a huge effort to go back and identify and change every pick program that generated a message.
This question is very close; but I'm not dealing with just system-generated status messages but rather an infinite number of phrases and types of phrases with no central generation mechanism.
Any ideas?
The lack of a "bottleneck" -- what you identify as the (missing) "central generation mechanism" -- is the architectural problem in this situation. Ideally, rearchitecting to put such a bottleneck in place (so you can keep using your general approach with a database of culture-appropriate renditions of messages, just with "placeholders" for e.g. the #XXXX in your example) would be best.
If that's just unfeasible, you can place the "bottleneck" at the other end of the pipe -- when a message is about to be emitted. At that point, or few points, you need to try and match the (English) string that's about to be emitted with a series of well-crafted regular expressions (with "placeholders" typically like (.*?)...) and thereby identify the appropriate key for the DB lookup. Yes, that still is a lot of work, but at least it should be feasible without the issues you mention wrt old translated pick code.
We use technique you propose with insertion points.
"Sent letter #{0:Letter Num} to Customer {1:Customer Full Name}"
Which might be (in reverse Pig Latin, say):
"Ustomercay {1:Customer Full Name} asway entsay etterlay #{0:Letter Num}"
Note that this handles cases where the particular target langue reverses the order of insertion etc. It does not handle subtleties like first, second, etc, which have to be handled with application logic/more phrases:
"This is your {0:first, second, third} warning"
In a pinch I suppose you could try something like foisting the job off onto Google if you don't have a translation on hand for a particular phrase, and stashing the translation for later.
Stashing the translations for later provides both a data collection point for building a message catalog and a rough (if sometimes laughably wonky) dynamically built starter set of translations. Once you begin the process, track which translations have been reviewed and how frequently each have been hit. Frequently hit machine translations can then be reviewed and refined.
Dynamic machine translation is not suitable for a product that you actually expect people to pay money for. The only way to do it is with static templates containing insertion points (as Cade Roux has demonstrated in his answer).
There's no getting around a thorough refactoring of your code to make this feasible. The alternative is to do nothing with those phrases (which is what you're doing now, and it's working out okay, right?). Usually no translation is better than embarrassingly bad translation.

Categories