SimpleService
=============

* :download:`Download example <PyObjCExample-SimpleService.zip>`

Shows how to implement entries for the Services menu.


.. rst-class:: tabber

Sources
-------

.. rst-class:: tabbertab

ServiceTest.py
..............

.. sourcecode:: python

    import Cocoa
    import objc
    
    
    def serviceSelector(fn):
        # this is the signature of service selectors
        return objc.selector(fn, signature=b"v@:@@o^@")
    
    
    def ERROR(s):
        # NSLog(u"ERROR: %s", s)
        return s
    
    
    class ServiceTest(Cocoa.NSObject):
        @serviceSelector
        def doOpenFileService_userData_error_(self, pboard, data, error):
            try:
                types = pboard.types()
                pboardString = None
                if Cocoa.NSStringPboardType in types:
                    pboardString = pboard.stringForType_(Cocoa.NSStringPboardType)
                if pboardString is None:
                    return ERROR(
                        Cocoa.NSLocalizedString(
                            "Error: Pasteboard doesn't contain a string.",
                            "Pasteboard couldn't give string.",
                        )
                    )
    
                if not Cocoa.NSWorkspace.sharedWorkspace().openFile_(pboardString):
                    return ERROR(
                        Cocoa.NSLocalizedString(
                            "Error: Couldn't open file %s.",
                            "Couldn't perform service operation for file %s.",
                        )
                        % pboardString
                    )
    
                return ERROR(None)
            except:  # noqa: E722, B001
                import traceback
    
                traceback.print_exc()
                return ERROR("Exception, see traceback")
    
        @serviceSelector
        def doCapitalizeService_userData_error_(self, pboard, data, err):
            # NSLog(u"doCapitalizeService_userData_error_(%s, %s)", pboard, data)
            try:
                types = pboard.types()
                pboardString = None
                if Cocoa.NSStringPboardType in types:
                    pboardString = pboard.stringForType_(Cocoa.NSStringPboardType)
                if pboardString is None:
                    return ERROR(
                        Cocoa.NSLocalizedString(
                            "Error: Pasteboard doesn't contain a string.",
                            "Pasteboard couldn't give string.",
                        )
                    )
    
                newString = Cocoa.NSString.capitalizedString(pboardString)
    
                if not newString:
                    return ERROR(
                        Cocoa.NSLocalizedString(
                            "Error: Couldn't capitalize string %s.",
                            "Couldn't perform service operation for string %s.",
                        )
                        % pboardString
                    )
    
                types = [Cocoa.NSStringPboardType]
                pboard.declareTypes_owner_([Cocoa.NSStringPboardType], None)
                pboard.setString_forType_(newString, Cocoa.NSStringPboardType)
                return ERROR(None)
            except:  # noqa: E722, B001
                import traceback
    
                traceback.print_exc()
                return ERROR("Exception, see traceback")

.. rst-class:: tabbertab

SimpleService_main.py
.....................

.. sourcecode:: python

    from Cocoa import NSRegisterServicesProvider
    from PyObjCTools import AppHelper
    from ServiceTest import ServiceTest
    
    
    def main():
        serviceProvider = ServiceTest.alloc().init()
        NSRegisterServicesProvider(serviceProvider, "PyObjCSimpleService")
        AppHelper.runConsoleEventLoop()
    
    
    if __name__ == "__main__":
        main()

.. rst-class:: tabbertab

rebuild.py
..........

.. sourcecode:: python

    #!/usr/bin/env python
    """
    Quickie script to update the services
    """
    import AppKit
    
    AppKit.NSUpdateDynamicServices()

.. rst-class:: tabbertab

setup.py
........

.. sourcecode:: python

    """
    Script for building the example.
    
    Usage:
        python3 setup.py py2app
    """
    
    from setuptools import setup
    
    plist = {
        "CFBundleIdentifier": "net.sf.pyobjc.PyObjCSimpleService",
        "CFBundleName": "PyObjCSimpleService",
        "LSBackgroundOnly": 1,
        "NSServices": [
            {
                "NSKeyEquivalent": {"default": "F"},
                "NSMenuItem": {"default": "Open File"},
                "NSMessage": "doOpenFileService",
                "NSPortName": "PyObjCSimpleService",
                "NSSendTypes": ["NSStringPboardType"],
            },
            {
                "NSMenuItem": {"default": "Capitalize String"},
                "NSMessage": "doCapitalizeService",
                "NSPortName": "PyObjCSimpleService",
                "NSReturnTypes": ["NSStringPboardType"],
                "NSSendTypes": ["NSStringPboardType"],
            },
        ],
    }
    
    
    setup(
        name="Simple Service",
        app=["SimpleService_main.py"],
        options={"py2app": {"plist": plist}},
        setup_requires=["py2app", "pyobjc-framework-Cocoa"],
    )

