pymud 0.21.3.post1__py3-none-any.whl → 0.21.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pymud/decorators.py +1 -1
- pymud/dialogs.py +5 -5
- pymud/extras.py +107 -65
- pymud/logger.py +1 -1
- pymud/modules.py +2 -2
- pymud/objects.py +3 -4
- pymud/protocol.py +1 -1
- pymud/pymud.py +27 -32
- pymud/session.py +2 -2
- pymud/settings.py +2 -2
- {pymud-0.21.3.post1.dist-info → pymud-0.21.4.dist-info}/METADATA +9 -1
- pymud-0.21.4.dist-info/RECORD +23 -0
- pymud-0.21.3.post1.dist-info/RECORD +0 -23
- {pymud-0.21.3.post1.dist-info → pymud-0.21.4.dist-info}/WHEEL +0 -0
- {pymud-0.21.3.post1.dist-info → pymud-0.21.4.dist-info}/entry_points.txt +0 -0
- {pymud-0.21.3.post1.dist-info → pymud-0.21.4.dist-info}/licenses/LICENSE.txt +0 -0
- {pymud-0.21.3.post1.dist-info → pymud-0.21.4.dist-info}/top_level.txt +0 -0
pymud/decorators.py
CHANGED
pymud/dialogs.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
import asyncio, webbrowser
|
2
|
-
from typing import Any
|
3
|
-
from prompt_toolkit.layout import AnyContainer,
|
4
|
-
from prompt_toolkit.widgets import
|
5
|
-
from prompt_toolkit.layout.dimension import
|
6
|
-
from prompt_toolkit import
|
2
|
+
from typing import Any
|
3
|
+
from prompt_toolkit.layout import AnyContainer, VSplit, HSplit, Window, WindowAlign
|
4
|
+
from prompt_toolkit.widgets import Dialog, Label, TextArea, Frame, RadioList
|
5
|
+
from prompt_toolkit.layout.dimension import D
|
6
|
+
from prompt_toolkit import HTML
|
7
7
|
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
|
8
8
|
from prompt_toolkit.formatted_text import FormattedText, AnyFormattedText
|
9
9
|
from prompt_toolkit.application.current import get_app
|
pymud/extras.py
CHANGED
@@ -1,39 +1,24 @@
|
|
1
1
|
# External Libraries
|
2
|
-
from functools import lru_cache
|
3
2
|
from unicodedata import east_asian_width
|
4
3
|
from wcwidth import wcwidth
|
5
4
|
from dataclasses import dataclass
|
6
|
-
import time, re,
|
5
|
+
import time, re, linecache, os
|
7
6
|
from typing import Optional, List, Dict
|
8
|
-
from typing import Iterable,
|
7
|
+
from typing import Iterable, Optional, Tuple
|
9
8
|
from prompt_toolkit import ANSI
|
10
9
|
from prompt_toolkit.application import get_app
|
11
|
-
from prompt_toolkit.
|
12
|
-
from prompt_toolkit.formatted_text import to_formatted_text, fragment_list_to_text
|
10
|
+
from prompt_toolkit.formatted_text import to_formatted_text
|
13
11
|
from prompt_toolkit.formatted_text.base import OneStyleAndTextTuple
|
14
12
|
from prompt_toolkit.layout.controls import UIContent, UIControl
|
15
|
-
from prompt_toolkit.layout.processors import Processor, Transformation
|
16
13
|
from prompt_toolkit.application.current import get_app
|
17
|
-
from prompt_toolkit.buffer import Buffer
|
18
|
-
from prompt_toolkit.document import Document
|
19
14
|
from prompt_toolkit.data_structures import Point
|
20
15
|
from prompt_toolkit.layout.controls import UIContent, FormattedTextControl
|
21
|
-
from prompt_toolkit.lexers import Lexer
|
22
16
|
from prompt_toolkit.mouse_events import MouseButton, MouseEvent, MouseEventType
|
23
|
-
from prompt_toolkit.selection import SelectionType
|
24
|
-
from prompt_toolkit.buffer import Buffer, ValidationState
|
25
|
-
from prompt_toolkit.utils import Event
|
26
17
|
|
27
|
-
from prompt_toolkit.filters import (
|
28
|
-
FilterOrBool,
|
29
|
-
)
|
30
18
|
from prompt_toolkit.formatted_text import (
|
31
19
|
StyleAndTextTuples,
|
32
20
|
to_formatted_text,
|
33
21
|
)
|
34
|
-
from prompt_toolkit.formatted_text.utils import fragment_list_to_text
|
35
|
-
from prompt_toolkit.history import InMemoryHistory
|
36
|
-
from prompt_toolkit.key_binding.key_bindings import KeyBindingsBase
|
37
22
|
from prompt_toolkit.layout.containers import (
|
38
23
|
Window,
|
39
24
|
WindowAlign,
|
@@ -42,12 +27,6 @@ from prompt_toolkit.layout.controls import (
|
|
42
27
|
|
43
28
|
FormattedTextControl,
|
44
29
|
)
|
45
|
-
from prompt_toolkit.layout.processors import (
|
46
|
-
Processor,
|
47
|
-
TransformationInput,
|
48
|
-
Transformation
|
49
|
-
)
|
50
|
-
from prompt_toolkit.lexers import Lexer
|
51
30
|
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
|
52
31
|
from prompt_toolkit.utils import get_cwidth
|
53
32
|
from prompt_toolkit.widgets import Button, MenuContainer, MenuItem
|
@@ -56,7 +35,6 @@ from prompt_toolkit.widgets.base import Border
|
|
56
35
|
from prompt_toolkit.layout.screen import _CHAR_CACHE, Screen, WritePosition
|
57
36
|
from prompt_toolkit.layout.utils import explode_text_fragments
|
58
37
|
from prompt_toolkit.formatted_text.utils import (
|
59
|
-
fragment_list_to_text,
|
60
38
|
fragment_list_width,
|
61
39
|
)
|
62
40
|
|
@@ -236,7 +214,6 @@ class VSplitWindow(Window):
|
|
236
214
|
upper = (total - 1) // 2
|
237
215
|
below = total - upper - 1
|
238
216
|
|
239
|
-
#if isNotMargin:
|
240
217
|
if isinstance(self.content, PyMudBufferControl):
|
241
218
|
b = self.content.buffer
|
242
219
|
if not b:
|
@@ -261,7 +238,6 @@ class VSplitWindow(Window):
|
|
261
238
|
|
262
239
|
else:
|
263
240
|
# 若内容行数大于屏幕行数,则倒序复制,确保即使有自动折行时,最后一行也保持在屏幕最底部
|
264
|
-
|
265
241
|
y = total
|
266
242
|
lineno = line_count
|
267
243
|
|
@@ -273,13 +249,10 @@ class VSplitWindow(Window):
|
|
273
249
|
line = ui_content.get_line(lineno)
|
274
250
|
visible_line_to_row_col[y] = (lineno, horizontal_scroll)
|
275
251
|
copy_line(line, lineno, 0, y, is_input=True)
|
276
|
-
|
277
252
|
|
278
253
|
else:
|
279
254
|
# 有split window
|
280
255
|
|
281
|
-
|
282
|
-
|
283
256
|
# 先复制下半部分,倒序复制,确保即使有自动折行时,最后一行也保持在屏幕最底部
|
284
257
|
y = total
|
285
258
|
lineno = line_count
|
@@ -298,7 +271,7 @@ class VSplitWindow(Window):
|
|
298
271
|
# 复制上半部分,正序复制,确保即使有自动折行时,第一行也保持在屏幕最顶部
|
299
272
|
y = -vertical_scroll_2
|
300
273
|
lineno = start_lineno
|
301
|
-
while y
|
274
|
+
while y < below and lineno < line_count:
|
302
275
|
line = ui_content.get_line(lineno)
|
303
276
|
visible_line_to_row_col[y] = (lineno, horizontal_scroll)
|
304
277
|
x = 0
|
@@ -385,7 +358,7 @@ class VSplitWindow(Window):
|
|
385
358
|
if not b:
|
386
359
|
return
|
387
360
|
start_lineno = b.start_lineno
|
388
|
-
if (start_lineno >= 0) and (start_lineno < b.lineCount - len(info.displayed_lines)):
|
361
|
+
if (start_lineno >= 0) and (start_lineno < b.lineCount - (len(info.displayed_lines) - 1) // 2):
|
389
362
|
b.start_lineno = b.start_lineno + 1
|
390
363
|
else:
|
391
364
|
b.start_lineno = -1
|
@@ -409,7 +382,8 @@ class VSplitWindow(Window):
|
|
409
382
|
b.start_lineno = 0
|
410
383
|
|
411
384
|
else:
|
412
|
-
b.start_lineno = b.lineCount - len(info.displayed_lines) - 1
|
385
|
+
b.start_lineno = b.lineCount - (len(info.displayed_lines) - 1) // 2
|
386
|
+
|
413
387
|
|
414
388
|
|
415
389
|
class EasternButton(Button):
|
@@ -532,14 +506,14 @@ class SessionSelectionState:
|
|
532
506
|
if self.start_row >= 0 and self.end_row >= 0 and self.start_col >= 0 and self.end_col >= 0:
|
533
507
|
if (self.start_row == self.end_row) and (self.start_col == self.end_col):
|
534
508
|
return False
|
535
|
-
elif self.start_row > self.end_row:
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
elif self.start_row == self.end_row and self.start_col > self.end_col:
|
541
|
-
|
542
|
-
|
509
|
+
# elif self.start_row > self.end_row:
|
510
|
+
# srow, scol = self.end_row, self.end_col
|
511
|
+
# erow, ecol = self.start_row, self.start_col
|
512
|
+
# self.start_row, self.end_row = srow, erow
|
513
|
+
# self.start_col, self.end_col = scol, ecol
|
514
|
+
# elif self.start_row == self.end_row and self.start_col > self.end_col:
|
515
|
+
# scol, ecol = self.end_col, self.start_col
|
516
|
+
# self.start_col, self.end_col = scol, ecol
|
543
517
|
|
544
518
|
return True
|
545
519
|
|
@@ -548,10 +522,50 @@ class SessionSelectionState:
|
|
548
522
|
@property
|
549
523
|
def rows(self):
|
550
524
|
if self.is_valid():
|
551
|
-
return self.end_row - self.start_row + 1
|
525
|
+
return abs(self.end_row - self.start_row) + 1
|
552
526
|
else:
|
553
527
|
return 0
|
554
528
|
|
529
|
+
@property
|
530
|
+
def actual_start_row(self):
|
531
|
+
if self.is_valid():
|
532
|
+
if self.start_row <= self.end_row:
|
533
|
+
return self.start_row
|
534
|
+
else:
|
535
|
+
return self.end_row
|
536
|
+
|
537
|
+
return -1
|
538
|
+
|
539
|
+
@property
|
540
|
+
def actual_start_col(self):
|
541
|
+
if self.is_valid():
|
542
|
+
if self.start_row <= self.end_row:
|
543
|
+
return self.start_col
|
544
|
+
else:
|
545
|
+
return self.end_col
|
546
|
+
|
547
|
+
return -1
|
548
|
+
|
549
|
+
@property
|
550
|
+
def actual_end_row(self):
|
551
|
+
if self.is_valid():
|
552
|
+
if self.start_row <= self.end_row:
|
553
|
+
return self.end_row
|
554
|
+
else:
|
555
|
+
return self.start_row
|
556
|
+
|
557
|
+
return -1
|
558
|
+
|
559
|
+
@property
|
560
|
+
def actual_end_col(self):
|
561
|
+
if self.is_valid():
|
562
|
+
if self.start_row <= self.end_row:
|
563
|
+
return self.end_col
|
564
|
+
else:
|
565
|
+
return self.start_col
|
566
|
+
|
567
|
+
return -1
|
568
|
+
|
555
569
|
|
556
570
|
class BufferBase:
|
557
571
|
def __init__(self, name, newline = "\n", max_buffered_lines = 10000) -> None:
|
@@ -561,6 +575,8 @@ class BufferBase:
|
|
561
575
|
self.start_lineno = -1
|
562
576
|
self.selection = SessionSelectionState(-1, -1, -1, -1)
|
563
577
|
|
578
|
+
self.mouse_point = Point(-1, -1)
|
579
|
+
|
564
580
|
def clear(self):
|
565
581
|
pass
|
566
582
|
|
@@ -576,12 +592,13 @@ class BufferBase:
|
|
576
592
|
def selection_range_at_line(self, lineno: int) -> Optional[Tuple[int, int]]:
|
577
593
|
if self.selection.is_valid():
|
578
594
|
if self.selection.rows > 1:
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
595
|
+
|
596
|
+
if lineno == self.selection.actual_start_row:
|
597
|
+
return (self.selection.actual_start_col, len(self.getLine(lineno)))
|
598
|
+
elif lineno == self.selection.actual_end_row:
|
599
|
+
return (0, self.selection.actual_end_col)
|
600
|
+
elif lineno > self.selection.actual_start_row and lineno < self.selection.actual_end_row:
|
601
|
+
return (0, len(self.getLine(lineno)))
|
585
602
|
|
586
603
|
elif self.selection.rows == 1:
|
587
604
|
if lineno == self.selection.start_row:
|
@@ -639,13 +656,11 @@ class SessionBuffer(BufferBase):
|
|
639
656
|
## limit buffered lines
|
640
657
|
if len(self._lines) > self.max_buffered_lines:
|
641
658
|
diff = len(self._lines) - self.max_buffered_lines
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
self.selection.start_row -= diff
|
648
|
-
self.selection.end_row -= diff
|
659
|
+
del self._lines[:diff]
|
660
|
+
## adjust selection
|
661
|
+
if self.selection.start_row >= 0:
|
662
|
+
self.selection.start_row -= diff
|
663
|
+
self.selection.end_row -= diff
|
649
664
|
|
650
665
|
get_app().invalidate()
|
651
666
|
|
@@ -707,8 +722,9 @@ class PyMudBufferControl(UIControl):
|
|
707
722
|
self.buffer = buffer
|
708
723
|
|
709
724
|
# 为MUD显示进行校正的处理,包括对齐校正,换行颜色校正等
|
710
|
-
self.FULL_BLOCKS = set("
|
711
|
-
self.SINGLE_LINES = set("
|
725
|
+
self.FULL_BLOCKS = set("▂▃▅▆▇▄█━◇◆")
|
726
|
+
self.SINGLE_LINES = set("┠┌└├┬┼┴╭╰─")
|
727
|
+
self.SINGLE_LINES_LEFT = set("┨┘┐┤")
|
712
728
|
self.DOUBLE_LINES = set("╔╚╠╦╪╩═")
|
713
729
|
self.ALL_COLOR_REGX = re.compile(r"(?:\[[\d;]+m)+")
|
714
730
|
self.AVAI_COLOR_REGX = re.compile(r"(?:\[[\d;]+m)+(?!$)")
|
@@ -734,17 +750,32 @@ class PyMudBufferControl(UIControl):
|
|
734
750
|
|
735
751
|
def width_correction(self, line: str) -> str:
|
736
752
|
new_str = []
|
737
|
-
for ch in line:
|
738
|
-
|
753
|
+
for idx, ch in enumerate(line):
|
754
|
+
|
739
755
|
if (east_asian_width(ch) in "FWA") and (wcwidth(ch) == 1):
|
756
|
+
|
740
757
|
if ch in self.FULL_BLOCKS:
|
741
|
-
new_str.append(ch)
|
758
|
+
new_str.append(ch * 2)
|
742
759
|
elif ch in self.SINGLE_LINES:
|
760
|
+
new_str.append(ch)
|
743
761
|
new_str.append("─")
|
744
762
|
elif ch in self.DOUBLE_LINES:
|
763
|
+
new_str.append(ch)
|
745
764
|
new_str.append("═")
|
765
|
+
elif ch in self.SINGLE_LINES_LEFT:
|
766
|
+
new_str.append("─")
|
767
|
+
new_str.append(ch)
|
768
|
+
elif idx == len(line) - 1:
|
769
|
+
new_str.append(" ")
|
770
|
+
new_str.append(ch)
|
746
771
|
else:
|
772
|
+
new_str.append(ch)
|
747
773
|
new_str.append(' ')
|
774
|
+
else:
|
775
|
+
new_str.append(ch)
|
776
|
+
|
777
|
+
# 添加一个不可见字符,用于允许选择行时选到最后一个字符
|
778
|
+
new_str.append("\u200B")
|
748
779
|
|
749
780
|
return "".join(new_str)
|
750
781
|
|
@@ -752,18 +783,27 @@ class PyMudBufferControl(UIControl):
|
|
752
783
|
return line.replace("\r", "").replace("\x00", "")
|
753
784
|
|
754
785
|
def tab_correction(self, line: str):
|
755
|
-
|
786
|
+
from .session import Session
|
787
|
+
while "\t" in line:
|
788
|
+
tab_index = line.find("\t")
|
789
|
+
left, right = line[:tab_index], line[tab_index + 1:]
|
790
|
+
left_width = get_cwidth(Session.PLAIN_TEXT_REGX.sub("", left))
|
791
|
+
tab_width = Settings.client["tabstop"] - (left_width % Settings.client["tabstop"])
|
792
|
+
line = left + " " * tab_width + right
|
793
|
+
|
794
|
+
return line
|
756
795
|
|
757
796
|
def line_correction(self, line: str):
|
758
797
|
# 处理\r符号(^M)
|
759
798
|
line = self.return_correction(line)
|
760
|
-
# 处理Tab(\r)符号(^I)
|
761
|
-
line = self.tab_correction(line)
|
762
799
|
|
763
800
|
# 美化(解决中文英文在Console中不对齐的问题)
|
764
801
|
if Settings.client["beautify"]:
|
765
802
|
line = self.width_correction(line)
|
766
803
|
|
804
|
+
# 处理Tab(\r)符号(^I)对齐
|
805
|
+
line = self.tab_correction(line)
|
806
|
+
|
767
807
|
return line
|
768
808
|
|
769
809
|
def create_content(self, width: int, height: int) -> UIContent:
|
@@ -878,6 +918,7 @@ class PyMudBufferControl(UIControl):
|
|
878
918
|
|
879
919
|
if buffer:
|
880
920
|
# Set the selection position.
|
921
|
+
buffer.mouse_point = position
|
881
922
|
if mouse_event.event_type == MouseEventType.MOUSE_DOWN:
|
882
923
|
buffer.exit_selection()
|
883
924
|
buffer.selection.start_row = position.y
|
@@ -888,9 +929,10 @@ class PyMudBufferControl(UIControl):
|
|
888
929
|
and mouse_event.button == MouseButton.LEFT
|
889
930
|
):
|
890
931
|
# Click and drag to highlight a selection
|
891
|
-
if buffer.selection.start_row >= 0:
|
932
|
+
if buffer.selection.start_row >= 0 and not (position.y == 0 and position.x == 0):
|
892
933
|
buffer.selection.end_row = position.y
|
893
934
|
buffer.selection.end_col = position.x
|
935
|
+
|
894
936
|
|
895
937
|
elif mouse_event.event_type == MouseEventType.MOUSE_UP:
|
896
938
|
# When the cursor was moved to another place, select the text.
|
@@ -899,7 +941,7 @@ class PyMudBufferControl(UIControl):
|
|
899
941
|
# the cursor can never be after the text, so the cursor
|
900
942
|
# will be repositioned automatically.)
|
901
943
|
|
902
|
-
if buffer.selection.start_row >= 0:
|
944
|
+
if buffer.selection.start_row >= 0 and position.y >= 0:
|
903
945
|
buffer.selection.end_row = position.y
|
904
946
|
buffer.selection.end_col = position.x
|
905
947
|
|
pymud/logger.py
CHANGED
pymud/modules.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
|
2
|
-
import importlib, importlib.util
|
2
|
+
import importlib, importlib.util
|
3
3
|
from typing import Any
|
4
4
|
from .settings import Settings
|
5
5
|
from .extras import DotDict
|
6
|
-
from .decorators import
|
6
|
+
from .decorators import PymudDecorator, print_exception
|
7
7
|
|
8
8
|
class PymudMeta(type):
|
9
9
|
def __new__(cls, name, bases, attrs):
|
pymud/objects.py
CHANGED
@@ -2,14 +2,13 @@
|
|
2
2
|
MUD会话(session)中, 支持的对象列表
|
3
3
|
"""
|
4
4
|
|
5
|
-
import asyncio, logging, re
|
6
|
-
from
|
7
|
-
from typing import Optional, Union, List, Dict, Tuple
|
5
|
+
import asyncio, logging, re
|
6
|
+
from typing import Union, List, Tuple
|
8
7
|
from collections.abc import Iterable
|
9
8
|
from collections import namedtuple
|
10
9
|
from typing import Any
|
11
10
|
from .settings import Settings
|
12
|
-
from .decorators import
|
11
|
+
from .decorators import print_exception
|
13
12
|
|
14
13
|
class CodeLine:
|
15
14
|
"""
|
pymud/protocol.py
CHANGED
pymud/pymud.py
CHANGED
@@ -1,15 +1,13 @@
|
|
1
|
-
import asyncio, functools,
|
1
|
+
import asyncio, functools, os, webbrowser, threading
|
2
2
|
from datetime import datetime
|
3
|
-
from
|
4
|
-
from prompt_toolkit.shortcuts import set_title, radiolist_dialog
|
3
|
+
from prompt_toolkit.shortcuts import set_title
|
5
4
|
from prompt_toolkit.output import ColorDepth
|
6
5
|
from prompt_toolkit.clipboard.pyperclip import PyperclipClipboard
|
7
6
|
from prompt_toolkit import HTML
|
8
7
|
from prompt_toolkit.buffer import Buffer
|
9
8
|
from prompt_toolkit.application import Application
|
10
|
-
from prompt_toolkit.filters import Condition
|
11
|
-
from prompt_toolkit.
|
12
|
-
from prompt_toolkit.layout import ConditionalContainer, Float, VSplit, HSplit, Window, WindowAlign, ScrollbarMargin, NumberedMargin, to_dimension
|
9
|
+
from prompt_toolkit.filters import Condition, is_true, to_filter
|
10
|
+
from prompt_toolkit.layout import ConditionalContainer, Float, VSplit, HSplit, Window, WindowAlign
|
13
11
|
from prompt_toolkit.layout.layout import Layout
|
14
12
|
from prompt_toolkit.layout.controls import FormattedTextControl
|
15
13
|
from prompt_toolkit.layout.dimension import D
|
@@ -18,26 +16,14 @@ from prompt_toolkit.styles import Style
|
|
18
16
|
from prompt_toolkit.widgets import Label, TextArea
|
19
17
|
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
|
20
18
|
from prompt_toolkit.cursor_shapes import CursorShape
|
21
|
-
from prompt_toolkit.key_binding import KeyPress, KeyPressEvent
|
19
|
+
from prompt_toolkit.key_binding import KeyBindings, KeyPress, KeyPressEvent
|
22
20
|
from prompt_toolkit.keys import Keys
|
23
|
-
from prompt_toolkit.
|
24
|
-
Condition,
|
25
|
-
is_true,
|
26
|
-
to_filter,
|
27
|
-
)
|
28
|
-
from prompt_toolkit.formatted_text import (
|
29
|
-
Template,
|
30
|
-
)
|
31
|
-
from prompt_toolkit.layout.processors import (
|
32
|
-
DisplayMultipleCursors,
|
33
|
-
HighlightSearchProcessor,
|
34
|
-
HighlightSelectionProcessor,
|
35
|
-
)
|
21
|
+
from prompt_toolkit.formatted_text import Template
|
36
22
|
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
37
|
-
from wcwidth import
|
23
|
+
from wcwidth import wcswidth
|
38
24
|
|
39
25
|
from .objects import CodeBlock
|
40
|
-
from .extras import BufferBase, LogFileBuffer,
|
26
|
+
from .extras import BufferBase, LogFileBuffer, PyMudBufferControl, EasternMenuContainer, VSplitWindow, DotDict, MenuItem
|
41
27
|
from .modules import Plugin
|
42
28
|
from .session import Session
|
43
29
|
from .settings import Settings
|
@@ -516,16 +502,17 @@ class PyMudApp:
|
|
516
502
|
b = self.consoleView.buffer
|
517
503
|
if b and b.selection.is_valid():
|
518
504
|
if not raw:
|
519
|
-
if b.selection.start_row == b.selection.end_row:
|
520
|
-
|
505
|
+
#if b.selection.start_row == b.selection.end_row:
|
506
|
+
if b.selection.rows == 1:
|
507
|
+
if b.selection.actual_end_col - b.selection.actual_start_col >= len(b.getLine(b.selection.start_row)):
|
521
508
|
# 单行且选中了整行,此时不校正显示位置匹配
|
522
|
-
line = b.getLine(b.selection.
|
509
|
+
line = b.getLine(b.selection.actual_start_row)
|
523
510
|
else:
|
524
511
|
# 单行且选中了部分内容,此时校正显示位置匹配
|
525
|
-
line = self.consoleView.line_correction(b.getLine(b.selection.
|
512
|
+
line = self.consoleView.line_correction(b.getLine(b.selection.actual_start_row))
|
526
513
|
|
527
|
-
start = max(0, b.selection.
|
528
|
-
end = min(len(line), b.selection.
|
514
|
+
start = max(0, b.selection.actual_start_col)
|
515
|
+
end = min(len(line) + 1, b.selection.actual_end_col)
|
529
516
|
line_plain = Session.PLAIN_TEXT_REGX.sub("", line).replace("\r", "").replace("\x00", "")
|
530
517
|
selection = line_plain[start:end]
|
531
518
|
self.app.clipboard.set_text(selection)
|
@@ -535,7 +522,7 @@ class PyMudApp:
|
|
535
522
|
else:
|
536
523
|
# 多行只认行
|
537
524
|
lines = []
|
538
|
-
for row in range(b.selection.
|
525
|
+
for row in range(b.selection.actual_start_row, b.selection.actual_end_row + 1):
|
539
526
|
line = b.getLine(row)
|
540
527
|
line_plain = Session.PLAIN_TEXT_REGX.sub("", line).replace("\r", "").replace("\x00", "")
|
541
528
|
lines.append(line_plain)
|
@@ -545,9 +532,10 @@ class PyMudApp:
|
|
545
532
|
|
546
533
|
else:
|
547
534
|
# RAW模式,直接复制原始内容
|
548
|
-
if b.selection.start_row == b.selection.end_row:
|
535
|
+
#if b.selection.start_row == b.selection.end_row:
|
536
|
+
if b.selection.rows == 1:
|
549
537
|
# 单行情况
|
550
|
-
line = b.getLine(b.selection.
|
538
|
+
line = b.getLine(b.selection.actual_start_row)
|
551
539
|
self.app.clipboard.set_text(line)
|
552
540
|
self.set_status(Settings.gettext("msg_copy", line))
|
553
541
|
if self.current_session:
|
@@ -556,7 +544,7 @@ class PyMudApp:
|
|
556
544
|
else:
|
557
545
|
# 多行只认行
|
558
546
|
lines = []
|
559
|
-
for row in range(b.selection.
|
547
|
+
for row in range(b.selection.actual_start_row, b.selection.actual_end_row + 1):
|
560
548
|
line = b.getLine(row)
|
561
549
|
lines.append(line)
|
562
550
|
copy_raw_text = "\n".join(lines)
|
@@ -924,7 +912,14 @@ class PyMudApp:
|
|
924
912
|
if not self._mouse_support:
|
925
913
|
mouse_support = Settings.gettext("status_mouseinh") + " "
|
926
914
|
|
915
|
+
mouse = "0, 0"
|
916
|
+
|
927
917
|
if self.current_session:
|
918
|
+
buffer = self.current_session.buffer
|
919
|
+
if buffer:
|
920
|
+
position = buffer.mouse_point
|
921
|
+
mouse = f"{position.y}, {position.x}"
|
922
|
+
|
928
923
|
if self.current_session._ignore:
|
929
924
|
tri_status = Settings.gettext("status_ignore") + " "
|
930
925
|
|
pymud/session.py
CHANGED
@@ -3,7 +3,7 @@ from pathlib import Path
|
|
3
3
|
from collections.abc import Iterable
|
4
4
|
from collections import OrderedDict
|
5
5
|
from prompt_toolkit.utils import get_cwidth
|
6
|
-
from wcwidth import wcswidth
|
6
|
+
from wcwidth import wcswidth
|
7
7
|
from typing import Union, Optional, Any, List, Tuple, Dict, Type
|
8
8
|
from .logger import Logger
|
9
9
|
from .extras import DotDict, SessionBuffer
|
@@ -11,7 +11,7 @@ from .protocol import MudClientProtocol
|
|
11
11
|
from .modules import ModuleInfo, Plugin
|
12
12
|
from .objects import BaseObject, Trigger, Alias, Command, Timer, SimpleAlias, SimpleTrigger, SimpleTimer, GMCPTrigger, CodeBlock, CodeLine
|
13
13
|
from .settings import Settings
|
14
|
-
from .decorators import exception
|
14
|
+
from .decorators import exception
|
15
15
|
|
16
16
|
class Session:
|
17
17
|
"""
|
pymud/settings.py
CHANGED
@@ -15,7 +15,7 @@ class Settings:
|
|
15
15
|
"APP 简要描述"
|
16
16
|
__version__ = importlib.metadata.version("pymud")
|
17
17
|
"APP 当前版本"
|
18
|
-
__release__ = "2025-
|
18
|
+
__release__ = "2025-06-08"
|
19
19
|
"APP 当前版本发布日期"
|
20
20
|
__author__ = "本牛(newstart)@北侠"
|
21
21
|
"APP 作者"
|
@@ -58,7 +58,7 @@ class Settings:
|
|
58
58
|
"naws_width" : 150, # 客户端NAWS宽度
|
59
59
|
"naws_height" : 40, # 客户端NAWS高度
|
60
60
|
"newline" : "\n", # 客户端换行符
|
61
|
-
"tabstop" :
|
61
|
+
"tabstop" : 8, # 制表符改成空格
|
62
62
|
"seperator" : ";", # 多个命令分隔符(默认;)
|
63
63
|
"appcmdflag" : "#", # app命令标记(默认#)
|
64
64
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pymud
|
3
|
-
Version: 0.21.
|
3
|
+
Version: 0.21.4
|
4
4
|
Summary: a MUD Client written in Python
|
5
5
|
Author-email: "newstart@pkuxkx" <crapex@hotmail.com>
|
6
6
|
Maintainer-email: "newstart@pkuxkx" <crapex@hotmail.com>
|
@@ -66,6 +66,14 @@ Dynamic: license-file
|
|
66
66
|
|
67
67
|
## 版本更新信息
|
68
68
|
|
69
|
+
### 0.21.4 (2025-06-08)
|
70
|
+
|
71
|
+
+ 问题修复: 修复了在多行选择碰到空行时,会导致从头开始全选的问题。
|
72
|
+
+ 问题修复: 修复了从后往前选择时,若再往后选择,会导致起始位置错误的问题。
|
73
|
+
+ 问题修复: 修复了纯文本行单行部分复制时,最后一个字符无法被选中和复制的问题。
|
74
|
+
+ 问题修复: 修复了美化模式下,当服务器使用tab对齐在本地显示中无法对齐的问题。为配合对齐,默认tabstop已修改为8。
|
75
|
+
+ 功能调整: 当上下分屏显示时,上半屏也能显示到最后一行,而不是仅显示到分屏处位置。
|
76
|
+
|
69
77
|
### 0.21.3 (2025-06-02)
|
70
78
|
|
71
79
|
+ 问题修复: 修复了当缓存行数超过规定值时,由于代码错误导致清屏的问题。
|
@@ -0,0 +1,23 @@
|
|
1
|
+
pymud/__init__.py,sha256=oeHz0NM7_DwChCY8f_vQ_fBq0e_HoTd0cahCFwaavWE,806
|
2
|
+
pymud/__main__.py,sha256=lIOBiJmi8X-EWXVIx_OoxSgUZ0FYKlZI8hXVnLUYTJQ,61
|
3
|
+
pymud/decorators.py,sha256=rNuDaKk65Cwc9K6t0-BpqNUORs8-8X5Xsv6YaLQ7hc4,9839
|
4
|
+
pymud/dialogs.py,sha256=1xo5NJjch-u7RSRcclhvUE4gi8POgiZWK84lNx_HJbs,6891
|
5
|
+
pymud/extras.py,sha256=cAN20jVWhPfnQoXmMyPPzESR-rddgc89nxkJ_U_HlI4,37916
|
6
|
+
pymud/i18n.py,sha256=qLgvrmYhVfkTHKpbBR-LfYMOrGgi0skHrelbsj7ItbE,3034
|
7
|
+
pymud/logger.py,sha256=F2LBUogdzv2WXHo10CNorDh2VleAX1Wbwmxc3zznHlM,5823
|
8
|
+
pymud/main.py,sha256=zaSjNhpbX3FMulKg-UNFrdiIJO8sOmmrUQrkPOalB-4,10224
|
9
|
+
pymud/modules.py,sha256=CsOqY1c59CrejltCS4wf7QqdCr5k_ghel8AUqlKVGIw,11873
|
10
|
+
pymud/objects.py,sha256=NlKAQnV6v9lSkz94zmgb513HPxskY8-tXnOdrYhuktc,38629
|
11
|
+
pymud/pkuxkx.py,sha256=qDVry-Vd6MNui0NKWZFT52IpmP1sKS5Dz74EDY4tVGQ,14740
|
12
|
+
pymud/protocol.py,sha256=noptJs6K0L9qM8VZIeP65H4k9FPLGJqxvm3qY2iAwvI,48315
|
13
|
+
pymud/pymud.py,sha256=SrPGSls1QqrfSzctNpHV1gt_-M9WpOWi5cGH2VF8W6w,53483
|
14
|
+
pymud/session.py,sha256=sTswAPEl5GWcxzYmgovG8lOlflNTd5k8ggW6zJ6vcMY,154690
|
15
|
+
pymud/settings.py,sha256=V4wHKP2UjmX_l2bKJoUJSfNbH7vs3GZlN4u-1tRFbxA,7697
|
16
|
+
pymud/lang/i18n_chs.py,sha256=2cyaHHLwpYEBBwuQXyRTxa1opX53fTv1f8_QDQeGlC0,16836
|
17
|
+
pymud/lang/i18n_eng.py,sha256=jcPz6Y5UuxJBQLY_e8UnEF3GYTlnAD44C14Oj7sK-QI,45935
|
18
|
+
pymud-0.21.4.dist-info/licenses/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
19
|
+
pymud-0.21.4.dist-info/METADATA,sha256=9A6Gmy-P_VeREtJ1br-nqqEtLl0Tvi2hZ3HMAl8WhDg,46531
|
20
|
+
pymud-0.21.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
21
|
+
pymud-0.21.4.dist-info/entry_points.txt,sha256=diPUOtTkhgC1hVny7Cdg4aRhaHSynMQoraE7ZhJxUcw,37
|
22
|
+
pymud-0.21.4.dist-info/top_level.txt,sha256=8Gp1eXjxixXjqhhti6tLCspV_8s9sNV3z5Em2_KRhD4,6
|
23
|
+
pymud-0.21.4.dist-info/RECORD,,
|
@@ -1,23 +0,0 @@
|
|
1
|
-
pymud/__init__.py,sha256=oeHz0NM7_DwChCY8f_vQ_fBq0e_HoTd0cahCFwaavWE,806
|
2
|
-
pymud/__main__.py,sha256=lIOBiJmi8X-EWXVIx_OoxSgUZ0FYKlZI8hXVnLUYTJQ,61
|
3
|
-
pymud/decorators.py,sha256=XaxcZqHw4s44lC2EAgB5kZmbNvJnHGmpZnoW75tUeNY,9844
|
4
|
-
pymud/dialogs.py,sha256=4kHycr47UgKQUHGX-KMZvERuWViPjT4hNrGhbe4j-NU,7056
|
5
|
-
pymud/extras.py,sha256=9jHJALSaydS-EMqDN4pHlkCcxii1uTz0Z3N1yuvcGlM,36778
|
6
|
-
pymud/i18n.py,sha256=qLgvrmYhVfkTHKpbBR-LfYMOrGgi0skHrelbsj7ItbE,3034
|
7
|
-
pymud/logger.py,sha256=WCsfXVkgl63qdq1RQEDJBnM7U0S6u8TeORFSMhcoydI,5840
|
8
|
-
pymud/main.py,sha256=zaSjNhpbX3FMulKg-UNFrdiIJO8sOmmrUQrkPOalB-4,10224
|
9
|
-
pymud/modules.py,sha256=DoCregng5iAj_Hq_yUvRPreRTv2Ehb6sV6_4jfdbsik,11912
|
10
|
-
pymud/objects.py,sha256=Z77KHbg06jIx9cIEiyHkWI5i3but4PFeZS_m2WHsFrs,38729
|
11
|
-
pymud/pkuxkx.py,sha256=qDVry-Vd6MNui0NKWZFT52IpmP1sKS5Dz74EDY4tVGQ,14740
|
12
|
-
pymud/protocol.py,sha256=KNKJYj9HFRoUy-jigNfhiQdDOM_kRSJE17QFpBarQTg,48335
|
13
|
-
pymud/pymud.py,sha256=40hn5XyMH9mtjimx_zG7N2M6fAGciee1izO08jsfFzQ,53486
|
14
|
-
pymud/session.py,sha256=vzOIyc1F8PVP1XadcGt-n7XOoiawJzYsIEBe0FU5oKY,154716
|
15
|
-
pymud/settings.py,sha256=S2sBEM7YtaDOVu3UpGfHBaU7zSB3Zhs7w-Z7PtdS0WQ,7697
|
16
|
-
pymud/lang/i18n_chs.py,sha256=2cyaHHLwpYEBBwuQXyRTxa1opX53fTv1f8_QDQeGlC0,16836
|
17
|
-
pymud/lang/i18n_eng.py,sha256=jcPz6Y5UuxJBQLY_e8UnEF3GYTlnAD44C14Oj7sK-QI,45935
|
18
|
-
pymud-0.21.3.post1.dist-info/licenses/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
19
|
-
pymud-0.21.3.post1.dist-info/METADATA,sha256=cfW1c3rEM8IdImBWtB6um8f_t4qUKcEPZJtYNl-woqY,45905
|
20
|
-
pymud-0.21.3.post1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
21
|
-
pymud-0.21.3.post1.dist-info/entry_points.txt,sha256=diPUOtTkhgC1hVny7Cdg4aRhaHSynMQoraE7ZhJxUcw,37
|
22
|
-
pymud-0.21.3.post1.dist-info/top_level.txt,sha256=8Gp1eXjxixXjqhhti6tLCspV_8s9sNV3z5Em2_KRhD4,6
|
23
|
-
pymud-0.21.3.post1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|