| View previous topic :: View next topic |
| Author |
Message |
Tol!k

Joined: 01 Apr 2008 Posts: 1727 Location: Арзамас
|
(Separately) Posted: Fri Aug 07, 2009 17:21 Post subject: |
|
|
| Bomm wrote: | Кстати при
"cmd.exe /C chcp 1251&echo %O|SetClip"
в буфер попадает "%O"
Как я понимаю, %O и прочие % "действуют" только в окне "Параметры", я с этим уже сталкивался
Пришлось написать пакетный файл и запускать его | В виде кнопки
| Code: | TOTALCMD#BAR#DATA
cmd.exe
/C chcp 1251&echo %O|SetClip
%commander_path%\Utils\SetClip.exe
имя файла в буфер обмена
1
-1 |
| Bomm wrote: | | А еще, можно ли так сделать, чтобы при этом "не мелькало" ДОС-окно | В параметрах кнопки есть галка "в свёрнутом виде" |
|
| Back to top |
|
 |
Bomm

Joined: 15 Jan 2005 Posts: 245 Location: Москва
|
(Separately) Posted: Tue Aug 11, 2009 09:03 Post subject: |
|
|
Обнаружил, что по той же причине неправильно копируется русский текст из плагина SynPlus
Также понял, что сие безобразие получилось после того, как я разрешил Windows обновляться (раньше я ей этого не позволял)
В связи с этим вопрос (на будущее):
кто работает в XP SP3, Vista, Win7 - там все нормально с русскими буквами, в частности при работе с Lst2Clip и SynPlus? _________________ Юрий Бомштейн |
|
| Back to top |
|
 |
