Wie kann ich ein einfaches Menü in Perl?
Ich arbeite an einem Perl-Skript, erfordert einige grundlegende Menü-Funktionalität. Letztendlich würde ich wie jedes Menü mit ein paar Optionen und dann entweder die option zum zurückkehren zum vorherigen Menü oder beenden.
Beispiel:
Dies ist ein Menü:
- Wahl 1
- Wahl 2
- Zurück zum vorherigen Menü
- Ausfahrt
Wählen Sie eine option:
Momentan habe ich ein Menü-Unterroutine machen den Menüs, aber es gibt keine Funktionen und erlaubt es, um zurück zum vorherigen Menü.
sub menu
{
for (;;) {
print "--------------------\n";
print "$_[0]\n";
print "--------------------\n";
for (my $i = 0; $i < scalar(@{ $_[1]}); $i++) {
print $i + 1, "\.\t ${ $_[1] }[$i]\n";
}
print "\n?: ";
my $i = <STDIN>; chomp $i;
if ($i && $i =~ m/[0-9]+/ && $i <= scalar(@{ $_[1]})) {
return ${ $_[1] }[$i - 1];
} else {
print "\nInvalid input.\n\n";
}
}
}
# Using the menu
my $choice1 = menu('Menu1 header', \@list_of_choices1);
# I would like this menu to give the option to go back to
# the first menu to change $choice1
my $choice2 = menu('Menu2 header', \@list_of_choices2);
Ich will nicht zu hart code alle Menüs und verwenden if/elsif-Anweisungen für alle von der Verarbeitung so wandte ich mich der Menü-Funktion.
Meine Menüs derzeit so Aussehen...
Menü-Header:
- Choice1
- Auswahl2
- Choice3
?: (Geben Sie hier eingeben)
Diese Lösung noch nicht erlauben den Benutzer, um zurück zum vorherigen Menü oder beenden obwohl. Ich wurde überlegt, einen menu-Klasse zu behandeln, die Menüs, aber ich bin noch nicht sehr gut mit objektorientiertem Perl. Dies ist ein kleines Programm, mit nur ein paar Menüs, so dass durch eine komplexe Menü-Aufbau-Modul kann overkill. Ich möchte, dass mein code so leicht wie möglich.
EDIT:
Danke für die schnellen Antworten! Es ist aber immer noch ein Problem. Wenn ich wählen Sie eine option aus "Menu1" und Laufe auf "Menu2" ich möchte, dass das speichern der Auswahl von "Menu1" für die spätere Verwendung:
Menu1:
- Choice1 <-- speichern Sie Wert, wenn ausgewählt, und gehen Sie zum nächsten Menü
- Auswahl2 <-- ...
- Exit <-- beenden
Menu2:
- Choice1 <-- speichern Sie Wert, wenn ausgewählt, und gehen Sie zum nächsten Menü
- Auswahl2 <-- ...
- Zurück <-- zurück zum vorherigen Menü erneut Wert
- Exit <-- beenden
Auswahl entweder Choice1 oder Auswahl2 sollte speichern einen Wert in einer Variablen für die spätere Verwendung und Fortschritt zum nächsten Menü. Dann, wenn Sie sich entscheiden, gehen Sie zurück zum ersten Menü Menu2, wird es geben Ihnen die Möglichkeit, erneut Ihre Auswahl und definieren Sie die variable. Ich versuche zu vermeiden Sie die Verwendung globaler Variablen, die macht dies sehr schwierig.
Nach voran durch alle Menüs und Einstellung der Werte aller dieser Variablen möchte ich eine Unterroutine ausführen zu verarbeiten, all der Wahlen, und drucken Sie eine endgültige Ausgabe.
sub main () {
# DO MENU STUFF HERE
# PROCESS RESULTS FROM MENU CHOICES
my $output = process($menu1_choice, $menu2_choice, $menu3_choice, ... );
}
Auch wenn jemand einen objektorientierten Ansatz, um diese Klassen benutzen oder einige andere Daten-Struktur, obwohl es vielleicht übertrieben, ich würde immer noch gerne sehen und versuchen, wickeln Sie meinen Kopf herum, die Idee!
- Frage mich, ob dies helfen würde: unix.stackexchange.com/questions/15756/ncurses-based-menus
- Begriff::Wählen Sie bietet die option
default
legt das Menü-element standardmäßig ausgewählt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Könnten Sie ein Modul, wie Begriff::Wählen:
Wenn Sie nicht wollen, zu gehen voll OO mit diesem, eine einfache Weise, Sie können diese viel flexibler ist es, die einzelnen Menü-Wahl zu kontrollieren, wie es ausgeführt wird. Lassen Sie uns sagen, jedes Menü ist ein array von hashes, die die Menü-Texten und einer coderef, die, was die Karte tut.
Den
menu
Unterprogramm nimmt ein array von Optionen, und jede option, die "weiß", wie Sie zur Durchführung Ihrer eigenen Aktion. Wenn Sie möchten, dass Sie zum wechseln zwischen Menüs die Menü-option ruft einfachmenu
wieder mit einer anderen Liste von Optionen, wie in der "zurück" - Beispiel aus@other_menu_choices
. Diese stellen die Verknüpfung zwischen den Menüs sehr einfach und es ist auch einfach hinzufügen exit-Optionen und so.Um diesen code sauber und lesbar, für alles andere als trivial Menü Aktionen, verwenden Sie eine benannte Referenz auf eine subroutine anstelle eines anonymen Subroutinen-Referenz. Zum Beispiel:
return $items[ $line - 1 ]{code}->();
? Warum geht es nicht wenn du es auf diese Weisereturn $items[ $line - 1 ]->{code};
? Ich Schätze, dass ich nicht vollständig verstehen, wie anonyme Subroutinen in hashes arbeiten.->
- operator für die Dereferenzierung, aber in einer zusammengesetzten Struktur kann es weggelassen werden, zwischen den Ebenen. So$ref->[0]->{foo}->[2]
ist das gleiche wie$ref->[0]{foo}[2]
. Aber für sub-refs haben, müssen Sie auf die->
zum aufrufen der sub, sonst Perl denkt, die Sie zurückgeben möchten die sub auf sich selbst. Man könnte also auch schreibenreturn $items[ $line - 1 ]->{code}->();
. Die->()
benötigt zum aufrufen der sub anstatt nur die Rückgabe als Wert.Nach ein paar Monaten der Programmierung mit Perl habe ich gelernt, viel mehr über den Umgang mit Objekten und schrieb eine einfache Objekt-orientierte Menüs erstellen-Modul auf der Grundlage von friedo Antwort.
Mit diesem Modul können Sie erstellen Menüs und verlinken Sie Sie relativ einfach. Finden Sie unter Beispiel für die Verwendung unter:
Dieser code erzeugt ein einfaches Menü mit einem Untermenü. Einmal im Untermenü können Sie leicht gehen Sie zurück zum vorherigen Menü.
Dank für all die tollen Antworten! Sie hat mir sehr geholfen, dies herauszufinden, und ich glaube nicht, dass ich würde haben endete mit einem so guten Lösung, ohne all die Hilfe!
EINE BESSERE LÖSUNG:
Verabschieden, um die hässlichen arrays von hashes!
Einige der code-interne Menü.pm und Posten.pm-Module kann die Optik leicht verwirrend, aber dieses neue design macht die Schnittstelle der Aufbau der Menüs selbst viel sauberer und effizienter.
Nachdem einige vorsichtige code-überarbeitung und Herstellung der einzelnen Menü-Elemente in Ihre eigenen Objekte war ich in der Lage zu schaffen eine viel sauberere Schnittstelle für die Erstellung von Menüs. Hier ist mein neuer code:
Dies ist ein test-Skript zeigt ein Beispiel, wie die Module zu bauen-Menüs.
Dem Menü.pm-Modul dient zum Aufbau der Menü-Objekte. Diese Menü-Objekte enthalten kann, die mehrere Menü::Element-Objekten. Die Objekte gespeichert sind in ein array, so wird die Reihenfolge beibehalten.
Den Punkt.Uhr-Modul gespeichert werden müssen, in einem Unterordner namens "Menü", um für es zu auf Sie verwiesen werden, richtig. Dieses Modul ermöglicht Ihnen das erstellen-Menü::Element-Objekten, die einen Namen enthalten und eine Subroutinen-Referenz. Diese Objekte werden, was der Benutzer wählt aus dem Menü.
Dieser Entwurf ist eine große Verbesserung gegenüber meinem vorherigen design und macht das erstellen von Menüs sehr viel einfacher und sauberer.
Lassen Sie mich wissen, was Sie denken.
Alle Kommentare, Gedanken, oder Ideen für Verbesserungen?
Folgenden wird ein Ansatz. Jede Entscheidung hat eine zugeordnete Unterprogramm. Wenn die Wahl gemacht ist, wird das entsprechende Unterprogramm aufgerufen. Hier bin ich mit anonymen Subroutinen, aber Sie können auch Referenzen auf benannte Subroutinen.
Danke an alle für die Antworten! Alle drei Antworten waren hilfreich, schließlich kommen mit meiner Lösung. Ich beschloss, gehen mit dem Begriff::Wählen Sie module, (Dank sid_com für die Idee). Meine Menü-Struktur war anders als Sie hatte ursprünglich vorgeschlagen, und es dauerte eine ganze Weile von meinen Kopf kratzen, um herauszufinden, wie man es tun, genau das, was ich wollte. Hoffentlich hilft diese Lösung jemand, der auf ein ähnliches problem.
Konstruierte ich das Menü wie unten dargestellt:
(Ich habe ersetzt meine Variablen mit mehr Allgemeinen Namen, so dass es einfacher ist, zu Folgen)
Ich bin noch sehr neu in objektorientierten Perl, so dass dies eine sehr lange Zeit brauchte, um herauszufinden, und es ist vielleicht nicht perfekt, aber es bekommt den job getan. Lassen Sie mich wissen, wenn Sie irgendwelche Ideen oder Verbesserungen!
Ich gefunden habe, dieses alte Modul ohne perldoc in meinem perl-Module...
Bitte, probieren Sie es aus...