Add pronoun parsing for msg_contents inlinefuncs
This commit is contained in:
parent
9cb807a73c
commit
9d6cb98349
15 changed files with 1063 additions and 24 deletions
|
|
@ -97,6 +97,8 @@ Up requirements to Django 3.2+, Twisted 21+
|
||||||
not support this (useful for getting a complete log).
|
not support this (useful for getting a complete log).
|
||||||
- Make `@lazy_property` decorator create read/delete-protected properties. This is
|
- Make `@lazy_property` decorator create read/delete-protected properties. This is
|
||||||
because it's used for handlers, and e.g. self.locks=[] is a common beginner mistake.
|
because it's used for handlers, and e.g. self.locks=[] is a common beginner mistake.
|
||||||
|
- Add `$pron()` inlinefunc for pronoun parsing in actor-stance strings using
|
||||||
|
`msg_contents`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using
|
||||||
|
|
||||||
- [**__unloggedin_look_command** [look, l]](evennia.commands.default.unloggedin.CmdUnconnectedLook) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
|
- [**__unloggedin_look_command** [look, l]](evennia.commands.default.unloggedin.CmdUnconnectedLook) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
|
||||||
- [**about** [version]](evennia.commands.default.system.CmdAbout) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
|
- [**about** [version]](evennia.commands.default.system.CmdAbout) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
|
||||||
- [**access** [hierarchy, groups]](evennia.commands.default.general.CmdAccess) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
|
- [**access** [groups, hierarchy]](evennia.commands.default.general.CmdAccess) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
|
||||||
- [**accounts** [account, listaccounts]](evennia.commands.default.system.CmdAccounts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
|
- [**accounts** [listaccounts, account]](evennia.commands.default.system.CmdAccounts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
|
||||||
- [**addcom** [aliaschan, chanalias]](evennia.commands.default.comms.CmdAddCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
- [**addcom** [aliaschan, chanalias]](evennia.commands.default.comms.CmdAddCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
||||||
- [**alias** [setobjalias]](evennia.commands.default.building.CmdSetObjAlias) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
- [**alias** [setobjalias]](evennia.commands.default.building.CmdSetObjAlias) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
||||||
- [**allcom**](evennia.commands.default.comms.CmdAllCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
- [**allcom**](evennia.commands.default.comms.CmdAllCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
||||||
|
|
@ -39,7 +39,7 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using
|
||||||
- [**create**](evennia.commands.default.building.CmdCreate) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
- [**create**](evennia.commands.default.building.CmdCreate) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
||||||
- [**create** [cr, cre]](evennia.commands.default.unloggedin.CmdUnconnectedCreate) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
|
- [**create** [cr, cre]](evennia.commands.default.unloggedin.CmdUnconnectedCreate) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
|
||||||
- [**cwho**](evennia.commands.default.comms.CmdCWho) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
- [**cwho**](evennia.commands.default.comms.CmdCWho) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
||||||
- [**delcom** [delaliaschan, delchanalias]](evennia.commands.default.comms.CmdDelCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
- [**delcom** [delchanalias, delaliaschan]](evennia.commands.default.comms.CmdDelCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
||||||
- [**desc** [describe]](evennia.commands.default.building.CmdDesc) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
- [**desc** [describe]](evennia.commands.default.building.CmdDesc) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
||||||
- [**destroy** [delete, del]](evennia.commands.default.building.CmdDestroy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
- [**destroy** [delete, del]](evennia.commands.default.building.CmdDestroy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
||||||
- [**dig**](evennia.commands.default.building.CmdDig) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
- [**dig**](evennia.commands.default.building.CmdDig) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
||||||
|
|
@ -65,17 +65,17 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using
|
||||||
- [**mvattr**](evennia.commands.default.building.CmdMvAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
- [**mvattr**](evennia.commands.default.building.CmdMvAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
||||||
- [**name** [rename]](evennia.commands.default.building.CmdName) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
- [**name** [rename]](evennia.commands.default.building.CmdName) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
||||||
- [**nick** [nickname, nicks]](evennia.commands.default.general.CmdNick) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
- [**nick** [nickname, nicks]](evennia.commands.default.general.CmdNick) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
||||||
- [**objects** [listobjects, db, stats, listobjs]](evennia.commands.default.building.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
|
- [**objects** [db, stats, listobjs, listobjects]](evennia.commands.default.building.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
|
||||||
- [**ooc** [unpuppet]](evennia.commands.default.account.CmdOOC) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
- [**ooc** [unpuppet]](evennia.commands.default.account.CmdOOC) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
||||||
- [**open**](evennia.commands.default.building.CmdOpen) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
- [**open**](evennia.commands.default.building.CmdOpen) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
|
||||||
- [**option** [options]](evennia.commands.default.account.CmdOption) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
- [**option** [options]](evennia.commands.default.account.CmdOption) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
||||||
- [**page** [tell]](evennia.commands.default.comms.CmdPage) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
- [**page** [tell]](evennia.commands.default.comms.CmdPage) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
||||||
- [**password**](evennia.commands.default.account.CmdPassword) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
- [**password**](evennia.commands.default.account.CmdPassword) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
||||||
- [**pose** [:, emote]](evennia.commands.default.general.CmdPose) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
|
- [**pose** [emote, :]](evennia.commands.default.general.CmdPose) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
|
||||||
- [**py** [!]](evennia.commands.default.system.CmdPy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
|
- [**py** [!]](evennia.commands.default.system.CmdPy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
|
||||||
- [**quell** [unquell]](evennia.commands.default.account.CmdQuell) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
- [**quell** [unquell]](evennia.commands.default.account.CmdQuell) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
||||||
- [**quit**](evennia.commands.default.account.CmdQuit) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
- [**quit**](evennia.commands.default.account.CmdQuit) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
|
||||||
- [**quit** [q, qu]](evennia.commands.default.unloggedin.CmdUnconnectedQuit) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
|
- [**quit** [qu, q]](evennia.commands.default.unloggedin.CmdUnconnectedQuit) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
|
||||||
- [**reload** [restart]](evennia.commands.default.system.CmdReload) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
|
- [**reload** [restart]](evennia.commands.default.system.CmdReload) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
|
||||||
- [**reset** [reboot]](evennia.commands.default.system.CmdReset) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
|
- [**reset** [reboot]](evennia.commands.default.system.CmdReset) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
|
||||||
- [**rss2chan**](evennia.commands.default.comms.CmdRSS2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
- [**rss2chan**](evennia.commands.default.comms.CmdRSS2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
|
||||||
|
|
|
||||||
|
|
@ -319,9 +319,11 @@ The `caller` is required, it's the the object to do the access-check for. The `a
|
||||||
|
|
||||||
These are used to implement actor-stance emoting. They are used by the
|
These are used to implement actor-stance emoting. They are used by the
|
||||||
[DefaultObject.msg_contents](evennia.objects.objects.DefaultObject.msg_contents) method
|
[DefaultObject.msg_contents](evennia.objects.objects.DefaultObject.msg_contents) method
|
||||||
by default.
|
by default. You can read a lot more about this on the page
|
||||||
|
[Change messages per receiver](../Concepts/Change-Messages-Per-Receiver.md).
|
||||||
|
|
||||||
These all require extra kwargs be passed into the parser:
|
On the parser side, all these inline functions require extra kwargs be passed into the parser
|
||||||
|
(done by `msg_contents` by default):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
parser.parse(string, caller=<obj>, receiver=<obj>, mapping={'key': <obj>, ...})
|
parser.parse(string, caller=<obj>, receiver=<obj>, mapping={'key': <obj>, ...})
|
||||||
|
|
@ -337,10 +339,13 @@ references to other objects accessible via these callables.
|
||||||
result of `you_obj.get_display_name(looker=receiver)`. This allows for a single string to echo differently
|
result of `you_obj.get_display_name(looker=receiver)`. This allows for a single string to echo differently
|
||||||
depending on who sees it, and also to reference other people in the same way.
|
depending on who sees it, and also to reference other people in the same way.
|
||||||
- `$You([key])` - same as `$you` but always capitalized.
|
- `$You([key])` - same as `$you` but always capitalized.
|
||||||
- `$conj(verb)` ([code](evennia.utils.funcparser.funcparser_callable_conjugate)) -- conjugates a verb between 4nd person presens to 3rd person presence depending on who
|
- `$conj(verb)` ([code](evennia.utils.funcparser.funcparser_callable_conjugate)) - conjugates a verb
|
||||||
|
between 2nd person presens to 3rd person presence depending on who
|
||||||
sees the string. For example `"$You() $conj(smiles)".` will show as "You smile." and "Tom smiles." depending
|
sees the string. For example `"$You() $conj(smiles)".` will show as "You smile." and "Tom smiles." depending
|
||||||
on who sees it. This makes use of the tools in [evennia.utils.verb_conjugation](evennia.utils.verb_conjugation)
|
on who sees it. This makes use of the tools in [evennia.utils.verb_conjugation](evennia.utils.verb_conjugation)
|
||||||
to do this, and only works for English verbs.
|
to do this, and only works for English verbs.
|
||||||
|
- `$pron(pronoun [,options])` ([code](evennia.utils.funcparser.funcparser_callable_pronoun)) - Dynamically
|
||||||
|
map pronouns (like his, herself, you, its etc) between 1st/2nd person to 3rd person.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
|
|
|
||||||
220
docs/source/Concepts/Change-Messages-Per-Receiver.md
Normal file
220
docs/source/Concepts/Change-Messages-Per-Receiver.md
Normal file
|
|
@ -0,0 +1,220 @@
|
||||||
|
# Sending different messages depending on viewpoint and receiver
|
||||||
|
|
||||||
|
Sending messages to everyong in a location is handled by the
|
||||||
|
[msg_contents](evennia.objects.objects.DefaultObject.msg_contents) method on
|
||||||
|
all [Objects](../Components/Objects.md). It's most commonly called on rooms.
|
||||||
|
|
||||||
|
```python
|
||||||
|
room.msg_contents("Anna walks into the room.")
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also embed references in the string:
|
||||||
|
|
||||||
|
```python
|
||||||
|
|
||||||
|
room.msg_contents("{anna} walks into the room.",
|
||||||
|
from_obj=caller,
|
||||||
|
mapping={'anna': anna_object})
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `exclude=object_or_list_of_object` to skip sending the message one or more targets.
|
||||||
|
|
||||||
|
The advantage of this is that `anna_object.get_display_name(looker)` will be called
|
||||||
|
for every onlooker; this allows the `{anna}` stanza to be different depending on who
|
||||||
|
sees the strings. How this is to work depends on the _stance_ of your game.
|
||||||
|
|
||||||
|
The stance indicates how your game echoes its messages to the player. Knowing how you want to
|
||||||
|
handle the stance is important for a text game. There are two main stances that are usually considered,
|
||||||
|
_Actor stance_ and _Director stance_.
|
||||||
|
|
||||||
|
| Stance | You see | Others in the same location see |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Actor stance | You pick up the stone | Anna picks up the stone |
|
||||||
|
|Director stance | Anna picks up the stone | Anna picks up the stone |
|
||||||
|
|
||||||
|
It's not unheard of to mix the two stances - with commands from the game being told
|
||||||
|
in Actor stance while Director stance is used for complex emoting and roleplaying. One should
|
||||||
|
usually try to be consistent however.
|
||||||
|
|
||||||
|
## Director Stance
|
||||||
|
|
||||||
|
While not so common as Actor stance, director stance has the advantage of simplicity, particularly
|
||||||
|
in roleplaying MUDs where longer roleplaying emotes are used. It is also a pretty simple stance to
|
||||||
|
implement technically since everyone sees the same text, regardless of viewpoint.
|
||||||
|
|
||||||
|
Here's an example of a flavorful text to show the room:
|
||||||
|
|
||||||
|
Tom picks up the gun, whistling to himself.
|
||||||
|
|
||||||
|
Everyone will see this string, both Tom and others. Here's how to send it to everyone in
|
||||||
|
the room.
|
||||||
|
|
||||||
|
```python
|
||||||
|
text = "Tom picks up the gun, whistling to himself."
|
||||||
|
room.msg_contents(text)
|
||||||
|
```
|
||||||
|
|
||||||
|
One may want to expand on it by making the name `Tom` be seen differently by different people,
|
||||||
|
but the English grammar of the sentence does not change. Not only is this pretty easy to do
|
||||||
|
technically, it's also easy to write for the player.
|
||||||
|
|
||||||
|
## Actor Stance
|
||||||
|
|
||||||
|
This means that the game addresses "you" when it does things. In actor stance, whenever you perform
|
||||||
|
an action, you should get a different message than those _observing_ you doing that action.
|
||||||
|
|
||||||
|
Tom picks up the gun, whistling to himself.
|
||||||
|
|
||||||
|
This is what _others_ should see. The player themselves should see this:
|
||||||
|
|
||||||
|
You pick up the gun, whistling to yourself.
|
||||||
|
|
||||||
|
Not only do you need to map "Tom" to "You" above, there are also grammatical differences -
|
||||||
|
"Tom walks" vs "You walk" and "himself" vs "yourself". This is a lot more complex to handle. For a
|
||||||
|
developer making simple "You/Tom pick/picks up the stone" messages, you could in principle hand-craft
|
||||||
|
the strings from every view point, but there's a better way.
|
||||||
|
|
||||||
|
The `msg_contents` method helps by parsing the ingoing string with a
|
||||||
|
[FuncParser functions](../Components/FuncParser.md) with some very specific `$inline-functions`. The inline funcs
|
||||||
|
basically provides you with a mini-language for building _one_ string that will change
|
||||||
|
appropriately depending on who sees it.
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
text = "$You() $conj(pick) up the gun, whistling to $pron(yourself)."
|
||||||
|
room.msg_contents(text, from_obj=caller, mapping={"gun": gun_object})
|
||||||
|
```
|
||||||
|
|
||||||
|
These are the inline-functions available:
|
||||||
|
|
||||||
|
- `$You()/$you()` - this is a reference to 'you' in the text. It will be replaced with "You/you" for
|
||||||
|
the one sending the text and with the return from `caller.get_display_name(looker)` for everyone else.
|
||||||
|
- `$conj(verb)` - this will conjugate the given verb depending on who sees the string (like `pick`
|
||||||
|
to `picks`). Enter the root form of the verb.
|
||||||
|
- `$pron(pronoun[,options])` - A pronoun is a word you want to use instead of a proper noun, like
|
||||||
|
_him_, _herself_, _its_, _me_, _I_, _their_ and so on. The `options` is a space- or comma-separated
|
||||||
|
set of options to help the system map your pronoun from 1st/2nd person to 3rd person and vice versa.
|
||||||
|
See next section.
|
||||||
|
|
||||||
|
### More on $pron()
|
||||||
|
|
||||||
|
The `$pron()` inline func maps between 1st/2nd person (I/you) to 3rd person (he/she etc). In short,
|
||||||
|
it translates between this table ...
|
||||||
|
|
||||||
|
| | Subject Pronoun | Object Pronoun | Possessive Adjective | Possessive Pronoun | Reflexive Pronoun |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| **1st person** | I | me | my | mine | myself |
|
||||||
|
| **1st person plural** | we | us | our | ours | ourselves |
|
||||||
|
| **2nd person** | you | you | your | yours | yourself |
|
||||||
|
| **2nd person plural** | you | you | your | yours | yourselves |
|
||||||
|
|
||||||
|
... to this table (in both directions):
|
||||||
|
|
||||||
|
| | Subject Pronoun | Object Pronoun | Possessive Adjective | Possessive Pronoun | Reflexive Pronoun |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| **3rd person male** | he | him | his | his | himself |
|
||||||
|
| **3rd person female** | she | her | her | hers | herself |
|
||||||
|
| **3rd person neutral** | it | it | its | theirs* | itself |
|
||||||
|
| **3rd person plural** | they | them | their | theirs | themselves |
|
||||||
|
|
||||||
|
> *) The neutral 3rd person possessive pronoun is not actually used in English. We set it to "theirs"
|
||||||
|
> just to have something to show should someone accidentally ask for a neutral possessive pronoun.
|
||||||
|
|
||||||
|
Some mappings are easy. For example, if you write `$pron(yourselves)` then the 3rd-person
|
||||||
|
form is always `themselves`. But because English grammar is the way it is, not all mappings
|
||||||
|
are 1:1. For example, if you write
|
||||||
|
`$pron(you)`, Evennia will not know which 3rd-persion equivalent this should map to - you need to
|
||||||
|
provide more info to help out. This can either be provided as a second space-separated option
|
||||||
|
to `$pron` or the system will try to figure it out on its own.
|
||||||
|
|
||||||
|
- `pronoun_type` - this is one of the columns in the table and can be set as a `$pron` option.
|
||||||
|
|
||||||
|
- `subject pronoun` (aliases `subject` or `sp`)
|
||||||
|
- `object pronoun` (aliases `object` or `op`)
|
||||||
|
- `possessive adjective` (aliases `adjective` or `pa`)
|
||||||
|
- `possessive pronoun` (aliases `pronoun` or `pp`).
|
||||||
|
|
||||||
|
(There is no need to specify reflexive pronouns since they
|
||||||
|
are all uniquely mapped 1:1). Speciying the pronoun-type is mainly needed when using `you`,
|
||||||
|
since the same 'you' is used to represent all sorts of things in English grammar.
|
||||||
|
If not specified and the mapping is not clear, a 'subject pronoun' (he/she/it/they) is assumed.
|
||||||
|
- `gender` - set in `$pron` option as
|
||||||
|
|
||||||
|
- `male`, or `m`
|
||||||
|
- `female'` or `f`
|
||||||
|
- `neutral`, or `n`
|
||||||
|
- `plural`, or `p` (yes plural is considered a 'gender' for this purpose).
|
||||||
|
|
||||||
|
If not set as an option the system will
|
||||||
|
look for a callable or property `.gender` on the current `from_obj`. A callable will be called
|
||||||
|
with no arguments and is expected to return a string 'male/female/neutral/plural'. If none
|
||||||
|
is found, a neutral gender is assumed.
|
||||||
|
- `viewpoint`- set in `$pron` option as
|
||||||
|
|
||||||
|
- `1st person` (aliases `1st` or `1`)
|
||||||
|
- `2nd person` (aliases `2nd` or `2`)
|
||||||
|
|
||||||
|
This is only needed if you want to have 1st person perspective - if
|
||||||
|
not, 2nd person is assumed wherever the viewpoint is unclear.
|
||||||
|
|
||||||
|
`$pron()` examples:
|
||||||
|
|
||||||
|
| Input | you see | others see | note |
|
||||||
|
| --- | --- | ---| --- |
|
||||||
|
| `$pron(I, male)` | I | he | |
|
||||||
|
| `$pron(I, f)` | I | she | |
|
||||||
|
| `$pron(my)` | my | its | figures out it's an possessive adjective, assumes neutral |
|
||||||
|
| `$pron(you)` | you | it | assumes neutral subject pronoun |
|
||||||
|
| `$pron(you, f)` | you | she | female specified, assumes subject pronoun |
|
||||||
|
| `$pron(you,op f)` | you | her | |
|
||||||
|
| `$pron(you,op p)` | you | them | |
|
||||||
|
| `$pron(you, f op)` | you | her | specified female and objective pronoun|
|
||||||
|
| `$pron(yourself)` | yourself | itself | |
|
||||||
|
| `$pron(its)` | your | its | |
|
||||||
|
| `$Pron(its)` | Your | Its | Using $Pron always capitalizes |
|
||||||
|
| `$pron(her)` | you | her | 3rd person -> 2nd person |
|
||||||
|
| `$pron(her, 1)` | I | her | 3rd person -> 1st person |
|
||||||
|
| `$pron(its, 1st)` | my | its | 3rd person -> 1st person |
|
||||||
|
|
||||||
|
|
||||||
|
Note the three last examples - instead of specifying the 2nd person form you
|
||||||
|
can also specify the 3rd-person and do a 'reverse' lookup - you will still see the proper 1st/2nd text.
|
||||||
|
So writing `$pron(her)` instead of `$pron(you, op f)` gives the same result.
|
||||||
|
|
||||||
|
The [$pron inlinefunc api is found here](evennia.utils.funcparser.funcparser_callable_pronoun)
|
||||||
|
|
||||||
|
# Referencing other objects
|
||||||
|
|
||||||
|
There is one more inlinefunc understood by `msg_contents`. This can be used natively to spruce up
|
||||||
|
your strings (for both director- and actor stance):
|
||||||
|
|
||||||
|
- `$Obj(name)/$obj(name)` references another entity, which must be supplied
|
||||||
|
in the `mapping` keyword argument to `msg_contents`. The object's `.get_display_name(looker)` will be
|
||||||
|
called and inserted instead. This is essentially the same as using the `{anna}` marker we used
|
||||||
|
in the first example at the top of this page, but using `$Obj/$obj` allows you to easily
|
||||||
|
control capitalization.
|
||||||
|
|
||||||
|
This is used like so:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# director stance
|
||||||
|
text = "Tom picks up the $obj(gun), whistling to himself"
|
||||||
|
|
||||||
|
# actor stance
|
||||||
|
text = "$You() $conj(pick) up the $obj(gun), whistling to $pron(yourself)"
|
||||||
|
|
||||||
|
room.msg_contents(text, from_obj=caller, mapping={"gun": gun_object})
|
||||||
|
```
|
||||||
|
Depending on your game, Tom may now see himself picking up `A rusty old gun`, whereas an onlooker
|
||||||
|
with a high gun smith skill may instead see him picking up `A rare-make Smith & Wesson model 686
|
||||||
|
in poor condition" ...`
|
||||||
|
|
||||||
|
# Recog systems and roleplaying
|
||||||
|
|
||||||
|
The `$funcparser` inline functions are very powerful for the game developer, but they may
|
||||||
|
be a bit too much to write for the regular player.
|
||||||
|
|
||||||
|
The [rpsystem contrib](evennia.contribs.rpsystem) implements a full dynamic emote/pose and recognition
|
||||||
|
system with short-descriptions and disguises. It uses director stance with a custom markup
|
||||||
|
language, like `/me` `/gun` and `/tall man` to refer to players and objects in the location. It can be
|
||||||
|
worth checking out for inspiration.
|
||||||
|
|
@ -19,6 +19,7 @@ evennia.server
|
||||||
evennia.server.initial_setup
|
evennia.server.initial_setup
|
||||||
evennia.server.inputfuncs
|
evennia.server.inputfuncs
|
||||||
evennia.server.manager
|
evennia.server.manager
|
||||||
|
evennia.server.markup
|
||||||
evennia.server.models
|
evennia.server.models
|
||||||
evennia.server.server
|
evennia.server.server
|
||||||
evennia.server.serversession
|
evennia.server.serversession
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ evennia.utils.verb\_conjugation
|
||||||
:maxdepth: 6
|
:maxdepth: 6
|
||||||
|
|
||||||
evennia.utils.verb_conjugation.conjugate
|
evennia.utils.verb_conjugation.conjugate
|
||||||
|
evennia.utils.verb_conjugation.pronouns
|
||||||
evennia.utils.verb_conjugation.tests
|
evennia.utils.verb_conjugation.tests
|
||||||
|
|
||||||
```
|
```
|
||||||
10
docs/source/api/evennia.utils.verb_conjugation.pronouns.md
Normal file
10
docs/source/api/evennia.utils.verb_conjugation.pronouns.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
```{eval-rst}
|
||||||
|
evennia.utils.verb\_conjugation.pronouns
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
.. automodule:: evennia.utils.verb_conjugation.pronouns
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -58,6 +58,7 @@ Concepts/Async-Process
|
||||||
Concepts/Banning
|
Concepts/Banning
|
||||||
Concepts/Bootstrap-&-Evennia
|
Concepts/Bootstrap-&-Evennia
|
||||||
Concepts/Building-Permissions
|
Concepts/Building-Permissions
|
||||||
|
Concepts/Change-Messages-Per-Receiver
|
||||||
Concepts/Clickable-Links
|
Concepts/Clickable-Links
|
||||||
Concepts/Colors
|
Concepts/Colors
|
||||||
Concepts/Concepts-Overview
|
Concepts/Concepts-Overview
|
||||||
|
|
@ -320,6 +321,7 @@ api/evennia.server.game_index_client.service
|
||||||
api/evennia.server.initial_setup
|
api/evennia.server.initial_setup
|
||||||
api/evennia.server.inputfuncs
|
api/evennia.server.inputfuncs
|
||||||
api/evennia.server.manager
|
api/evennia.server.manager
|
||||||
|
api/evennia.server.markup
|
||||||
api/evennia.server.models
|
api/evennia.server.models
|
||||||
api/evennia.server.portal
|
api/evennia.server.portal
|
||||||
api/evennia.server.portal.amp
|
api/evennia.server.portal.amp
|
||||||
|
|
@ -393,6 +395,7 @@ api/evennia.utils.utils
|
||||||
api/evennia.utils.validatorfuncs
|
api/evennia.utils.validatorfuncs
|
||||||
api/evennia.utils.verb_conjugation
|
api/evennia.utils.verb_conjugation
|
||||||
api/evennia.utils.verb_conjugation.conjugate
|
api/evennia.utils.verb_conjugation.conjugate
|
||||||
|
api/evennia.utils.verb_conjugation.pronouns
|
||||||
api/evennia.utils.verb_conjugation.tests
|
api/evennia.utils.verb_conjugation.tests
|
||||||
api/evennia.web
|
api/evennia.web
|
||||||
api/evennia.web.admin
|
api/evennia.web.admin
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,8 @@ _COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||||
# the sessid_max is based on the length of the db_sessid csv field (excluding commas)
|
# the sessid_max is based on the length of the db_sessid csv field (excluding commas)
|
||||||
_SESSID_MAX = 16 if _MULTISESSION_MODE in (1, 3) else 1
|
_SESSID_MAX = 16 if _MULTISESSION_MODE in (1, 3) else 1
|
||||||
|
|
||||||
_MSG_CONTENTS_PARSER = funcparser.FuncParser(
|
# init the actor-stance funcparser for msg_contents
|
||||||
{
|
_MSG_CONTENTS_PARSER = funcparser.FuncParser(funcparser.ACTOR_STANCE_CALLABLES)
|
||||||
"you": funcparser.funcparser_callable_you,
|
|
||||||
"You": funcparser.funcparser_callable_You,
|
|
||||||
"conj": funcparser.funcparser_callable_conjugate
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectSessionHandler:
|
class ObjectSessionHandler:
|
||||||
|
|
@ -729,8 +724,9 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
on the valid OOB outmessage form `(message, {kwargs})`,
|
on the valid OOB outmessage form `(message, {kwargs})`,
|
||||||
where kwargs are optional data passed to the `text`
|
where kwargs are optional data passed to the `text`
|
||||||
outputfunc. The message will be parsed for `{key}` formatting and
|
outputfunc. The message will be parsed for `{key}` formatting and
|
||||||
`$You/$you()/$You(key)` and `$conj(verb)` inline function callables.
|
`$You/$you()/$You()`, `$obj(name)`, `$conj(verb)` and `$pron(pronoun, option)`
|
||||||
The `key` is taken from the `mapping` kwarg {"key": object, ...}`.
|
inline function callables.
|
||||||
|
The `name` is taken from the `mapping` kwarg {"name": object, ...}`.
|
||||||
The `mapping[key].get_display_name(looker=recipient)` will be called
|
The `mapping[key].get_display_name(looker=recipient)` will be called
|
||||||
for that key for every recipient of the string.
|
for that key for every recipient of the string.
|
||||||
exclude (list, optional): A list of objects not to send to.
|
exclude (list, optional): A list of objects not to send to.
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ from evennia.utils.utils import (
|
||||||
safe_convert_to_types)
|
safe_convert_to_types)
|
||||||
from evennia.utils import search
|
from evennia.utils import search
|
||||||
from evennia.utils.verb_conjugation.conjugate import verb_actor_stance_components
|
from evennia.utils.verb_conjugation.conjugate import verb_actor_stance_components
|
||||||
|
from evennia.utils.verb_conjugation.pronouns import pronoun_to_viewpoints
|
||||||
|
|
||||||
# setup
|
# setup
|
||||||
|
|
||||||
|
|
@ -1082,8 +1083,8 @@ def funcparser_callable_you(*args, caller=None, receiver=None, mapping=None, cap
|
||||||
if hasattr(caller, "get_display_name") else str(caller))
|
if hasattr(caller, "get_display_name") else str(caller))
|
||||||
|
|
||||||
|
|
||||||
def funcparser_callable_You(*args, you=None, receiver=None, mapping=None, capitalize=True,
|
def funcparser_callable_you_capitalize(
|
||||||
**kwargs):
|
*args, you=None, receiver=None, mapping=None, capitalize=True, **kwargs):
|
||||||
"""
|
"""
|
||||||
Usage: $You() - capitalizes the 'you' output.
|
Usage: $You() - capitalizes the 'you' output.
|
||||||
|
|
||||||
|
|
@ -1094,6 +1095,8 @@ def funcparser_callable_You(*args, you=None, receiver=None, mapping=None, capita
|
||||||
|
|
||||||
def funcparser_callable_conjugate(*args, caller=None, receiver=None, **kwargs):
|
def funcparser_callable_conjugate(*args, caller=None, receiver=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
Usage: $conj(word, [options])
|
||||||
|
|
||||||
Conjugate a verb according to if it should be 2nd or third person.
|
Conjugate a verb according to if it should be 2nd or third person.
|
||||||
|
|
||||||
Keyword Args:
|
Keyword Args:
|
||||||
|
|
@ -1130,6 +1133,146 @@ def funcparser_callable_conjugate(*args, caller=None, receiver=None, **kwargs):
|
||||||
return second_person_str if caller == receiver else third_person_str
|
return second_person_str if caller == receiver else third_person_str
|
||||||
|
|
||||||
|
|
||||||
|
def funcparser_callable_pronoun(*args, caller=None, receiver=None, capitalize=False, **kwargs):
|
||||||
|
"""
|
||||||
|
|
||||||
|
Usage: $prop(word, [options])
|
||||||
|
|
||||||
|
Adjust pronouns to the expected form. Pronouns are words you use instead of a
|
||||||
|
proper name, such as 'him', 'herself', 'theirs' etc. These look different
|
||||||
|
depending on who sees the outgoing string.
|
||||||
|
|
||||||
|
The parser maps between this table ...
|
||||||
|
|
||||||
|
==================== ======= ======= ========== ========== ===========
|
||||||
|
1st/2nd person Subject Object Possessive Possessive Reflexive
|
||||||
|
Pronoun Pronoun Adjective Pronoun Pronoun
|
||||||
|
==================== ======= ======= ========== ========== ===========
|
||||||
|
1st person I me my mine myself
|
||||||
|
1st person plural we us our ours ourselves
|
||||||
|
2nd person you you your yours yourself
|
||||||
|
2nd person plural you you your yours yourselves
|
||||||
|
==================== ======= ======= ========== ========== ===========
|
||||||
|
|
||||||
|
... and this table (and vice versa).
|
||||||
|
|
||||||
|
==================== ======= ======= ========== ========== ===========
|
||||||
|
3rd person Subject Object Possessive Possessive Reflexive
|
||||||
|
Pronoun Pronoun Adjective Pronoun Pronoun
|
||||||
|
==================== ======= ======= ========== ========== ===========
|
||||||
|
3rd person male he him his his himself
|
||||||
|
3rd person female she her her hers herself
|
||||||
|
3rd person neutral it it its itself
|
||||||
|
3rd person plural they them their theirs themselves
|
||||||
|
==================== ======= ======= ========== ========== ===========
|
||||||
|
|
||||||
|
This system will examine `caller` for either a property or a callable `.gender` to
|
||||||
|
get a default gender fallback (if not specified in the call). If a callable,
|
||||||
|
`.gender` will be called without arguments and should return a string
|
||||||
|
`male`/`female`/`neutral`/`plural` (plural is considered a gender for this purpose).
|
||||||
|
If no `gender` property/callable is found, `neutral` is used as a fallback.
|
||||||
|
|
||||||
|
The pronoun-type default (if not spefified in call) is `subject pronoun`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pronoun (str): Input argument to parsed call. This can be any of the pronouns
|
||||||
|
in the table above. If given in 1st/second form, they will be mappped to
|
||||||
|
3rd-person form for others viewing the message (but will need extra input
|
||||||
|
via the `gender`, see below). If given on 3rd person form, this will be
|
||||||
|
mapped to 2nd person form for `caller` unless `viewpoint` is specified
|
||||||
|
in options.
|
||||||
|
options (str, optional): A space- or comma-separated string detailing `pronoun_type`,
|
||||||
|
`gender`/`plural` and/or `viewpoint` to help the mapper differentiate between
|
||||||
|
non-unique cases (such as if `you` should become `him` or `they`).
|
||||||
|
Allowed values are:
|
||||||
|
|
||||||
|
- `subject pronoun`/`subject`/`sp` (I, you, he, they)
|
||||||
|
- `object pronoun`/`object/`/`op` (me, you, him, them)
|
||||||
|
- `possessive adjective`/`adjective`/`pa` (my, your, his, their)
|
||||||
|
- `possessive pronoun`/`pronoun`/`pp` (mine, yours, his, theirs)
|
||||||
|
- `male`/`m`
|
||||||
|
- `female`/`f`
|
||||||
|
- `neutral`/`n`
|
||||||
|
- `plural`/`p`
|
||||||
|
- `1st person`/`1st`/`1`
|
||||||
|
- `2nd person`/`2nd`/`2`
|
||||||
|
- `3rd person`/`3rd`/`3`
|
||||||
|
|
||||||
|
Keyword Args:
|
||||||
|
|
||||||
|
caller (Object): The object creating the string. If this has a property 'gender',
|
||||||
|
it will be checked for a string 'male/female/neutral' to determine
|
||||||
|
the 3rd person gender (but if `pronoun_type` contains a gender
|
||||||
|
component, that takes precedence). Provided automatically to the
|
||||||
|
funcparser.
|
||||||
|
receiver (Object): The recipient of the string. This being the same as
|
||||||
|
`caller` or not helps determine 2nd vs 3rd-person forms. This is
|
||||||
|
provided automatically by the funcparser.
|
||||||
|
capitalize (bool): The input retains its capitalization. If this is set the output is
|
||||||
|
always capitalized.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
====================== ============= ===========
|
||||||
|
Input caller sees others see
|
||||||
|
====================== ============= ===========
|
||||||
|
$pron(I, m) I he
|
||||||
|
$pron(you,fo) you her
|
||||||
|
$pron(yourself) yourself itself
|
||||||
|
$pron(its) your its
|
||||||
|
$pron(you,op,p) you them
|
||||||
|
====================== ============= ===========
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
There is no option to specify reflexive pronouns since they are all unique
|
||||||
|
and the mapping can always be auto-detected.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not args:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
pronoun, *options = args
|
||||||
|
# options is either multiple args or a space-separated string
|
||||||
|
if len(options) == 1:
|
||||||
|
options = options[0]
|
||||||
|
|
||||||
|
# default differentiators
|
||||||
|
default_pronoun_type = "subject pronoun"
|
||||||
|
default_gender = "neutral"
|
||||||
|
default_viewpoint = "2nd person"
|
||||||
|
|
||||||
|
if hasattr(caller, "gender"):
|
||||||
|
if callable(caller, gender):
|
||||||
|
default_gender = caller.gender()
|
||||||
|
else:
|
||||||
|
default_gender = caller.gender
|
||||||
|
|
||||||
|
if "viewpoint" in kwargs:
|
||||||
|
# passed into FuncParser initialization
|
||||||
|
default_viewpoint = kwargs["viewpoint"]
|
||||||
|
|
||||||
|
pronoun_1st_or_2nd_person, pronoun_3rd_person = pronoun_to_viewpoints(
|
||||||
|
pronoun, options,
|
||||||
|
pronoun_type=default_pronoun_type, gender=default_gender, viewpoint=default_viewpoint)
|
||||||
|
|
||||||
|
if capitalize:
|
||||||
|
pronoun_1st_or_2nd_person = pronoun_1st_or_2nd_person.capitalize()
|
||||||
|
pronoun_3rd_person = pronoun_3rd_person.capitalize()
|
||||||
|
|
||||||
|
return pronoun_1st_or_2nd_person if caller == receiver else pronoun_3rd_person
|
||||||
|
|
||||||
|
|
||||||
|
def funcparser_callable_pronoun_capitalize(
|
||||||
|
*args, caller=None, receiver=None, capitalize=True, **kwargs):
|
||||||
|
"""
|
||||||
|
Usage: $Pron(word) - always maps to a capitalized word.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return funcparser_callable_pronoun(
|
||||||
|
*args, caller=caller, receiver=receiver, capitalize=capitalize, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# these are made available as callables by adding 'evennia.utils.funcparser' as
|
# these are made available as callables by adding 'evennia.utils.funcparser' as
|
||||||
# a callable-path when initializing the FuncParser.
|
# a callable-path when initializing the FuncParser.
|
||||||
|
|
||||||
|
|
@ -1176,6 +1319,10 @@ SEARCHING_CALLABLES = {
|
||||||
ACTOR_STANCE_CALLABLES = {
|
ACTOR_STANCE_CALLABLES = {
|
||||||
# requires `you`, `receiver` and `mapping` to be passed into parser
|
# requires `you`, `receiver` and `mapping` to be passed into parser
|
||||||
"you": funcparser_callable_you,
|
"you": funcparser_callable_you,
|
||||||
"You": funcparser_callable_You,
|
"You": funcparser_callable_you_capitalize,
|
||||||
|
"obj": funcparser_callable_you,
|
||||||
|
"Obj": funcparser_callable_you_capitalize,
|
||||||
"conj": funcparser_callable_conjugate,
|
"conj": funcparser_callable_conjugate,
|
||||||
|
"pron": funcparser_callable_pronoun,
|
||||||
|
"Pron": funcparser_callable_pronoun_capitalize,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ The gametime module handles the global passage of time in the mud.
|
||||||
It also supplies some useful methods to convert between
|
It also supplies some useful methods to convert between
|
||||||
in-mud time and real-world time as well allows to get the
|
in-mud time and real-world time as well allows to get the
|
||||||
total runtime of the server and the current uptime.
|
total runtime of the server and the current uptime.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
@ -244,8 +245,11 @@ def schedule(
|
||||||
script (Script): The created Script handling the sceduling.
|
script (Script): The created Script handling the sceduling.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
schedule(func, min=5, sec=0) # Will call 5 minutes past the next (in-game) hour.
|
::
|
||||||
schedule(func, hour=2, min=30, sec=0) # Will call the next (in-game) day at 02:30.
|
|
||||||
|
schedule(func, min=5, sec=0) # Will call 5 minutes past the next (in-game) hour.
|
||||||
|
schedule(func, hour=2, min=30, sec=0) # Will call the next (in-game) day at 02:30.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
seconds = real_seconds_until(sec=sec, min=min, hour=hour, day=day, month=month, year=year)
|
seconds = real_seconds_until(sec=sec, min=min, hour=hour, day=day, month=month, year=year)
|
||||||
script = create_script(
|
script = create_script(
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ Test the funcparser module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
from unittest.mock import MagicMock, patch
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
from simpleeval import simple_eval
|
from simpleeval import simple_eval
|
||||||
from parameterized import parameterized
|
from parameterized import parameterized
|
||||||
|
|
@ -306,6 +307,10 @@ class TestDefaultCallables(TestCase):
|
||||||
("$You() $conj(smile) at $You(char1).", "You smile at You.", "Char1 smiles at Char1."),
|
("$You() $conj(smile) at $You(char1).", "You smile at You.", "Char1 smiles at Char1."),
|
||||||
("$You() $conj(smile) at $You(char2).", "You smile at Char2.", "Char1 smiles at You."),
|
("$You() $conj(smile) at $You(char2).", "You smile at Char2.", "Char1 smiles at You."),
|
||||||
("$You(char2) $conj(smile) at $you(char1).", "Char2 smile at you.", "You smiles at Char1."),
|
("$You(char2) $conj(smile) at $you(char1).", "Char2 smile at you.", "You smiles at Char1."),
|
||||||
|
("$You() $conj(smile) to $pron(yourself,m).", "You smile to yourself.",
|
||||||
|
"Char1 smiles to himself."),
|
||||||
|
("$You() $conj(smile) to $pron(herself).", "You smile to yourself.",
|
||||||
|
"Char1 smiles to herself.") # reverse reference
|
||||||
])
|
])
|
||||||
def test_conjugate(self, string, expected_you, expected_them):
|
def test_conjugate(self, string, expected_you, expected_them):
|
||||||
"""
|
"""
|
||||||
|
|
@ -464,3 +469,5 @@ class TestCallableSearch(test_resources.EvenniaTest):
|
||||||
|
|
||||||
ret = self.parser.parse(string, caller=self.char1, return_str=False, raise_errors=True)
|
ret = self.parser.parse(string, caller=self.char1, return_str=False, raise_errors=True)
|
||||||
self.assertEqual(expected, ret)
|
self.assertEqual(expected, ret)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2628,3 +2628,40 @@ def strip_unsafe_input(txt, session=None, bypass_perms=None):
|
||||||
txt = strip_tags(txt)
|
txt = strip_tags(txt)
|
||||||
txt = _STRIP_UNSAFE_TOKENS(txt)
|
txt = _STRIP_UNSAFE_TOKENS(txt)
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
|
|
||||||
|
def copy_word_case(base_word, new_word):
|
||||||
|
"""
|
||||||
|
Converts a word to use the same capitalization as a first word.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
base_word (str): A word to get the capitalization from.
|
||||||
|
new_word (str): A new word to capitalize in the same way as `base_word`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The `new_word` with capitalization matching the first word.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
This is meant for words. Longer sentences may get unexpected results.
|
||||||
|
|
||||||
|
If the two words have a mix of capital/lower letters _and_ `new_word`
|
||||||
|
is longer than `base_word`, the excess will retain its original case.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Word
|
||||||
|
if base_word.istitle():
|
||||||
|
return new_word.title()
|
||||||
|
# word
|
||||||
|
elif base_word.islower():
|
||||||
|
return new_word.lower()
|
||||||
|
# WORD
|
||||||
|
elif base_word.isupper():
|
||||||
|
return new_word.upper()
|
||||||
|
else:
|
||||||
|
# WorD - a mix. Handle each character
|
||||||
|
maxlen = len(base_word)
|
||||||
|
shared, excess = new_word[:maxlen], new_word[maxlen - 1:]
|
||||||
|
return "".join(char.upper() if base_word[ic].isupper() else char.lower()
|
||||||
|
for ic, char in enumerate(new_word)) + excess
|
||||||
|
|
||||||
|
|
|
||||||
560
evennia/utils/verb_conjugation/pronouns.py
Normal file
560
evennia/utils/verb_conjugation/pronouns.py
Normal file
|
|
@ -0,0 +1,560 @@
|
||||||
|
"""
|
||||||
|
English pronoun mapping between 1st/2nd person and 3rd person perspective (and vice-versa).
|
||||||
|
|
||||||
|
This file is released under the Evennia regular BSD License.
|
||||||
|
(Griatch 2021)
|
||||||
|
|
||||||
|
Pronouns are words you use instead of a proper name, such as 'him', 'herself', 'theirs' etc. These
|
||||||
|
look different depending on who sees the outgoing string. This mapping maps between 1st/2nd case and
|
||||||
|
the 3rd person case and back. In some cases, the mapping is not unique; it is assumed the system can
|
||||||
|
differentiate between the options in some other way.
|
||||||
|
|
||||||
|
|
||||||
|
==================== ======= ======== ========== ========== ===========
|
||||||
|
viewpoint/pronouns Subject Object Possessive Possessive Reflexive
|
||||||
|
Pronoun Pronoun Adjective Pronoun Pronoun
|
||||||
|
==================== ======= ======== ========== ========== ===========
|
||||||
|
1st person I me my mine myself
|
||||||
|
1st person plural we us our ours ourselves
|
||||||
|
2nd person you you your yours yourself
|
||||||
|
2nd person plural you you your yours yourselves
|
||||||
|
|
||||||
|
3rd person male he him his his himself
|
||||||
|
3rd person female she her her hers herself
|
||||||
|
3rd person neutral it it its theirs* itself
|
||||||
|
3rd person plural they them their theirs themselves
|
||||||
|
==================== ======= ======== ========== ========== ===========
|
||||||
|
|
||||||
|
> `*`) Not formally used, we use `theirs` here as a filler.
|
||||||
|
|
||||||
|
"""
|
||||||
|
from evennia.utils.utils import copy_word_case
|
||||||
|
|
||||||
|
DEFAULT_PRONOUN_TYPE = "object_pronoun"
|
||||||
|
DEFAULT_VIEWPOINT = "2nd person"
|
||||||
|
DEFAULT_GENDER = "neutral"
|
||||||
|
|
||||||
|
PRONOUN_MAPPING = {
|
||||||
|
# 1st/2nd person -> 3rd person mappings
|
||||||
|
"I": {
|
||||||
|
"subject pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "he",
|
||||||
|
"female": "she",
|
||||||
|
"neutral": "it"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"me": {
|
||||||
|
"object pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "him",
|
||||||
|
"female": "her",
|
||||||
|
"neutral": "it"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"my": {
|
||||||
|
"possessive adjective": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "his",
|
||||||
|
"female": "her",
|
||||||
|
"neutral": "its"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mine": {
|
||||||
|
"possessive pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "his",
|
||||||
|
"female": "hers",
|
||||||
|
"neutral": "theirs", # colloqial,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"myself": {
|
||||||
|
"reflexive_pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "himself",
|
||||||
|
"female": "herself",
|
||||||
|
"neutral": "itself",
|
||||||
|
"plural": "themselves",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"you": {
|
||||||
|
"subject pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "he",
|
||||||
|
"female": "she",
|
||||||
|
"neutral": "it",
|
||||||
|
"plural": "they",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"object pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "him",
|
||||||
|
"female": "her",
|
||||||
|
"neutral": "it",
|
||||||
|
"plural": "them",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"your": {
|
||||||
|
"possessive adjective": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "his",
|
||||||
|
"female": "her",
|
||||||
|
"neutral": "its",
|
||||||
|
"plural": "their",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"yours": {
|
||||||
|
"possessive pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "his",
|
||||||
|
"female": "hers",
|
||||||
|
"neutral": "theirs", # colloqial
|
||||||
|
"plural": "theirs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"yourself": {
|
||||||
|
"reflexive_pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"male": "himself",
|
||||||
|
"female": "herself",
|
||||||
|
"neutral": "itself",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"we": {
|
||||||
|
"subject pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"plural": "they"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"us": {
|
||||||
|
"object pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"plural": "them"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"our": {
|
||||||
|
"possessive adjective": {
|
||||||
|
"3rd person": {
|
||||||
|
"plural": "their"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ours": {
|
||||||
|
"possessive pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"plural": "theirs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ourselves": {
|
||||||
|
"reflexive pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"plural": "themselves"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ours": {
|
||||||
|
"possessive pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"plural": "theirs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ourselves": {
|
||||||
|
"reflexive pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"plural": "themselves"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"yourselves": {
|
||||||
|
"reflexive_pronoun": {
|
||||||
|
"3rd person": {
|
||||||
|
"plural": "themselves"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
# 3rd person to 1st/second person mappings
|
||||||
|
"he": {
|
||||||
|
"subject pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "I",
|
||||||
|
"plural": "we" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "you",
|
||||||
|
"plural": "you" # pluralis majestatis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"him": {
|
||||||
|
"object pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "me",
|
||||||
|
"plural": "us" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "you",
|
||||||
|
"plural": "you" # pluralis majestatis
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"his": {
|
||||||
|
"possessive adjective": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "my",
|
||||||
|
"plural": "our" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "your",
|
||||||
|
"plural": "your" # pluralis majestatis
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"possessive pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "mine",
|
||||||
|
"plural": "ours" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "yours",
|
||||||
|
"plural": "yours" # pluralis majestatis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"himself": {
|
||||||
|
"reflexive pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "myself",
|
||||||
|
"plural": "ourselves" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "yours",
|
||||||
|
"plural": "yours" # pluralis majestatis
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"she": {
|
||||||
|
"subject pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "I",
|
||||||
|
"plural": "you" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "you",
|
||||||
|
"plural": "we" # pluralis majestatis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"her": {
|
||||||
|
"object pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "me",
|
||||||
|
"plural": "us" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "you",
|
||||||
|
"plural": "you" # pluralis majestatis
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"possessive adjective": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "my",
|
||||||
|
"plural": "our" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "your",
|
||||||
|
"plural": "your" # pluralis majestatis
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"hers": {
|
||||||
|
"possessive pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "mine",
|
||||||
|
"plural": "ours" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "yours",
|
||||||
|
"plural": "yours" # pluralis majestatis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"herself": {
|
||||||
|
"reflexive pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "myself",
|
||||||
|
"plural": "ourselves" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "yourself",
|
||||||
|
"plural": "yourselves" # pluralis majestatis
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"it": {
|
||||||
|
"subject pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "I",
|
||||||
|
"plural": "we" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "you",
|
||||||
|
"plural": "you" # pluralis majestatis
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"object pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "me",
|
||||||
|
"plural": "us" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "you",
|
||||||
|
"plural": "you" # pluralis majestatis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"its": {
|
||||||
|
"possessive adjective": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "my",
|
||||||
|
"plural": "our" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "your",
|
||||||
|
"plural": "your" # pluralis majestatis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"theirs": {
|
||||||
|
"possessive pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "mine",
|
||||||
|
"plural": "ours" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "yours",
|
||||||
|
"plural": "yours" # pluralis majestatis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"itself": {
|
||||||
|
"reflexive pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"neutral": "myself",
|
||||||
|
"plural": "ourselves" # pluralis majestatis
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"neutral": "yourself",
|
||||||
|
"plural": "yourselves" # pluralis majestatis
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"they": {
|
||||||
|
"subject pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"plural": "we",
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"plural": "you",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"them": {
|
||||||
|
"object pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"plural": "us",
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"plural": "you",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"their": {
|
||||||
|
"possessive adjective": {
|
||||||
|
"1st person": {
|
||||||
|
"plural": "our",
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"plural": "your",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"themselves": {
|
||||||
|
"reflexive pronoun": {
|
||||||
|
"1st person": {
|
||||||
|
"plural": "ourselves",
|
||||||
|
},
|
||||||
|
"2nd person": {
|
||||||
|
"plural": "yourselves",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ALIASES = {
|
||||||
|
"m": "male",
|
||||||
|
"f": "female",
|
||||||
|
"n": "neutral",
|
||||||
|
"p": "plural",
|
||||||
|
"1st": "1st person",
|
||||||
|
"2nd": "2nd person",
|
||||||
|
"3rd": "3rd person",
|
||||||
|
"1": "1st person",
|
||||||
|
"2": "2nd person",
|
||||||
|
"3": "3rd person",
|
||||||
|
"s": "subject pronoun",
|
||||||
|
"sp": "subject pronoun",
|
||||||
|
"subject": "subject pronoun",
|
||||||
|
"op": "object pronoun",
|
||||||
|
"object": "object pronoun",
|
||||||
|
"pa": "possessive adjective",
|
||||||
|
"pp": "possessive pronoun",
|
||||||
|
}
|
||||||
|
|
||||||
|
PRONOUN_TYPES = ["subject pronoun", "object pronoun", "possessive adjective",
|
||||||
|
"possessive pronoun", "reflexive pronoun"]
|
||||||
|
VIEWPOINTS = ["1st person", "2nd person", "3rd person"]
|
||||||
|
GENDERS = ["male", "female", "neutral", "plural"] # including plural as a gender for simplicity
|
||||||
|
|
||||||
|
|
||||||
|
def pronoun_to_viewpoints(pronoun,
|
||||||
|
options=None, pronoun_type="object_pronoun",
|
||||||
|
gender="neutral", viewpoint="2nd person"):
|
||||||
|
"""
|
||||||
|
Access function for determining the forms of a pronount from different viewpoints.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pronoun (str): A valid English pronoun, such as 'you', 'his', 'themselves' etc.
|
||||||
|
options (str or list, optional): A list or space-separated string of options to help
|
||||||
|
the engine when there is no unique mapping to use. This could for example
|
||||||
|
be "2nd female" (alias 'f') or "possessive adjective" (alias 'pa' or 'a').
|
||||||
|
pronoun_type (str, optional): An explicit object pronoun to separate cases where
|
||||||
|
there is no unique mapping. Pronoun types defined in `options` take precedence.
|
||||||
|
Values are
|
||||||
|
|
||||||
|
- `subject pronoun`/`subject`/`sp` (I, you, he, they)
|
||||||
|
- `object pronoun`/`object/`/`op` (me, you, him, them)
|
||||||
|
- `possessive adjective`/`adjective`/`pa` (my, your, his, their)
|
||||||
|
- `possessive pronoun`/`pronoun`/`pp` (mine, yours, his, theirs)
|
||||||
|
|
||||||
|
gender (str, optional): Specific gender to use (plural counts a gender for this purpose).
|
||||||
|
A gender specified in `options` takes precedence. Values and aliases are:
|
||||||
|
|
||||||
|
- `male`/`m`
|
||||||
|
- `female`/`f`
|
||||||
|
- `neutral`/`n`
|
||||||
|
- `plural`/`p`
|
||||||
|
|
||||||
|
viewpoint (str, optional): A specified viewpoint of the one talking, to use
|
||||||
|
when there is no unique mapping. A viewpoint given in `options` take
|
||||||
|
precedence. Values and aliases are:
|
||||||
|
|
||||||
|
- `1st person`/`1st`/`1`
|
||||||
|
- `2nd person`/`2nd`/`2`
|
||||||
|
- `3rd person`/`3rd`/`3`
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: A tuple `(1st/2nd_person_pronoun, 3rd_person_pronoun)` to show to the one sending the
|
||||||
|
string and others respectively. If pronoun is invalid, the word is returned verbatim.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
The capitalization of the original word will be retained.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not pronoun:
|
||||||
|
return pronoun
|
||||||
|
|
||||||
|
pronoun_lower = "I" if pronoun == "I" else pronoun.lower()
|
||||||
|
|
||||||
|
if pronoun_lower not in PRONOUN_MAPPING:
|
||||||
|
return pronoun
|
||||||
|
|
||||||
|
# differentiators
|
||||||
|
|
||||||
|
if pronoun_type not in PRONOUN_TYPES:
|
||||||
|
pronoun_type = DEFAULT_PRONOUN_TYPE
|
||||||
|
if viewpoint not in VIEWPOINTS:
|
||||||
|
viewpoint = DEFAULT_VIEWPOINT
|
||||||
|
if gender not in GENDERS:
|
||||||
|
gender = DEFAULT_GENDER
|
||||||
|
|
||||||
|
if options:
|
||||||
|
# option string/list will override the kwargs differentiators given
|
||||||
|
if isinstance(options, str):
|
||||||
|
options = options.split()
|
||||||
|
options = [str(part).strip().lower() for part in options]
|
||||||
|
options = [ALIASES.get(opt, opt) for opt in options]
|
||||||
|
|
||||||
|
for opt in options:
|
||||||
|
if opt in PRONOUN_TYPES:
|
||||||
|
pronoun_type = opt
|
||||||
|
elif opt in VIEWPOINTS:
|
||||||
|
viewpoint = opt
|
||||||
|
elif opt in GENDERS:
|
||||||
|
gender = opt
|
||||||
|
|
||||||
|
# step down into the mapping, using differentiators as needed
|
||||||
|
pronoun_types = PRONOUN_MAPPING[pronoun_lower]
|
||||||
|
# this has one or more pronoun-types
|
||||||
|
if len(pronoun_types) == 1:
|
||||||
|
pronoun_type, viewpoints = next(iter(pronoun_types.items()))
|
||||||
|
elif pronoun_type in pronoun_types:
|
||||||
|
viewpoints = pronoun_types[pronoun_type]
|
||||||
|
elif DEFAULT_PRONOUN_TYPE in pronoun_types:
|
||||||
|
pronoun_type = DEFAULT_PRONOUN_TYPE
|
||||||
|
viewpoints = pronoun_types[pronoun_type]
|
||||||
|
else:
|
||||||
|
# not enough info - grab the first of the mappings
|
||||||
|
pronoun_type, viewpoints = next(iter(pronoun_types.items()))
|
||||||
|
|
||||||
|
# we have one or more viewpoints at this point
|
||||||
|
if len(viewpoints) == 1:
|
||||||
|
viewpoint, genders = next(iter(viewpoints.items()))
|
||||||
|
elif viewpoint in viewpoints:
|
||||||
|
genders = viewpoints[viewpoint]
|
||||||
|
elif DEFAULT_VIEWPOINT in viewpoints:
|
||||||
|
viewpoint = DEFAULT_VIEWPOINT
|
||||||
|
genders = viewpoints[viewpoint]
|
||||||
|
else:
|
||||||
|
# not enough info - grab first of mappings
|
||||||
|
viewpoint, genders = next(iter(viewpoints.items()))
|
||||||
|
|
||||||
|
# we have one or more possible genders (including plural forms)
|
||||||
|
if len(genders) == 1:
|
||||||
|
gender, mapped_pronoun = next(iter(genders.items()))
|
||||||
|
elif gender in genders:
|
||||||
|
mapped_pronoun = genders[gender]
|
||||||
|
elif DEFAULT_GENDER in genders:
|
||||||
|
gender = DEFAULT_GENDER
|
||||||
|
mapped_pronoun = genders[gender]
|
||||||
|
else:
|
||||||
|
# not enough info - grab first mapping
|
||||||
|
gender, mapped_pronoun = next(iter(genders.items()))
|
||||||
|
|
||||||
|
# keep the same capitalization as the original
|
||||||
|
if pronoun != "I":
|
||||||
|
# don't remap I, since this is always capitalized.
|
||||||
|
mapped_pronoun = copy_word_case(pronoun, mapped_pronoun)
|
||||||
|
if mapped_pronoun == "i":
|
||||||
|
mapped_pronoun = mapped_pronoun.upper()
|
||||||
|
|
||||||
|
if viewpoint == "3rd person":
|
||||||
|
# the remapped viewpoing is in 3rd person, meaning the ingoing viewpoing
|
||||||
|
# must have been 1st or 2nd person.
|
||||||
|
return pronoun, mapped_pronoun
|
||||||
|
else:
|
||||||
|
# the remapped viewpoint is 1st or 2nd person, so ingoing must have been
|
||||||
|
# in 3rd person form.
|
||||||
|
return mapped_pronoun, pronoun
|
||||||
|
|
@ -5,7 +5,7 @@ Unit tests for verb conjugation.
|
||||||
|
|
||||||
from parameterized import parameterized
|
from parameterized import parameterized
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from . import conjugate
|
from . import conjugate, pronouns
|
||||||
|
|
||||||
|
|
||||||
class TestVerbConjugate(TestCase):
|
class TestVerbConjugate(TestCase):
|
||||||
|
|
@ -239,3 +239,49 @@ class TestVerbConjugate(TestCase):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.assertEqual(expected, conjugate.verb_actor_stance_components(verb))
|
self.assertEqual(expected, conjugate.verb_actor_stance_components(verb))
|
||||||
|
|
||||||
|
|
||||||
|
class TestPronounMapping(TestCase):
|
||||||
|
"""
|
||||||
|
Test pronoun viewpoint mapping
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@parameterized.expand([
|
||||||
|
("you", "m", "you", "he"),
|
||||||
|
("you", "f op", "you", "her"),
|
||||||
|
("I", "", "I", "it"),
|
||||||
|
("I", "p", "I", "it"), # plural is invalid
|
||||||
|
("I", "m", "I", "he"),
|
||||||
|
("Me", "n", "Me", "It"),
|
||||||
|
("your", "p", "your", "their"),
|
||||||
|
("ours", "", "ours", "theirs"),
|
||||||
|
("yourself", "", "yourself", "itself"),
|
||||||
|
("yourself", "m", "yourself", "himself"),
|
||||||
|
("yourself", "f", "yourself", "herself"),
|
||||||
|
("yourself", "p", "yourself", "itself"), # plural is invalid
|
||||||
|
("yourselves", "", "yourselves", "themselves"),
|
||||||
|
("he", "", "you", "he"), # assume 2nd person
|
||||||
|
("he", "1", "I", "he"),
|
||||||
|
("he", "1 p", "we", "he"),
|
||||||
|
("her", "p", "you", "her"),
|
||||||
|
("her", "pa", "your", "her"),
|
||||||
|
("their", "pa", "your", "their"),
|
||||||
|
("their", "pa", "your", "their"),
|
||||||
|
("itself", "", "yourself", "itself"),
|
||||||
|
("themselves", "", "yourselves", "themselves"),
|
||||||
|
("herself", "", "yourself", "herself"),
|
||||||
|
])
|
||||||
|
def test_mapping_with_options(self, pronoun, options,
|
||||||
|
expected_1st_or_2nd_person,
|
||||||
|
expected_3rd_person):
|
||||||
|
"""
|
||||||
|
Test the pronoun mapper.
|
||||||
|
|
||||||
|
"""
|
||||||
|
received_1st_or_2nd_person, received_3rd_person = (
|
||||||
|
pronouns.pronoun_to_viewpoints(pronoun, options)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(expected_1st_or_2nd_person, received_1st_or_2nd_person)
|
||||||
|
self.assertEqual(expected_3rd_person, received_3rd_person)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue