diff --git a/copytk.py b/copytk.py index 1665825..191ddcc 100644 --- a/copytk.py +++ b/copytk.py @@ -11,6 +11,7 @@ import subprocess import shutil from datetime import datetime import time +import platform logdir = '/tmp/tmplog' @@ -862,8 +863,14 @@ class EasyCopyAction(EasyMotionAction): class QuickCopyAction(PaneJumpAction): - def __init__(self, stdscr): + def __init__(self, stdscr, options_prefix='@copytk-quickcopy-'): super().__init__(stdscr) + self.options_prefix = options_prefix + self._load_options(options_prefix) + self.em_label_chars = ''.join(( c for c in self.em_label_chars if c not in self.next_batch_char )) + log('constructor finished') + + def _load_options(self, prefix='@copytk-quickcopy-'): # Load in the tiers of match expressions. # Options for this are in the form: @copytk-quickcopy-match-- # Each tier list is terminated by a missing option at the index. @@ -872,15 +879,15 @@ class QuickCopyAction(PaneJumpAction): tier_ctr = 0 log('getting options') while True: - l = get_tmux_option('@copytk-quickcopy-match-' + str(tier_ctr), aslist=True, userlist=True) + l = get_tmux_option(prefix + 'match-' + str(tier_ctr), aslist=True, userlist=True) if l == None or len(l) == 0: break tier_exprs.append(l) tier_ctr += 1 self.tier_exprs = tier_exprs - self.next_batch_char = get_tmux_option_key_curses('@copytk-quickcopy-next-batch-char', ' n', aslist=True) - self.em_label_chars = ''.join(( c for c in self.em_label_chars if c not in self.next_batch_char )) - log('constructor finished') + self.next_batch_char = get_tmux_option_key_curses(prefix + 'next-batch-char', ' n', aslist=True) + self.min_match_len = get_tmux_option(prefix + 'min-match-len', 4) + self.pack_tiers = str2bool(get_tmux_option(prefix + 'pack-tiers', 'on')) def _matchobj(self, start, end, tier=0): return ( @@ -937,8 +944,7 @@ class QuickCopyAction(PaneJumpAction): for expr in exprs: allmatches.extend(self._matchobjs(self.find_expr_matches(expr), tier)) # Filter out matches shorter than the minimum - min_match_len = get_tmux_option('@copytk-quickcopy-min-match-len', 4) - return [ m for m in allmatches if m[1] >= min_match_len ] + return [ m for m in allmatches if m[1] >= self.min_match_len ] def arrange_matches(self, matches, pack_tiers=True): # Arrange the set of matches into batches of non-overlapping ones, by tier, and by shortness (shorter preferred) @@ -1050,17 +1056,16 @@ class QuickCopyAction(PaneJumpAction): else: return batch - def run(self): + def run_quickselect(self): log('quickcopy run') # Get a list of all matches matches = self.find_matches() log('find_matches() result: ' + str(matches)) - if len(matches) == 0: return + if len(matches) == 0: raise ActionCanceled() log('got matches') # Group them into display batches - pack_tiers = str2bool(get_tmux_option('@copytk-quickcopy-pack-tiers', 'on')) - batches = self.arrange_matches(matches) + batches = self.arrange_matches(matches, self.pack_tiers) log('arrange_matches() result: ' + str(batches)) log('arranged matches') @@ -1074,19 +1079,71 @@ class QuickCopyAction(PaneJumpAction): if selected: break if not selected: raise ActionCanceled() - # Got result. Do copy. + # Got result. selected_data = selected[0][2] log('Copied: ' + selected_data) + return selected_data, selected + + def run(self): + selected_data, selected = self.run_quickselect() execute_copy(selected_data) # Flash highlights self.match_locations = None hl_ranges = [ (match[4], match[5]) for match in selected ] flash_only_one = str2bool(get_tmux_option('@copytk-flash-only-one', 'on')) - if flash_only_one: hl_ranges = [ hl_ranges[0] ] + if flash_only_one: hl_ranges = [ hl_ranges[-1] ] self.flash_highlight_range(hl_ranges, preflash=True) - + +class QuickOpenAction(QuickCopyAction): + + def __init__(self, stdscr): + super().__init__(stdscr, options_prefix='@copytk-quickopen-') + self.command_extra_env = self.load_env_file() + + def load_env_file(self): + fn = os.path.expanduser(get_tmux_option('@copytk-quickopen-env-file', '~/.tmux-copytk-env')) + if not os.path.exists(fn): + return {} + ret = {} + with open(fn, 'r') as f: + for line in f: + line = line.strip() + if not len(line): continue + if line[0] == '#': continue + parts = line.split('=') + if len(parts) < 2: continue + name = parts[0] + value = '='.join(parts[1:]) + if len(value) >= 2 and value[0] in ('"', "'") and value[-1] in ('"', "'"): + value = value[1:-1] + ret[name] = value + log('Loaded env file: ' + str(ret)) + return ret + + def run(self): + selected_data, selected = self.run_quickselect() + log('quickopen selected: ' + selected_data) + + default_open_cmd = 'xdg-open' + if platform.system() == 'Darwin': + default_open_cmd = 'open' + open_cmd = get_tmux_option('@copytk-quickopen-open-command', default_open_cmd) + env = dict(os.environ) + env.update(self.command_extra_env) + full_cmd = 'nohup ' + open_cmd + " '" + selected_data + "' &>/dev/null & disown" + log('Command: ' + full_cmd) + log('Env: ' + str(env)) + subprocess.Popen( + full_cmd, + executable='/bin/bash', + shell=True, + env=env, + close_fds=True + ) + + def run_easymotion(stdscr): nkeys = 1 if args.search_nkeys: @@ -1104,7 +1161,8 @@ def run_quickcopy(stdscr): log('run_quickcopy') QuickCopyAction(stdscr).run() - +def run_quickopen(stdscr): + QuickOpenAction(stdscr).run() @@ -1194,6 +1252,8 @@ try: curses.wrapper(run_easycopy) elif args.action == 'quickcopy': curses.wrapper(run_quickcopy) + elif args.action == 'quickopen': + curses.wrapper(run_quickopen) else: print('Invalid action') exit(1) diff --git a/copytk.tmux b/copytk.tmux index 6176623..4c9b20f 100755 --- a/copytk.tmux +++ b/copytk.tmux @@ -24,6 +24,10 @@ tmux bind-key -T prefix C-s run-shell -b "python3 $CURRENT_DIR/copytk.py easycop tmux bind-key -T prefix Q run-shell -b "python3 $CURRENT_DIR/copytk.py quickcopy" tmux bind-key -T prefix C-q run-shell -b "python3 $CURRENT_DIR/copytk.py quickcopy" +# tmux prefix: quickopen action bindings +tmux bind-key -T prefix P run-shell -b "python3 $CURRENT_DIR/copytk.py quickopen" +tmux bind-key -T prefix C-p run-shell -b "python3 $CURRENT_DIR/copytk.py quickopen" + # bindings to enter copytk prefix tmux bind-key -T copy-mode-vi S switch-client -T copytk tmux bind-key -T copy-mode S switch-client -T copytk @@ -47,3 +51,8 @@ tmux set -g @copytk-quickcopy-match-3-2 ''\''([^'\'\\'n]*)'\' # Match whole lines tmux set -g @copytk-quickcopy-match-4-0 lines +tmux set -g @copytk-quickopen-match-0-0 urls +tmux set -g @copytk-quickopen-match-0-1 abspaths + + +