Implemented history deletion from fish_config

Fixes https://github.com/fish-shell/fish-shell/issues/250
This commit is contained in:
ridiculousfish 2012-07-27 00:31:00 -07:00
parent 390700ca71
commit e7cbcc83a4
6 changed files with 261 additions and 9353 deletions

View file

@ -29,6 +29,8 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
D07A7D3C15A7A38100811FC6 /* builtin_scripts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0F5E28215A7A32D00315DFF /* builtin_scripts.cpp */; }; D07A7D3C15A7A38100811FC6 /* builtin_scripts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0F5E28215A7A32D00315DFF /* builtin_scripts.cpp */; };
D07B247315BCC15700D4ADB4 /* add-shell in Resources */ = {isa = PBXBuildFile; fileRef = D07B247215BCC15700D4ADB4 /* add-shell */; };
D07B247615BCC4BE00D4ADB4 /* install.sh in Resources */ = {isa = PBXBuildFile; fileRef = D07B247515BCC4BE00D4ADB4 /* install.sh */; };
D0C4FD9515A7D80700212EF1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0C4FD9415A7D7EE00212EF1 /* config.fish */; }; D0C4FD9515A7D80700212EF1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0C4FD9415A7D7EE00212EF1 /* config.fish */; };
D0C4FD9615A7D80C00212EF1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0CBD580159EE48F0024809C /* config.fish */; }; D0C4FD9615A7D80C00212EF1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0CBD580159EE48F0024809C /* config.fish */; };
D0CBD57B159EE4640024809C /* completions in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0CBD578159EE4600024809C /* completions */; }; D0CBD57B159EE4640024809C /* completions in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0CBD578159EE4600024809C /* completions */; };
@ -279,6 +281,8 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
D03EE83814DF88B200FC7150 /* lru.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lru.h; sourceTree = "<group>"; }; D03EE83814DF88B200FC7150 /* lru.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lru.h; sourceTree = "<group>"; };
D07B247215BCC15700D4ADB4 /* add-shell */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "add-shell"; path = "build_tools/osx_package_scripts/add-shell"; sourceTree = "<group>"; };
D07B247515BCC4BE00D4ADB4 /* install.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = install.sh; path = osx/install.sh; sourceTree = "<group>"; };
D09B1C1914FC7B5B00F91077 /* postfork.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = postfork.cpp; sourceTree = "<group>"; }; D09B1C1914FC7B5B00F91077 /* postfork.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = postfork.cpp; sourceTree = "<group>"; };
D09B1C1A14FC7B5B00F91077 /* postfork.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = postfork.h; sourceTree = "<group>"; }; D09B1C1A14FC7B5B00F91077 /* postfork.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = postfork.h; sourceTree = "<group>"; };
D0A0850313B3ACEE0099B651 /* builtin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = builtin.h; sourceTree = "<group>"; }; D0A0850313B3ACEE0099B651 /* builtin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = builtin.h; sourceTree = "<group>"; };
@ -599,9 +603,11 @@
D0D02AAB15985C14008E62BD /* Resources */ = { D0D02AAB15985C14008E62BD /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D07B247215BCC15700D4ADB4 /* add-shell */,
D0CBD586159EF0E10024809C /* launch_fish.scpt */, D0CBD586159EF0E10024809C /* launch_fish.scpt */,
D0CBD580159EE48F0024809C /* config.fish */, D0CBD580159EE48F0024809C /* config.fish */,
D0C4FD9415A7D7EE00212EF1 /* config.fish */, D0C4FD9415A7D7EE00212EF1 /* config.fish */,
D07B247515BCC4BE00D4ADB4 /* install.sh */,
D0CBD578159EE4600024809C /* completions */, D0CBD578159EE4600024809C /* completions */,
D0CBD579159EE4600024809C /* functions */, D0CBD579159EE4600024809C /* functions */,
D0CBD57A159EE4600024809C /* tools */, D0CBD57A159EE4600024809C /* tools */,
@ -805,6 +811,8 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D0CBD587159EF0E10024809C /* launch_fish.scpt in Resources */, D0CBD587159EF0E10024809C /* launch_fish.scpt in Resources */,
D07B247315BCC15700D4ADB4 /* add-shell in Resources */,
D07B247615BCC4BE00D4ADB4 /* install.sh in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View file

@ -3639,15 +3639,12 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
bool save_history = false; bool save_history = false;
bool clear_history = false; bool clear_history = false;
wcstring delete_string;
wcstring search_string;
static const struct woption long_options[] = static const struct woption long_options[] =
{ {
{ L"prefix", required_argument, 0, 'p' }, { L"prefix", no_argument, 0, 'p' },
{ L"delete", required_argument, 0, 'd' }, { L"delete", no_argument, 0, 'd' },
{ L"search", no_argument, 0, 's' }, { L"search", no_argument, 0, 's' },
{ L"contains", required_argument, 0, 'c' }, { L"contains", no_argument, 0, 'c' },
{ L"save", no_argument, 0, 'v' }, { L"save", no_argument, 0, 'v' },
{ L"clear", no_argument, 0, 'l' }, { L"clear", no_argument, 0, 'l' },
{ L"help", no_argument, 0, 'h' }, { L"help", no_argument, 0, 'h' },
@ -3658,24 +3655,25 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
int opt_index = 0; int opt_index = 0;
woptind = 0; woptind = 0;
history_t *history = reader_get_history(); history_t *history = reader_get_history();
/* Use the default history if we have none (which happens if invoked non-interactively, e.g. from webconfig.py */
if (! history)
history = &history_t::history_with_name(L"fish");
while((opt = wgetopt_long_only( argc, argv, L"pdscvl", long_options, &opt_index )) != -1) while((opt = wgetopt_long_only( argc, argv, L"pdscvl", long_options, &opt_index )) != -1)
{ {
switch(opt) switch(opt)
{ {
case 'p': case 'p':
search_prefix = true; search_prefix = true;
search_string = woptarg;
break; break;
case 'd': case 'd':
delete_item = true; delete_item = true;
delete_string = woptarg;
break; break;
case 's': case 's':
search_history = true; search_history = true;
break; break;
case 'c': case 'c':
search_string = woptarg;
break; break;
case 'v': case 'v':
save_history = true; save_history = true;
@ -3687,6 +3685,9 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
builtin_print_help( parser, argv[0], stdout_buffer ); builtin_print_help( parser, argv[0], stdout_buffer );
return STATUS_BUILTIN_OK; return STATUS_BUILTIN_OK;
break; break;
case EOF:
/* Remainder are arguments */
break;
case '?': case '?':
append_format(stderr_buffer, BUILTIN_ERR_UNKNOWN, argv[0], argv[woptind-1]); append_format(stderr_buffer, BUILTIN_ERR_UNKNOWN, argv[0], argv[woptind-1]);
return STATUS_BUILTIN_ERROR; return STATUS_BUILTIN_ERROR;
@ -3697,6 +3698,9 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
} }
} }
/* Everything after is an argument */
const wcstring_list_t args(argv + woptind, argv + argc);
if (argc == 1) if (argc == 1)
{ {
wcstring full_history; wcstring full_history;
@ -3709,29 +3713,36 @@ static int builtin_history( parser_t &parser, wchar_t **argv )
if (search_history) if (search_history)
{ {
int res = STATUS_BUILTIN_ERROR; int res = STATUS_BUILTIN_ERROR;
for (wcstring_list_t::const_iterator iter = args.begin(); iter != args.end(); ++iter)
if (search_string.empty())
{ {
append_format(stderr_buffer, BUILTIN_ERR_COMBO2, argv[0], L"Use --search with either --contains or --prefix"); const wcstring &search_string = *iter;
return res; if (search_string.empty())
} {
append_format(stderr_buffer, BUILTIN_ERR_COMBO2, argv[0], L"Use --search with either --contains or --prefix");
return res;
}
history_search_t searcher = history_search_t(*history, search_string, search_prefix?HISTORY_SEARCH_TYPE_PREFIX:HISTORY_SEARCH_TYPE_CONTAINS); history_search_t searcher = history_search_t(*history, search_string, search_prefix?HISTORY_SEARCH_TYPE_PREFIX:HISTORY_SEARCH_TYPE_CONTAINS);
while (searcher.go_backwards()) while (searcher.go_backwards())
{ {
stdout_buffer.append(searcher.current_string()); stdout_buffer.append(searcher.current_string());
stdout_buffer.append(L"\n"); stdout_buffer.append(L"\n");
res = STATUS_BUILTIN_OK; res = STATUS_BUILTIN_OK;
}
} }
return res; return res;
} }
if (delete_item) if (delete_item)
{ {
if (delete_string[0] == '"' && delete_string[delete_string.length() - 1] == '"') for (wcstring_list_t::const_iterator iter = args.begin(); iter != args.end(); ++iter)
delete_string = delete_string.substr(1, delete_string.length() - 2); {
wcstring delete_string = *iter;
history->remove(delete_string); if (delete_string[0] == '"' && delete_string[delete_string.length() - 1] == '"')
delete_string = delete_string.substr(1, delete_string.length() - 2);
history->remove(delete_string);
}
return STATUS_BUILTIN_OK; return STATUS_BUILTIN_OK;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -106,6 +106,7 @@ body {
padding-left: 30px; padding-left: 30px;
padding-right: 30px; padding-right: 30px;
border-radius: 5; border-radius: 5;
width: 100%;
} }
#detail_function { #detail_function {
@ -221,6 +222,11 @@ body {
word-wrap: break-word; word-wrap: break-word;
} }
/* The CSS we apply when a table row is filtered */
.data_table_row_filtered {
display: none;
}
.no_overflow { .no_overflow {
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
@ -275,6 +281,37 @@ body {
margin-bottom: 5pt; margin-bottom: 5pt;
} }
img.delete_icon {
width: 20px;
height: 20px;
cursor: pointer;
text-decoration: none;
border: none;
}
#table_filter_container {
/* top right bottom left*/
padding: 0 10 10 30;
text-align: right;
position: relative;
bottom: 10px;
}
.table_filter_text_box {
width: 250px;
padding: 5 10 5 10;
background-color: #888;
border: #222 solid 3px;
border-radius: 15px;
font-size: 12pt;
color: white;
font-weight: bold;
}
.text_box_transient {
color: #C8C8C8;
}
</style> </style>
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="jquery.js"></script>
@ -307,20 +344,27 @@ function request_failed(jqXHR, textStatus, errorThrown) {
} }
/* Runs a GET request, parses the JSON, and invokes the handler for each element in it. The JSON result is assumed to be an array. */ /* Runs a GET request, parses the JSON, and invokes the handler for each element in it. The JSON result is assumed to be an array. */
function run_get_request(url, handler) { function run_get_request_with_bulk_handler(url, handler) {
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: url, url: url,
success: function(data){ success: function(data){
$('#global_error').text('') $('#global_error').text('')
$.each($.parseJSON(data), function(idx, contents) { handler($.parseJSON(data))
handler(contents)
})
}, },
error: request_failed error: request_failed
}) })
} }
function run_get_request(url, handler) {
run_get_request_with_bulk_handler(url, function(json_contents){
$.each(json_contents, function(idx, contents){
handler(contents)
})
})
}
/* As above but with POST request. */ /* As above but with POST request. */
function run_post_request(url, data_map, handler) { function run_post_request(url, data_map, handler) {
$.ajax({ $.ajax({
@ -469,16 +513,33 @@ function switch_tab(new_tab) {
$('#detail_function').show() $('#detail_function').show()
$('#master_detail_table').show() $('#master_detail_table').show()
} else if (new_tab == 'tab_variables') { } else if (new_tab == 'tab_variables') {
run_get_request('/variables/', function(contents){ run_get_request_with_bulk_handler('/variables/', function(json_contents){
var name = contents[0] var rows = new Array()
var value = contents[1] for (var i = 0; i < json_contents.length; i++) {
var flags = contents[2] var contents = json_contents[i]
create_data_table_element([name, value]) var name = contents[0]
var value = contents[1]
var flags = contents[2]
var row = create_data_table_element_text([name, value], false)
rows[i] = row
}
$('#data_table').append(rows.join(''))
}) })
$('#data_table').show() $('#data_table').show()
} else if (new_tab == 'tab_history') { } else if (new_tab == 'tab_history') {
run_get_request('/history/', function(contents){ // Clear the history map
create_data_table_element([contents]) history_element_map.length = 0
run_get_request_with_bulk_handler('/history/', function(json_contents){
start = new Date().getTime()
var rows = new Array()
for (var i = 0; i < json_contents.length; i++) {
var history_text = json_contents[i]
rows[i] = create_data_table_element_text([history_text], true)
history_element_map[last_global_element_identifier] = history_text
}
$('#data_table').append(rows.join(''))
end = new Date().getTime()
//alert(rows.length + " rows in " + (end - start) + " msec")
}) })
$('#data_table').show() $('#data_table').show()
} else { } else {
@ -999,36 +1060,53 @@ function toggle_overflow(who) {
$(who).toggleClass('no_overflow') $(who).toggleClass('no_overflow')
} }
function escape_HTML(foo) {
return foo.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}
/* Given the image, walk up to the table */
function tell_fish_to_delete_element(idx) {
var row_elem = $('#data_table_row_' + idx)
var txt = history_element_map[idx]
run_post_request('/delete_history_item/', {
what: txt
}, function(contents){
if (contents == "OK") {
row_elem.remove();
} else {
show_error(contents)
}
});
}
/* Creates a new row in the data table */ /* Creates a new row in the data table */
function create_data_table_element(contents_list) { var last_global_element_identifier = 0
var row = $('<tr>', { var history_element_map = new Array();
class: 'data_table_row'
}) function create_data_table_element_text(contents_list, show_delete_button) {
var element_identifier = (++last_global_element_identifier).toString()
lines = new Array()
var result_str = '<tr class="data_table_row" id="data_table_row_' + element_identifier + '">'
for (idx = 0; idx < contents_list.length; idx++) { for (idx = 0; idx < contents_list.length; idx++) {
/* If we have more than one, then align the first one right, subsequent ones left */ /* If we have more than one, then align the first one right, subsequent ones left */
if (idx == 0 && contents_list.length > 1) { if (idx == 0 && contents_list.length > 1) {
cell = $('<td>', { result_str += '<td class="data_table_cell no_overflow" style="text-align: right; padding-right: 30px;">'
class: 'data_table_cell no_overflow',
style: 'text-align: right; padding-right: 30px;'
});
} else { } else {
cell = $('<td>', { result_str += '<td class="data_table_cell no_overflow" style="text-align: left; padding-right: 30px;" onClick:"toggle_overflow(this)">'
class: 'data_table_cell no_overflow',
style: 'text-align: left',
onClick: 'toggle_overflow(this)'
});
} }
text_list = contents_list[idx].split("\n") text_list = contents_list[idx].split("\n")
for (j=0; j < text_list.length; j++) { for (j=0; j < text_list.length; j++) {
cell.append($('<p>', { if (j > 0) result_str += '<br>'
text: text_list[j] result_str += escape_HTML(text_list[j]);
}))
} }
result_str += '</td>'
row.append(cell)
} }
$('#data_table').append(row) if (show_delete_button) {
result_str += '<td class="data_table_cell" style="text-align: right; width: 25px"><a onClick="tell_fish_to_delete_element(' + element_identifier + ')"><img class="delete_icon" src="delete.png"></a></td>'
}
result_str += '</tr>'
return result_str
} }
/* Put stuff in colorpicker_term256 */ /* Put stuff in colorpicker_term256 */
@ -1061,6 +1139,54 @@ function populate_colorpicker_term256() {
} }
} }
/* Update the filter text box */
function update_table_filter_text_box(allow_transient_message) {
var box = $('.table_filter_text_box')
var has_transient = box.hasClass('text_box_transient')
if (! allow_transient_message && has_transient) {
box.val('')
box.removeClass('text_box_transient')
has_transient = false
} else if (allow_transient_message && ! has_transient && ! box.val().length) {
box.val('Filter')
box.addClass('text_box_transient')
has_transient = true
}
var search_text = box.val()
if (has_transient || search_text.length == 0) {
/* Unfilter all */
$('.data_table_row_filtered').removeClass('data_table_row_filtered')
} else {
/* Helper function to return whether a node (or its descendants) matches the given text */
function match_text(node) {
if (node.nodeType == 3) {
return node.nodeValue.indexOf(search_text) != -1
} else {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
if (match_text(node.childNodes[i])) {
return true;
}
}
}
return false
}
$('.data_table_row').each(function(idx) {
var row = $(this)
var is_hidden = row.hasClass('data_table_row_filtered')
var should_be_hidden = ! match_text(this)
if (is_hidden && ! should_be_hidden) {
row.removeClass('data_table_row_filtered')
} else if (! is_hidden && should_be_hidden) {
row.addClass('data_table_row_filtered')
}
})
}
return true
}
$(document).ready(function() { $(document).ready(function() {
populate_colorpicker_term256() populate_colorpicker_term256()
switch_tab('tab_colors') switch_tab('tab_colors')
@ -1096,7 +1222,13 @@ $(document).ready(function() {
<div id="detail_function"></div> <div id="detail_function"></div>
</div> </div>
</div> </div>
<table id="data_table"><tr><td></td></tr> <table id="data_table">
<div id="table_filter_container">
<input type="text" class="table_filter_text_box text_box_transient" value="Filter" onInput="update_table_filter_text_box(false)" onFocus="update_table_filter_text_box(false)" onBlur="update_table_filter_text_box(true)">
</div>
<tr><td>
</td></tr>
<tr><td></td></tr>
</table> </table>
<div class="footer"> <div class="footer">
</div> </div>

File diff suppressed because one or more lines are too long

View file

@ -1,27 +1,34 @@
#!/usr/bin/env python #!/usr/bin/env python
try: #Python2 # Whether we're Python 2
import sys
IS_PY2 = sys.version_info[0] == 2
if IS_PY2:
import SimpleHTTPServer import SimpleHTTPServer
except ImportError: #Python3
import http.server as SimpleHTTPServer
try: #Python2
import SocketServer import SocketServer
except ImportError: #Python3 else:
import http.server as SimpleHTTPServer
import socketserver as SocketServer import socketserver as SocketServer
import webbrowser import webbrowser
import subprocess import subprocess
import re, json, socket, os, sys, cgi, select import re, json, socket, os, sys, cgi, select, time
def run_fish_cmd(text): def run_fish_cmd(text):
from subprocess import PIPE from subprocess import PIPE
p = subprocess.Popen(["fish"], stdin=PIPE, stdout=PIPE, stderr=PIPE) p = subprocess.Popen(["fish"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
try: #Python2 if IS_PY2:
out, err = p.communicate(text) out, err = p.communicate(text)
except TypeError: #Python3 else:
out, err = p.communicate(bytes(text, 'utf-8')) out, err = p.communicate(bytes(text, 'utf-8'))
out = str(out, 'utf-8') out = str(out, 'utf-8')
err = str(err, 'utf-8') err = str(err, 'utf-8')
return(out, err) return(out, err)
def escape_fish_cmd(text):
# Replace one backslash with two, and single quotes with backslash-quote
escaped = text.replace('\\', '\\\\').replace("'", "\\'")
return "'" + escaped + "'"
named_colors = { named_colors = {
'black' : '000000', 'black' : '000000',
@ -105,6 +112,13 @@ class FishVar:
class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def write_to_wfile(self, txt):
if IS_PY2:
self.wfile.write(txt)
else: # Python 3
self.wfile.write(bytes(txt, 'utf-8'))
def do_get_colors(self): def do_get_colors(self):
# Looks for fish_color_*. # Looks for fish_color_*.
# Returns an array of lists [color_name, color_description, color_value] # Returns an array of lists [color_name, color_description, color_value]
@ -207,8 +221,8 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
# Use \x1e ("record separator") to distinguish between history items. The first # Use \x1e ("record separator") to distinguish between history items. The first
# backslash is so Python passes one backslash to fish # backslash is so Python passes one backslash to fish
out, err = run_fish_cmd('for val in $history; echo -n $val \\x1e; end') out, err = run_fish_cmd('for val in $history; echo -n $val \\x1e; end')
result = out.split('\x1e') result = out.split(' \x1e')
if result: result.pop() if result: result.pop() # Trim off the trailing element
return result return result
@ -233,6 +247,11 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
out, err = run_fish_cmd('functions ' + func_name) out, err = run_fish_cmd('functions ' + func_name)
return out return out
def do_delete_history_item(self, history_item_text):
# It's really lame that we always return success here
out, err = run_fish_cmd('builtin history --save --delete -- ' + escape_fish_cmd(history_item_text))
return True
def do_GET(self): def do_GET(self):
p = self.path p = self.path
if p == '/colors/': if p == '/colors/':
@ -242,7 +261,10 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
elif p == '/variables/': elif p == '/variables/':
output = self.do_get_variables() output = self.do_get_variables()
elif p == '/history/': elif p == '/history/':
# start = time.time()
output = self.do_get_history() output = self.do_get_history()
# end = time.time()
# print "History: ", end - start
elif re.match(r"/color/(\w+)/", p): elif re.match(r"/color/(\w+)/", p):
name = re.match(r"/color/(\w+)/", p).group(1) name = re.match(r"/color/(\w+)/", p).group(1)
output = self.do_get_color_for_variable(name) output = self.do_get_color_for_variable(name)
@ -252,22 +274,16 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
# Return valid output # Return valid output
self.send_response(200) self.send_response(200)
self.send_header('Content-type','text/html') self.send_header('Content-type','text/html')
try: #Python2 self.write_to_wfile('\n')
self.wfile.write('\n')
except TypeError: #Python3
self.wfile.write(bytes('\n', 'utf-8'))
# Output JSON # Output JSON
try: #Python2 self.write_to_wfile(json.dumps(output))
self.wfile.write(json.dumps(output))
except TypeError: #Python3
self.wfile.write(bytes(json.dumps(output), 'utf-8'))
def do_POST(self): def do_POST(self):
p = self.path p = self.path
try: #Python2 if IS_PY2:
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type')) ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
except AttributeError: #Python3 else: # Python 3
ctype, pdict = cgi.parse_header(self.headers['content-type']) ctype, pdict = cgi.parse_header(self.headers['content-type'])
if ctype == 'multipart/form-data': if ctype == 'multipart/form-data':
postvars = cgi.parse_multipart(self.rfile, pdict) postvars = cgi.parse_multipart(self.rfile, pdict)
@ -310,22 +326,25 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
what = postvars.get(b'what') what = postvars.get(b'what')
what[0] = str(what[0]).lstrip("b'").rstrip("'") what[0] = str(what[0]).lstrip("b'").rstrip("'")
output = [self.do_get_function(what[0])] output = [self.do_get_function(what[0])]
elif p == '/delete_history_item/':
what = postvars.get('what')
if what == None: #Will be None for python3
what = postvars.get(b'what')
what[0] = str(what[0]).lstrip("b'").rstrip("'")
if self.do_delete_history_item(what[0]):
output = ["OK"]
else:
output = ["Unable to delete history item"]
else: else:
return SimpleHTTPServer.SimpleHTTPRequestHandler.do_POST(self) return SimpleHTTPServer.SimpleHTTPRequestHandler.do_POST(self)
# Return valid output # Return valid output
self.send_response(200) self.send_response(200)
self.send_header('Content-type','text/html') self.send_header('Content-type','text/html')
try: #Python2 self.write_to_wfile('\n')
self.wfile.write('\n')
except TypeError: #Python3
self.wfile.write(bytes('\n', 'utf-8'))
# Output JSON # Output JSON
try: #Python2 self.write_to_wfile(json.dumps(output))
self.wfile.write(json.dumps(output))
except TypeError: #Python3
self.wfile.write(bytes(json.dumps(output), 'utf-8'))
def log_request(self, code='-', size='-'): def log_request(self, code='-', size='-'):
""" Disable request logging """ """ Disable request logging """