palle
Joined: 15 Apr 2021 Posts: 12
|
(Separately) Posted: Thu Feb 12, 2026 18:02 Post subject: |
|
|
Добрый день!
Надоело следить за раскладкой при копировании с помощью Lst2Clip.
Я скормил readme.htm из комплекта утилиты нейросетям и получил работающий питон-скрипт, повторяющий её функционал и даже с сохранением синтаксиса командной строки.
 Hidden text | Code: | """ListToClip — transform file paths / text lines, copy result to clipboard.
Usage:
python ListToClip.py /L [options] — read from stdin
python ListToClip.py /L:"source" [opts] — read from file or inline text
pythonw ListToClip.py /L:"source" [opts] — same, no console window
Options:
/U Mapped drive → UNC
/NE Remove file extension
/PD:start,end Limit path depth
/RB Remove trailing slash
/P:"text" Add prefix
/S:"text" Add suffix
/R:"old"="new" Replace (repeatable, spaces preserved inside quotes)
Requires: pip install pyperclip
"""
from __future__ import annotations
import ctypes
import ctypes.wintypes as w
import os
import re
import subprocess
import sys
import pyperclip
# ── Защита от pythonw.exe (нет консоли → stdout/stderr = None) ────────────
if sys.stdout is None:
sys.stdout = open(os.devnull, "w", encoding="utf-8")
if sys.stderr is None:
sys.stderr = open(os.devnull, "w", encoding="utf-8")
# ── Raw command line ──────────────────────────────────────────────────────
_GetCommandLineW = ctypes.windll.kernel32.GetCommandLineW
_GetCommandLineW.restype = ctypes.c_wchar_p
def _raw_cmdline() -> str:
return _GetCommandLineW() or ""
def _split_cmdline(cmd: str) -> list[str]:
"""Split keeping backslashes literal; only quotes toggle quoting."""
args: list[str] = []
buf: list[str] = []
q = False
i = 0
n = len(cmd)
while i < n:
ch = cmd[i]
if ch == '"':
q = not q
elif not q and ch.isspace():
if buf:
args.append("".join(buf))
buf.clear()
i += 1
while i < n and cmd[i].isspace():
i += 1
continue
else:
buf.append(ch)
i += 1
if buf:
args.append("".join(buf))
return args
def _argv() -> list[str]:
parts = _split_cmdline(_raw_cmdline())
if not parts:
return sys.argv[1:]
lo = parts[0].replace("/", "\\").lower()
py = lo.endswith(("\\python.exe", "\\pythonw.exe", "\\py.exe")) or \
lo in ("python.exe", "pythonw.exe", "py.exe", "python", "pythonw", "py")
start = 1
if py and len(parts) >= 2 and parts[1].lower().endswith((".py", ".pyw")):
start = 2
return parts[start:]
# ── /R:"old"="new" — парсинг прямо из сырой строки ───────────────────────
def _extract_q(s: str) -> tuple[str | None, str]:
"""Extract quoted value: '"...' → (content, rest)."""
if not s or s[0] != '"':
return None, s
i = 1
buf: list[str] = []
while i < len(s):
if s[i] == '"':
return "".join(buf), s[i + 1:]
buf.append(s[i])
i += 1
return "".join(buf), ""
def _parse_replacements(raw: str) -> list[tuple[str, str]]:
result: list[tuple[str, str]] = []
up = raw.upper()
i = 0
while True:
pos = up.find("/R:", i)
if pos == -1:
break
rest = raw[pos + 3:]
if rest.startswith('"'):
old, after = _extract_q(rest)
if old is not None and after.startswith("="):
new, _ = _extract_q(after[1:])
if new is not None:
if old: # пустой old — skip
result.append((old, new))
i = pos + 3
continue
# unquoted fallback
tok = ""
for ch in rest:
if ch.isspace():
break
tok += ch
if "=" in tok:
l, r = tok.split("=", 1)
if l:
result.append((l, r))
i = pos + 3
return result
# ── UNC ───────────────────────────────────────────────────────────────────
def _to_unc(path: str) -> str:
if len(path) < 2 or path[1] != ":":
return path
drv = path[0].upper()
try:
out = subprocess.run(
["net", "use"], capture_output=True, text=True, timeout=5,
creationflags=subprocess.CREATE_NO_WINDOW,
).stdout
for line in out.splitlines():
parts = line.split()
for j, p in enumerate(parts):
if p.upper() == f"{drv}:" and j + 1 < len(parts) and parts[j + 1].startswith("\\\\"):
return parts[j + 1].rstrip("\\") + path[2:]
except Exception:
pass
try:
import win32wnet # type: ignore
return win32wnet.WNetGetUniversalName(path, 1)
except Exception:
pass
return path
# ── Path helpers ──────────────────────────────────────────────────────────
def _sep(p: str) -> str:
return "\\" if "\\" in p else "/" if "/" in p else "\\"
def _rm_ext(p: str) -> str:
r, e = os.path.splitext(p)
return r if e else p
def _depth(path: str, start: int, end: int) -> str:
sep = _sep(path)
unc = path.startswith("\\\\")
pfx, work = (path[:2], path[2:]) if unc else ("", path)
pts = [x for x in work.split(sep) if x]
n = len(pts)
s, e = max(0, start), max(0, end)
if s + e >= n:
return path
mid = sep.join(pts[:s]) + sep + "..." + sep + sep.join(pts[n - e:])
if unc:
mid = pfx + mid
elif len(path) >= 2 and path[1] == ":" and not mid[:2].upper().startswith(path[0].upper() + ":"):
mid = path[0] + ":" + sep + mid
return mid
def _rm_slash(p: str) -> str:
if re.fullmatch(r"[A-Za-z]:[\\/]", p):
return p
return p.rstrip("\\/") if len(p) > 1 and p[-1] in "\\/" else p
# ── Argument parsing ─────────────────────────────────────────────────────
def _parse_args(argv: list[str]) -> dict:
cfg: dict = dict(
source=None, unc=False, no_ext=False, pd=None,
rb=False, pfx="", sfx="", repl=[],
)
for a in argv:
u = a.upper()
if u == "/L":
cfg["source"] = None
elif u.startswith("/L:"):
cfg["source"] = a[3:]
elif u == "/U":
cfg["unc"] = True
elif u == "/NE":
cfg["no_ext"] = True
elif u.startswith("/PD:"):
ns = a[4:].split(",")
cfg["pd"] = (int(ns[0] or 0), int(ns[1] or 0) if len(ns) > 1 else 0)
elif u == "/RB":
cfg["rb"] = True
elif u.startswith("/P:"):
v = a[3:]
cfg["pfx"] = v[1:-1] if len(v) >= 2 and v[0] == '"' and v[-1] == '"' else v
elif u.startswith("/S:"):
v = a[3:]
cfg["sfx"] = v[1:-1] if len(v) >= 2 and v[0] == '"' and v[-1] == '"' else v
return cfg
# ── Input ─────────────────────────────────────────────────────────────────
def _decode(data: bytes) -> str:
for bom, enc in ((b"\xff\xfe", "utf-16le"), (b"\xfe\xff", "utf-16be"), (b"\xef\xbb\xbf", "utf-8-sig")):
if data.startswith(bom):
return data.decode(enc, errors="replace")
try:
return data.decode("utf-8")
except UnicodeDecodeError:
return data.decode("cp1251", errors="replace")
def _split_quoted(text: str) -> list[str]:
out: list[str] = []
buf: list[str] = []
q = False
i = 0
n = len(text)
while i < n:
ch = text[i]
if ch == '"':
q = not q
elif not q and ch.isspace():
if buf:
out.append("".join(buf))
buf.clear()
i += 1
while i < n and text[i].isspace():
i += 1
continue
else:
buf.append(ch)
i += 1
if buf:
out.append("".join(buf))
return [t for t in out if t]
def _lines(cfg: dict) -> list[str]:
src = cfg["source"]
# stdin
if src is None:
out: list[str] = []
try:
for ln in sys.stdin:
ln = ln.rstrip("\r\n")
if ln:
out.append(ln.lstrip("\ufeff"))
except (KeyboardInterrupt, OSError):
pass
return out
# normalize
if src.upper().startswith("/L:"):
src = src[3:]
if src.startswith("@") and len(src) > 1:
src = src[1:]
if src.startswith("\\\\?\\") or src.startswith("\\\\.\\"):
src = src[4:]
# file
if os.path.isfile(src):
text = _decode(open(src, "rb").read()).lstrip("\ufeff")
return [ln for ln in text.splitlines() if ln.strip()]
# inline
if "\n" in src or "\r" in src:
return [ln for ln in src.splitlines() if ln.strip()]
parts = _split_quoted(src)
return parts if len(parts) > 1 else ([src.strip()] if src.strip() else [])
# ── Processing ────────────────────────────────────────────────────────────
def _process(line: str, cfg: dict) -> str:
s = line.rstrip("\r\n")
if not s.strip():
return s
if cfg["unc"]:
s = _to_unc(s)
if cfg["no_ext"]:
s = _rm_ext(s)
if cfg["pd"]:
s = _depth(s, *cfg["pd"])
if cfg["rb"]:
s = _rm_slash(s)
for old, new in cfg["repl"]:
s = s.replace(old, new)
return cfg["pfx"] + s + cfg["sfx"]
# ── Main ──────────────────────────────────────────────────────────────────
def main() -> None:
argv = _argv()
if not argv:
print(__doc__)
print("Error: /L must be the first parameter.")
sys.exit(1)
f = argv[0].upper()
if f != "/L" and not f.startswith("/L:"):
print(__doc__)
print(f"Error: /L must be the first parameter. Got: {argv[0]}")
sys.exit(1)
cfg = _parse_args(argv)
cfg["repl"] = _parse_replacements(_raw_cmdline())
results = [_process(ln, cfg) for ln in _lines(cfg) if ln.strip()]
if not results:
print("No lines to process.", file=sys.stderr)
return
output = "\n".join(results)
print(output)
try:
pyperclip.copy(output)
print(f"\n--- Copied {len(results)} line(s) to clipboard ---", file=sys.stderr)
except Exception:
print("\n--- Warning: Could not copy to clipboard ---", file=sys.stderr)
if __name__ == "__main__":
main()
|
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|