I want to cascade the SyntaxHighlighting Engine of AvalonEdit. I have 2 HighlightingDefinitions. The first one is the main syntax. The second one is a complex multiline-preprocessor-markup-language. For this reason it is too complicated to embbed the second grammar in the first one. The easier way is to render the first syntax, and change the affected line-parts (based on the second syntax) afterwards.
So I instantiated a new HighlightingColorizer with the second language and added it to the LineTransformers. But the second language colorizes the complete document and not only the lineparts with the preprocessor-directives: the non-preprocessor-code is black.
As I debugged the ColorizeLine-method of the second line transformer, the lines of the non-highlighted code (= no preprocessor code) have not been colorized, as expected. But the color of the lines are black.
So does the HighlightingColorizer reset all previous highlighting of the whole document before it starts to colorize?
Or what else could be the problem? How can I properly cascade 2 HighlightingColorizers?
The problem is that the HighlightingColorizer does not directly store a reference to the DocumentHighlighter, but instead stores it via TextView.Services. This is done to allow attaching the same colorizer to multiple editors, so that each editor gets its own DocumentHighlighter.
When you attach a second colorizer, it overwrites the IHighlighter stored in the service container; and both colorizers end up using the new highlighter.
Also, note that the 'copy to clipboard' logic in HtmlClipboard directly accesses the IHighlighter service, it does not use any colorizers. (copying text to Word preserves the syntax highlighting only, no other transformations like fold markers)
There are essentially two approaches to solve this issue:
Do not store the additional highlighter as a service. You can do this by creating your own copy of the HighlightingColorizer class, and use a field in that class instead of accessing textView.Services. This is an easy change, but additional highlighters will not be used when copying text to the clipboard.
Create an IHighlighter implementation that combines the HighlightedLines from multiple DocumentHighlighters. This is the approach we are using for the C# semantic highlighting in SharpDevelop 5, which works as an additional highlighter that extends the existing .xshd-based C# highlighting. However, this approach is complex (merging HighlightedLines is non-trivial given the ordering and nesting constraints on the sections), and requires an API change to the IHighlighter interface in order to deal with the OnHighlightStateChanged notification (AvalonEdit 4.x uses a derived class nested in HighlightingColorizer to get access to this callback; AvalonEdit 5.0 will use an event).
Related
I am attempting to use Specflow to automate web tests using Selenium. So far, things are going mostly fine, but I am now running into a problem. One of my steps allow for a user to input a variable, the step looks like this:
Given I click the (VARIABLE) Menu
And the code behind it is fairly simple, just clicking on a link based on the text that is passed:
driver.FindElement(By.XPath("Xpath to get to the variable")).Click();
However, there is a later step that must use this information. That is fine, you can use "ScenarioContext.Current.Add(string, variable)" and I know about that and have been using it. It functions for the needs that I was first informed of.
My problem is that now the business wants to be able to add multiple items at the same time. This presents two problems. Attempting to just call the step a second time throws an exception: "An item with the same key has already been added." and if I put this into a Scenario Outline, which would allow me to call the variable a second time in a second run, I cannot use the first variable in the final step.
Logically, this means that passing in a variable multiple times is the problem (which makes sense, given it's passing in as a string) and so passing the variable in as an array seems the logical way to go. The idea is that when I pass the parameter from one step to another as an array instead of as a string I theoretically won't run into this error and then I will be able to iterate through the items in the array in that later step with a for loop. This seems like something that SpecFlow should be able to do, but I am having issues finding out just how to achieve this. Does anyone have an idea on how to do this? I attempted to merely use:
Scenario.Context.Current.Add(string, variable).ToArray();
However, that does not work, and all of the examples of "ToArray" I can find in the SpecFlow documentation doesn't seem to be actually changing the variables you pass from one step to another into an array, it seems to be used solely inside of individual steps and never passed between steps. Is passing parameters using ScenarioContext.Current.Add(string, variable) as an array possible in SpecFlow?
Thanks in advance.
the simplest solution to your problem is to add an array (or list) to the context in the first step and then to get it out and add to it and then replace it again in future steps:
List<string> list = new List<String>();
list.Add(variable)
ScenarioContext.Current.Add(name, list);
then later
List<String> currentList = (List<String>) ScenarioContext.Current[string];
currentList.Add(variable);
ScenarioContext.Current[name]=list;
However I feel duty bound to point out some issues with your current solution. You should investigate the PageObject pattern and hide your element selection XPath inside your page objects. Imagine the business decides to change the element that information is stored in. Now you have to change every test that does this:
driver.FindElement(By.XPath("Xpath to get to the variable")).Click();
for that variable. Using the page object pattern this is hidden inside the page object and you would only have a single place to change.
I personally would also consider sharing data using context injection as I find this allows strong typing of the data (so no cast is required like in the example above) and it allows you to know what data is stored, its not just a random bag of stuff).
Is there a way to check for the size of a class in C#?
My reason for asking is:
I have a routine that stores a class's data in a file, and a different routine that loads this object (class) from that same file. Each attribute is stored in a specific order, and if you change this class you have to be reminded of these export/import routines needs changing.
An example in C++ (no matter how clumsy or bad programming this might be) would be
the following:
#define PERSON_CLASS_SIZE 8
class Person
{
char *firstName;
}
...
bool ExportPerson(Person p)
{
if (sizeof(Person) != PERSON_CLASS_SIZE )
{
CatastrophicAlert("You have changed the Person class and not fixed this export routine!")
}
}
Thus before compiletime you need to know the size of Person, and modify export/import routines with this size accordingly.
Is there a way to do something similar to this in C#, or are there other ways of "making sure" a different developer changes import/export routines if he changes a class.
... Apart from the obvious "just comment this in the class, this guarantees that a developer never screws things up"-answer.
Thanks in advance.
Each attribute is stored in a specific order, and if you change this class you have to be reminded of these export/import routines needs changing.
It sounds like you're writing your own serialization mechanism. If that's the case, you should probably include some sort of "fingerprint" of the expected properties in the right order, and validate that at read time. You can then include the current fingerprint in a unit test, which will then fail if a property is added. The appropriate action can then be taken (e.g. migrating existing data) and the unit test updated.
Just checking the size of the class certainly wouldn't find all errors - if you added one property and deleted one of the same size in the same change, you could break data without noticing it.
A part from the fact that probably is not the best way to achieve what you need,
I think the fastest way is to use Cecil. You can get the IL body of the entire class.
What could be the best (as in performant, simple) way to iterate over TreeChanges in LibGit2Sharp?
If I access the .Patch property, I retrieve the full text of the changes. This is not quite enough for me... ideally I would like to be able to iterate over the diff lines, and per each line retrieve the status of the line (modified, added, deleted) and build my own output out of it.
Update:
Let's say I want to build my own diff output. What I'd like to do is to iterate over the changed lines, and during iteration I would check for the type of change (added, removed), and construct my output.
For example:
var diff = "";
foreach (LineChange line in changes) // Bogus class "LineChange"
{
if (line.Type == LineChange.TYPE_ADDED)
diff += "+";
else
diff += "-";
diff += line.Content;
diff += "\n";
}
The above is just a simple example what kind of flexibility I'm looking for. To be able to go through the changes, and run some logic along with it depending on the line change types. The Patch property is already "built", one way would be to parse it, but it seems silly that the library first builds the output, and then I parse it... I'd rather use the building ingredients directly.
I need this kind of functionality so that I can display a visual diff of changes which involves far more code and logic than the simple example I gave above.
As far as I can see, this information is not exposed by libgit2sharp, but it's provided by libgit2 in the case of blob diffs (but not for tree diffs). The relevant code is in ContentChanges.cs, specifically in the constructor and in the LineCallback() method (the code for tree diffs is in TreeChanges.cs).
Because of this, I think you have two options:
Invoke the method git_diff_blobs(), that's used internally by ContentChanges, yourself, either using reflection (it's an internal method in NativeMethods), or by copying the PInvoke signature to your project. You will most likely also need Utf8Marshaler.
Modify the code of ContentChanges, so that it fits your needs. If you do this, it might make sense to create a pull request for that change, so that others could use it too.
#svick is right. It's not exposed.
It might be useful to open an issue/feature request to further discuss this topic. Indeed, exposing a full blown line based diffgram might not fit the current "grain" of the library. However, provided you can come up with a scenario/use case that would benefit most of the users, some research may be invested in order to widen the API.
Beside this option, there might be other solutions: post-process the current produced patch against the previous version of the file
See this SO question for potential leads
Neil Fraser's "Diff Strategies" paper is also a great source of strategies and potential caveats regarding what a diff tool might aim at
DiffPlex, as a working visualization tool, might be inspirational as well
With some more work, one might even achieve something similar to the following kind of visualization (from Perforce 4 viewer)
(source: macworld.com)
Note: In order to ease this, it might be useful to expose in C# the libgit2 diffing options.
I'm making a jquery clone for C#. Right now I've got it set up so that every method is an extension method on IEnumerable<HtmlNode> so it works well with existing projects that are already using HtmlAgilityPack. I thought I could get away without preserving state... however, then I noticed jQuery has two methods .andSelf and .end which "pop" the most recently matched elements off an internal stack. I can mimic this functionality if I change my class so that it always operates on SharpQuery objects instead of enumerables, but there's still a problem.
With JavaScript, you're given the Html document automatically, but when working in C# you have to explicitly load it, and you could use more than one document if you wanted. It appears that when you call $('xxx') you're essentially creating a new jQuery object and starting fresh with an empty stack. In C#, you wouldn't want to do that, because you don't want to reload/refetch the document from the web. So instead, you load it once either into a SharpQuery object, or into an list of HtmlNodes (you just need the DocumentNode to get started).
In the jQuery docs, they give this example
$('ul.first').find('.foo')
.css('background-color', 'red')
.end().find('.bar')
.css('background-color', 'green')
.end();
I don't have an initializer method because I can't overload the () operator, so you just start with sq.Find() instead, which operates on the root of the document, essentially doing the same thing. But then people are going to try and write sq.Find() on one line, and then sq.Find() somewhere down the road, and (rightfully) expect it to operate on the root of the document again... but if I'm maintaining state, then you've just modified the context after the first call.
So... how should I design my API? Do I add another Init method that all queries should begin with that resets the stack (but then how do I force them to start with that?), or add a Reset() that they have to call at the end of their line? Do I overload the [] instead and tell them to start with that? Do I say "forget it, no one uses those state-preserved functions anyway?"
Basically, how would you like that jQuery example to be written in C#?
sq["ul.first"].Find(".foo") ...
Downfalls: Abuses the [] property.
sq.Init("ul.first").Find(".foo") ...
Downfalls: Nothing really forces the programmer to start with Init, unless I add some weird "initialized" mechanism; user might try starting with .Find and not get the result he was expecting. Also, Init and Find are pretty much identical anyway, except the former resets the stack too.
sq.Find("ul.first").Find(".foo") ... .ClearStack()
Downfalls: programmer may forget to clear the stack.
Can't do it.
end() not implemented.
Use two different objects.
Perhaps use HtmlDocument as the base that all queries should begin with, and then every method thereafter returns a SharpQuery object that can be chained. That way the HtmlDocument always maintains the initial state, but the SharpQuery objects may have different states. This unfortunately means I have to implement a bunch of stuff twice (once for HtmlDocument, once for the SharpQuery object).
new SharpQuery(sq).Find("ul.first").Find(".foo") ...
The constructor copies a reference to the document, but resets the stack.
I think the major stumbling block you're running into here is that you're trying to get away with just having one SharpQuery object for each document. That's not how jQuery works; in general, jQuery objects are immutable. When you call a method that changes the set of elements (like find or end or add), it doesn't alter the existing object, but returns a new one:
var theBody = $('body');
// $('body')[0] is the <body>
theBody.find('div').text('This is a div');
// $('body')[0] is still the <body>
(see the documentation of end for more info)
SharpQuery should operate the same way. Once you create a SharpQuery object with a document, method calls should return new SharpQuery objects, referencing a different set of elements of the same document. For instance:
var sq = SharpQuery.Load(new Uri("http://api.jquery.com/category/selectors/"));
var header = sq.Find("h1"); // doesn't change sq
var allTheLinks = sq.Find(".title-link") // all .title-link in the whole document; also doesn't change sq
var someOfTheLinks = header.Find(".title-link"); // just the .title-link in the <h1>; again, doesn't change sq or header
The benefits of this approach are several. Because sq, header, allTheLinks, etc. are all the same class, you only have one implementation of each method. Yet each of these objects references the same document, so you don't have multiple copies of each node, and changes to the nodes are reflected in every SharpQuery object on that document (e.g. after allTheLinks.text("foo"), someOfTheLinks.text() == "foo".).
Implementing end and the other stack-based manipulations also becomes easy. As each method creates a new, filtered SharpQuery object from another, it retains a reference to that parent object (allTheLinks to header, header to sq). Then end is as simple as returning a new SharpQuery containing the same elements as the parent, like:
public SharpQuery end()
{
return new SharpQuery(this.parent.GetAllElements());
}
(or however your syntax shakes out.)
I think this approach will get you the most jQuery-like behavior, with a fairly easy implementation. I'll definitely be keeping an eye on this project; it's a great idea.
I would lean towards a variant on option 2. In jQuery $() is a function call. C# doesn't have global functions, a static function call is the closest. I would use a method that indicates you're creating a wrapper like..
SharpQuery.Create("ul.first").Find(".foo")
I wouldn't be concerned about shortening SharpQuery to sq since intellisense means users won't have to type the whole thing (and if they have resharper they only need to type SQ anyways).
Some background information:
I am working on a C#/WPF application, which basically is about creating, editing, saving and loading some data model.
The data model contains of a hierarchy of various objects. There is a "root" object of class A, which has a list of objects of class B, which each has a list of objects of class C, etc. Around 30 classes involved in total.
Now my problem is that I want to prompt the user with the usual "you have unsaved changes, save?" dialog, if he tries to exit the program. But how do I know if the data in current loaded model is actually changed?
There is of course ways to solve this, like e.g. reloading the model from file and compare against the one in memory value by value or make every UI control set a flag indicating the model has been changed. Now instead, I want to create a hash value based on the model state on load and generate a new value when the user tries to exit, and compare those two.
Now the question:
So inspired of that, I was wondering if there exist some way to generate a hash value from the (value)state of some arbitrary complex object? Preferably in a generic way, e.g. no need to apply attributes to each involved class/field.
One idea could be to use some of .NET's serialization functionality (assuming it will work out-of-the-box in this case) and apply a hash function to the content of the resulting file. However, I guess there exist some more suitable approach.
Thanks in advance.
Edit:
Point taken about the hashing and possible collisions. Instead, I am going for deep comparing value by value. I am already using the XML serializer for persistence, so I am just going to serialize and compare chars. Not pretty, but it does the trick in this case.
Ok you can use reflection and some sort of recursive function of course.
But keep in mind that every object is a model of a particular thing. I mean there maybe a lot of "unimportant" fields and properties.
And, thanks to #compie!
You can create a hash function just for your domain. But this requires strong mathematic skills.
And you can try to use classic hash functions like SHA. Just assume that your object is a string or byte array.
Because this is a WPF app, it may be easier than you think to be notified of changes as they happen. The event architecture of WPF allows you to create event handlers at a level somewhere above where the event actually originates. So, you could create event handlers for the various "change" events of your UI elements in the root window of your interface and set the "changed" flag at that scope.
WPF Routed Events Overview
I would advice against this. Different objects can have the same hash. It's not safe to rely on this for checking if changes have to be saved.