Is there a LibreOffice BASIC (or other) REPL interactive shell?

I am on Ubuntu 14.04, LibroOffice 4.2.8.2. Does this - or any other later version - have a possibility for a BASIC REPL shell? That is, some form of a terminal program, where I could type stuff like rg = ThisComponent.CurrentSelection, and then inspect the variable rg?

I’m guessing, python could probably be used in this role somehow, instead of BASIC - note that in Ubuntu 14.04, I did:

sudo apt-get install libreoffice-script-provider-python

This installs a script /usr/lib/libreoffice/program/pythonscript.py, but if I run it, it fails:

$ python2.7 /usr/lib/libreoffice/program/pythonscript.py
Traceback (most recent call last):
  File "/usr/lib/libreoffice/program/pythonscript.py", line 19, in <module>
    import uno
ImportError: No module named uno

$ sudo apt-get install python-uno
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Package python-uno is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
However the following packages replace it:
  libreoffice-script-provider-python

E: Package 'python-uno' has no installation candidate

$ apt-show-versions -R python.*uno
python3-uno:amd64/trusty-security 1:4.2.8-0ubuntu5.1 uptodate
python3-uno:i386 not installed

So, there is only a python3 module of uno on this OS; still, even if I’d get an interactive shell with:

$ python3
Python 3.4.3 (default, Nov 17 2016, 01:08:31) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import uno
>>> print(uno)
<module 'uno' from '/usr/lib/python3/dist-packages/uno.py'>
>>> dir(uno)
['Any', 'Bool', 'ByteSequence', 'Char', 'Enum', 'Type', '__builtin__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_g_ctx', '_g_delegatee', '_impl_extractName', '_uno_extract_printable_stacktrace', '_uno_import', '_uno_struct__eq__', '_uno_struct__getattr__', '_uno_struct__init__', '_uno_struct__repr__', '_uno_struct__setattr__', '_uno_struct__str__', 'absolutize', 'createUnoStruct', 'fileUrlToSystemPath', 'generateUuid', 'getClass', 'getComponentContext', 'getConstantByName', 'getCurrentContext', 'getTypeByName', 'invoke', 'isInterface', 'os', 'pyuno', 'setCurrentContext', 'socket', 'sys', 'systemPathToFileUrl', 'unicode']
>>> 

… I still don’t know what (if anything) can I use to “get” a currently open document, or a selection in it - what could I use here?

Hello,

If you want to work interactively with LO using Python, this post should be of help.

There are also Object inspectors you can use - MRI or XRay. You can find links for these in the answer on this post under ‘Useful Extensions’ section.

Thanks for that @Ratslinger - I ended up finding the same post, which helped me come up with the session transcript I posted as an answer here.

Well, apparently there is a way with python3 on Ubuntu 14.04; you have to use (import) either the pyuno.so which is included in the LibreOffice Ubuntu distribution, or the python3-uno module - they seem to be equivalent, though. Here is a transcript of my test shell session:

$ # http://www.openoffice.org/udk/python/python-bridge.html
$ which soffice 
/usr/bin/soffice
$ ls -la `which soffice`
lrwxrwxrwx 1 root root 34 Apr 29 00:53 /usr/bin/soffice -> ../lib/libreoffice/program/soffice
$ readlink -f `which soffice`
/usr/lib/libreoffice/program/soffice
$ dirname $(readlink -f `which soffice`)
/usr/lib/libreoffice/program
$ cd $(dirname $(readlink -f `which soffice`))

$ ls py*
pythonloader.py  pythonloader.unorc  pythonscript.py  pyuno.so

# note: this process runs in the foreground of the shell - so make it run as background with &;
# it starts a LibreOffice instance, can open a document there, say calc .ods
# there is no separate python executable in this directory on Ubuntu 14.04; just pythonloader.py, pythonloader.unorc  pythonscript.py  pyuno.so
# ./soffice "-accept=socket,host=localhost,port=2002;urp;" # Warning: -accept=socket,host=localhost,port=2002;urp; is deprecated. Use:

$ ./soffice "--accept=socket,host=localhost,port=2002;urp;" &
[1] 22783

$ python3
Python 3.4.3 (default, Nov 17 2016, 01:08:31) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyuno
>>> dir(pyuno)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_createUnoStructHelper', 'absolutize', 'checkEnum', 'checkType', 'experimentalExtraMagic', 'fileUrlToSystemPath', 'generateUuid', 'getClass', 'getComponentContext', 'getConstantByName', 'getCurrentContext', 'getTypeByName', 'invoke', 'isInterface', 'setCurrentContext', 'systemPathToFileUrl']
>>> import uno
>>> dir(uno)
['Any', 'Bool', 'ByteSequence', 'Char', 'Enum', 'Type', '__builtin__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_g_ctx', '_g_delegatee', '_impl_extractName', '_uno_extract_printable_stacktrace', '_uno_import', '_uno_struct__eq__', '_uno_struct__getattr__', '_uno_struct__init__', '_uno_struct__repr__', '_uno_struct__setattr__', '_uno_struct__str__', 'absolutize', 'createUnoStruct', 'fileUrlToSystemPath', 'generateUuid', 'getClass', 'getComponentContext', 'getConstantByName', 'getCurrentContext', 'getTypeByName', 'invoke', 'isInterface', 'os', 'pyuno', 'setCurrentContext', 'socket', 'sys', 'systemPathToFileUrl', 'unicode']

