ntg-context - mailing list for ConTeXt users
 help / color / mirror / Atom feed
* Checking for a macro in a string without expanding it
@ 2021-11-16 19:22 Joey McCollum via ntg-context
  2021-11-16 20:09 ` Jairo A. del Rio via ntg-context
  2021-11-16 21:04 ` Hans Hagen via ntg-context
  0 siblings, 2 replies; 8+ messages in thread
From: Joey McCollum via ntg-context @ 2021-11-16 19:22 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: Joey McCollum


[-- Attachment #1.1: Type: text/plain, Size: 1619 bytes --]

As the subject of this question suggests, this is really more of a question
about expansion control (a topic that is still a bit obscure to me).
Suppose I have a macro \inner that expects a single argument or an
assignment of parameters in brackets. For my purposes, I don't want this
macro to do anything when it is typeset, so I'll just define it as empty:

```
\def\inner[#1]\empty
```

Now suppose I have another macro \outer that invokes this macro with some
specific input and sets some plain text after it:

```
\def\outer{\inner[123] etc.}
```

What I'd like to do is parse the argument of \inner in \outer. I was hoping
that a string search in Lua would work, but I'm not having any luck. A
minimal (non)-working example is included below:

```

\def\inner[#1]\empty

\def\outer{\inner[123] etc.}


\startluacode

local userdata = userdata or {}

function userdata.parseinner(str)

local innerparams = ""

    if string.find(str, "\\inner(%b[])") then

      i, j = string.find(str, "\\inner(%b[])")

      innerparams = string.sub(str, i+1, j-1) -- we just want the content
inside the brackets

    end

    context(innerparams)

    return

end

\stopluacode

\def\parseinner#1{\ctxlua{userdata.parseinner([==[#1]==])}}


\starttext

Testing:\blank

\parseinner{\outer}

\stoptext
```

My problem is that when I pass \outer to the \parseinner macro, it gets
fully expanded, so there isn't anything left to match "\\inner%b[]". Is
there a way to expand \outer when I pass it to the \parseinner macro
without also expanding the \inner macro inside it? Or is there some other
preferred way of doing this?

Joey

[-- Attachment #1.2: Type: text/html, Size: 2910 bytes --]

[-- Attachment #2: Type: text/plain, Size: 493 bytes --]

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Checking for a macro in a string without expanding it
  2021-11-16 19:22 Checking for a macro in a string without expanding it Joey McCollum via ntg-context
@ 2021-11-16 20:09 ` Jairo A. del Rio via ntg-context
  2021-11-16 21:18   ` Hans Hagen via ntg-context
  2021-11-16 21:04 ` Hans Hagen via ntg-context
  1 sibling, 1 reply; 8+ messages in thread
From: Jairo A. del Rio via ntg-context @ 2021-11-16 20:09 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: Jairo A. del Rio


[-- Attachment #1.1: Type: text/plain, Size: 3273 bytes --]

If I understand it correctly, you may need something like this...?

% Protection is key
\protected\def\inner[#1]{\empty}
% \outer is (or was) already defined in \CONTEXT
% Please use another name
\def\Outer{\inner[123] and \inner[some text] etc.}
\startluacode
local implement = interfaces.implement
local argument = tokens.scanners.argument
local function parseinner()
  local r = {}
  local str = argument()
  str = str:gsub("\\inner%s*(%b[])",function(s)r[#r+1] = s:sub(2,#s-1)end)
  context(table.concat(r," ")) -- Change " " by another spacer if needed
end
implement{name = "parseinner", public = true, actions = parseinner}
\stopluacode
\starttext
\parseinner{\Outer}
\stoptext

However, this will only work with very simple cases (no nesting, etc.).
Hope this helps.

Best regards,

Jairo

El mar, 16 de nov. de 2021 a la(s) 14:22, Joey McCollum via ntg-context (
ntg-context@ntg.nl) escribió:

> As the subject of this question suggests, this is really more of a
> question about expansion control (a topic that is still a bit obscure to
> me). Suppose I have a macro \inner that expects a single argument or an
> assignment of parameters in brackets. For my purposes, I don't want this
> macro to do anything when it is typeset, so I'll just define it as empty:
>
> ```
> \def\inner[#1]\empty
> ```
>
> Now suppose I have another macro \outer that invokes this macro with some
> specific input and sets some plain text after it:
>
> ```
> \def\outer{\inner[123] etc.}
> ```
>
> What I'd like to do is parse the argument of \inner in \outer. I was
> hoping that a string search in Lua would work, but I'm not having any luck.
> A minimal (non)-working example is included below:
>
> ```
>
> \def\inner[#1]\empty
>
> \def\outer{\inner[123] etc.}
>
>
> \startluacode
>
> local userdata = userdata or {}
>
> function userdata.parseinner(str)
>
> local innerparams = ""
>
>     if string.find(str, "\\inner(%b[])") then
>
>       i, j = string.find(str, "\\inner(%b[])")
>
>       innerparams = string.sub(str, i+1, j-1) -- we just want the content
> inside the brackets
>
>     end
>
>     context(innerparams)
>
>     return
>
> end
>
> \stopluacode
>
> \def\parseinner#1{\ctxlua{userdata.parseinner([==[#1]==])}}
>
>
> \starttext
>
> Testing:\blank
>
> \parseinner{\outer}
>
> \stoptext
> ```
>
> My problem is that when I pass \outer to the \parseinner macro, it gets
> fully expanded, so there isn't anything left to match "\\inner%b[]". Is
> there a way to expand \outer when I pass it to the \parseinner macro
> without also expanding the \inner macro inside it? Or is there some other
> preferred way of doing this?
>
> Joey
>
> ___________________________________________________________________________________
> If your question is of interest to others as well, please add an entry to
> the Wiki!
>
> maillist : ntg-context@ntg.nl /
> http://www.ntg.nl/mailman/listinfo/ntg-context
> webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
> archive  : https://bitbucket.org/phg/context-mirror/commits/
> wiki     : http://contextgarden.net
>
> ___________________________________________________________________________________
>

[-- Attachment #1.2: Type: text/html, Size: 5293 bytes --]

[-- Attachment #2: Type: text/plain, Size: 493 bytes --]

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Checking for a macro in a string without expanding it
  2021-11-16 19:22 Checking for a macro in a string without expanding it Joey McCollum via ntg-context
  2021-11-16 20:09 ` Jairo A. del Rio via ntg-context
@ 2021-11-16 21:04 ` Hans Hagen via ntg-context
  1 sibling, 0 replies; 8+ messages in thread
From: Hans Hagen via ntg-context @ 2021-11-16 21:04 UTC (permalink / raw)
  To: Joey McCollum via ntg-context; +Cc: Hans Hagen

On 11/16/2021 8:22 PM, Joey McCollum via ntg-context wrote:
> As the subject of this question suggests, this is really more of a 
> question about expansion control (a topic that is still a bit obscure to 
> me). Suppose I have a macro \inner that expects a single argument or an 
> assignment of parameters in brackets. For my purposes, I don't want this 
> macro to do anything when it is typeset, so I'll just define it as empty:
> 
> ```
> \def\inner[#1]\empty
> ```
> 
> Now suppose I have another macro \outer that invokes this macro with 
> some specific input and sets some plain text after it:
> 
> ```
> \def\outer{\inner[123] etc.}
> ```
> 
> What I'd like to do is parse the argument of \inner in \outer. I was 
> hoping that a string search in Lua would work, but I'm not having any 
> luck. A minimal (non)-working example is included below:
> 
> ```
> 
> \def\inner[#1]\empty
> 
> \def\outer{\inner[123] etc.}
> 
> 
> \startluacode
> 
> local userdata = userdata or {}
> 
> function userdata.parseinner(str)
> 
> local innerparams = ""
> 
>      if string.find(str, "\\inner(%b[])") then
> 
>        i, j = string.find(str, "\\inner(%b[])")
> 
>        innerparams = string.sub(str, i+1, j-1) -- we just want the 
> content inside the brackets
> 
>      end
> 
>      context(innerparams)
> 
>      return
> 
> end
> 
> \stopluacode
> 
> \def\parseinner#1{\ctxlua{userdata.parseinner([==[#1]==])}}
> 
> 
> \starttext
> 
> Testing:\blank
> 
> \parseinner{\outer}
> 
> \stoptext
> 
> ```
> 
> My problem is that when I pass \outer to the \parseinner macro, it gets 
> fully expanded, so there isn't anything left to match "\\inner%b[]". Is 
> there a way to expand \outer when I pass it to the \parseinner macro 
> without also expanding the \inner macro inside it? Or is there some 
> other preferred way of doing this?

One can always abuse native tex:

\starttext

\def\MyOuter#1%
   {\beginlocalcontrol % hides the next
    \let\Indeed\empty
    \def\MyInner[##1]{\gdef\Indeed{##1}}%
    \setbox\scratchbox\hpack{#1}%
    \endlocalcontrol  % but only if needed
    \Indeed}

whatever: \MyOuter{\MyInner[oeps]}%

\edef\ItWorks{\MyOuter{\MyInner[oeps]}}

whatever: \meaningless\ItWorks

\stoptext



-- 

-----------------------------------------------------------------
                                           Hans Hagen | PRAGMA ADE
               Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
        tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Checking for a macro in a string without expanding it
  2021-11-16 20:09 ` Jairo A. del Rio via ntg-context
@ 2021-11-16 21:18   ` Hans Hagen via ntg-context
  2021-11-16 22:15     ` Joey McCollum via ntg-context
  2021-11-17 11:36     ` Henning Hraban Ramm via ntg-context
  0 siblings, 2 replies; 8+ messages in thread
From: Hans Hagen via ntg-context @ 2021-11-16 21:18 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: Hans Hagen

On 11/16/2021 9:09 PM, Jairo A. del Rio via ntg-context wrote:
> If I understand it correctly, you may need something like this...?
> 
> % Protection is key
> \protected\def\inner[#1]{\empty}
> % \outer is (or was) already defined in \CONTEXT
> % Please use another name
> \def\Outer{\inner[123] and \inner[some text] etc.}
> \startluacode
> local implement = interfaces.implement
> local argument = tokens.scanners.argument
> local function parseinner()
>    local r = {}
>    local str = argument()
>    str = str:gsub("\\inner%s*(%b[])",function(s)r[#r+1] = s:sub(2,#s-1)end)
>    context(table.concat(r," ")) -- Change " " by another spacer if needed
> end
> implement{name = "parseinner", public = true, actions = parseinner}
> \stopluacode
> \starttext
> \parseinner{\Outer}
> \stoptext
> 
> However, this will only work with very simple cases (no nesting, etc.). 
> Hope this helps.
well, if we start talking weird code ...

\starttext

\tolerant\def\MyInnerOuter#1\MyInner[#2]#3\MyDone\ignorearguments{#2}

\def\MyOuter#1{\MyInnerOuter#1\MyDone\ignorearguments}

whatever: \MyOuter{\MyInner[oeps]}\par
whatever: \MyOuter{\InnerMy[oeps]}\par

\edef\ItWorksA{\MyOuter{\MyInner[oeps]}}
\edef\ItWorksB{\MyOuter{\InnerMy[oeps]}}

whatever: \meaningless\ItWorksA\par
whatever: \meaningless\ItWorksB\par

\stoptext

(1) we're tolerant so no problem when no match
(2) the ignore hack quits scanning because tex will keep looking

it's pretty fast and needs no lua magic, only a twisted mind

Hans

-----------------------------------------------------------------
                                           Hans Hagen | PRAGMA ADE
               Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
        tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Checking for a macro in a string without expanding it
  2021-11-16 21:18   ` Hans Hagen via ntg-context
@ 2021-11-16 22:15     ` Joey McCollum via ntg-context
  2021-11-17  8:02       ` Hans Hagen via ntg-context
  2021-11-17 11:36     ` Henning Hraban Ramm via ntg-context
  1 sibling, 1 reply; 8+ messages in thread
From: Joey McCollum via ntg-context @ 2021-11-16 22:15 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: Joey McCollum


[-- Attachment #1.1: Type: text/plain, Size: 3507 bytes --]

I'm not sure if my mind is twisted enough! I can follow how Jairo's answer
works, and that does what I need it to, but it's not as clear to me what
the last two TeX-only approaches are doing at a low level.

Perhaps more importantly, I should clarify that for my purposes, the
\MyOuter macro is the \currentbtxrighttext macro, which is defined in a
separate module that I'd prefer not to modify. I want to be able to detect
and parse the parameters of a \loc macro that a user can specify in a
citation as follows:

```
\cite[lefttext={See}, righttext={\loc[vol=8,p=223] for further
details}][clementinehomilies]
```

Because the locator parameters may need to be parenthesized or formatted
differently depending on the category of the bibliography entry, they
should be typeset separately from the plain part of the righttext. This is
why I'd like to be able to parse the parameters and then expand the \loc
macro itself as empty when the righttext is typeset.

Joey

On Tue, Nov 16, 2021 at 4:19 PM Hans Hagen via ntg-context <
ntg-context@ntg.nl> wrote:

> On 11/16/2021 9:09 PM, Jairo A. del Rio via ntg-context wrote:
> > If I understand it correctly, you may need something like this...?
> >
> > % Protection is key
> > \protected\def\inner[#1]{\empty}
> > % \outer is (or was) already defined in \CONTEXT
> > % Please use another name
> > \def\Outer{\inner[123] and \inner[some text] etc.}
> > \startluacode
> > local implement = interfaces.implement
> > local argument = tokens.scanners.argument
> > local function parseinner()
> >    local r = {}
> >    local str = argument()
> >    str = str:gsub("\\inner%s*(%b[])",function(s)r[#r+1] =
> s:sub(2,#s-1)end)
> >    context(table.concat(r," ")) -- Change " " by another spacer if needed
> > end
> > implement{name = "parseinner", public = true, actions = parseinner}
> > \stopluacode
> > \starttext
> > \parseinner{\Outer}
> > \stoptext
> >
> > However, this will only work with very simple cases (no nesting, etc.).
> > Hope this helps.
> well, if we start talking weird code ...
>
> \starttext
>
> \tolerant\def\MyInnerOuter#1\MyInner[#2]#3\MyDone\ignorearguments{#2}
>
> \def\MyOuter#1{\MyInnerOuter#1\MyDone\ignorearguments}
>
> whatever: \MyOuter{\MyInner[oeps]}\par
> whatever: \MyOuter{\InnerMy[oeps]}\par
>
> \edef\ItWorksA{\MyOuter{\MyInner[oeps]}}
> \edef\ItWorksB{\MyOuter{\InnerMy[oeps]}}
>
> whatever: \meaningless\ItWorksA\par
> whatever: \meaningless\ItWorksB\par
>
> \stoptext
>
> (1) we're tolerant so no problem when no match
> (2) the ignore hack quits scanning because tex will keep looking
>
> it's pretty fast and needs no lua magic, only a twisted mind
>
> Hans
>
> -----------------------------------------------------------------
>                                            Hans Hagen | PRAGMA ADE
>                Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
>         tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
> -----------------------------------------------------------------
>
> ___________________________________________________________________________________
> If your question is of interest to others as well, please add an entry to
> the Wiki!
>
> maillist : ntg-context@ntg.nl /
> http://www.ntg.nl/mailman/listinfo/ntg-context
> webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
> archive  : https://bitbucket.org/phg/context-mirror/commits/
> wiki     : http://contextgarden.net
>
> ___________________________________________________________________________________
>

[-- Attachment #1.2: Type: text/html, Size: 4858 bytes --]

[-- Attachment #2: Type: text/plain, Size: 493 bytes --]

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Checking for a macro in a string without expanding it
  2021-11-16 22:15     ` Joey McCollum via ntg-context
@ 2021-11-17  8:02       ` Hans Hagen via ntg-context
  0 siblings, 0 replies; 8+ messages in thread
From: Hans Hagen via ntg-context @ 2021-11-17  8:02 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: Hans Hagen

On 11/16/2021 11:15 PM, Joey McCollum via ntg-context wrote:
> I'm not sure if my mind is twisted enough! I can follow how Jairo's 
> answer works, and that does what I need it to, but it's not as clear to 
> me what the last two TeX-only approaches are doing at a low level.
> 
> Perhaps more importantly, I should clarify that for my purposes, the 
> \MyOuter macro is the \currentbtxrighttext macro, which is defined in a 
> separate module that I'd prefer not to modify. I want to be able to 
> detect and parse the parameters of a \loc macro that a user can specify 
> in a citation as follows:
> 
> ```
> \cite[lefttext={See}, righttext={\loc[vol=8,p=223] for further 
> details}][clementinehomilies]
> ```
> 
> Because the locator parameters may need to be parenthesized or formatted 
> differently depending on the category of the bibliography entry, they 
> should be typeset separately from the plain part of the righttext. This 
> is why I'd like to be able to parse the parameters and then expand the 
> \loc macro itself as empty when the righttext is typeset.
in that case: just redefine \loc on the fly depending on where it's used 
and/or use keys

\cite[lefttext={See},volume=8,page=223]

or so .. imo parsing content is not really a good solution and probably 
also not reliable

Hans

-----------------------------------------------------------------
                                           Hans Hagen | PRAGMA ADE
               Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
        tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Checking for a macro in a string without expanding it
  2021-11-16 21:18   ` Hans Hagen via ntg-context
  2021-11-16 22:15     ` Joey McCollum via ntg-context
@ 2021-11-17 11:36     ` Henning Hraban Ramm via ntg-context
  2021-11-17 12:37       ` Hans Hagen via ntg-context
  1 sibling, 1 reply; 8+ messages in thread
From: Henning Hraban Ramm via ntg-context @ 2021-11-17 11:36 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: Henning Hraban Ramm



> Am 16.11.2021 um 22:18 schrieb Hans Hagen via ntg-context <ntg-context@ntg.nl>:

> it's pretty fast and needs no lua magic, only a twisted mind

May I quote you as “ConTeXt needs a twisted mind”? ;D

Hraban
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Checking for a macro in a string without expanding it
  2021-11-17 11:36     ` Henning Hraban Ramm via ntg-context
@ 2021-11-17 12:37       ` Hans Hagen via ntg-context
  0 siblings, 0 replies; 8+ messages in thread
From: Hans Hagen via ntg-context @ 2021-11-17 12:37 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: Hans Hagen

On 11/17/2021 12:36 PM, Henning Hraban Ramm via ntg-context wrote:
> 
> 
>> Am 16.11.2021 um 22:18 schrieb Hans Hagen via ntg-context <ntg-context@ntg.nl>:
> 
>> it's pretty fast and needs no lua magic, only a twisted mind
> 
> May I quote you as “ConTeXt needs a twisted mind”? ;D
How about "Context tries to untwist your tex mind". After all this is 
not really user code is it?

-----------------------------------------------------------------
                                           Hans Hagen | PRAGMA ADE
               Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
        tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2021-11-17 12:37 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-16 19:22 Checking for a macro in a string without expanding it Joey McCollum via ntg-context
2021-11-16 20:09 ` Jairo A. del Rio via ntg-context
2021-11-16 21:18   ` Hans Hagen via ntg-context
2021-11-16 22:15     ` Joey McCollum via ntg-context
2021-11-17  8:02       ` Hans Hagen via ntg-context
2021-11-17 11:36     ` Henning Hraban Ramm via ntg-context
2021-11-17 12:37       ` Hans Hagen via ntg-context
2021-11-16 21:04 ` Hans Hagen via ntg-context

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).