pymud 0.20.1.post1__py3-none-any.whl → 0.20.2__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/extras.py CHANGED
@@ -40,6 +40,8 @@ from prompt_toolkit.layout.controls import (
40
40
  )
41
41
  from prompt_toolkit.layout.processors import (
42
42
  Processor,
43
+ TransformationInput,
44
+ Transformation
43
45
  )
44
46
  from prompt_toolkit.lexers import Lexer
45
47
  from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
@@ -64,10 +66,11 @@ class MudFormatProcessor(Processor):
64
66
  self.FULL_BLOCKS = set("▂▃▅▆▇▄█")
65
67
  self.SINGLE_LINES = set("┌└├┬┼┴╭╰─")
66
68
  self.DOUBLE_LINES = set("╔╚╠╦╪╩═")
67
- self.START_COLOR_REGX = re.compile(r"^\[[\d;]+m")
68
- self.COLOR_REGX = re.compile(r"\[[\d;]+m")
69
+ self.ALL_COLOR_REGX = re.compile(r"(?:\[[\d;]+m)+")
70
+ self.AVAI_COLOR_REGX = re.compile(r"(?:\[[\d;]+m)+(?!$)")
69
71
  self._color_start = ""
70
72
  self._color_correction = False
73
+ self._color_line_index = 0
71
74
 
72
75
  def width_correction(self, line: str) -> str:
73
76
  new_str = []
@@ -91,48 +94,52 @@ class MudFormatProcessor(Processor):
91
94
  def tab_correction(self, line: str):
92
95
  return line.replace("\t", " " * Settings.client["tabstop"])
93
96
 
94
- def color_correction(self, line: str):
95
- # 注:发现processer处理并非自上而下逐行处理的,因此不能使用这种颜色校正方式。
96
- if self._color_correction:
97
- other = self.COLOR_REGX.findall(line)
98
-
99
- line = f"{self._color_start}{line}"
100
- logging.debug(f"已校正增加颜色标志 {self._color_start}: {line}")
101
-
102
- if other:
103
- self._color_correction = False
104
- self._color_start = ""
105
- logging.debug(f"颜色校正结束: {line}")
106
- else:
107
- color = self.START_COLOR_REGX.findall(line)
108
- if color:
109
- other = self.COLOR_REGX.findall(line)
110
- if len(other) == 1:
111
- self._color_correction = True
112
- self._color_start = color[0]
113
- logging.debug(f"获取到一个颜色开头 {color[0]}: {line}")
114
-
115
- return line
116
-
117
97
  def line_correction(self, line: str):
118
98
  # 处理\r符号(^M)
119
99
  line = self.return_correction(line)
120
100
  # 处理Tab(\r)符号(^I)
121
101
  line = self.tab_correction(line)
122
- # 处理颜色跨行问题。发现processer处理并非自上而下逐行处理的,因此不能使用这种颜色校正方式。
123
- # line = self.color_correction(line)
102
+
124
103
  # 美化(解决中文英文在Console中不对齐的问题)
125
104
  if Settings.client["beautify"]:
126
105
  line = self.width_correction(line)
127
106
 
128
107
  return line
129
108
 
130
- def apply_transformation(self, transformation_input):
109
+ def apply_transformation(self, transformation_input: TransformationInput):
131
110
  # 准备(先还原为str)
132
111
  line = fragment_list_to_text(transformation_input.fragments)
112
+
113
+ # 颜色校正
114
+ thislinecolors = len(self.AVAI_COLOR_REGX.findall(line))
115
+ if thislinecolors == 0:
116
+ lineno = transformation_input.lineno - 1
117
+ while lineno > 0:
118
+ lastline = transformation_input.document.lines[lineno]
119
+ allcolors = self.ALL_COLOR_REGX.findall(lastline)
120
+
121
+ if len(allcolors) == 0:
122
+ lineno = lineno - 1
123
+
124
+ elif len(allcolors) == 1:
125
+ colors = self.AVAI_COLOR_REGX.findall(lastline)
126
+
127
+ if len(colors) == 1:
128
+ line = f"{colors[0]}{line}"
129
+ break
130
+
131
+ else:
132
+ break
133
+
134
+ else:
135
+ break
136
+
137
+ # 其他校正
133
138
  line = self.line_correction(line)
139
+
134
140
  # 处理ANSI标记(生成FormmatedText)
135
141
  fragments = to_formatted_text(ANSI(line))
142
+
136
143
  return Transformation(fragments)
137
144
 
138
145
  class SessionBuffer(Buffer):
pymud/logger.py CHANGED
@@ -16,7 +16,7 @@ class Logger:
16
16
  :param raw: 记录带ANSI标记的原始内容,还是记录纯文本内容,默认为True,即记录带ANSI标记的原始内容。
17
17
  """
18
18
 
19
- _esc_regx = re.compile(r"\x1b\[[\d;]+[abcdmz]", flags = re.IGNORECASE)
19
+ # _esc_regx = re.compile(r"\x1b\[[\d;]+[abcdmz]", flags = re.IGNORECASE)
20
20
 
21
21
  def __init__(self, name, mode = 'a', encoding = "utf-8", errors = "ignore", raw = False):
22
22
  self._name = name
@@ -147,7 +147,9 @@ class Logger:
147
147
  newline = True
148
148
 
149
149
  if not self._raw:
150
- data = self._esc_regx.sub("", data)
150
+ from .session import Session
151
+ data = Session.PLAIN_TEXT_REGX.sub("", data)
152
+ #data = self._esc_regx.sub("", data)
151
153
 
152
154
  self._stream.write(data)
153
155
 
pymud/objects.py CHANGED
@@ -609,7 +609,7 @@ class MatchObject(BaseObject):
609
609
 
610
610
  if state.result == self.SUCCESS:
611
611
  self.event.set()
612
-
612
+
613
613
  self.state = state
614
614
  return state
615
615
 
pymud/protocol.py CHANGED
@@ -475,7 +475,7 @@ class MudClientProtocol(Protocol):
475
475
  self._mtts_index += 1
476
476
  self.log.debug('回复第二次MTTS子协商: IAC SB TTYPE IS "XTERM" IAC SE')
477
477
  elif self._mtts_index == 2:
478
- # 第三次收到,回复客户端终端支持的标准功能,此处默认设置775(支持ANSI, VT100, UTF-8, TRUECOLOR, MNES),后续功能完善后再更改
478
+ # 第三次收到,回复客户端终端支持的标准功能,此处默认设置783(支持ANSI, VT100, UTF-8, 256 COLORS, TRUECOLOR, MNES),后续功能完善后再更改
479
479
  # 根据完善的终端模拟功能,修改终端标准
480
480
  # 1 "ANSI" Client supports all common ANSI color codes.
481
481
  # 2 "VT100" Client supports all common VT100 codes.
@@ -489,9 +489,9 @@ class MudClientProtocol(Protocol):
489
489
  # 512 "MNES" Client supports the Mud New Environment Standard for information exchange.
490
490
  # 1024 "MSLP" Client supports the Mud Server Link Protocol for clickable link handling.
491
491
  # 2048 "SSL" Client supports SSL for data encryption, preferably TLS 1.3 or higher.
492
- self.session.write(IAC + SB + TTYPE + IS + b"MTTS 775" + IAC + SE)
492
+ self.session.write(IAC + SB + TTYPE + IS + b"MTTS 783" + IAC + SE)
493
493
  self._mtts_index += 1
494
- self.log.debug('回复第三次MTTS子协商: IAC SB TTYPE IS "MTTS 775" IAC SE')
494
+ self.log.debug('回复第三次MTTS子协商: IAC SB TTYPE IS "MTTS 783" IAC SE')
495
495
  else:
496
496
  self.log.warning(f'收到第{self._mtts_index + 1}次(正常为3次)的MTTS子协商, 将不予应答')
497
497
  else:
pymud/pymud.py CHANGED
@@ -229,7 +229,8 @@ class PyMudApp:
229
229
  content = HSplit(
230
230
  [
231
231
  self.console,
232
- Window(char = "—", height = 1),
232
+ ConditionalContainer(content = Window(char = "—", height = 1), filter = Settings.client["status_divider"]),
233
+ #Window(char = "—", height = 1),
233
234
  Window(content = self.statusView, height = Settings.client["status_height"]),
234
235
  ]
235
236
  ),
@@ -241,7 +242,7 @@ class PyMudApp:
241
242
  content = VSplit(
242
243
  [
243
244
  self.console,
244
- Window(char = "|", width = 1),
245
+ ConditionalContainer(content = Window(char = "|", width = 1), filter = Settings.client["status_divider"]),
245
246
  Window(content = self.statusView, width = Settings.client["status_width"]),
246
247
  ]
247
248
  ),
@@ -311,12 +312,14 @@ class PyMudApp:
311
312
  MenuItem(Settings.text["closesession"], handler = self.act_close_session),
312
313
  MenuItem(Settings.text["autoreconnect"], handler = self.act_autoreconnect),
313
314
  MenuItem("-", disabled=True),
314
- MenuItem(Settings.text["echoinput"], handler = self.act_echoinput),
315
315
  MenuItem(Settings.text["nosplit"], handler = self.act_nosplit),
316
+ MenuItem(Settings.text["echoinput"], handler = self.act_echoinput),
317
+ MenuItem(Settings.text["beautify"], handler = self.act_beautify),
316
318
  MenuItem(Settings.text["copy"], handler = self.act_copy),
317
319
  MenuItem(Settings.text["copyraw"], handler = self.act_copyraw),
318
320
  MenuItem(Settings.text["clearsession"], handler = self.act_clearsession),
319
321
  MenuItem("-", disabled=True),
322
+
320
323
  MenuItem(Settings.text["reloadconfig"], handler = self.act_reload),
321
324
  ]
322
325
  ),
@@ -484,6 +487,7 @@ class PyMudApp:
484
487
 
485
488
  ``注意: 复制的内容仅存在于运行环境的剪贴板中。若使用ssh远程,该复制命令不能访问本地剪贴板。``
486
489
  """
