aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--NEWS7
-rwxr-xr-xtransmission-remote-cli55
2 files changed, 58 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index 5f62c47..0bbe329 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+1.7.0 2014-05-14
+ BUGFIXES:
+ - Check if 'transmission-remote' exists before executing it
+ - File list: Visual mode for operating on multiple files
+ - Add torrent by hash with shift-a
+
+
1.6.3 2013-11-07
BUGFIXES:
- Properly handle East-Asian wide characters in progress bar/torrent title
diff --git a/transmission-remote-cli b/transmission-remote-cli
index 540a058..96de53e 100755
--- a/transmission-remote-cli
+++ b/transmission-remote-cli
@@ -16,7 +16,7 @@
# http://www.gnu.org/licenses/gpl-3.0.txt #
########################################################################
-VERSION = '1.6.3'
+VERSION = '1.7.0'
TRNSM_VERSION_MIN = '1.90'
TRNSM_VERSION_MAX = '2.82'
@@ -28,7 +28,6 @@ CONNECTION_ERROR = 1
JSON_ERROR = 2
CONFIGFILE_ERROR = 3
-
# use simplejson if available because it seems to be faster
try:
import simplejson as json
@@ -63,6 +62,7 @@ from subprocess import call, Popen
import netrc
import operator
import urlparse
+from distutils.spawn import find_executable
locale.setlocale(locale.LC_ALL, '')
ENCODING = locale.getpreferredencoding() or 'UTF-8'
@@ -199,6 +199,7 @@ class Normalizer:
authhandler = None
session_id = 0
+vmode_id = -1
# Handle communication with Transmission server.
class TransmissionRequest:
@@ -900,6 +901,7 @@ class Interface:
ord('N'): self.start_now_torrent,
ord('v'): self.verify_torrent,
ord('y'): self.verify_torrent,
+ ord('V'): self.V_key,
ord('r'): self.r_key,
curses.KEY_DC: self.r_key,
ord('R'): self.remove_torrent_local_data,
@@ -1142,6 +1144,11 @@ class Interface:
# File list
if self.selected_torrent > -1 and self.details_category_focus == 1:
self.select_unselect_file(c)
+ # Do nothing in other detail tabs
+ elif self.selected_torrent > -1:
+ pass
+ else:
+ self.add_torrent_by_hash()
def a_key(self, c):
# File list
@@ -1157,6 +1164,11 @@ class Interface:
else:
self.add_torrent()
+ def V_key(self, c):
+ # File list
+ if self.selected_torrent > -1 and self.details_category_focus == 1:
+ self.select_unselect_file(c)
+
def o_key(self, c):
if self.selected_torrent == -1:
self.draw_options_dialog()
@@ -1216,6 +1228,15 @@ class Interface:
msg.extend(wrap(error, self.width-4))
self.dialog_ok("\n".join(msg))
+ def add_torrent_by_hash(self):
+ hash = self.dialog_input_text("Add torrent by hash")
+ if hash:
+ error = server.add_torrent('magnet:?xt=urn:btih:{}'.format(hash))
+ if error:
+ msg = wrap("Couldn't add torrent \"%s\":" % hash)
+ msg.extend(wrap(error, self.width-4))
+ self.dialog_ok("\n".join(msg))
+
def enter_key(self, c):
# Torrent list
if self.focus > -1 and self.selected_torrent == -1:
@@ -1460,6 +1481,13 @@ class Interface:
elif c == curses.KEY_END or c == ord('G'):
self.focus_detaillist, self.scrollpos_detaillist = \
self.move_to_end(1, self.detaillistitems_per_page, len(self.torrent_details['files']))
+ # visual mode
+ global vmode_id
+ if vmode_id > -1:
+ if vmode_id < self.focus_detaillist:
+ self.selected_files = range(vmode_id, self.focus_detaillist + 1)
+ else:
+ self.selected_files = range(self.focus_detaillist, vmode_id + 1)
list_len = 0
# peer list movement
@@ -1563,6 +1591,18 @@ class Interface:
self.selected_files = []
else:
self.selected_files = range(0, len(self.torrent_details['files']))
+ elif c == ord('V'):
+ global vmode_id
+ if self.selected_files:
+ self.selected_files = []
+ if vmode_id != -1:
+ vmode_id = -1
+ else:
+ try:
+ self.selected_files.pop(self.selected_files.index(self.focus_detaillist))
+ except ValueError:
+ self.selected_files.append(self.focus_detaillist)
+ vmode_id = self.focus_detaillist
def move_to_next_directory_in_filelist(self):
if self.selected_torrent > -1 and self.details_category_focus == 1:
@@ -2527,6 +2567,8 @@ class Interface:
"Incoming:%d " % self.torrent_details['peersFrom']['fromIncoming'] + \
"Cache:%d)" % self.torrent_details['peersFrom']['fromCache'],
curses.A_REVERSE)
+ elif vmode_id > -1:
+ self.screen.addstr((self.height-1), 0, "-- VISUAL --", curses.A_REVERSE)
else:
self.screen.addstr((self.height-1), 0, "Torrent%s:" % ('s','')[len(self.torrents) == 1],
curses.A_REVERSE)
@@ -2621,6 +2663,7 @@ class Interface:
if self.details_category_focus == 1 and self.focus_detaillist > -1:
help = [('enter', 'Open File'),
('space','(De)Select File'),
+ ('V','Visually Select Files'),
('left/right','De-/Increase Priority'),
('escape','Unfocus/-select')] + help
elif self.details_category_focus == 2:
@@ -2647,6 +2690,7 @@ class Interface:
" m Move torrent\n" + \
" n Reannounce torrent\n" + \
" a Add torrent\n" + \
+ " A Add torrent by hash\n" + \
" Del/r Remove torrent and keep content\n" + \
" Shift+Del/R Remove torrent and delete content\n"
@@ -2699,6 +2743,7 @@ class Interface:
" Space Select/Deselect focused file\n" + \
" a Select/Deselect all files\n" + \
" A Select/Deselect directory\n" + \
+ " V Visually select files\n" + \
" Esc Unfocus+Unselect or Back to torrent list\n" + \
" q/Backspace Back to torrent list"
else:
@@ -3161,7 +3206,7 @@ class Interface:
server.set_option('seed-queue-size', queue_size)
elif c == ord('k'):
- self.blank_lines = not self.blank_lines
+ self.blank_lines = not self.blank_lines
elif c == ord('v'):
viewer = self.dialog_input_text('File Viewer\nExample: xdg-viewer %s', self.file_viewer)
@@ -3548,6 +3593,8 @@ if __name__ == '__main__':
if transmissionremote_args:
cmd = ['transmission-remote', '%s:%s' %
(config.get('Connection', 'host'), config.get('Connection', 'port'))]
+ if find_executable(cmd[0]) is None:
+ quit("Command not found: %s\n" % cmd[0], 128)
# one argument and it doesn't start with '-' --> treat it like it's a torrent link/url
if len(transmissionremote_args) == 1 and not transmissionremote_args[0].startswith('-'):
@@ -3566,7 +3613,7 @@ if __name__ == '__main__':
try:
retcode = call(cmd)
except OSError, msg:
- quit("Could not execute the above command: %s\n" % msg, 128)
+ quit("Could not execute the above command: %s\n" % msg.strerror, 128)
quit('', retcode)