# discord-ext-pager
[![PyPI](https://img.shields.io/pypi/v/discord-ext-pager?label=View%20on%20pypi&style=flat-square)](https://pypi.org/project/discord-ext-pager/)
A simple view-based paginator library for discord.py 2.0. Works with Python 3.8+.
## Usage
[discord-ext-pager] is available on PyPI, and as such can be installed using pip.
Users of Danny's [discord-ext-menus] will find some familiarity
in this library. Provided are the following classes:
- PaginatorView:
The view class that manages pagination and navigation.
- PageSource:
The base class for sources the paginator view can accept.
- ListPageSource:
The base class for formatting a list of items.
- AsyncIteratorPageSource:
The base class for formatting an asynchronous iterator of items.
- PageOption:
A subclass of `discord.SelectOption` used for presenting navigation options.
- StopAction:
An enum for customizing PaginatorView's stop button behaviour.
- TimeoutAction:
An enum for customizing PaginatorView's timeout behaviour.
[discord-ext-pager]: https://pypi.org/project/discord-ext-pager/
[discord-ext-menus]: https://github.com/Rapptz/discord-ext-menus
The `PaginatorView` can be instantiated and used by itself, but page formatting
is handled by subclassing one of the `PageSource` base classes.
```py
from typing import List
from discord.ext.pager import ListPageSource, PageSource, PaginatorView
class EmbedListPageSource(ListPageSource[object, PageSource, PaginatorView]):
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# These type parameters denote the page item type,
# source type for page options (demonstrated later),
# and view type. Only needed for static typing.
"""Takes a list of items and formats it in an embed."""
def format_page(self, view: PaginatorView, page: List[object]):
index = self.current_index * self.page_size
description = "\n".join(
f"{i}. {x}"
for i, x in enumerate(page, start=index + 1)
)
return discord.Embed(description=description)
# Anywhere a channel or interaction is available:
fruits = ["🍎 Apple", "🍊 Orange", "🍋 Lemon"]
source = EmbedListPageSource(fruits, page_size=2)
view = PaginatorView(sources=source, timeout=180)
await view.start(interaction)
```
If the navigation select menu is desired, the `get_page_options()` method
should be overridden to return a list of `PageOption` objects for the user
to select from:
```py
from typing import List
from discord.ext.pager import ListPageSource, PageOption, PageSource, PaginatorView
class MessageSource(PageSource[str, PageSource, PaginatorView]):
"""A single page for displaying a string."""
def __init__(self, message: str):
super().__init__(current_index=0)
self.message = message
def get_page(self, index: int):
return self.message
def format_page(self, view: PaginatorView, page: str):
# If we don't specify both content and embed, either will
# persist as the user clicks between options
return {"content": page, "embed": None}
class MessageNavigator(ListPageSource[MessageSource, MessageSource, PaginatorView]):
"""A list of messages for the user to select from."""
def get_page_options(self, view: PaginatorView, page: List[MessageSource]):
# PageOption() takes the same arguments as discord.SelectOption,
# except that source= is also required
return [PageOption(source=source, label=source.message) for source in page]
def format_page(self, view: PaginatorView, page: List[MessageSource]):
description = "\n".join(source.message for source in page)
embed = discord.Embed(description=description)
return {"content": None, "embed": embed}
hands = "👈👉👆👇🫵🤞🫰🤘🤙🤛🤜✊👊👋👏🙌"
source = MessageNavigator([MessageSource(s) for s in hands], page_size=5)
view = PaginatorView(sources=source)
await view.start(ctx)
```
When an option is selected, the `PageSource` contained within that option
is appended to `PaginatorView.sources`, causing that source to be displayed.
Another button is automatically provided for users to back out to the last
page source. This can be manually triggered by passing a list of page sources
to the `PaginatorView(sources=)` argument.
## Examples
Click on an example below to see its source code:
[![Tag leaderboard](https://github.com/thegamecracks/discord-ext-pager/blob/main/docs/images/thegamebot_tags.png?raw=true)](https://github.com/thegamecracks/thegamebot/blob/04d9909877685acd24654a911b1853e2143fc316/bot/cogs/tags/__init__.py#L123-L162)
[![Help command](https://github.com/thegamecracks/discord-ext-pager/blob/main/docs/images/thegamebot_help.png?raw=true)](https://github.com/thegamecracks/thegamebot/blob/04d9909877685acd24654a911b1853e2143fc316/bot/cogs/helpcommand.py#L26-L249)
Raw data
{
"_id": null,
"home_page": "",
"name": "discord-ext-pager",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "discord,discord.py,paginator,view",
"author": "thegamecracks",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/96/2e/a93bb4defd6ee0b90ac6831408561b6f0731710995909af74fce9259fef9/discord-ext-pager-1.1.3.tar.gz",
"platform": null,
"description": "# discord-ext-pager\n\n[![PyPI](https://img.shields.io/pypi/v/discord-ext-pager?label=View%20on%20pypi&style=flat-square)](https://pypi.org/project/discord-ext-pager/)\n\nA simple view-based paginator library for discord.py 2.0. Works with Python 3.8+.\n\n## Usage\n\n[discord-ext-pager] is available on PyPI, and as such can be installed using pip.\n\nUsers of Danny's [discord-ext-menus] will find some familiarity\nin this library. Provided are the following classes:\n\n- PaginatorView:\n The view class that manages pagination and navigation.\n- PageSource:\n The base class for sources the paginator view can accept.\n- ListPageSource:\n The base class for formatting a list of items.\n- AsyncIteratorPageSource:\n The base class for formatting an asynchronous iterator of items.\n- PageOption:\n A subclass of `discord.SelectOption` used for presenting navigation options.\n- StopAction:\n An enum for customizing PaginatorView's stop button behaviour.\n- TimeoutAction:\n An enum for customizing PaginatorView's timeout behaviour.\n\n[discord-ext-pager]: https://pypi.org/project/discord-ext-pager/\n[discord-ext-menus]: https://github.com/Rapptz/discord-ext-menus\n\nThe `PaginatorView` can be instantiated and used by itself, but page formatting\nis handled by subclassing one of the `PageSource` base classes.\n\n```py\nfrom typing import List\nfrom discord.ext.pager import ListPageSource, PageSource, PaginatorView\n\nclass EmbedListPageSource(ListPageSource[object, PageSource, PaginatorView]):\n # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n # These type parameters denote the page item type,\n # source type for page options (demonstrated later),\n # and view type. Only needed for static typing.\n \"\"\"Takes a list of items and formats it in an embed.\"\"\"\n\n def format_page(self, view: PaginatorView, page: List[object]):\n index = self.current_index * self.page_size\n description = \"\\n\".join(\n f\"{i}. {x}\"\n for i, x in enumerate(page, start=index + 1)\n )\n return discord.Embed(description=description)\n\n# Anywhere a channel or interaction is available:\nfruits = [\"\ud83c\udf4e Apple\", \"\ud83c\udf4a Orange\", \"\ud83c\udf4b Lemon\"]\nsource = EmbedListPageSource(fruits, page_size=2)\nview = PaginatorView(sources=source, timeout=180)\nawait view.start(interaction)\n```\n\nIf the navigation select menu is desired, the `get_page_options()` method\nshould be overridden to return a list of `PageOption` objects for the user\nto select from:\n\n```py\nfrom typing import List\nfrom discord.ext.pager import ListPageSource, PageOption, PageSource, PaginatorView\n\nclass MessageSource(PageSource[str, PageSource, PaginatorView]):\n \"\"\"A single page for displaying a string.\"\"\"\n\n def __init__(self, message: str):\n super().__init__(current_index=0)\n self.message = message\n\n def get_page(self, index: int):\n return self.message\n\n def format_page(self, view: PaginatorView, page: str):\n # If we don't specify both content and embed, either will\n # persist as the user clicks between options\n return {\"content\": page, \"embed\": None}\n\nclass MessageNavigator(ListPageSource[MessageSource, MessageSource, PaginatorView]):\n \"\"\"A list of messages for the user to select from.\"\"\"\n\n def get_page_options(self, view: PaginatorView, page: List[MessageSource]):\n # PageOption() takes the same arguments as discord.SelectOption,\n # except that source= is also required\n return [PageOption(source=source, label=source.message) for source in page]\n\n def format_page(self, view: PaginatorView, page: List[MessageSource]):\n description = \"\\n\".join(source.message for source in page)\n embed = discord.Embed(description=description)\n return {\"content\": None, \"embed\": embed}\n\nhands = \"\ud83d\udc48\ud83d\udc49\ud83d\udc46\ud83d\udc47\ud83e\udef5\ud83e\udd1e\ud83e\udef0\ud83e\udd18\ud83e\udd19\ud83e\udd1b\ud83e\udd1c\u270a\ud83d\udc4a\ud83d\udc4b\ud83d\udc4f\ud83d\ude4c\"\nsource = MessageNavigator([MessageSource(s) for s in hands], page_size=5)\nview = PaginatorView(sources=source)\nawait view.start(ctx)\n```\n\nWhen an option is selected, the `PageSource` contained within that option\nis appended to `PaginatorView.sources`, causing that source to be displayed.\nAnother button is automatically provided for users to back out to the last\npage source. This can be manually triggered by passing a list of page sources\nto the `PaginatorView(sources=)` argument.\n\n## Examples\n\nClick on an example below to see its source code:\n\n[![Tag leaderboard](https://github.com/thegamecracks/discord-ext-pager/blob/main/docs/images/thegamebot_tags.png?raw=true)](https://github.com/thegamecracks/thegamebot/blob/04d9909877685acd24654a911b1853e2143fc316/bot/cogs/tags/__init__.py#L123-L162)\n\n[![Help command](https://github.com/thegamecracks/discord-ext-pager/blob/main/docs/images/thegamebot_help.png?raw=true)](https://github.com/thegamecracks/thegamebot/blob/04d9909877685acd24654a911b1853e2143fc316/bot/cogs/helpcommand.py#L26-L249)\n",
"bugtrack_url": null,
"license": "",
"summary": "A view-based paginator library for discord.py 2.0",
"version": "1.1.3",
"project_urls": {
"Homepage": "https://github.com/thegamecracks/discord-ext-pager"
},
"split_keywords": [
"discord",
"discord.py",
"paginator",
"view"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "fa06d07ec77392d7acb98255df05f5f8d0f9b60c73b3abdfba680c7990808536",
"md5": "1e99f9f2a7089f12003f9ac6b537ab47",
"sha256": "af95256386f9ae7947554320e0381a2bac20f754a40388bd4b90495cddd7c4d2"
},
"downloads": -1,
"filename": "discord_ext_pager-1.1.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1e99f9f2a7089f12003f9ac6b537ab47",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 13469,
"upload_time": "2023-11-13T19:19:09",
"upload_time_iso_8601": "2023-11-13T19:19:09.671962Z",
"url": "https://files.pythonhosted.org/packages/fa/06/d07ec77392d7acb98255df05f5f8d0f9b60c73b3abdfba680c7990808536/discord_ext_pager-1.1.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "962ea93bb4defd6ee0b90ac6831408561b6f0731710995909af74fce9259fef9",
"md5": "26aea9983c860b1ac929d1667d134720",
"sha256": "75add7c3a11ab3e0a700d381083fde9f15933dce5ba9d6e151fb48e7cc838879"
},
"downloads": -1,
"filename": "discord-ext-pager-1.1.3.tar.gz",
"has_sig": false,
"md5_digest": "26aea9983c860b1ac929d1667d134720",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 14887,
"upload_time": "2023-11-13T19:19:11",
"upload_time_iso_8601": "2023-11-13T19:19:11.103283Z",
"url": "https://files.pythonhosted.org/packages/96/2e/a93bb4defd6ee0b90ac6831408561b6f0731710995909af74fce9259fef9/discord-ext-pager-1.1.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-11-13 19:19:11",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "thegamecracks",
"github_project": "discord-ext-pager",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "discord-ext-pager"
}