490
+
487
491
  b = self.consoleView.buffer
488
492
  if b.selection_state:
489
493
  cur1, cur2 = b.selection_state.original_cursor_position, b.document.cursor_position
@@ -501,7 +505,8 @@ class PyMudApp:
501
505
  line = self.mudFormatProc.line_correction(b.document.current_line)
502
506
  start = max(0, scol)
503
507
  end = min(ecol, len(line))
504
- line_plain = re.sub(r"\x1b\[[\d;]+[abcdmz]", "", line, flags = re.IGNORECASE).replace("\r", "").replace("\x00", "")
508
+ #line_plain = re.sub(r"\x1b\[[0-9;]*[a-zA-Z]", "", line, flags = re.IGNORECASE).replace("\r", "").replace("\x00", "")
509
+ line_plain = Session.PLAIN_TEXT_REGX.sub("", line).replace("\r", "").replace("\x00", "")
505
510
  #line_plain = re.sub("\x1b\\[[^mz]+[mz]", "", line).replace("\r", "").replace("\x00", "")
506
511
  selection = line_plain[start:end]
507
512
  self.app.clipboard.set_text(selection)
@@ -513,7 +518,8 @@ class PyMudApp:
513
518
  lines = []
514
519
  for row in range(srow, erow + 1):
515
520
  line = b.document.lines[row]
516
- line_plain = re.sub(r"\x1b\[[\d;]+[abcdmz]", "", line, flags = re.IGNORECASE).replace("\r", "").replace("\x00", "")
521
+ #line_plain = re.sub(r"\x1b\[[0-9;]*[a-zA-Z]", "", line, flags = re.IGNORECASE).replace("\r", "").replace("\x00", "")
522
+ line_plain = Session.PLAIN_TEXT_REGX.sub("", line).replace("\r", "").replace("\x00", "")
517
523
  lines.append(line_plain)
518
524
 
519
525
  self.app.clipboard.set_text("\n".join(lines))
@@ -733,6 +739,13 @@ class PyMudApp:
733
739
  new_sess = list(self.sessions.keys())[0]
734
740
  self.activate_session(new_sess)
735
741
 
742
+ def act_beautify(self):
743
+ "菜单: 打开/关闭美化显示"
744
+ val = not Settings.client["beautify"]
745
+ Settings.client["beautify"] = val
746
+ if self.current_session:
747
+ self.current_session.info(f"显示美化已{'打开' if val else '关闭'}!")
748
+
736
749
  def act_echoinput(self):
737
750
  "菜单: 显示/隐藏输入指令"
738
751
  val = not Settings.client["echo_input"]
@@ -879,7 +892,10 @@ class PyMudApp:
879
892
 
880
893
  def get_statusbar_right_text(self):
881
894
  "状态栏右侧内容"
882
- con_str, mouse_support, tri_status = "", "", ""
895
+ con_str, mouse_support, tri_status, beautify = "", "", "", ""
896
+ if not Settings.client["beautify"]:
897
+ beautify = "美化已关闭 "
898
+
883
899
  if not self._mouse_support:
884
900
  mouse_support = "鼠标已禁用 "
885
901
 
@@ -909,13 +925,17 @@ class PyMudApp:
909
925
  else:
910
926
  con_str = "已连接:{:.0f}秒".format(sec)
911
927
 
912
- return "{}{}{} {} {} ".format(mouse_support, tri_status, con_str, Settings.__appname__, Settings.__version__)
928
+ return "{}{}{}{} {} {} ".format(beautify, mouse_support, tri_status, con_str, Settings.__appname__, Settings.__version__)
913
929
 
914
930
  def get_statuswindow_text(self):
915
931
  "状态窗口: status_maker 的内容"
916
932
  text = ""
917
- if self.current_session:
918
- text = self.current_session.get_status()
933
+
934
+ try:
935
+ if self.current_session:
936
+ text = self.current_session.get_status()
937
+ except Exception as e:
938
+ text = f"{e}"
919
939
 
920
940
  return text
921
941
 
pymud/session.py CHANGED
@@ -1,4 +1,4 @@
1
- import asyncio, logging, re, math, os, pickle, datetime, importlib, importlib.util, sysconfig, time
1
+ import asyncio, logging, re, math, os, pickle, datetime, importlib, importlib.util, sysconfig, time, dataclasses
2
2
  from collections.abc import Iterable
3
3
  from collections import OrderedDict
4
4
  import logging, queue
@@ -30,7 +30,8 @@ class Session:
30
30
 
31
31
  """
32
32
  #_esc_regx = re.compile("\x1b\\[[^mz]+[mz]")
33
- _esc_regx = re.compile(r"\x1b\[[\d;]+[abcdmz]", flags = re.IGNORECASE)
33
+ #_esc_regx = re.compile(r"\x1b\[[\d;]+[abcdmz]", flags = re.IGNORECASE)
34
+ PLAIN_TEXT_REGX = re.compile("\x1b\\[[0-9;]*[a-zA-Z]", flags = re.IGNORECASE | re.ASCII)
34
35
 
35
36
  _sys_commands = (
36
37
  "help",
@@ -108,7 +109,10 @@ class Session:
108
109
  self.loop = loop or asyncio.get_running_loop()
109
110
  self.syslog = logging.getLogger("pymud.Session")
110
111
 
111
- self.application = app
112
+ from .pymud import PyMudApp
113
+ if isinstance(app, PyMudApp):
114
+ self.application = app
115
+
112
116
  self.name = name
113
117
  self._transport = None
114
118
  self._protocol = None
@@ -529,7 +533,7 @@ class Session:
529
533
  :return: 经处理后的纯文本字符串
530
534
 
531
535
  """
532
- plainText = self._esc_regx.sub("", rawText)
536
+ plainText = Session.PLAIN_TEXT_REGX.sub("", rawText)
533
537
  if trim_newline:
534
538
  plainText = plainText.rstrip("\n").rstrip("\r")
535
539
 
@@ -1926,6 +1930,154 @@ class Session:
1926
1930
 
1927
1931
  self.disconnect()
1928
1932
 
