Konversation/Scripts/Guide til scripting

    From KDE UserBase Wiki
    Revision as of 14:40, 5 August 2011 by Claus chr (talk | contribs) (Importing a new version from external source)
    Other languages:

    Introduktion

    Konversation har indbygget understøttelse af at køre eksterne scripts, som sammen med D-Bus og Konversations egne D-Bus-metoder dækker de fleste almindelige scriptingbehov, så som visning af information i det aktuelle chatvindue eller kontrol af et andet program eller endda af Konversation selv. Denne guide er en introduktion til at skrive et script til Konversation. Den dækker kun de vigtigste begreber, som er nødvendige for at komme i gang. Sprog- og systemspecifikke nuancer er overladt som en øvelse til brugeren.

    Forudsætninger

    Alt hvad du skal bruge for at komme i gang er en teksteditor og et programmerings- eller scriptingsporg. Konversation understøtter ethvert programmeringssprog, som:

    1. Kan modtage og behandle kommandolinjeargumenter (argv'er).
    2. Kan forbinde til og kalde D-Bus eller i det mindste foretage eksterne systemkald (så som at køre programmet qdbus). Det er nok bedst og sikrest at bruge sprogets egne bindinger til D-Bus, hvis sådanne findes i stedet for at udføre et systemkald for at køre qdbus.

    I øjeblikket vides Python, BASH (eller Shell) og Perl at virke og have eksempler, som følger med Konversation, men ethvert sprog, som opfylder de to betingelser vil kunne bruges. Denne guide vil give eksempler i Python.

    1. Tilfælde: Vis information i det aktuelle chatvindue

    Et af de mest almindelige scriptingscenarier er nok at få noget tekst vist i Konversations aktuelle faneblad (kanal eller privat meddelelse), hvor data sædvanligvis kommer fra en ekstern kilde. Denne kilde kunne være scriptet selv, et andet program (som i scriptet media, der følger med Konversation) eller internettet (som fx at indsamle vejrinformation og vise den i Konversation). Hvad kilden end er, så er der tre skridt, der skal udføres:

    1. Få fat i inputtet - opfang og fortolk kommandoen, som brugeren sendte fra Konversation.
    2. Behandl data - saml information fra kilder og omform den baseret på input.
    3. Send outputtet - smid informationen tilbage til Konversation via D-Bus.

    Det følgende er et nonsenseksempel på en script til Konversation, som i grove træk følger dette mønster.


    #!/usr/bin/env python
    # mood - a Konversation script to display a witty remark based on the user's mood.
    # Usage: /exec mood [mood_string]
    
    import sys
    import subprocess
    
    command = ['qdbus', 'org.kde.konversation', '/irc']
    
    argc = len(sys.argv)
    
    if argc < 2:
        command.append("error")
        text = "Server required"
    elif argc < 3:
        command.append("error")
        text = "Target required"
    elif argc < 4:
        command.append("error")
        text = "No mood given"
    else:
        server = sys.argv[1]
        target = sys.argv[2]
        mood   = sys.argv[3]
    
        if mood == "hungry":
            text = "Hungry! Anyone got a horse?"
        elif mood == "sleepy":
            text = "I yawn, therefore I am."
        elif mood == "gloomy":
            text = "Roses are red. Violets are blue, and so am I ..."
        elif mood == "happy":
            text = "Thinking happy thoughts (with a dash of pixie dust)."
        elif mood == "hyper":
            text = "Just a spoonful of sugar? I think I took a whole jar! *cartwheels*"
        elif mood == "excited":
            text = "Are we there yet? Are we there yet? Are we there yet?"
        else:
            text = "What were we talking about again?"
    
            command.append("say")
            command.append(server)
            command.append(target)
    
    command.append(text)
    
    subprocess.Popen(command).communicate()
    

    Få fat i inputtet

    Når Konversation kalder et eksternt script, så kørers det med nogle forud definerede argumenter som her:

    script_navn server mål [yderligere argumenter ...]

    Argumenterne er sædvanligvis gemt i en samling (en liste eller en tabel, afhængigt af sproget) kaldet "argv" og indekseret fra 0 til N, hvor N er antallet af argumenter.

    • argv[0] er altid scriptets navn. I de fleste tilfælde kan det trygt ignoreres.
    • argv[1] er adressen på den server, som brugeren aktuelt er forbundet til. I tilfælde af, at der er forbindelse til flere servere, så vil det altid være den server, som kanal- eller forespørgselsvinduet er forbundet til.
    • argv[2] er målet, dvs. navnet på det chatvindue, hvor kommandoen til at køre scriptet kom fra, hvilket som regel vil være det vindue, hvor outputtet skal vises. Selvfølgelig kan du altid ændre dette.
    • argv[3] til argv[N] vil være de ekstra argumenter, som brugeren sender ved kaldet af scriptet i Konversation. Det kan være hvad som helst fra "flag", der (de)aktiverer valgmuligheder i scriptet over data til tekst, der kan vises i scriptets output. Nogle scripts har ingen ekstra argumenter som fx uptime og sysinfo.

    Remember

    Even if your script doesn't require additional arguments or even if the user didn't supply them, Konversation will always send the system and target arguments. Meaning, argv[1] and argv[2] will always be set. The minimum argument count will always be 3 (remember, indexing starts at 0).


    Processing the Data

    In the example script, the mood variable, supplied by the user in argv[3] of the script, is compared to predefined values and the appropriate remark is assigned to the text variable. This is a simple example of data processing. You can also fetch data from a predefined data source, like the fortune script. Or assemble information coming from the operating system, such as done in the sysinfo script. Whatever information or text you need to be displayed in Konversation, you create that here.

    Warning

    A word of caution: Be careful when creating multi-line text output, as your server or the channel you're sending to may have anti-flooding policies. When dealing with a potentially large, it might be best to have it displayed in another way (like in a text editor).


    Now that the needed information is processed and assembled, it's time to prepare it for sending back into Konversation, which is discussed in the next section.

    Sending the Output

    Controlling Konversation externally, like through a script or the command-line, involves using its D-Bus methods. Konversation has several of them, including a group whose purpose is to display messages. Sending D-Bus messages can be tedious. Fortunately, Qt provides a much easier way of doing that, using the helper program "qdbus". Without going into much detail, all the D-Bus commands we will be sending to make Konversation display messages starts with this string: qdbus org.kde.konversation /irc

    Depending on what kind of message the script will be sending, additional options will be added to that command. Here are but a few examples:

     qdbus org.kde.konversation /irc say server target message
    

    This is probably the command that will be most commonly used. It sends message to the chat window target connected to server. If you want the message to be sent to the same chat window where the script was called from, use argv[1] and argv[2] for server and target, respectively. Of course you can always change the target to any channel or nick you want in that server.

     qdbus org.kde.konversation /irc error message
    

    This displays the message in the same chat window where the script was invoked. The difference is that the message isn't actually sent to the IRC server and is only visible to the user. The message is also formatted as something like "[D-Bus] Error: message". Useful for informing the user about errors in using the script or if something fails in the script. It doesn't need a server or a target.

     qdbus org.kde.konversation /irc sayToAll message
    

    Sends the message to all channels and query windows in all servers. Please use sparingly and observe proper netiquette. It doesn't require a server and a target.

     qdbus org.kde.konversation /irc actionToAll message
    

    sayToAll's action sibling. Sends the message to all channels and query windows in all servers BUT prepends "/me" to the actual message, resulting in displaying something like "*YourNick message*". Again, netiquette applies.

    Note

    To send an action ("/me") message only to the current chat window (where the script was called from), compose the actual message as "/me message" and use the say variant of the command (first one in this list if you got lost ).


    There are other /irc related qdbus commands, some of which change the user's status instead of displaying the command. Feel free to explore other possibilities. Another Qt helper program, "qdbusviewer", provides a graphical interface for browsing through the available commands for Konversation and other "D-Bus aware" programs. You will probably need it a lot especially for the second scripting scenario discussed later.

    Getting the Script to Run

    Now it's time to actually make the script run in Konversation. Here are the steps:

    • Make your script executable.

    chmod +x script_name does it all. It would be better to not include extensions (.sh, .py, .pl, etc.) in your filename, to make it easier to call the script.

    • Place the script in either one of two folders:
      • If you want your script to be available all users in your system, put the script together with the other scripts installed with Konversation. This may vary from distro to distro (or your own personal tinkering), but common a location is /usr/share/apps/konversation/scripts/. In case it's not there, get the output of the command kde4-config --install data and append /konversation/scripts/ to it. Consult your distribution's support channel if it's still not there.
      • If you want the script just for yourself, simply place the script in ~/.kde/share/apps/konversation/scripts/. Some distros might still be using ~/.kde4/ instead so adjust accordingly.
      • Post version 1.3.1 note: another way to find out where the installed scripts are is to run this command in Konversation's input line (using the media script as an example, since it comes with any Konversation installation): /exec --showpath media. Note that if there are two scripts with the same name in the user's home and in the system locations, the one in the user's home will take precedence and be the one shown here.
    • To actually run the script, you need to invoke it by running this command in Konversation's input line:

    /exec script_name [additional arguments]

    This will call your script and pass the arguments to it. Remember that your script_name is always argv[0], and that the current server and chat window are passed as argv[1] and argv[2], even if you didn't include them in your command. Therefore, any additional arguments would be argv[3] and so on.

    • For convenience, you can create a command alias in Konversation so that you can invoke your script simply using /script_name instead of the actual syntax given above. To manually do this, go to Settings -> Configure Konversation -> Command Aliases page. Click on the New button and enter "script_name" as the Alias and "/exec script_name" as the Replacement. So next time you need to run your script, you can simply do use /script_name [arguments]
    • Alternately, whenever Konversation is started, it automatically creates a command alias of "/script_name" for "/exec script_name" for every script it finds in the scripts/ directories mentioned earlier.

    For the previous example, the script is named "mood" and can be invoked either using /mood [mood] or /exec mood [mood], like:

    /mood gloomy
    

    That's basically all you need to know to make a Konversation script. To make it a bit more interesting, let's have an example of another common scripting scenario.

    Case 2: Controlling an External Program from Konversation

    Thanks to D-Bus, and the fact that a lot of KDE applications have D-Bus methods, you can control any KDE application right from within Konversation. Even without D-Bus, you can let your script start, stop, or possibly even control other applications simply with a command in Konversation. This lets you do a lot of things, like sending a command to a terminal emulator, opening a bug report in a browser providing only the report number (like the bug script), or simply running a system command (and probably displaying the results of that command, as the cmd script does).

    The following script performs the first example. It first makes Yakuake visible and then runs the command supplied by the user. The script is rather simple and doesn't involve displaying anything back to the user, except in the case of an error when calling the script itself.

    #!/usr/bin/env python
    # yakrun - Konversation script that runs the command supplied by the user in Yakuake and toggles Yakuake's state
    # Usage: /exec yakrun [command]
    
    import sys
    import subprocess
    
    errorCommand  = ['qdbus', 'org.kde.konversation', '/irc', 'error']
    toggleCommand = ['qdbus', 'org.kde.yakuake', '/yakuake/window', 'toggleWindowState']
    runCommand    = ['qdbus', 'org.kde.yakuake', '/yakuake/sessions', 'runCommand']
    
    argc = len(sys.argv)
    
    if argc < 4:
        text = "No command to run."
    
        errorCommand.append(text)
    
        subprocess.Popen(errorCommand).communicate()
    else:
        command = " ".join(sys.argv[3:])
    
        runCommand.append(command)
    
        subprocess.Popen(toggleCommand).communicate()
        subprocess.Popen(runCommand).communicate()
    

    Language-specific Notes

    • Be careful when processing arguments and assembling them into a single string with spaces, which might be more error-prone in some languages, such as BASH.