Announcement

Collapse
No announcement yet.

Man page runner

Collapse
This topic is closed.
X
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Man page runner

    Simple python krunner plugin, that will show the entered man page in the KDE Help center

    Linking to: https://www.kubuntuforums.net/showth...l=1#post360818

    Quick copy&paste from https://techbase.kde.org/Development...4/PythonRunner and editing few lines.

    metadata.desktop:
    Code:
    [Desktop Entry]
    Name=Man page runner
    Comment=Simple python krunner plugin, that will show the entered man page in the KDE Help center
    Type=Service
    Icon=help-browser
    ServiceTypes=Plasma/Runner
    X-Plasma-API=python
    X-Plasma-MainScript=code/main.py
    X-KDE-PluginInfo-Author=<your name>  
    X-KDE-PluginInfo-Email=<your email>
    X-KDE-PluginInfo-Name=manpage_runner
    X-KDE-PluginInfo-Version=0.1
    X-KDE-PluginInfo-Website=http://plasma.kde.org/
    X-KDE-PluginInfo-License=LGPLv3
    X-KDE-PluginInfo-EnabledByDefault=true
    main.py:
    Code:
    from PyKDE4 import plasmascript
    from PyKDE4.plasma import Plasma
    from PyKDE4.kdeui import KIcon
    
    from subprocess import call
     
    class ManPageRunner(plasmascript.Runner):
     
        def init(self):
            # called upon creation to let us run any intialization
            # tell the user how to use this runner
            self.addSyntax(Plasma.RunnerSyntax("? :q:", "Display :q: manpage with the KHelpcenter"))
     
        def match(self, context):
            # called by krunner to let us add actions for the user
            if not context.isValid():
                return
     
            q = context.query()
     
            # look for our keyword '?'
            if not q.startsWith("? "):
                 return
     
            # ignore less than 3 characters (in addition to the keyword)
            if q.length() < 3:
                return
     
            # strip the keyword and leading space
            q = q[2:]
            q = q.trimmed()
     
            # now create an action for the user, and send it to krunner
            m = Plasma.QueryMatch(self.runner)
            m.setText("man page for: '%s'" % q)
            m.setType(Plasma.QueryMatch.ExactMatch)
            m.setIcon(KIcon("help-browser"))
            m.setData(q)
            context.addMatch(q, m)
     
        def run(self, context, match):
            # called by KRunner when the user selects our action,        
            # so lets keep our promise
            call(["khelpcenter", "man:" + match.data().toString()])
    
     
     
    def CreateRunner(parent):
        # called by krunner, must simply return an instance of the runner object
        return ManPageRunner(parent)



    Seems to work...

    Last edited by Rog132; Oct 21, 2014, 09:42 AM.
    A good place to start: Topic: Top 20 Kubuntu FAQs & Answers
    Searching FAQ's: Google Search 'FAQ from Kubuntuforums'

    #2
    Thanks, Rog132 - this looks pretty interesting. However, I was not able to ge the krunner plugin to work.

    I largely followed the instructions from the link you posted:
    Quick copy&paste from https://techbase.kde.org/Development...4/PythonRunner and editing few lines.
    The plugin installs and appears in the krunner config menu, but when I type, for example,
    Code:
    ?ls
    nothing happens...

    I'm wondering if that has anything to do with missing Python support? The instructions linked to in the above link are very old and I don't really want to build KDE from the SVN repo...

    Also, for anyone else reading this: initially I didn't realize that you create the plugin folder tree anywhere you like and then install it afterwards with the command:
    Code:
    plasmapkg --type runner --install root/folder/of/plugin

    Comment


      #3
      At here...

      At here:

      - tested with the KDE 4.13 ('buntu 14.04) & KDE 4.14 ('buntu 14.10).
      - the package 'plasma-scriptengine-python' is installed.
      - after the installation I need to restart the krunner/plasma/Kubuntu - the surest way is to boot the system...


      There is a space between the question mark (?) and the man page keyword (ls) so:

      A good place to start: Topic: Top 20 Kubuntu FAQs & Answers
      Searching FAQ's: Google Search 'FAQ from Kubuntuforums'

      Comment


        #4
        More...

        Purging

        Purging packages: plasma-scriptengine-python python-kde4 python-qt4 python-sip

        Trying with Krunner => nothing happens - starting the krunner from the konsole, there is no error messages.



        Looking error messages

        Reinstallling the plasma-scriptengine-python, it will draw the python-kde4 python-qt4 python-sip.

        Making a typo to the main.py.



        Shutting the Krunner down:
        Code:
        kquitapp krunner
        Starting the Krunner again:
        Code:
        krunner
        Yes twice
        Code:
        krunner
        => there are error messages in the konsole.

        A good place to start: Topic: Top 20 Kubuntu FAQs & Answers
        Searching FAQ's: Google Search 'FAQ from Kubuntuforums'

        Comment


          #5
          Thanks, Rog132! As I suspected, the Python support was not installed; installing 'plasma-scriptengine-python' and dependencies solved the problem for me - it works now!
          (I just had no idea what the right package would be... too many Python packages... to read all the names/descriptions.)

          I actually changed the code so that you don't have a space after '?' to make it more consistent with the browser display (using '#') and save some typing. But you are right to point this out.

          Comment


            #6
            Btw. I noticed one thing that is rather annoying: for some entries there are apparently several versions of the manual available, so that khelpcenter asks me which one I want.
            Is there something we can do to avoid that? Maybe just choose the latest?
            And why are there multiple versions anyway...?

            Comment


              #7
              Well...




              If you type: (konsole) 'man man' or '? man(1)' or '?man(1) it will tell (the show part is with the terminal):

              ...
              DESCRIPTION
              man is the system's manual pager. Each page argument given to man is normally the name of a program, utility or
              function. The manual page associated with each of these arguments is then found and displayed. A section, if
              provided, will direct man to look only in that section of the manual. The default action is to search in all of
              the available sections following a pre-defined order ("1 n l 8 3 2 3posix 3pm 3perl 5 4 9 6 7" by default, unless
              overridden by the SECTION directive in /etc/manpath.config), and to show only the first page found, even if page
              exists in several sections.

              The table below shows the section numbers of the manual followed by the types of pages they contain.

              1 Executable programs or shell commands
              2 System calls (functions provided by the kernel)
              3 Library calls (functions within program libraries)
              4 Special files (usually found in /dev)
              5 File formats and conventions eg /etc/passwd
              6 Games
              7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7)
              8 System administration commands (usually only for root)
              9 Kernel routines [Non standard]
              ...

              The KDE Help Center is showing the whole truth...


              ...of course you could add more lines to the main.py to show the first/last hit.
              Last edited by OneLine; Oct 26, 2014, 12:23 AM.
              Have you tried ?

              - How to Ask a Question on the Internet and Get It Answered
              - How To Ask Questions The Smart Way

              Comment


                #8
                But what if I don't want the whole truth? ;-)

                Comment


                  #9
                  Well, uh, haven't you heard, "The truth IS out there".
                  Using Kubuntu Linux since March 23, 2007
                  "It is a capital mistake to theorize before one has data." - Sherlock Holmes

                  Comment


                    #10
                    Well... OK, so I could modify the query string in the Python code so as to append, for example, '(1)' which would get me the entry from the first section (if there is one), but then I would have to know in which section an entry can be found. And this still does not solve the problem with multiple languages (I also have German language packages installed).

                    Ideally I would just want the behavior of man at the command line, but I don't really see how I ca do that from the Python script... any ideas?

                    Comment


                      #11
                      See also...

                      ...Ideally I would just want the behavior of man at the command line, but I don't really see how I ca do that from the Python script... any ideas?...

                      This can be done in the main.py with the Python but in this it is done with a (Ba)sh helper script.

                      Man page of the man:



                      Short: The man pages are stored to the database - the 'whatis' is showing one-line manual page descriptions.


                      The 'whatis' output can be piped to only show the one man page section number:
                      Code:
                      whatis man | awk '{print $2}' | sort | head -1


                      More:
                      - man whatis
                      - man awk
                      - man sort
                      - man head

                      Adding a helper script (whatisno):
                      Code:
                      #!/bin/sh
                      
                      whatis $1 | awk '{print $2}' | sort | head -1



                      Editing the main.py:

                      Code:
                      ...
                      from subprocess import call, check_output
                      ...
                              onlyOne = check_output(["whatisno", match.data().toString()])
                              call(["khelpcenter", "man:" + match.data().toString() + onlyOne])
                      ...
                      Seems to work...at here...etc...
                      Last edited by Rog132; Oct 28, 2014, 03:23 AM.
                      A good place to start: Topic: Top 20 Kubuntu FAQs & Answers
                      Searching FAQ's: Google Search 'FAQ from Kubuntuforums'

                      Comment


                        #12
                        Hi Rog132,
                        Thanks for your explanation!
                        I had some things to take car of in my real life and didn't get to look at your solution for a while.
                        Basically it works the way you suggest, except if you have multiple languages.
                        But I modified your approach a bit, so that it does.

                        Now, with this modified run method, it does what I want:
                        Code:
                            def run(self, context, match):
                                ''' called by KRunner when the user selects our action '''
                                name = match.data().toString()
                                if name[-3] == '(' and name[-1] == ')':
                                    # specific section was requested
                                    manno = name[-2] # extract section number
                                    name = name[:-3] # extract program name
                                else:
                                    # identify the lowest available section number
                                    manno = check_output(["whatis {:s} | awk '{{print $2}}' | sort | head -n 1".format(name)], shell=True)[1] # as string
                                    # and keep name
                                # now construct absolute path, to avoid different languages
                                manpath = '/usr/share/man/man{1:s}/{0:s}.{1:s}.gz' # hopefully general enough...
                                manpg = manpath.format(name,manno) # insert program name and section number
                                # so lets keep our promise
                                call(["khelpcenter", "man:" + manpg])
                        I admit that hard-coding the manual path is a bit hackish and should be avoided, but I don't know how to do this better (I looked at the $MANPATH variable, but that has a lot of junk and it is not obvious which entry to select).

                        Basically the command 'whatis' was the key, and that was the thing I didn't know. :-)

                        Chopstick

                        P/S Don't forget, as I did initially, to run plasmapkg --type runner --upgrade path/to/runner and kquitapp and restart krunner (twice, as Rog132 explained)

                        Comment

                        Working...
                        X