1933
+ def getMaxLength(self, iter: Iterable):
1934
+ return wcswidth(sorted(iter, key = lambda s: wcswidth(s), reverse = True)[0])
1935
+
1936
+ def splitByPrintableWidth(self, str, printable_length):
1937
+ strlist = []
1938
+ startindex = 0
1939
+ remain = False
1940
+ split_str = ""
1941
+ for idx in range(1, len(str)):
1942
+ remain = True
1943
+ split_str = str[startindex:idx]
1944
+ if wcswidth(split_str) >= printable_length:
1945
+ strlist.append(split_str)
1946
+ startindex = idx
1947
+ remain = False
1948
+
1949
+ if remain:
1950
+ strlist.append(str[startindex:])
1951
+
1952
+ return strlist
1953
+
1954
+ def buildDisplayLines(self, vars: DotDict, title: str):
1955
+ MIN_MARGIN = 4
1956
+ KEY_WIDTH = (self.getMaxLength(vars.keys()) // 4) * 4 + 4
1957
+ VALUE_WIDTH = 20
1958
+ VAR_WIDTH = KEY_WIDTH + 3 + VALUE_WIDTH
1959
+ display_lines = []
1960
+ vars_simple = {}
1961
+ vars_complex = {}
1962
+
1963
+ for k, v in vars.items():
1964
+ if k in ("%line", "%raw", "%copy"):
1965
+ continue
1966
+
1967
+ if dataclasses.is_dataclass(v) or (isinstance(v, Iterable) and not isinstance(v, str)):
1968
+ vars_complex[k] = v
1969
+ else:
1970
+ vars_simple[k] = v
1971
+
1972
+ totalWidth = self.application.get_width() - 2
1973
+
1974
+ # draw title
1975
+ left_margin = (totalWidth - len(title)) // 2
1976
+ right_margin = totalWidth - len(title) - left_margin
1977
+ title_line = "{}{}{}".format("=" * left_margin, title, "=" * right_margin)
1978
+ display_lines.append(title_line)
1979
+
1980
+ # draw simple vars
1981
+ vars_per_line = totalWidth // VAR_WIDTH
1982
+ left_margin = (totalWidth - vars_per_line * VAR_WIDTH) // 2
1983
+ left_margin = min(MIN_MARGIN, left_margin)
1984
+ right_margin = totalWidth - vars_per_line * VAR_WIDTH - left_margin
1985
+ right_margin = min(left_margin, right_margin)
1986
+
1987
+ line = " " * left_margin
1988
+ cursor = left_margin
1989
+ var_count = 0
1990
+
1991
+ var_keys = sorted(vars_simple.keys())
1992
+ for key in var_keys:
1993
+ if len(key) < KEY_WIDTH:
1994
+ name = key.rjust(KEY_WIDTH)
1995
+ else:
1996
+ name = key.rjust(KEY_WIDTH + VAR_WIDTH)
1997
+
1998
+ value_dis = vars_simple[key].__repr__()
1999
+ var_display = "{0} = {1}".format(name, value_dis)
2000
+
2001
+ if (cursor + wcswidth(var_display) > totalWidth) or (var_count >= vars_per_line):
2002
+ display_lines.append(line)
2003
+
2004
+ line = " " * left_margin
2005
+ cursor = left_margin
2006
+ var_count = 0
2007
+
2008
+ line += var_display
2009
+ cursor += wcswidth(var_display)
2010
+ var_count += 1
2011
+
2012
+ # 下一处判定
2013
+ for x in range(vars_per_line, 0, -1):
2014
+ next_start = left_margin + (vars_per_line - x) * VAR_WIDTH
2015
+ if cursor < next_start:
2016
+ line += " " * (next_start - cursor)
2017
+ cursor = next_start
2018
+
2019
+ if (vars_per_line - x) > var_count:
2020
+ var_count = (vars_per_line - x)
2021
+ break
2022
+
2023
+ if cursor > left_margin:
2024
+ display_lines.append(line)
2025
+
2026
+ var_keys = sorted(vars_complex.keys())
2027
+ for key in var_keys:
2028
+ name = key.rjust(KEY_WIDTH)
2029
+ value_dis = vars_complex[key].__repr__()
2030
+ allow_len = totalWidth - left_margin - KEY_WIDTH - 3 - right_margin
2031
+ line = "{0}{1} = ".format(" " * left_margin, name.rjust(KEY_WIDTH))
2032
+ if wcswidth(value_dis) > allow_len:
2033
+ value = vars_complex[key]
2034
+ if isinstance(value, dict):
2035
+ max_len = self.getMaxLength(value.keys())
2036
+ line += '{'
2037
+ display_lines.append(line)
2038
+ line = " " * (left_margin + KEY_WIDTH + 4)
2039
+ for k, v in value.items():
2040
+ subvalue_dis = "{},".format(v.__repr__())
2041
+ allow_len_subvalue = allow_len - max_len - 4
2042
+ if wcswidth(subvalue_dis) > allow_len_subvalue:
2043
+ subvalue_lines = self.splitByPrintableWidth(subvalue_dis, allow_len_subvalue)
2044
+ line += "{0}: ".format(k.ljust(max_len))
2045
+ for subline in subvalue_lines:
2046
+ line += subline
2047
+ display_lines.append(line)
2048
+ line = " " * (left_margin + KEY_WIDTH + 4 + max_len + 2)
2049
+
2050
+ line = " " * (left_margin + KEY_WIDTH + 4)
2051
+ else:
2052
+ val_line = "{0}: {1}".format(k.ljust(max_len), subvalue_dis)
2053
+ line += val_line
2054
+ display_lines.append(line)
2055
+ line = " " * (left_margin + KEY_WIDTH + 4)
2056
+ line = line[:-1] + '}'
2057
+ display_lines.append(line)
2058
+ elif isinstance(value, list):
2059
+ line += '['
2060
+ for v in value:
2061
+ val_line = "{0},".format(v.__repr__())
2062
+ line += val_line
2063
+ display_lines.append(line)
2064
+ line = " " * (left_margin + KEY_WIDTH + 4)
2065
+ line = line[:-1] + ']'
2066
+ display_lines.append(line)
2067
+ else:
2068
+ value_lines = self.splitByPrintableWidth(value_dis, allow_len)
2069
+ for val_line in value_lines:
2070
+ line += val_line
2071
+ display_lines.append(line)
2072
+ line = " " * (left_margin + KEY_WIDTH + 3)
2073
+ else:
2074
+ line = "{0}{1} = {2}".format(" " * left_margin, key.rjust(KEY_WIDTH), vars_complex[key].__repr__())
2075
+ display_lines.append(line)
2076
+
2077
+ display_lines.append("=" * totalWidth)
2078
+
2079
+ return display_lines
2080
+
1929
2081
  def handle_variable(self, code: CodeLine = None, *args, **kwargs):
1930
2082
  '''
1931
2083
  嵌入命令 #variable / #var 的执行函数,操作会话变量。
@@ -1951,62 +2103,20 @@ class Session:
1951
2103
  #args = code.code[2:]
1952
2104
 
1953
2105
  if len(args) == 0:
1954
- vars = self._variables
1955
- vars_simple = {}
1956
- vars_complex = {}
1957
- for k, v in vars.items():
1958
- # 不显示line, raw两个系统变量
1959
- if k in ("%line", "%raw"):
1960
- continue
1961
-
1962
- if isinstance(v, Iterable) and not isinstance(v, str):
1963
- vars_complex[k] = v
1964
- else:
1965
- vars_simple[k] = v
1966
-
1967
- width = self.application.get_width() - 2 # 保留2个字符,防止 > 导致换行
2106
+ lines = self.buildDisplayLines(self._variables, f" VARIABLE LIST IN SESSION {self.name} ")
1968
2107
 
1969
- title = f" VARIABLE LIST IN SESSION {self.name} "
1970
- left = (width - len(title)) // 2
1971
- right = width - len(title) - left
1972
- self.writetobuffer("="*left + title + "="*right, newline = True)
1973
-
1974
- # print vars in simple, 每个变量占40格,一行可以多个变量
1975
- # 这里可以考虑调整一下,默认40, 但如果一个变量值太长,则选择占两个位置
1976
- var_count = len(vars_simple)
1977
- var_per_line = (width - 2) // 40
1978
- lines = math.ceil(var_count / var_per_line)
1979
- left_space = (width - var_per_line * 40) // 2
1980
- if left_space > 4: left_space = 4
1981
-
1982
- var_keys = sorted(vars_simple.keys())
1983
-
1984
- for idx in range(0, lines):
1985
- start = idx * var_per_line
1986
- end = (idx + 1) * var_per_line
1987
- if end > var_count: end = var_count
1988
- self.writetobuffer(" " * left_space)
1989
- line_vars = var_keys[start:end]
1990
- for var in line_vars:
1991
- repr = vars_simple[var].__repr__()
1992
- vwidth = 22 - (wcswidth(repr) - len(repr))
1993
- self.writetobuffer("{0} = {1}".format(var.rjust(20), repr.ljust(vwidth)))
1994
- #self.writetobuffer("{0:>18} = {1:<19}".format(var, vars_simple[var].__repr__()))
1995
-
1996
- self.writetobuffer("", newline = True)
1997
-
1998
- # print vars in complex, 每个变量占1行
1999
- var_keys = sorted(vars_complex.keys())
2000
- for key in var_keys:
2001
- self.writetobuffer(" " * left_space)
2002
- self.writetobuffer("{0:>20} = {1}".format(key, vars_complex[key].__repr__()), newline = True)
2003
-
2004
- self.writetobuffer("="*width, newline = True)
2108
+ for line in lines:
2109
+ self.writetobuffer(line, newline = True)
2005
2110
 
2006
2111
  elif len(args) == 1:
2007
2112
  if args[0] in self._variables.keys():
2008
2113
  obj = self.getVariable(args[0])
2009
- self.info(f"变量{args[0]}值为:{obj}")
2114
+ var_dict = {args[0] : obj}
2115
+ lines = self.buildDisplayLines(var_dict, f" VARIABLE [{args[0]}] IN SESSION {self.name} ")
2116
+
2117
+ for line in lines:
2118
+ self.writetobuffer(line, newline = True)
2119
+
2010
2120
  else:
2011
2121
  self.warning(f"当前session中不存在名称为 {args[0]} 的变量")
2012
2122
 
@@ -2018,6 +2128,7 @@ class Session:
2018
2128
  val = args[1]
2019
2129
 
2020
2130
  self.setVariable(args[0], val)
2131
+ self.info(f"成功设置变量 {args[0]} 值为 {val}")
2021
2132
 
2022
2133
  def handle_global(self, code: CodeLine = None, *args, **kwargs):
2023
2134
  '''
@@ -2043,55 +2154,21 @@ class Session:
2043
2154
  #args = code.code[2:]
2044
2155
 
2045
2156
  if len(args) == 0:
2046
- vars = self.application.globals
2047
- vars_simple = {}
2048
- vars_complex = {}
2049
- for k, v in vars.items():
2050
- if isinstance(v, Iterable) and not isinstance(v, str):
2051
- vars_complex[k] = v
2052
- else:
2053
- vars_simple[k] = v
2054
-
2055
- width = self.application.get_width() - 2 # 保留2个字符,防止 > 导致换行
2056
-
2057
- title = f" GLOBAL VARIABLES LIST "
2058
- left = (width - len(title)) // 2
2059
- right = width - len(title) - left
2060
- self.writetobuffer("="*left + title + "="*right, newline = True)
2157
+ lines = self.buildDisplayLines(self.application.globals, f" GLOBAL VARIABLES LIST ")
2061
2158
 
2062
- # print vars in simple, 每个变量占40格,一行可以多个变量
2063
- var_count = len(vars_simple)
2064
- var_per_line = (width - 2) // 40
2065
- lines = math.ceil(var_count / var_per_line)
2066
- left_space = (width - var_per_line * 40) // 2
2067
- if left_space > 4: left_space = 4
2068
-
2069
- var_keys = sorted(vars_simple.keys())
2070
-
2071
- for idx in range(0, lines):
2072
- start = idx * var_per_line
2073
- end = (idx + 1) * var_per_line
2074
- if end > var_count: end = var_count
2075
- self.writetobuffer(" " * left_space)
2076
- line_vars = var_keys[start:end]
2077
- for var in line_vars:
2078
- repr = vars_simple[var].__repr__()
2079
- vwidth = 22 - (wcswidth(repr) - len(repr))
2080
- self.writetobuffer("{0} = {1}".format(var.rjust(20), repr.ljust(vwidth)))
2081
-
2082
- self.writetobuffer("", newline = True)
2083
-
2084
- # print vars in complex, 每个变量占1行
2085
- for k, v in vars_complex.items():
2086
- self.writetobuffer(" " * left_space)
2087
- self.writetobuffer("{0:>20} = {1}".format(k, v.__repr__()), newline = True)
2088
-
2089
- self.writetobuffer("="*width, newline = True)
2159
+ for line in lines:
2160
+ self.writetobuffer(line, newline = True)
2090
2161
 
2091
2162
  elif len(args) == 1:
2092
2163
  var = args[0]
2093
2164
  if var in self.application.globals.keys():
2094
- self.info("{0:>20} = {1:<22}".format(var, self.application.get_globals(var).__repr__()), "全局变量")
2165
+ # self.info("{0:>20} = {1:<22}".format(var, self.application.get_globals(var).__repr__()), "全局变量")
2166
+
2167
+ var_dict = {var : self.application.get_globals(var)}
2168
+ lines = self.buildDisplayLines(var_dict, f" GLOBAL VARIABLE [{var}] ")
2169
+
2170
+ for line in lines:
2171
+ self.writetobuffer(line, newline = True)
2095
2172
  else:
2096
2173
  self.info("全局空间不存在名称为 {} 的变量".format(var), "全局变量")
2097
2174
 
@@ -2102,6 +2179,7 @@ class Session:
2102
2179
  except:
2103
2180
  val = args[1]
2104
2181
  self.application.set_globals(args[0], val)
2182
+ self.info(f"成功设置全局变量 {args[0]} 值为 {val}")
2105
2183
 
2106
2184
  def _handle_objs(self, name: str, objs: dict, *args):
2107
2185
  if len(args) == 0:
@@ -2932,14 +3010,18 @@ class Session:
2932
3010
  triggered_enabled += 1
2933
3011
  if not block:
2934
3012
  triggered += 1
2935
- info_enabled.append(f" {Settings.INFO_STYLE}{tri.__detailed__()} 正常触发。{Settings.CLR_STYLE}")
2936
- info_enabled.append(f" {Settings.INFO_STYLE}捕获:{state.wildcards}{Settings.CLR_STYLE}")
3013
+ # info_enabled.append(f" {Settings.INFO_STYLE}{tri.__detailed__()} 正常触发。{Settings.CLR_STYLE}")
3014
+ # info_enabled.append(f" {Settings.INFO_STYLE}捕获:{state.wildcards}{Settings.CLR_STYLE}")
3015
+ info_enabled.append(f" {tri.__detailed__()} 正常触发。")
3016
+ info_enabled.append(f" 捕获:{state.wildcards}")
2937
3017
 
2938
3018
  if not tri.keepEval: # 非持续匹配的trigger,匹配成功后停止检测后续Trigger
2939
- info_enabled.append(f" {Settings.WARN_STYLE}该触发器未开启keepEval, 会阻止后续触发器。{Settings.CLR_STYLE}")
3019
+ info_enabled.append(f" {Settings.WARN_STYLE}该触发器未开启keepEval, 会阻止后续触发器。{Settings.CLR_STYLE}")
3020
+ #info_enabled.append(f" 该触发器未开启keepEval, 会阻止后续触发器。")
2940
3021
  block = True
2941
3022
  else:
2942
- info_enabled.append(f" {Settings.WARN_STYLE}{tri.__detailed__()} 可以触发,但由于优先级与keepEval设定,触发器不会触发。{Settings.CLR_STYLE}")
3023
+ info_enabled.append(f" {Settings.WARN_STYLE}{tri.__detailed__()} 可以触发,但由于优先级与keepEval设定,触发器不会触发。{Settings.CLR_STYLE}")
3024
+ #info_enabled.append(f" {tri.__detailed__()} 可以触发,但由于优先级与keepEval设定,触发器不会触发。")
2943
3025
 
2944
3026
 
2945
3027
  for tri in tris_disabled:
@@ -2950,35 +3032,38 @@ class Session:
2950
3032
 
2951
3033
  if state.result == Trigger.SUCCESS:
2952
3034
  triggered_disabled += 1
2953
- info_disabled.append(f" {Settings.INFO_STYLE}{tri.__detailed__()} 可以匹配触发。{Settings.CLR_STYLE}")
3035
+ # info_disabled.append(f" {Settings.INFO_STYLE}{tri.__detailed__()} 可以匹配触发。{Settings.CLR_STYLE}")
3036
+ info_disabled.append(f" {tri.__detailed__()} 可以匹配触发。")
2954
3037
 
2955
3038
  if triggered_enabled + triggered_disabled == 0:
2956
3039
  info_all.append("")
2957
3040
 
2958
3041
  if triggered_enabled == 0:
2959
- info_enabled.insert(0, f"使能的触发器中,没有可以触发的。")
3042
+ info_enabled.insert(0, f"{Settings.INFO_STYLE} 使能的触发器中,没有可以触发的。")
2960
3043
  elif triggered < triggered_enabled:
2961
- info_enabled.insert(0, f"使能的触发器中,共有 {triggered_enabled} 个可以触发,实际触发 {triggered} 个,另有 {triggered_enabled - triggered} 个由于 keepEval 原因实际不会触发。")
3044
+ info_enabled.insert(0, f"{Settings.INFO_STYLE} 使能的触发器中,共有 {triggered_enabled} 个可以触发,实际触发 {triggered} 个,另有 {triggered_enabled - triggered} 个由于 keepEval 原因实际不会触发。")
2962
3045
  else:
2963
- info_enabled.insert(0, f"使能的触发器中,共有 {triggered_enabled} 个全部可以被正常触发。")
3046
+ info_enabled.insert(0, f"{Settings.INFO_STYLE} 使能的触发器中,共有 {triggered_enabled} 个全部可以被正常触发。")
2964
3047
 
2965
3048
  if triggered_disabled > 0:
2966
- info_disabled.insert(0, f"未使能的触发器中,共有 {triggered_disabled} 个可以匹配。")
3049
+ info_disabled.insert(0, f"{Settings.INFO_STYLE} 未使能的触发器中,共有 {triggered_disabled} 个可以匹配。")
2967
3050
  else:
2968
- info_disabled.insert(0, f"未使能触发器,没有可以匹配的。")
2969
-
3051
+ info_disabled.insert(0, f"{Settings.INFO_STYLE} 未使能触发器,没有可以匹配的。")
3052
+
3053
+ info_all.append("")
2970
3054
  if triggered_enabled + triggered_disabled == 0:
2971
- info_all.append(f"PYMUD 触发器测试: {'响应模式' if docallback else '测试模式'}")
3055
+ #info_all.append(f"PYMUD 触发器测试: {'响应模式' if docallback else '测试模式'}")
2972
3056
  info_all.append(f" 测试内容: {line}")
2973
3057
  info_all.append(f" 测试结果: 没有可以匹配的触发器。")
2974
3058
  else:
2975
- info_all.append(f"PYMUD 触发器测试: {'响应模式' if docallback else '测试模式'}")
3059
+ #info_all.append(f"PYMUD 触发器测试: {'响应模式' if docallback else '测试模式'}")
2976
3060
  info_all.append(f" 测试内容: {line}")
2977
3061
  info_all.append(f" 测试结果: 有{triggered}个触发器可以被正常触发,一共有{triggered_enabled + triggered_disabled}个满足匹配触发要求。")
2978
3062
  info_all.extend(info_enabled)
2979
3063
  info_all.extend(info_disabled)
2980
-
2981
- self.info("\n".join(info_all), "PYMUD 触发器测试")
3064
+
3065
+ title = f"触发器测试 - {'响应模式' if docallback else '测试模式'}"
3066
+ self.info("\n".join(info_all), title)
2982
3067
  #self.info("PYMUD 触发器测试 完毕")
2983
3068
 
2984
3069
  def handle_plugins(self, code: CodeLine = None, *args, **kwargs):
@@ -3102,7 +3187,7 @@ class Session:
3102
3187
  '''
3103
3188
 
3104
3189
  new_text, new_code = code.expand(self, *args, **kwargs)
3105
- self.warning(new_text[6:])
3190
+ self.warning(new_text[9:])
3106
3191
 
3107
3192
  def handle_error(self, code: CodeLine = None, *args, **kwargs):
3108
3193
  '''
@@ -3118,23 +3203,23 @@ class Session:
3118
3203
  '''
3119
3204
 
3120
3205
  new_text, new_code = code.expand(self, *args, **kwargs)
3121
- self.error(new_text[6:])
3206
+ self.error(new_text[7:])
3122
3207
 
3123
- def info2(self, msg, title = "PYMUD INFO", style = Settings.INFO_STYLE):
3208
+ def info2(self, msg, title = "消息", style = Settings.INFO_STYLE):
3124
3209
  msg = f"{msg}"
3125
3210
 
3126
- if Settings.client["newline"] in msg:
3127
- new_lines = list()
3128
- msg_lines = msg.split(Settings.client["newline"])
3129
- for line in msg_lines:
3130
- new_lines.append("{}{}".format(style, line))
3211
+ # if Settings.client["newline"] in msg:
3212
+ # new_lines = list()
3213
+ # msg_lines = msg.split(Settings.client["newline"])
3214
+ # for line in msg_lines:
3215
+ # new_lines.append("{}{}".format(style, line))
3131
3216
 
3132
- msg = Settings.client["newline"].join(new_lines)
3217
+ # msg = Settings.client["newline"].join(new_lines)
3133
3218
 
3134
3219
  # 将颜色跨行显示移动到了MudFormatProcessor中,此处无需再处理(不行,还得恢复)
3135
- self.writetobuffer("{}[{}] {}{}".format(style, title, msg, Settings.CLR_STYLE), newline = True)
3220
+ self.writetobuffer("{}{}{}{}".format(style, title, msg, Settings.CLR_STYLE), newline = True)
3136
3221
 
3137
- def info(self, msg, title = "PYMUD INFO", style = Settings.INFO_STYLE):
3222
+ def info(self, msg, title = "提示", style = Settings.INFO_STYLE):
3138
3223
  """
3139
3224
  使用默认的INFO_STYLE(绿色)输出信息,并自动换行。信息格式类似 [title] msg
3140
3225
 
@@ -3144,7 +3229,7 @@ class Session:
3144
3229
  """
3145
3230
  self.info2(msg, title, style)
3146
3231
 
3147
- def warning(self, msg, title = "PYMUD WARNING", style = Settings.WARN_STYLE):
3232
+ def warning(self, msg, title = "警告", style = Settings.WARN_STYLE):
3148
3233
  """
3149
3234
  使用默认的WARN_STYLE(黄色)输出信息,并自动换行。信息格式类似 [title] msg
3150
3235
 
@@ -3154,7 +3239,7 @@ class Session:
3154
3239
  """
3155
3240
  self.info2(msg, title, style)
3156
3241
 
3157
- def error(self, msg, title = "PYMUD ERROR", style = Settings.ERR_STYLE):
3242
+ def error(self, msg, title = "错误", style = Settings.ERR_STYLE):
3158
3243
  """
3159
3244
  使用默认的ERR_STYLE(红色)输出信息,并自动换行。信息格式类似 [title] msg
3160
3245
 
pymud/settings.py CHANGED
@@ -11,9 +11,9 @@ class Settings:
11
11
  "APP 名称, 默认PYMUD"
12
12
  __appdesc__ = "a MUD client written in Python"
13
13
  "APP 简要描述"
14
- __version__ = "0.20.1"
14
+ __version__ = "0.20.2"
15
15
  "APP 当前版本"
16
- __release__ = "2024-11-16"
16
+ __release__ = "2024-11-25"
17
17
  "APP 当前版本发布日期"
18
18
  __author__ = "本牛(newstart)@北侠"
19
19
  "APP 作者"
@@ -69,6 +69,7 @@ class Settings:
69
69
  "echo_input" : False,
70
70
  "beautify" : True, # 专门为解决控制台下PKUXKX字符画对不齐的问题
71
71
 
72
+ "status_divider" : True, # 是否显示状态栏的分隔线
72
73
  "status_display" : 1, # 状态窗口显示情况设置,0-不显示,1-显示在下方,2-显示在右侧
73
74
  "status_width" : 30, # 右侧状态栏的宽度
74
75
  "status_height" : 6, # 下侧状态栏的高度
@@ -84,6 +85,7 @@ class Settings:
84
85
  "session" : "会话",
85
86
  "connect" : "连接/重新连接",
86
87
  "disconnect" : "断开连接",
88
+ "beautify" : "打开/关闭美化显示",
87
89
  "echoinput" : "显示/隐藏输入指令",
88
90
  "nosplit" : "取消分屏",
89
91
  "copy" : "复制(纯文本)",
@@ -174,8 +176,8 @@ class Settings:
174
176
  "value" : "fg:green",
175
177
  }
176
178
 
177
- INFO_STYLE = "\x1b[32m" #"\x1b[38;2;0;128;255m"
178
- WARN_STYLE = "\x1b[33m"
179
- ERR_STYLE = "\x1b[31m"
179
+ INFO_STYLE = "\x1b[48;5;22m\x1b[38;5;252m" #"\x1b[38;2;0;128;255m"
180
+ WARN_STYLE = "\x1b[48;5;220m\x1b[38;5;238m"
181
+ ERR_STYLE = "\x1b[48;5;160m\x1b[38;5;252m"
180
182
  CLR_STYLE = "\x1b[0m"
181
183
 
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymud
3
- Version: 0.20.1.post1
3
+ Version: 0.20.2
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>
7
- License: GNU GENERAL PUBLIC LICENSE
7
+ License: GNU GENERAL PUBLIC LICENSE
8
8
  Version 3, 29 June 2007
9
9
 
10
10
  Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
@@ -737,12 +737,23 @@ Requires-Dist: prompt-toolkit
737
737
 
738
738
  ## 版本更新信息
739
739
 
740
+ ### 0.20.2 (2024-11-26)
741
+ + 功能调整: MTTS协商中,将256 Color明确写入协商回复。原先仅包含ANSI 和 TrueColor。推测武庙特殊颜色偶尔不正常与此有关(已测试无关)。
742
+ + 功能调整: 修复了纯文本正则处理,目前理论上支持所有ANSI控制代码的处置,以正确响应纯文本触发器。
743
+ + 功能调整: 修改了#var和#global的显示实现,提高了变量打印排列的整齐度和辨识度,以适应长值变量和复杂变量。
744
+ + 问题修复: 修复了单行颜色代码跨行无法显示问题。现在星宿毒草可以正常辨认颜色了。
745
+ + 功能调整: 调整了info/warning/error的显示处理,默认样式进行了修改。
746
+ + 功能新增: 新增菜单选项:打开/关闭美化,以便于更好的在触发器时复制出正确的内容(以前计算可能不准确)。
747
+ + 功能新增: 状态栏的分隔符可以通过本地设置取消了。在pymud.cfg的client中新增设置,将 status_divider 设置为 false 即可。
748
+ + 功能调整: 在pymud.cfg的client中可以支持将buffer_lines设置为0了,表示不清除缓存。
749
+ + 功能新增: 为状态栏显示函数增加了异常保护,再有status_maker出错的时候,状态栏会显示出错信息。
750
+
740
751
  ### 0.20.1 (2024-11-16)
741
752
  + 功能调整: 会话中触发器匹配实现进行部分调整,减少循环次数以提高响应速度
742
753
  + 功能调整: #test / #show 触发器测试功能调整,现在会对使能的和未使能的触发器均进行匹配测试。其中,#show 命令仅测试,而 #test 命令会导致触发器真正响应。
743
754
  + 功能新增: pymud对象新增了一个持续运行的1s的周期定时任务。该任务中会刷新页面显示。可以使用 session.application.addTimerTickCallback 和 session.application.removeTimerTickCallback 来注册和解除定时器回调。
744
755
 
745
- ## 0.20.0 (2024-08-25)
756
+ ### 0.20.0 (2024-08-25)
746
757
  + 功能调整: 将模块主入口函数从__main__.py中移动到main.py中,以使可以在当前目录下,可直接使用pymud,也可使用python -m pymud启动
747
758
  + 功能调整: 使用argsparser标准模块来配置命令行,可以使用 pymud -h 查看命令行具体参数及说明
748
759
  + 功能新增: 命令行参数增加指定启动目录的功能,参数为 -s, --startup_dir。即可以从任意目录通过指定脚本目录方式启动PyMUD了。
@@ -804,21 +815,21 @@ Requires-Dist: prompt-toolkit
804
815
  + 问题修复: 修复 #var 等命令中,若含有中文则等号位置不对齐的问题
805
816
  + 功能调整: 在 #tri 等命令中,当对象的 group 为空时,将不再显示 group 属性,减少无用信息
806
817
 
807
- ## 0.19.4 (2024-04-20)
818
+ ### 0.19.4 (2024-04-20)
808
819
  + 功能调整: info 现在 msg 恢复为可接受任何类型参数,不一定是 str
809
820
  + 功能调整: #var, #global 指令中,现在可以使用参数扩展了,例如 #var max_qi @qi
810
821
  + 功能调整: #var, #global 指令中,现在对字符串会先使用 eval 转换类型,转换失败时使用 str 类型。例如, #var myvar 1 时,myvar类型将为int
811
822
  + 功能调整: 变量替代时,会自动实现类型转化,当被替代变量值为非 str 类型时不会再报错
812
823
  + 问题修复: 修复之前从后向前选择时,无法复制的问题
813
824
 
814
- ## 0.19.3post2 (2024-04-05)
825
+ ### 0.19.3post2 (2024-04-05)
815
826
  + 问题修复: 一次发送多个命令时,发送顺序可能不正确的情况
816
827
  + 功能增加: 新增一个exec_async函数,是exec函数的异步形式。可以在其他会话中异步执行一段代码
817
828
  + 帮助完善: 帮助文档逻辑完善,已完成整个包的内置文档的编写和修改
818
829
  + 注: 由于我没弄太明白 readthedocs.io 网站对于读取github源代码的逻辑,目前只能通过新发布正式版本的形式来使 readthedocs.io 网站的文档中的类参考自动更新。
819
830
  + 问题修复: 修复退出程序时的小bug
820
831
 
821
- ## 0.19.2post2 (2024-03-24)
832
+ ### 0.19.2post2 (2024-03-24)
822
833
  + 错误修复:订正部分错别字、错误帮助、错别格式
823
834
  + 系统完善:完善帮助体系,按reST格式重写所有有关的docstring
824
835
  + 功能调整:session.exec_command / exec_command_async / exec 系列命令调整,现在可以在exec时带变量参数了。例如 session.exec("dazuo @dzpt"),直接调用 dzpt的变量值
@@ -832,14 +843,14 @@ Requires-Dist: prompt-toolkit
832
843
  + 帮助完善: 帮助文档逻辑完善
833
844
  + 实现调整: 改用官方示例的task清除方式,每个任务结束后清除
834
845
 
835
- ## 0.19.1 (2024-03-06)
846
+ ### 0.19.1 (2024-03-06)
836
847
  + 功能新增: 新增鼠标启用禁用功能,以适用于ssh远程情况下的复制功能。F2快捷键可以切换状态。当鼠标禁用时,底部状态栏右侧会显示“鼠标已禁用状态”
837
848
  + 功能新增: 新增快捷键F1会直接通过浏览器打开帮助网址 https://pymud.readthedocs.io/
838
849
  + 功能新增: 新增默认快捷键F3=#ig, F4=#cls, F11=#close, F12=#exit。此几个快捷键通过配置文件进行配置,可以自行定义或修改。F1、F2为写死的系统功能。
839
850
  + 功能调整: 将除#session之外的所有其他#命令实现统一到Session类中实现,这些命令均支持通过Session.exec_command运行
840
851
  + 功能调整: python -m pymud init时,创建的pymud.cfg文件增加了keys字典
841
852
 
842
- ## 0.19.0 (2024-03-01)
853
+ ### 0.19.0 (2024-03-01)
843
854
  + 实现调整: session.info/warning/error处理多行时,会给每一行加上同样颜色
844
855
  + 功能新增: 初次运行时,可以使用python -m pymud init来初始化环境,自动创建目录并在该目录中建立配置文件和样例脚本文件
845
856
  + 实现调整: 将缓冲清除行数的实现调整到SessionBuffer中,减少代码耦合并进一步降低内存占用
@@ -849,7 +860,7 @@ Requires-Dist: prompt-toolkit
849
860
  + 实现调整: 调整COPY-RAW模式复制,即使仅选中行中的部分内容,也自动识别整行(多行模式也是整个多行)
850
861
  + 功能新增: Settings中新增keys字典,用于定义快捷键。可定义快捷键参见prompt_toolkit中Keys的定义。其值为可在session.exec_command运行支持的所有内容。该字典内容可以被pymud.cfg所覆盖。
851
862
 
852
- ## 0.18.4post4 (2024-02-23)
863
+ ### 0.18.4post4 (2024-02-23)
853
864
  + 功能新增:新增Settings.client["buffer_lines"],表示保留的缓冲行数(默认5000)。当Session内容缓冲行数达到该值2倍时(10000行),将截取一半(5000行),后一半内容进行保留,前一半丢弃。此功能是为了减少长时挂机的内存消耗和响应时间。
854
865
  + 功能修复:解决在显示美化(Settings.client["beautify"])打开之后,复制部分文字不能正确判断起始终止的问题。
855
866
  + 功能调整:修改缓冲行数判断逻辑,加快客户端判断响应速度。
@@ -857,21 +868,21 @@ Requires-Dist: prompt-toolkit
857
868
  + 功能调整:将帮助窗口中的链接改到帮助网址: https://pymud.readthedocs.org
858
869
  + 问题修复:修复了随包提供的pkuxkx.py样例脚本中的几处错误
859
870
 
860
- ## 0.18.3 (2024-02-07)
871
+ ### 0.18.3 (2024-02-07)
861
872
  + 功能调整:原#unload时通过调用__del__来实现卸载的时间不可控,现将模块卸载改为调用unload函数。若需卸载时人工清除有关定时器、触发器等,请在Configuration类下新增unload函数(参数仅self),并在其中进行实现
862
873
  + 功能新增:新增会话Variable和全局Global的删除接口。可以通过session.delVariable(name)删除一个变量,可以通过session.delGlobal(name)来删除一个全局Global变量
863
874
 
864
- ## 0.18.2 (2024-02-06)
875
+ ### 0.18.2 (2024-02-06)
865
876
  + 问题修复:修改了定时器实现,以避免出现递归调用超限异常
866
877
  + 问题修复:修改了参数替代时的默认值,从None改为字符串"None",以避免替代时报None异常
867
878
 
868
- ## 0.18.1 (2024-02-05)
879
+ ### 0.18.1 (2024-02-05)
869
880
  + 问题修复:统一处置了task.cancel的参数和create_task的name属性,以适应更低版本的python环境(低至3.7)
870
881
  + 实现调整:为解决同步/异步执行问题,在CodeLine和CodeBlock的实现中,会通过调用命令来判断是否使用同步模式(默认为异步)。#gag、#replace为强制同步,#wa为强制异步。当同时存在时,同步失效,异步执行。
871
882
  + 实现调整:将%line、%raw的访问传递到触发器内部的执行中,避免同步异步问题。
872
883
  + 新增文档:将帮助文档添加到本项目,帮助文档自动同步到 pymud.readthedocs.org (文档内容暂未更新)
873
884
 
874
- ## 0.18.0 (2024-01-24)
885
+ ### 0.18.0 (2024-01-24)
875
886
  + 问题修复:修复了delTrigger/delAlias等等无法删除对象的问题
876
887
  + 功能调整:delTrigger等函数,修改为既可以接受Trigger对象本身,也可以接受其id。其他类似
877
888
  + 功能增加:增加了delTriggers(注意,带s)等函数,可以删除多个指定对象。可接受列表、元组等可迭代对象,并且其内容既可以为对象本身,也可以为id。
@@ -890,13 +901,13 @@ Requires-Dist: prompt-toolkit
890
901
  + 功能调整:从菜单里点击创建会话时,会自动以登录名为本会话创建id变量
891
902
  + 当前已知问题:由于同步/异步执行问题,在SimpleTrigger中,#gag和#replace的执行结果会很奇怪,可能会隐藏和替换掉非触发行。可行的办法为在onSuccess里,调用session.replace进行处理。
892
903
 
893
- ## 0.17.4 (2024-01-08)
904
+ ### 0.17.4 (2024-01-08)
894
905
  + 问题修复:修复了DotDict在dump时出现错误的问题
895
906
  + 问题修复:修改了reconnect的实现方式,修复了断开重连时报错的问题
896
907
  + 功能增加:为Session增加两个事件属性,分别为event_connected和event_disconnected,接受一个带有session参数的函数,在连接和连接断开时触发。
897
908
  + 功能调整:调整了时间显示格式,只显示到秒,不显示毫秒数。
898
909
 
899
- ## 0.17.3 (2024-01-02)
910
+ ### 0.17.3 (2024-01-02)
900
911
  + 问题修复:修复了原有的#repeat功能。命令行#repeat/#rep可以重复输入上一次命令(这个基本没用,主要是我在远程连接时,手机上没有方向键...)
901
912
  + 问题修复:修改定时器的实现方式,真正修复了定时器每reload后会新增一个的bug。
902
913
  + 功能增加:命令行使用#tri, #ali, #cmd, #ti时,除了接受on/off参数外,增加了del参数,可以删除对应的触发器、别名、命令、定时器。例如:#ti tm_test del 可以删除id为“tm_test”的定时器。
@@ -904,7 +915,7 @@ Requires-Dist: prompt-toolkit
904
915
  + 功能调整:调整了Timer和SimpleTimer在#timer时的显示格式。
905
916
  + 实现调整:调整了Session.clean实现中各对象清理的顺序,将任务清除移到了最后。
906
917
 
907
- ## 0.17.2post4 (2023-12-29)
918
+ ### 0.17.2post4 (2023-12-29)
908
919
  + 功能修改:会话菜单 "显示/隐藏命令" 和 "打开/关闭自动重连" 操作后,增加在当前会话中提示状态信息。
909
920
  + 功能修改:Timer实现进行修改,以确保一个定时器仅创建一个任务。
910
921
  + 功能调整:Timer对象在复位Session对象时,也同时复位。目的是确保reload时不重新创建定时器任务。
@@ -913,7 +924,7 @@ Requires-Dist: prompt-toolkit
913
924
  + 问题修复:修复会话特定脚本模块会被其他会话加载的bug。
914
925
  + 问题修复:修复定时器Timer中的bug。
915
926
 
916
- ## 0.17.1post1 (2023-12-27)
927
+ ### 0.17.1post1 (2023-12-27)
917
928
  本版对模块功能进行了整体调整,支持加载/卸载/重载/预加载多个模块,具体内容如下:
918
929
  + 当模块中存在名为Configuration类时,以主模块形式加载,即:自动创建该Configuration类的实例(与原脚本相同)
919
930
  + 当模块中不存在名为Configuration类时,以子模块形式加载,即:仅加载该模块,但不会创建Configuration的实例
@@ -954,7 +965,7 @@ Requires-Dist: prompt-toolkit
954
965
  + 功能修改:auto_reconnect设定目前对正常/异常断开均有效。若设置为True,当连接断开后15s后自动重连
955
966
  + 功能修改:会话菜单下增加“打开/关闭自动重连”子菜单,可以动态切换自动重连是否打开。
956
967
 
957
- ## 0.17.0 (2023-12-24)
968
+ ### 0.17.0 (2023-12-24)
958
969
  + 功能修改:调整修改GMCP数据的wildcards处理方式,恢复为eval,其余不变。(回滚0.16.2版更改)
959
970
  + 功能修改:将本地pymud.cfg文件的读取默认编码调整为utf8,以避免加载出现问题
960
971
  + 问题修复:sessions.py中,修复系统command与会话command重名的问题(这次才发现)
@@ -980,7 +991,7 @@ Requires-Dist: prompt-toolkit
980
991
  + 功能修改:所有匹配类对象的匹配模式patterns支持动态修改,涉及Alias,Trigger,Command。修改方式为直接对其patterns属性赋值。如tri.patterns = aNewPattern
981
992
  + 功能修改:连接/断开连接时刻都会在提示中增加时刻信息,而不论是否异常。
982
993
 
983
- ## 0.16.2 (2023-12-19)
994
+ ### 0.16.2 (2023-12-19)
984
995
  + 功能修改:归一化#命令和非#命令处理,使session.exec_command、exec_command_async、exec_command_after均可以处理#命令,例如session.exec_command("#save")。同时,也可以在命令行使用#all发送#命令,如"#all #save"此类
985
996
  + 功能修改:调整脚本加载与变量自动加载的顺序。当前为连接自动加载时,首先加载变量,然后再加载脚本。目的是使脚本的变化可以覆盖加载的变量内容,而不是反向覆盖。
986
997
  + 功能修改:会话变量保存和加载可以配置是否打开,默认为打开。见Settings.client["var_autosave] 和 Settings.client["var_autoload"]。同理,该配置可以被本地pymud.cfg所覆盖
@@ -989,7 +1000,7 @@ Requires-Dist: prompt-toolkit
989
1000
  + 功能修改:增加GMCP默认处理。当未使用GMCPTrigger对对应的GMCP消息进行处理时,默认使用[GMCP] name: value的形式输出GMCP收到的消息,以便于个人脚本调试。
990
1001
  + 功能修改:修改GMCP数据的处理方式从eval修改为json.load,其余不变。
991
1002
 
992
- ## 0.16.1.post2 (2023-12-12)
1003
+ ### 0.16.1.post2 (2023-12-12)
993
1004
  + 问题修复:修复__init__.py中的__all__变量为字符串
994
1005
  + 功能增加:可以加载自定义Settings。在执行python -m pymud时,会自动从当前目录读取pymud.cfg文件。使用json格式将配置信息写在该文件中即可。支持模块中settings.py里的sessions, client, server, styles, text字段内容。
995
1006
  + 功能增加:增加全局变量集,可以使用session.setGlobal和session.getGlobal进行访问,以便于跨session通信。也可以使用#global在命令行访问
@@ -1010,5 +1021,5 @@ Requires-Dist: prompt-toolkit
1010
1021
  + 功能修改:CodeLine的执行运行处理修改为不删除中间的多余空白
1011
1022
  + 问题修复:修改github项目地址为原pymud地址
1012
1023
 
1013
- ## 0.15.8 (2023-12-05)
1014
- 首次发布到pip,增加模块使用
1024
+ ### 0.15.8 (2023-12-05)
1025
+ 首次发布到pip
@@ -0,0 +1,19 @@
1
+ pymud/__init__.py,sha256=AP4Edhx90gMKrNfD1O_KVciA3SOnyX5Qt9fZY_JhsTY,574
2
+ pymud/__main__.py,sha256=hFzZjadLlcOuoLM7D8wFiFVO8mqF7vMuo9y-9xfIhRc,64
3
+ pymud/dialogs.py,sha256=p-LidObSuDyOeMif5CsqhF5qq3rizZ1lmThWHrxDyRg,6726
4
+ pymud/extras.py,sha256=lCRlNIaYqrcCLGe8zrulFvh7aC5nU_jHFMD2sI9JCrU,40955
5
+ pymud/logger.py,sha256=sq9HhZ6-prY34NnDUO1NjaCRy-e5-fr2j0na8FKp9ks,5789
6
+ pymud/main.py,sha256=b_Ui_cN4W8IfhYNyc1duwr3Bp7pYYZQusKTSafCWZIA,6534
7
+ pymud/modules.py,sha256=XoqTeYfZCgqDsV3SYxeehzsbkTzs0swelAUIxyWuL9g,7423
8
+ pymud/objects.py,sha256=qSOFuVZvMh3lxjg6x5JUzcr_sTSgakWWySh801x7TNQ,39457
9
+ pymud/pkuxkx.py,sha256=jRQRUs2xtw7GzYHtLYZXOASnqMumKh0iCoOeKZs8NnU,11467
10
+ pymud/protocol.py,sha256=nlsyXMBAHEf_067mPNGDHzN_zIm9808D8YDIZTNrygg,49118
11
+ pymud/pymud.py,sha256=nfCOgKKBU1rPU7sSiZhD1GxJ2HqaPV3entB4T0kH_Wk,52478
12
+ pymud/session.py,sha256=dO6asU6Pva9JjuhecyUHDCp1qH59FkSIUsmJbTjtFDI,139001
13
+ pymud/settings.py,sha256=zGVSAo7pHdBiFhYhdS8xf-RJV99cceb24gjRcvgkJBY,7353
14
+ pymud-0.20.2.dist-info/LICENSE.txt,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
15
+ pymud-0.20.2.dist-info/METADATA,sha256=5hRMzKEYu0WEfscG9qIkhjPhbjq6zf_K4sk4pOzQDyw,75639
16
+ pymud-0.20.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
17
+ pymud-0.20.2.dist-info/entry_points.txt,sha256=diPUOtTkhgC1hVny7Cdg4aRhaHSynMQoraE7ZhJxUcw,37
18
+ pymud-0.20.2.dist-info/top_level.txt,sha256=8Gp1eXjxixXjqhhti6tLCspV_8s9sNV3z5Em2_KRhD4,6
19
+ pymud-0.20.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.5.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,19 +0,0 @@
1
- pymud/__init__.py,sha256=AP4Edhx90gMKrNfD1O_KVciA3SOnyX5Qt9fZY_JhsTY,574
2
- pymud/__main__.py,sha256=hFzZjadLlcOuoLM7D8wFiFVO8mqF7vMuo9y-9xfIhRc,64
3
- pymud/dialogs.py,sha256=p-LidObSuDyOeMif5CsqhF5qq3rizZ1lmThWHrxDyRg,6726
4
- pymud/extras.py,sha256=Gr-gX7YRWZMmeKV73sk7h_Gf5eZVJ6GcAXvSEfJ4uMI,41124
5
- pymud/logger.py,sha256=gtGm8y9RY_CpRpJ0udgKknRxyjsEPrrRyWecUDgBgZM,5662
6
- pymud/main.py,sha256=b_Ui_cN4W8IfhYNyc1duwr3Bp7pYYZQusKTSafCWZIA,6534
7
- pymud/modules.py,sha256=XoqTeYfZCgqDsV3SYxeehzsbkTzs0swelAUIxyWuL9g,7423
8
- pymud/objects.py,sha256=HNWoE6mhUV9SgRsD-2yISt5rVi8h2mTR1sapEZVklNI,39441
9
- pymud/pkuxkx.py,sha256=jRQRUs2xtw7GzYHtLYZXOASnqMumKh0iCoOeKZs8NnU,11467
10
- pymud/protocol.py,sha256=QfDXjlg2OcJXmVoXf_3mAemnYotRXDUlEZNQjhkfXdA,49106
11
- pymud/pymud.py,sha256=pkTb21UV2ccYhG44JjfGdvUSPIWbu_y-vUwBqqzeHaM,51425
12
- pymud/session.py,sha256=GAxenTtUy75A-LAfznMOx753BWd-tyozgngeNdJux4Q,135208
13
- pymud/settings.py,sha256=ZsKGkjcNGNwqeb2DztwhIrCcRDPYYN1SxtdjWNAJ9CY,7145
14
- pymud-0.20.1.post1.dist-info/LICENSE.txt,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
15
- pymud-0.20.1.post1.dist-info/METADATA,sha256=TD5fbQU363NwQw5jDJc4Me_6gkLvkaYcGyyn1BnpCwU,74350
16
- pymud-0.20.1.post1.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
17
- pymud-0.20.1.post1.dist-info/entry_points.txt,sha256=diPUOtTkhgC1hVny7Cdg4aRhaHSynMQoraE7ZhJxUcw,37
18
- pymud-0.20.1.post1.dist-info/top_level.txt,sha256=8Gp1eXjxixXjqhhti6tLCspV_8s9sNV3z5Em2_KRhD4,6
19
- pymud-0.20.1.post1.dist-info/RECORD,,