.. doctest docs/specs/noi/memo.rst .. _noi.specs.memo: ========================= Memo commands in Lino Noi ========================= >>> from lino import startup >>> startup('lino_book.projects.noi1e.settings.demo') >>> from lino.api.doctest import * The :attr:`description ` of a ticket and the text of a comment (:mod:`short_text `) are :doc:`rich text fields `. And additionally they can contain memo markup commands (see :doc:`/specs/memo`). Lino Noi `memo` command reference ================================= .. _memo.url: url === Insert a link to an external web page. The first argument is the URL (mandatory). If no other argument is given, the URL is used as text. Otherwise the remaining text is used as the link text. The link will always open in a new window (``target="_blank"``) Usage examples: - ``[url http://www.example.com]`` - ``[url http://www.example.com example]`` - ``[url http://www.example.com another example]`` .. test: >>> ses = rt.login() >>> print(ses.parse_memo("See [url http://www.example.com].")) See http://www.example.com. >>> print(ses.parse_memo("See [url http://www.example.com example].")) See example. >>> print(ses.parse_memo("""See [url https://www.example.com ... another example].""")) See another example. A possible situation is that you forgot the space: >>> print(ses.parse_memo("See [urlhttp://www.example.com].")) See [urlhttp://www.example.com]. .. _memo.ticket: ticket ====== Refer to a ticket. Usage example: See ``[ticket 1]``. .. _memo.company: company ======= Refer to a company. Usage example:: I met Joe from [company 1] and we agreed... .. >>> print(rt.login('robin').parse_memo("See [company 100].")) See #100. >>> print(rt.login().parse_memo("See [company 1].")) See [ERROR Company matching query does not exist. in '[company 1]' at position 4-15]. .. _memo.person: person ====== Refer to a person. Usage example:: I met [person 7 Joe] and we agreed... .. _memo.py: py == Refer to a Python object. Usage examples: - ``[py lino]`` - ``[py lino.modlib.memo.parser]`` - ``[py lino_xl.lib.tickets.models.Ticket]`` - ``[py lino_xl.lib.tickets.models.Ticket tickets.Ticket]`` .. >>> ses = rt.login() >>> print(ses.parse_memo("[py lino].")) lino. >>> print(ses.parse_memo("[py lino_xl.lib.tickets.models.Ticket].")) lino_xl.lib.tickets.models.Ticket. >>> print(ses.parse_memo("[py lino_xl.lib.tickets.models.Ticket.foo].")) lino_xl.lib.tickets.models.Ticket.foo. >>> print(ses.parse_memo("[py lino_xl.lib.tickets.models.Ticket Ticket].")) Ticket. Non-breaking spaces are removed from command text: >>> print(ses.parse_memo(u"[py lino].")) lino. .. >>> from lino.utils.diag import analyzer >>> print(analyzer.show_memo_commands()) ... #doctest: +NORMALIZE_WHITESPACE - [company ...] : Insert a reference to the specified database object. The first argument is mandatory and specifies the primary key. All remaining arguments are used as the text of the link. - [person ...] : Insert a reference to the specified database object. The first argument is mandatory and specifies the primary key. All remaining arguments are used as the text of the link. - [ticket ...] : Insert a reference to the specified database object. The first argument is mandatory and specifies the primary key. All remaining arguments are used as the text of the link. The ``obj2memo`` method ======================= You might want to programmatically generate a text containing memo markup. For example when your code knows some database object and you want to create a description which would refer to your object if rendered with memo: >>> ar = rt.login('robin') >>> obj = rt.models.tickets.Ticket.objects.get(pk=1) >>> txt = ar.obj2memo(obj) >>> print(txt) [ticket 1] (Föö fails to bar when baz) Let's also check whether the produced text is valid: >>> print(ar.parse_memo(txt)) #1 (Föö fails to bar when baz) Suggesters ========== There are two suggesters in :ref:`noi`: when the user types a "#", they get a list of tickets. When they type a "@", they get a list with all users. Every site instance has its global memo parser: >>> mp = dd.plugins.memo.parser >>> mp.suggesters.keys() dict_keys(['@', '#']) A suggester always returns a maximum of 5 suggestions: >>> len(list(mp.suggesters['#'].get_suggestions())) 5 >>> list(mp.suggesters['#'].get_suggestions("12")) [(12, '#12 (⚒ Foo cannot bar)')] >>> list(mp.suggesters['#'].get_suggestions("why")) [(20, '#20 (⚒ Why is foo so bar)'), (29, '#29 (☾ Why is foo so bar)'), (38, '#38 (☐ Why is foo so bar)'), (47, '#47 (☑ Why is foo so bar)'), (56, '#56 (☒ Why is foo so bar)')] >>> list(mp.suggesters['@'].get_suggestions()) [('jean', 'Jean'), ('luc', 'Luc'), ('marc', 'Marc'), ('mathieu', 'Mathieu'), ('robin', 'Robin Rood')] >>> list(mp.suggesters['@'].get_suggestions("ma")) [('marc', 'Marc'), ('mathieu', 'Mathieu'), ('romain', 'Romain Raffault')] >>> mp.suggesters['#'].get_object("1") Ticket #1 ('#1 (⚹ Föö fails to bar when baz)') >>> mp.parse("#1", ar) '#1' Bleaching ========= Comments a being bleached by default. Check whether content has been bleached >>> print(comments.Comment.objects.filter(body="o:OfficeDocumentSettings").first()) None >>> obj = comments.Comment.objects.filter(body__contains="and follow your welcome messages").first() >>> print(obj.short_preview) breaking (...) Above comments were created by the :fixture:`demo2` fixture of :mod:`lino.modlib.comments`. .. _permalink_uris: Permalink URIs ============== Note that the URI of the link depends on the context. Of course it depends on the site's front end (specfied in the :attr:`default_ui ` setting). But when the front end is :mod:`lino.modlib.extjs`, then we also get a different URL depending on whether :attr:`lino.core.requests.BaseRequest.permalink_uris` is set or not: Usually we want a "javascript:..." URI because we don't want the page to reload when executing an action. For example when calling it e.g. from :meth:`send_summary_emails `, we want a "permalink" whose URI also works in the recipients email client where the JS application isn't yet loaded. In that case we must explicitly set :attr:`lino.core.requests.BaseRequest.permalink_uris` to True. >>> ses = rt.login('robin', ... renderer=settings.SITE.kernel.default_renderer) >>> print(ses.parse_memo("See [ticket 1].")) See #1. >>> ses.permalink_uris = True >>> print(ses.parse_memo("See [ticket 1].")) See #1. While the :mod:`lino.modlib.bootstrap3` front end will render it like this: >>> ses = rt.login(renderer=dd.plugins.bootstrap3.renderer) >>> print(ses.parse_memo("See [ticket 1].")) See #1. When using this front end, the :attr:`permalink_uris ` parameter has no effect: >>> ses.permalink_uris = True >>> print(ses.parse_memo("See [ticket 1].")) See #1. Or the plain text renderer will render: >>> ses = rt.login() >>> print(ses.parse_memo("See [ticket 1].")) See #1. >>> ses.permalink_uris = True >>> print(ses.parse_memo("See [ticket 1].")) See #1.