# get the uno component context from the PyUNO runtime
>>> localContext1 = pyuno.getComponentContext()
>>> dir(localContext1)
['/services/com.sun.star.security.AccessController/mode', '/singletons/com.sun.star.configuration.Update', ...
>>> localContext2 = uno.getComponentContext()
>>> dir(localContext2)
['/services/com.sun.star.security.AccessController/mode', '/singletons/com.sun.star.configuration.Update', ...
>>> len(dir(localContext1))
61
>>> len(dir(localContext2))
61
# create the UnoUrlResolver
>>> resolver1 = localContext1.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", localContext1 )
>>> resolver2 = localContext2.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", localContext2 )
# connect to the running office
>>> ctx1 = resolver1.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
>>> ctx2 = resolver2.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
>>> smgr1 = ctx1.ServiceManager
>>> smgr2 = ctx2.ServiceManager
# get the central desktop object
>>> desktop1 = smgr1.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx1)
>>> desktop2 = smgr2.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx2)
# access the current document
>>> model1 = desktop1.getCurrentComponent()
>>> model2 = desktop2.getCurrentComponent()
>>> len(dir(model1))
259
>>> len(dir(model2))
259
>>> dir(model1)
['ActionLocks', 'AllVersions', 'AllowMacroExecution', 'ApplyFormDesignMode', 'AreaLinks', 'Args', ...
>>> dir(model2)
['ActionLocks', 'AllVersions', 'AllowMacroExecution', 'ApplyFormDesignMode', 'AreaLinks', 'Args', ...
>>> model1.getArgs()
((com.sun.star.beans.PropertyValue){ Name = (string)"URL", Handle = (long)0x0, Value = (any){ (string)"file:///home/USERNAME/Desktop/memleak.ods" }, State = (com.sun.star.beans.PropertyState)DIRECT_VALUE }, ...
>>> model1.getArgs()[0].Name
'URL'
>>> model1.getArgs()[0].Value
'file:///home/USERNAME/Desktop/memleak.ods'
# BASIC: ThisComponent.CurrentSelection
>>> model1.getCurrentSelection()
pyuno object (com.sun.star.uno.XInterface)0x11516c8{implementationName=ScCellObj, ... # for the default single-cell selection in calc
>>> model1.getCurrentSelection()
pyuno object (com.sun.star.uno.XInterface)0x131a0e8{implementationName=ScCellRangeObj, ... # multi-cell selection in calc
>>> cursel1 = model1.getCurrentSelection()
>>> dir(cursel1)
['AbsoluteName', 'ArrayFormula', 'ArrayTokens', 'AsianVerticalMode', 'BottomBorder', ...
>>> cursel1.Rows
pyuno object (com.sun.star.table.XTableRows)0x133bd08{implementationName=ScTableRowsObj, ...
>>> cursel1.getRows()
pyuno object (com.sun.star.table.XTableRows)0x1350138{implementationName=ScTableRowsObj, ...
>>> cursel1.Columns
pyuno object (com.sun.star.table.XTableColumns)0xf6e878{implementationName=ScTableColumnsObj, ...
>>> cursel1.getColumns()
pyuno object (com.sun.star.table.XTableColumns)0x13549d8{implementationName=ScTableColumnsObj, ...
# [http://ooo-forums.apache.org/en/forum/viewtopic.php?f=20&t=54301 [Solved] Calc - Get exact cell content with Python (View topic) • Apache OpenOffice Community Forum]
# http://christopher5106.github.io/office/2015/12/06/openoffice-libreoffice-automate-your-office-tasks-with-python-macros.html
>>> oArea1 = cursel1.getRangeAddress()
>>> oArea1
(com.sun.star.table.CellRangeAddress){ Sheet = (short)0x0, StartColumn = (long)0x8, StartRow = (long)0x14, EndColumn = (long)0x8, EndRow = (long)0x17 }
>>> oArea1.StartRow
20
>>> oArea1.EndRow
23
>>> active_sheet1 = model1.CurrentController.ActiveSheet
>>> active_sheet1
pyuno object (com.sun.star.sheet.XSpreadsheet)0x13b58d8{implementationName=ScTableSheetObj, ...
>>> oCell1 = active_sheet1.getCellByPosition(oArea1.StartColumn, oArea1.StartRow)
>>> oCell1
pyuno object (com.sun.star.table.XCell)0x13dba88{implementationName=ScCellObj, ...
>>> oCell1.String
'Hello World'

Also, if you want to have scripts available in LO, in Ubuntu 14.04 they are in the directory /usr/lib/libreoffice/share/Scripts/python (owned by root)

@sdaau Also, user scripts are located in /home/YOUR_DIRECTORY/.config/libreoffice/4/user/Scripts/python. I just remembered this post and the link within. Briefly looked at this and haven’t had time enough to dig in.