Scenario
Imagine that you have a module X whose functionalities are available to the user through a Command Line Interface. Such module doesn't do much in and of itself but it allows for other people to create plugin-like modules they can hook-up to module X. Ideally, the plugins could be used through X's CLI.
Thus my question:
What do you need to do in order to hook-up whatever functionality
a plugin might provide to X's CLI?
This means the plugin would need to provide some structure describing the command, what needs to be called and hopefully a usage message for the plugin. Therefore, when you run X's CLI, the plugin's command and help message shows up in the regular X's CLI's help message.
Example
main.p6:
use Hello;
use Print;
multi MAIN('goodbye') {
put 'goodbye'
}
lib/Hello.pm6:
unit module Hello;
our %command = %(
command => 'hello',
routine => sub { return "Hello" },
help => 'print hello.'
);
lib/Print.pm6:
unit module Print;
our %command = %(
command => 'print',
routine => sub { .print for 1..10 },
help => 'print numbers 1 through 10.'
);
The program main.p6 is a simplified version of this scenario. I'd like to integrate the information provided by both Hello.pm6 and Print.pm6 through
their respective %command variables into two new MAIN subs in main.p6.
Is this possible? If so, how would I go about achieving it?
This looks kinda specific for a StackOverflow question, but I will give it a try anyway. There are a couple of issues here. First one is to register the commands as such, so that MAIN can issue a message saying "this does that", and second is to actually perform the command. If both can be known at compile time, this can probably be fixed. But let's see how the actual code would go. I'll just do the first part, and I leave the rest as an exercise.
The first thing is that %command needs somehow to be exported. You can't do it the way you are doing it now. First, because it's not explicitly exported; if it were, you would end up with several symbols with the same name in the outer scope. So we need to change that to a class, so that the actual symbols are lexical to the class, and don't pollute the outer scope.
unit class Hello;
has %.command = %(
command => 'hello',
routine => sub { return "Hello" },
help => 'print hello.'
);
(Same would go for Print)
As long as we have that, the rest is not so difficult, only we have to use introspection to know what's actually there, as a small hack:
use Hello;
use Print;
my #packages= MY::.keys.grep( /^^<upper> <lower>/ );
my #commands = do for #packages -> $p {
my $foo = ::($p).new();
$foo.command()<command>
};
multi MAIN( $command where * eq any(#commands) ) {
say "We're doing $command";
}
We check the symbol table looking for packages that start with a capital letter, followed by other non-capital letter. It so happens that the only packages are the ones we're interested in, but of course, if you would want to use this as a plugin mechanism you should just use whatever pattern would be unique to them.
We then create instances of these new packages, and call the command auto-generated method to get the name of the command. And that's precisely what we use to check if we're doing the correct command in the MAIN subroutine, by using the where signature to check if the string we're using is actually in the list of known commands.
Since the functions and the rest of the things are available also from #packages, actually calling them (or giving an additional message or whatever) is left as an exercise.
Update: you might want to check out this other StackOveflow answer as an alternative mechanism for signatures in modules.
Related
I created a completionitemprovider for my extension, but now the suggestions based on words in the document aren't shown. Do I have to provide each word in the document?
export class ScriptViewProvider implements vscode.CompletionItemProvider
...
extension.context.subscriptions.push(vscode.languages.registerCompletionItemProvider(
["language"],
this));
...
async provideCompletionItems(document : vscode.TextDocument, position : vscode.Position) : Promise<vscode.CompletionItem[]> {
let completions : vscode.CompletionItem[] = [];
let completion = new vscode.CompletionItem("bla", vscode.CompletionItemKind.Field);
completions.push(completion);
return completions;
}
It brings up "bla" when I type "b", but none of the other words in the document appear.
See this comment of an open VS Code issue.
When your CompletionProvider was registered using a DocumentSelector that is more significant than that of other providers and returns at least one completion item, the other providers are skipped.
The word-based suggestions provider is less significant and so it does not contribute any suggestions.
Depending on the nature of your extension you could try to define a less specific DocumentSelector when registering your CompletionProvider.
If this is not possible I think there is no other option than to providing all completion items yourself (including word-based suggestions).
I'm trying to write a token that allows nested content with matching delimiters. Where (AB) should result in a match to at least "AB" if not "(AB)". And (A(c)B) would return two matches "(A(c)B)" and so on.
Code boiled down from its source:
#!/home/hsmyers/rakudo741/bin/perl6
use v6d;
my #tie;
class add-in {
method tie($/) { #tie.push: $/; }
}
grammar tied {
rule TOP { <line>* }
token line {
<.ws>?
[
| <tie>
| <simpleNotes>
]+
<.ws>?
}
token tie {
[
|| <.ws>? <simpleNotes>+ <tie>* <simpleNotes>* <.ws>?
|| <openParen> ~ <closeParen> <tie>
]+
}
token openParen { '(' }
token closeParen { ')' }
token simpleNotes {
[
| <[A..Ga..g,'>0..9]>
| <[|\]]>
| <blank>
]
}
}
my $text = "(c2D) | (aA) (A2 | B)>G A>F G>E (A,2 |\nD)>F A>c d>f |]";
tied.parse($text, actions => add-in.new).say;
$text.say;
for (#tie) {
s:g/\v/\\n/;
say "«$_»";
}
This gives a partially correct result of:
«c2D»
«aA»
«(aA)»
«A2 | B»
«\nD»
«A,2 |\nD»
«(A,2 |\nD)>F A>c d>f |]»
«(c2D) | (aA) (A2 | B)>G A>F G>E (A,2 |\nD)>F A>c d>f |]»
BTW, I'm not concerned about the newline, it is there only to check if the approach can span text over two lines. So stirring the ashes I see captures with and without parenthesis, and a very greedy capture or two.
Clearly I have a problem within my code. My knowledge of perl6 can best be described as "beginner" So I ask for your help. I'm looking for a general solution or at least an example that can be generalized and as always suggestions and corrections are welcome.
There are a few added complexities that you have. For instance, you define a tie as being either (...) or just the .... But that inner contents is identical to the line.
Here's a rewritten grammar that greatly simplifies what you want. When writing grammars, it's helpful to start from the small and go up.
grammar Tied {
rule TOP { <notes>+ %% \v+ }
token notes {
[
| <tie>
| <simple-note>
] +
%%
<.ws>?
}
token open-tie { '(' }
token close-tie { ')' }
token tie { <.open-tie> ~ <.close-tie> <notes> }
token simple-note { <[A..Ga..g,'>0..9|\]]> }
}
A few stylistic notes here. Grammars are classes, and it's customary to capitalize them. Tokens are methods, and tend to be lower case with kebap casing (you can of course use any type you want, though). In the tie token, you'll notice that I used <.open-tie>. The . means that we don't need to capture it (that is, we're just using it for matching and nothing else). In the notes token I was able to simplify things a lot by using the %% and making TOP a rule which auto adds some whitespace.
Now, the order that I would create the tokens is this:
<simple-note> because it's the most base level item. A group of them would be
<notes>, so I make that next. While doing that, I realize that a run of notes can also include a…
<tie>, so that's the next one. Inside of a tie though I'm just going to have another run of notes, so I can use <notes> inside it.
<TOP> at last, because if a line just has a run of notes, we can omit line and use %% \v+
Actions (often given the same name as your grammar, plus -Actions, so here I use class Tied-Actions { … }) are normally used to create an abstract syntax tree. But really, the best way to think of this is asking each level of the grammar what we want from it. I find that whereas writing grammars it's easiest to build from the smallest element up, for actions, it's easiest to go from the TOP down. This will also help you build more complex actions down the road:
What do we want from TOP?
In our case, we just want all the ties that we found in each <note> token. That can be done with a simple loop (because we did a quantifier on <notes> it will be Positional:
method TOP ($/) {
my #ties;
#ties.append: .made for $<notes>;
make #ties;
}
The above code creates our temp variable, loops through each <note> and appends on everything that <note> made for us — which is nothing at the moment, but that's okay. Then, because we want the ties from TOP, so we make them, which allows us to access it after parsing.
What do you want from <notes>?
Again, we just want the ties (but maybe some other time, you want ties and glisses, or some other information). So we can grab the ties basically doing the exact same thing:
method notes ($/) {
my #ties;
#ties.append: .made for $<tie>.grep(*.defined);
make #ties;
}
The only differences is rather than doing just for $<tie>, we have to grab just the defined ones — this is a consequence of doing the [<foo>|<bar>]+: $<foo> will have a slot for each quantified match, whether or note <foo> did the matching (this is when you would often want to pop things out to, say, proto token note with a tie and a simple note variant, but that's a bit advaned for this). Again, we grab the whatever $<tie> made for us — we'll define that later, and we "make" it. Whatever we make is what other actions will find made by <notes> (like in TOP).
What do you want from <tie>?
Here I'm going to just go for the content of the tie — it's easy enough to grab the parentheses too if you want. You'd think we'd just use make ~$<notes>, but that leaves off something important: $<notes> also has some ties. But those are easy enough to grab:
method tie ($/) {
my #ties = ~$<notes>;
#ties.append: $<notes>.made;
make #ties;
}
This ensures that we pass along not only the current outer tie, but also each individual inner tie (which in turn may haev another inner one, and so on).
When you parse, all you need to do is grab the .made of the Match:
say Tied.parse("a(b(c))d");
# 「a(b(c))d」
# notes => 「a(b(c))d」
# simple-note => 「a」
# tie => 「(b(c))」 <-- there's a tie!
# notes => 「b(c)」
# simple-note => 「b」
# tie => 「(c)」 <-- there's another!
# notes => 「c」
# simple-note => 「c」
# simple-note => 「d」
say Tied.parse("a(b(c))d", actions => TiedActions).made;
# [b(c) c]
Now, if you really only will ever need the ties —and nothing else— (which I don't think is the case), you can things much more simply. Using the same grammar, use instead the following actions:
class Tied-Actions {
has #!ties;
method TOP ($/) { make #!ties }
method tie ($/) { #!ties.push: ~$<notes> }
}
This has several disadvantages over the previous: while it works, it's not very scalable. While you'll get every tie, you won't know anything about its context. Also, you have to instantiate Tied-Actions (that is, actions => TiedActions.new), whereas if you can avoid using any attributes, you can pass the type object.
I need to fill an input box with a first name and last name. The user will press "Randomize" and it will pull a random first and last name and fill the inputs.
My question is I'm not sure if I should put the names in tables (firstNames, lastNames) or just store them in a javascript file and pull straight from that.
I'm trying to follow the Single Responsibility Principle so I'm inclined to choose the former, but then I have two more models, two more seeders, two more tables, and probably a class to pull all that together. And then do I fill from a CSV file or just from a manually populated seeder? It seems like a lot of work and extra files for a 1-time use.
I know I'll get crap for this being an opinion based question but there is no one or where else to ask.
Also if you know of a place to ask these kind of questions that won't get me ripped apart I'd appreciate that.
I would suggest using the Faker PHP library. That way you wouldn't have to create extra tables, models, or have to worry about finding yourself fake data.
To install it in your project, simply add the dependency in your composer.json file. and run a composer update.
"require-dev": {
"fzaninotto/faker": "1.3.*#dev"
},
Then you can use it to create fake first and last names for you (in your controller most likely)
$faker = Faker\Factory::create();
$firstName = $faker->firstName;
$lastName = $faker->lastName;
Edit:
To add your own names you can either edit or override the name provider file located here.
I would like to suggest Fakerino a new fake generator PHP library, with a modern approach, easy to extend with custom data, custom fake data class, or pre-configured groups of data.
https://github.com/niklongstone/Fakerino
<?php
include ('../Fakerino/vendor/autoload.php');
use Fakerino\Fakerino;
$fakerino = Fakerino::create();
echo $fakerino->fake('Surname')->toJson(); //["Donovan"]
echo $fakerino->fake('NameFemale'); //Alice
//with configuration
$fakerino = Fakerino::create('./conf.php');
print_r($fakerino->fake('fake1')->toArray());
/*
Array(
[0] => Arthur
[1] => Doyle
)
*/
//conf.php
<?php
$conf['fake'] = array(
'fake1' => array('NameMale', 'Surname' => null),
'fake2' => array('NameFemale', 'Surname' => null)
);
crosspost: https://orchard.codeplex.com/discussions/459007
First question I have is what would be the repercussions of having 2 PartHandlers for the same Part in 2 different modules?
I got into this predicament because I have to run a method once a specific Content Type is created. It would be as easy to hook onto OnCreated for the part, however, here is my scenario:
Module A contains the part and the original handler
Module B contains the service where the method is
Module B has a reference to Module A
Therefore, I am unable to reference Module B within Module A (circular reference). So what I did was to copy the exact same PartHandler in Module A and placed it in Module B.
Would anything be wrong with that?
Then comes my second question, which I think could solve all these problems: Can we create a PartHandler for the Content Item's default Content Part? (i.e. the part where all custom fields are attached to)
This would definately make things easier as I could consolidate stuff that need to run there.
UPDATE 1 (to better explain question 2)
ContentDefinitionManager.AlterPartDefinition("EventItem",
builder => builder
.WithField("StartDate", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("Start Date")
.WithSetting("DateTimeFieldSettings.Display", "DateOnly")
.WithSetting("DateTimeFieldSettings.Required", "true"))
.WithField("StartTime", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("Start Time")
.WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
.WithField("EndDate", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("End Date")
.WithSetting("DateTimeFieldSettings.Display", "DateOnly"))
.WithField("EndTime", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("End Time")
.WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
.WithField("Intro", cfg => cfg
.OfType("TextField")
.WithDisplayName("Intro")
.WithSetting("TextFieldSettings.Flavor", "textarea"))
ContentDefinitionManager.AlterTypeDefinition(
"EventItem"
, cfg =>
cfg
.DisplayedAs("Event Item")
.WithPart("TitlePart")
.WithPart("EventItem")
.WithPart("LocationPart")
.WithPart("AutoroutePart", builder => builder
.WithSetting("AutorouteSettings.AllowCustomPattern", "true")
.WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false")
.WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Title', Pattern: 'learn/events/{Content.Slug}', Description: 'learn/events/event-title'}]")
.WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
.WithPart("CommonPart")
.Draftable()
.Creatable()
);
I'm talking about creating a ContentHandler for the EventItem part which holds all the custom fields. How can I go about it when EventItemPart is not defined in any class in the solution?
The following below won't work since it can't find the class EventItemPart:
OnCreated<EventItemPart>((context, keynotes) =>
questionService.SetDefaultQuestions(context.ContentItem));
Cross-answer as well.
Bertrand's perfectly right. Why do you need to reference B in A in first place? If the service from B needs A and A needs this service, then it belongs to A (at least the interface - contract).
You can always split interface and actual implementation for your service, having one in different module than another. If implementation of your service requires stuff from B, then put the interface in A, but actual implementation in B. This way A doesn't even need to know about the existence of B, but still be able to use the service via it's interface - it's the beauty of IoC pattern and Orchard modularity:)
You may use ContentPart or IContent as a type argument in handler generic methods. It's perfectly valid. This way you'd be able to plug in to events on all items, and perform custom filtering afterwards (based on type name, some field existence etc.). In your case it may look like:
OnCreated<ContentPart>((context, part) =>
{
if(part.ContentItem.ContentType != "EventItem") return;
questionService.SetDefaultQuestions(context.ContentItem);
});
Update: no need to do this: .WithPart("EventItem"). This 'fake' part will be automatically added by framework.
Cross-answer:
none
However, repeating yourself is almost always wrong, especially if it's done for a bad reason. Why is are the service and the part in two different modules? Why does A need B? A circular reference indicates tight coupling. If the tight coupling is justified, then it should happen in a single module. If it's not, then you need to re-do your design to remove it.
You can create a handler for anything, but your explanation of your scenario is way to vague and abstract to give any useful advice.
I am going through the RavenDB tutorial on the RavenDb.net website.
It was going fine until I got to the code block for creating an index.
This code segment is direct from RavenDB.Net website.
store.DatabaseCommands.PutIndex("OrdersContainingProduct", new IndexDefinition<Order>
{
Map = orders => from order in orders
from line in order.OrderLines
select new { line.ProductId }
});
I get an error on compile: "The non-generic type 'Raven.Database.Indexing.IndexDefinition' cannot be used with type arguments."
If IndexDefinition is non-generic, why is it used as generic in the sample code? Where is the disconnect?
Thank you for your time
Jim
Depending on your using statements you may be referencing the wrong IndexDefinition class (from another Raven assembly). Try adding this to the beginning of your file:
using Raven.Client.Indexes;
You might need to remove other using statements as well. I guess this is one reason why Microsoft recommends using unique names for classes even in the presence of namespaces.