mirror of
https://github.com/CrispyConductor/tmux-copy-toolkit.git
synced 2026-09-10 04:06:14 -04:00
More
This commit is contained in:
parent
ccb3ec067e
commit
3ce1e9c602
|
|
@ -1,5 +1,69 @@
|
|||
# Note: The regexes in this file are not intended to correctly validate
|
||||
# all instances of the given type. They are designed to match the most
|
||||
# common variants while specifically excluding less-common ones that could
|
||||
# introduce false matches.
|
||||
|
||||
import re
|
||||
|
||||
def make_path_regexes():
|
||||
# This is not intended to match all valid paths - that would result in too many matches.
|
||||
# Note: Spaces, as a common delimiter, are handled specially. They are only allowed in
|
||||
# paths with at least 3 elements, and never in the first or last element. There cannot
|
||||
# be more than one consecutive space, and it cannot be at the beginning or end of the
|
||||
# element.
|
||||
edge_delimiters = r'[][\s:=,#$"{}<>()' + "'" + ']'
|
||||
edge_delimiters_w_slash = r'[][\s:=,#$"{}<>()/' + "'" + ']'
|
||||
leader = r'(?:^|' + edge_delimiters + ')'
|
||||
leader_w_slash = r'(?:^|' + edge_delimiters_w_slash + ')'
|
||||
follower = r'(?:$|' + edge_delimiters + ')'
|
||||
path_el = r'[a-zA-Z0-9_-]{1,30}'
|
||||
inner_path_el = r'[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25}'
|
||||
either_path_el = r'(?:' + path_el + '|' + inner_path_el + ')'
|
||||
basic_filename = path_el + r'\.' + r'[a-zA-Z][a-zA-Z0-9]{0,5}'
|
||||
path_filename = either_path_el + r'\.' + r'[a-zA-Z0-9]{1,6}'
|
||||
sep = r'[\\/]'
|
||||
root = r'(?:/|~/|[A-Z]:' + sep + ')'
|
||||
abspath = root + r'(?:' + either_path_el + sep + ')*' + r'(?:' + path_filename + '|' + path_el + sep + '?)'
|
||||
relpath2 = path_el + sep + r'(?:' + path_el + sep + '?|' + path_filename + ')'
|
||||
relpath3 = path_el + sep + r'(?:' + either_path_el + sep + r')+' + r'(?:' + path_el + sep + '?|' + path_filename + ')'
|
||||
anypath = r'(?:' + abspath + '|' + relpath2 + '|' + relpath3 + ')'
|
||||
rabspath = leader + '(' + abspath + ')' + follower
|
||||
ranypath = leader + '(' + anypath + ')' + follower
|
||||
rfilename = leader_w_slash + '(' + basic_filename + ')' + follower
|
||||
return rabspath, ranypath, rfilename
|
||||
|
||||
def test_path_regexes():
|
||||
testpaths = r'''
|
||||
foo
|
||||
foo/bar
|
||||
foo/bar/baz
|
||||
baz.mp3
|
||||
123.456
|
||||
C:\fooo
|
||||
C:\fooo.bar
|
||||
C:/fooo.bar
|
||||
/fooo
|
||||
/fooo.bar
|
||||
/abc/def/ghi
|
||||
foo bar/baz
|
||||
foo/bar baz/fiz
|
||||
foo/bar baz/fiz.buz
|
||||
'''.split('\n')
|
||||
testpaths = [ p.strip() for p in testpaths if len(p.strip()) ]
|
||||
|
||||
abspath, anypath, filename = make_path_regexes()
|
||||
|
||||
print('abspath: ' + abspath)
|
||||
print('anypath: ' + anypath)
|
||||
print('filename: ' + filename)
|
||||
|
||||
for p in testpaths:
|
||||
m1 = re.fullmatch(abspath, p)
|
||||
m2 = re.fullmatch(anypath, p)
|
||||
m3 = re.fullmatch(filename, p)
|
||||
print(f'{p} - {"ABS" if m1 else ""} {"PATH" if m2 else ""} {"FILE" if m3 else ""}')
|
||||
|
||||
|
||||
# Note: This url regex is not a validator, nor is it intended to be. It is intended
|
||||
# to match the most common kinds of URLs that are used and avoid unintended matches.
|
||||
# Notably, spaces in urls are not matched; with spaces there's too great a chance
|
||||
|
|
@ -119,8 +183,25 @@ def test_url_regex():
|
|||
else:
|
||||
print(f'{u} - No Match')
|
||||
|
||||
test_url_regex()
|
||||
def print_rex(name, r, comment=None):
|
||||
rxstr = "r'" + r.replace("'", "'+\"'\"+r'") + "'"
|
||||
if comment:
|
||||
print(f"\t# {comment}")
|
||||
print(f"\t'{name}': {rxstr}")
|
||||
|
||||
r = make_url_regex()
|
||||
print("r'" + r.replace("'", "'+\"'\"+r'") + "'")
|
||||
#test_url_regex()
|
||||
|
||||
#print('URL:')
|
||||
print_rex('urls', make_url_regex(), 'matches common types of urls and things that look like urls')
|
||||
print
|
||||
|
||||
#test_path_regexes()
|
||||
|
||||
absp, anyp, fn = make_path_regexes()
|
||||
#print('ABS PATH:')
|
||||
print_rex('abspaths', absp, 'Unix and window style absolute paths')
|
||||
#print('PATH:')
|
||||
print_rex('paths', anyp, 'Absolute or relative paths')
|
||||
#print('FILE:')
|
||||
print_rex('filenames', fn, 'Isolated filenames without paths')
|
||||
|
||||
|
|
|
|||
24
copytk.py
24
copytk.py
|
|
@ -31,8 +31,25 @@ tmux_command = find_command_path('tmux')
|
|||
|
||||
# strings that can be used to map to regexes in the quickcopy matches
|
||||
match_expr_presets = {
|
||||
# generated by _regex_builds.py
|
||||
'urls': r'(?:^|[][\s:=,#"{}()'+"'"+r'])([a-zA-Z][a-zA-Z0-9]{1,5}://(?:[a-zA-Z0-9_]+(?::[a-zA-Z0-9_-]+)?@)?(?:(?:[a-zA-Z0-9][\w-]*\.)*[a-zA-Z][\w-]*|(?:[0-2]?[0-9]{1,2}\.){3}[0-2]?[0-9]{1,2})(?::[0-9]{1,5})?(?:/(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?/?)?(?:\?(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?&)*(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?)?)?(?:#(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?&)*(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?)?)?)(?:$|[][\s:=,#"{}()'+"'"+r'])'
|
||||
# matches common types of urls and things that look like urls
|
||||
'urls': r'(?:^|[][\s:=,#"{}()'+"'"+r'])([a-zA-Z][a-zA-Z0-9]{1,5}://(?:[a-zA-Z0-9_]+(?::[a-zA-Z0-9_-]+)?@)?(?:(?:[a-zA-Z0-9][\w-]*\.)*[a-zA-Z][\w-]*|(?:[0-2]?[0-9]{1,2}\.){3}[0-2]?[0-9]{1,2})(?::[0-9]{1,5})?(?:/(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?/?)?(?:\?(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?&)*(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?)?)?(?:#(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?&)*(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?)?)?)(?:$|[][\s:=,#"{}()'+"'"+r'])',
|
||||
# Unix and window style absolute paths
|
||||
'abspaths': r'(?:^|[][\s:=,#$"{}<>()'+"'"+r'])((?:/|~/|[A-Z]:[\\/])(?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})[\\/])*(?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})\.[a-zA-Z0-9]{1,6}|[a-zA-Z0-9_-]{1,30}[\\/]?))(?:$|[][\s:=,#$"{}<>()'+"'"+r'])',
|
||||
# Absolute or relative paths
|
||||
'paths': r'(?:^|[][\s:=,#$"{}<>()'+"'"+r'])((?:(?:/|~/|[A-Z]:[\\/])(?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})[\\/])*(?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})\.[a-zA-Z0-9]{1,6}|[a-zA-Z0-9_-]{1,30}[\\/]?)|[a-zA-Z0-9_-]{1,30}[\\/](?:[a-zA-Z0-9_-]{1,30}[\\/]?|(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})\.[a-zA-Z0-9]{1,6})|[a-zA-Z0-9_-]{1,30}[\\/](?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})[\\/])+(?:[a-zA-Z0-9_-]{1,30}[\\/]?|(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})\.[a-zA-Z0-9]{1,6})))(?:$|[][\s:=,#$"{}<>()'+"'"+r'])',
|
||||
# Isolated filenames without paths
|
||||
'filenames': r'(?:^|[][\s:=,#$"{}<>()/'+"'"+r'])([a-zA-Z0-9_-]{1,30}\.[a-zA-Z][a-zA-Z0-9]{0,5})(?:$|[][\s:=,#$"{}<>()'+"'"+r'])'
|
||||
|
||||
# long regexes generated by _regex_builds.py
|
||||
# matches things that look like common URLs. does not match esoteric URLs.
|
||||
# 'urls': r'(?:^|[][\s:=,#"{}()'+"'"+r'])([a-zA-Z][a-zA-Z0-9]{1,5}://(?:[a-zA-Z0-9_]+(?::[a-zA-Z0-9_-]+)?@)?(?:(?:[a-zA-Z0-9][\w-]*\.)*[a-zA-Z][\w-]*|(?:[0-2]?[0-9]{1,2}\.){3}[0-2]?[0-9]{1,2})(?::[0-9]{1,5})?(?:/(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?/?)?(?:\?(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?&)*(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?)?)?(?:#(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?&)*(?:(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)+(?:=(?:[\w.~%/&-]+|(?:[\w.~%/&-]*\([\w.~%/&-]*\)[\w.~%/&-]*)+)?)?)?)?)(?:$|[][\s:=,#"{}()'+"'"+r'])',
|
||||
# matches things that look like UNIX or Windows style absolute paths
|
||||
# 'abspaths': r'(?:^|[][\s:=,#$"{}()'+"'"+r'])((?:/|~/|[A-Z]:[\\/])(?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})[\\/])*(?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})\.[a-zA-Z0-9]{1,6}|[a-zA-Z0-9_-]{1,30}[\\/]?))(?:$|[][\s:=,#$"{}()'+"'"+r'])',
|
||||
# matches both things that look like absolute paths, and relative paths with at least one separator
|
||||
# may also match spaces in path components, but never at the beginning or end, and only in an inner component
|
||||
# 'paths': r'(?:^|[][\s:=,#$"{}()'+"'"+r'])((?:(?:/|~/|[A-Z]:[\\/])(?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})[\\/])*(?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})\.[a-zA-Z0-9]{1,6}|[a-zA-Z0-9_-]{1,30}[\\/]?)|[a-zA-Z0-9_-]{1,30}[\\/](?:[a-zA-Z0-9_-]{1,30}[\\/]?|(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})\.[a-zA-Z0-9]{1,6})|[a-zA-Z0-9_-]{1,30}[\\/](?:(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})[\\/])+(?:[a-zA-Z0-9_-]{1,30}[\\/]?|(?:[a-zA-Z0-9_-]{1,30}|[a-zA-Z0-9_-]{1,25}\\? [a-zA-Z0-9_-]{1,25})\.[a-zA-Z0-9]{1,6})))(?:$|[][\s:=,#$"{}()'+"'"+r'])',
|
||||
# matches things that look like an isolated filename (no path)
|
||||
# 'filenames': r'(?:^|[][\s:=,#$"{}()'+"'"+r'])([a-zA-Z0-9_-]{1,30}\.[a-zA-Z][a-zA-Z0-9]{0,5})(?:$|[][\s:=,#$"{}()'+"'"+r'])'
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -764,6 +781,8 @@ class EasyMotionAction(PaneJumpAction):
|
|||
locs = self._em_filter_locs(locs)
|
||||
if filter_locs:
|
||||
locs = [ l for l in locs if filter_locs(l) ]
|
||||
if len(locs) == 0:
|
||||
raise ActionCanceled()
|
||||
self._em_sort_locs_cursor_proximity(locs, sort_close_to)
|
||||
|
||||
# Assign each match a label
|
||||
|
|
@ -1024,6 +1043,7 @@ class QuickCopyAction(PaneJumpAction):
|
|||
log('quickcopy run')
|
||||
# Get a list of all matches
|
||||
matches = self.find_matches()
|
||||
if len(matches) == 0: return
|
||||
log('got matches')
|
||||
|
||||
# Group them into display batches
|
||||
|
|
|
|||
10
copytk.tmux
10
copytk.tmux
|
|
@ -29,7 +29,13 @@ tmux bind-key -T copy-mode-vi S switch-client -T copytk
|
|||
tmux bind-key -T copy-mode S switch-client -T copytk
|
||||
|
||||
|
||||
# Match URLs
|
||||
tmux set -g @copytk-quickcopy-match-0-0 urls
|
||||
tmux set -g @copytk-quickcopy-match-1-0 '[0-9]{4,}'
|
||||
tmux set -g @copytk-quickcopy-match-2-0 lines
|
||||
tmux set -g @copytk-quickcopy-match-0-1 abspaths
|
||||
tmux set -g @copytk-quickcopy-match-1-0 paths
|
||||
tmux set -g @copytk-quickcopy-match-1-0 filenames
|
||||
# Match numbers
|
||||
tmux set -g @copytk-quickcopy-match-2-0 '-?[0-9]+(?:\.[0-9]+)?(?:[eE]-?[0-9]+)?'
|
||||
# Match whole lines
|
||||
tmux set -g @copytk-quickcopy-match-3-0 lines
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue