mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-25 12:23:09 +00:00
Fix to add a little explanatory text to colors in the web config interface
This commit is contained in:
parent
4885842ae8
commit
4bd63020ca
2 changed files with 339 additions and 258 deletions
|
@ -124,6 +124,8 @@ body {
|
|||
/* Make our border overlap the detail, even if we're unselected (so it doesn't jump when selected) */
|
||||
position: relative;
|
||||
left: 1px;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 0px;
|
||||
}
|
||||
|
||||
.selected_master_elem {
|
||||
|
@ -143,9 +145,32 @@ body {
|
|||
.master_element_text {
|
||||
text-decoration: none;
|
||||
padding-bottom: 1px;
|
||||
border-bottom: 1px solid white;
|
||||
border-bottom-style: inherit;
|
||||
border-bottom-color: inherit;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.master_element_description {
|
||||
text-decoration: none;
|
||||
padding-top: 15px;
|
||||
font-size: 10pt;
|
||||
border-bottom-style: inherit;
|
||||
border-bottom-color: inherit;
|
||||
border-bottom-width: 1px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.selected_master_elem > .master_element_description {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* We have a newline between the label and description; hide it initially, but show it when it's selected */
|
||||
.master_element > br { display: none; }
|
||||
.selected_master_elem > br { display: inherit; }
|
||||
|
||||
/* Set this class to suppress the border bottom on master_element_texts with visible descriptions */
|
||||
.master_element_no_border { border-bottom-width: 0 }
|
||||
|
||||
#colorpicker_term256 {
|
||||
border: solid #444 1px;
|
||||
}
|
||||
|
@ -416,10 +441,12 @@ function switch_tab(new_tab) {
|
|||
/* Keep track of whether this is the first element */
|
||||
var first = true
|
||||
run_get_request('/colors/', function(key_and_values){
|
||||
/* Result is name, description, value */
|
||||
var key = key_and_values[0]
|
||||
var style = new Style(key_and_values[1])
|
||||
var description = key_and_values[1]
|
||||
var style = new Style(key_and_values[2])
|
||||
style_map[key] = style
|
||||
elem = create_master_element(key, style.color, '', select_color_master_element)
|
||||
elem = create_master_element(key, description, style.color, '', select_color_master_element)
|
||||
if (first) {
|
||||
/* It's the first element, so select it, so something gets selected */
|
||||
select_color_master_element(elem)
|
||||
|
@ -432,7 +459,7 @@ function switch_tab(new_tab) {
|
|||
/* Keep track of whether this is the first element */
|
||||
var first = true
|
||||
run_get_request('/functions/', function(contents){
|
||||
elem = create_master_element(contents, 'AAAAAA', '11pt', select_function_master_element)
|
||||
elem = create_master_element(contents, false/* description */, 'AAAAAA', '11pt', select_function_master_element)
|
||||
if (first) {
|
||||
/* It's the first element, so select it, so something gets selected */
|
||||
select_function_master_element(elem)
|
||||
|
@ -493,6 +520,7 @@ function reflect_style() {
|
|||
/* Unselect everything */
|
||||
$('.colorpicker_cell_selected').removeClass('colorpicker_cell_selected')
|
||||
$('.modifier_cell_selected').removeClass('modifier_cell_selected')
|
||||
$('.master_element_no_border').removeClass('master_element_no_border')
|
||||
|
||||
/* Now update the color picker with the current style (if we have one) */
|
||||
style = current_style()
|
||||
|
@ -519,7 +547,16 @@ function reflect_style() {
|
|||
|
||||
/* In the master list, ensure the color is visible against the dark background. If we're deselecting, use COLOR_NORMAL */
|
||||
master_color = style.color ? master_color_for_color(style.color) : COLOR_NORMAL
|
||||
$('.selected_master_elem').children('.master_element_text').css({'color': master_color, 'border-bottom-color': master_color})
|
||||
//$('.selected_master_elem').children('.master_element_text').css({'color': master_color, 'border-bottom-color': master_color})
|
||||
|
||||
var selected_elem = $('.selected_master_elem');
|
||||
var desc_elems = selected_elem.children('.master_element_description')
|
||||
selected_elem.css({'color': master_color})
|
||||
selected_elem.children().css({'border-bottom-color': master_color})
|
||||
if (desc_elems.length) {
|
||||
/* We have a description element, so hide the bottom border of the master element */
|
||||
selected_elem.children('.master_element_text').addClass('master_element_no_border')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -908,33 +945,51 @@ var show_labels = 0
|
|||
var COLOR_NORMAL = 'CCC'
|
||||
|
||||
/* Adds a new element to master */
|
||||
function create_master_element(contents, color, font_size, click_handler) {
|
||||
function create_master_element(contents, description_or_false, color, font_size, click_handler) {
|
||||
/* In the master list, ensure the color is visible against the dark background */
|
||||
var master_color = color ? master_color_for_color(color) : COLOR_NORMAL
|
||||
var style_str = 'color: #' + master_color + '; border-bottom: 1px solid #' + master_color + ' ;'
|
||||
var master_style = 'color: #' + master_color
|
||||
var master_children_style = 'border-bottom-color: #' + master_color
|
||||
var text_style = ''
|
||||
|
||||
if (font_size.length > 0) {
|
||||
style_str += 'font-size: ' + font_size + ';'
|
||||
text_style += 'font-size: ' + font_size + ';'
|
||||
}
|
||||
|
||||
if (contents.length >= 20) {
|
||||
style_str += 'letter-spacing:-2px;'
|
||||
text_style += 'letter-spacing:-2px;'
|
||||
}
|
||||
|
||||
elem = $('<div/>', {
|
||||
class: 'master_element',
|
||||
id: 'master_' + contents,
|
||||
style: master_style,
|
||||
click: function(){
|
||||
click_handler(this)
|
||||
}
|
||||
}).append(
|
||||
$("<span/>", {
|
||||
class: 'master_element_text',
|
||||
style: style_str,
|
||||
style: text_style,
|
||||
text: contents,
|
||||
})
|
||||
)
|
||||
|
||||
/* Append description if we have one */
|
||||
if (description_or_false) {
|
||||
/* Newline between label and description */
|
||||
elem.append($('<br/>'))
|
||||
elem.append(
|
||||
$('<span/>', {
|
||||
class: 'master_element_description',
|
||||
text: description_or_false
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/* Update border color of the master element's children */
|
||||
elem.children().css(master_children_style)
|
||||
|
||||
elem.appendTo('#master')
|
||||
return elem
|
||||
}
|
||||
|
|
|
@ -7,248 +7,274 @@ import subprocess
|
|||
import re, json, socket, os, sys, cgi, select
|
||||
|
||||
def run_fish_cmd(text):
|
||||
from subprocess import PIPE
|
||||
p = subprocess.Popen(["fish"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
||||
out, err = p.communicate(text)
|
||||
return out, err
|
||||
from subprocess import PIPE
|
||||
p = subprocess.Popen(["fish"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
||||
out, err = p.communicate(text)
|
||||
return out, err
|
||||
|
||||
named_colors = {
|
||||
'black' : '000000',
|
||||
'red' : 'FF0000',
|
||||
'green' : '00FF00',
|
||||
'brown' : '725000',
|
||||
'yellow' : 'FFFF00',
|
||||
'blue' : '0000FF',
|
||||
'magenta' : 'FF00FF',
|
||||
'purple' : 'FF00FF',
|
||||
'cyan' : '00FFFF',
|
||||
'white' : 'FFFFFF'
|
||||
'black' : '000000',
|
||||
'red' : 'FF0000',
|
||||
'green' : '00FF00',
|
||||
'brown' : '725000',
|
||||
'yellow' : 'FFFF00',
|
||||
'blue' : '0000FF',
|
||||
'magenta' : 'FF00FF',
|
||||
'purple' : 'FF00FF',
|
||||
'cyan' : '00FFFF',
|
||||
'white' : 'FFFFFF'
|
||||
}
|
||||
|
||||
def parse_one_color(comp):
|
||||
""" A basic function to parse a single color value like 'FFA000' """
|
||||
if comp in named_colors:
|
||||
# Named color
|
||||
return named_colors[comp]
|
||||
elif re.match(r"[0-9a-fA-F]{3}", comp) is not None or re.match(r"[0-9a-fA-F]{6}", comp) is not None:
|
||||
# Hex color
|
||||
return comp
|
||||
else:
|
||||
# Unknown
|
||||
return ''
|
||||
""" A basic function to parse a single color value like 'FFA000' """
|
||||
if comp in named_colors:
|
||||
# Named color
|
||||
return named_colors[comp]
|
||||
elif re.match(r"[0-9a-fA-F]{3}", comp) is not None or re.match(r"[0-9a-fA-F]{6}", comp) is not None:
|
||||
# Hex color
|
||||
return comp
|
||||
else:
|
||||
# Unknown
|
||||
return ''
|
||||
|
||||
|
||||
def parse_color(color_str):
|
||||
""" A basic function to parse a color string, for example, 'red' '--bold' """
|
||||
comps = color_str.split(' ')
|
||||
color = 'normal'
|
||||
background_color = ''
|
||||
bold, underline = False, False
|
||||
for comp in comps:
|
||||
# Remove quotes
|
||||
comp = comp.strip("'\" ")
|
||||
if comp == '--bold':
|
||||
bold = True
|
||||
elif comp == '--underline':
|
||||
underline = True
|
||||
elif comp.startswith('--background='):
|
||||
# Background color
|
||||
background_color = parse_one_color(comp[len('--background='):])
|
||||
else:
|
||||
# Regular color
|
||||
maybe_color = parse_one_color(comp)
|
||||
if maybe_color: color = maybe_color
|
||||
|
||||
return [color, background_color, bold, underline]
|
||||
|
||||
|
||||
""" A basic function to parse a color string, for example, 'red' '--bold' """
|
||||
comps = color_str.split(' ')
|
||||
color = 'normal'
|
||||
background_color = ''
|
||||
bold, underline = False, False
|
||||
for comp in comps:
|
||||
# Remove quotes
|
||||
comp = comp.strip("'\" ")
|
||||
if comp == '--bold':
|
||||
bold = True
|
||||
elif comp == '--underline':
|
||||
underline = True
|
||||
elif comp.startswith('--background='):
|
||||
# Background color
|
||||
background_color = parse_one_color(comp[len('--background='):])
|
||||
else:
|
||||
# Regular color
|
||||
maybe_color = parse_one_color(comp)
|
||||
if maybe_color: color = maybe_color
|
||||
|
||||
return [color, background_color, bold, underline]
|
||||
|
||||
|
||||
def parse_bool(val):
|
||||
val = val.lower()
|
||||
if val.startswith('f') or val.startswith('0'): return False
|
||||
if val.startswith('t') or val.startswith('1'): return True
|
||||
return bool(val)
|
||||
val = val.lower()
|
||||
if val.startswith('f') or val.startswith('0'): return False
|
||||
if val.startswith('t') or val.startswith('1'): return True
|
||||
return bool(val)
|
||||
|
||||
class FishVar:
|
||||
""" A class that represents a variable """
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.universal = False
|
||||
self.exported = False
|
||||
|
||||
def get_json_obj(self):
|
||||
# Return an array(3): name, value, flags
|
||||
flags = []
|
||||
if self.universal: flags.append('universal')
|
||||
if self.exported: flags.append('exported')
|
||||
return [self.name, self.value, ', '.join(flags)]
|
||||
""" A class that represents a variable """
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.universal = False
|
||||
self.exported = False
|
||||
|
||||
def get_json_obj(self):
|
||||
# Return an array(3): name, value, flags
|
||||
flags = []
|
||||
if self.universal: flags.append('universal')
|
||||
if self.exported: flags.append('exported')
|
||||
return [self.name, self.value, ', '.join(flags)]
|
||||
|
||||
class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||
|
||||
def do_get_colors(self):
|
||||
"Look for fish_color_*"
|
||||
result = []
|
||||
remaining = set(['normal',
|
||||
'error',
|
||||
'command',
|
||||
'end',
|
||||
'param',
|
||||
'comment',
|
||||
'match',
|
||||
'search_match',
|
||||
'operator',
|
||||
'escape',
|
||||
'quote',
|
||||
'redirection',
|
||||
'valid_path',
|
||||
'autosuggestion'
|
||||
])
|
||||
|
||||
out, err = run_fish_cmd('set -L')
|
||||
for line in out.split('\n'):
|
||||
for match in re.finditer(r"^fish_color_(\S+) ?(.*)", line):
|
||||
color_name, color_value = [x.strip() for x in match.group(1, 2)]
|
||||
result.append([color_name, parse_color(color_value)])
|
||||
remaining.discard(color_name)
|
||||
|
||||
# Ensure that we have all the color names we know about, so that if the
|
||||
# user deletes one he can still set it again via the web interface
|
||||
for x in remaining:
|
||||
result.append([x, parse_color('')])
|
||||
|
||||
# Sort our result (by their keys)
|
||||
result.sort()
|
||||
|
||||
return result
|
||||
|
||||
def do_get_functions(self):
|
||||
out, err = run_fish_cmd('functions')
|
||||
out = out.strip()
|
||||
|
||||
# Not sure why fish sometimes returns this with newlines
|
||||
if "\n" in out:
|
||||
return out.split('\n')
|
||||
else:
|
||||
return out.strip().split(', ')
|
||||
|
||||
def do_get_variable_names(self, cmd):
|
||||
" Given a command like 'set -U' return all the variable names "
|
||||
out, err = run_fish_cmd(cmd)
|
||||
return out.split('\n')
|
||||
|
||||
def do_get_variables(self):
|
||||
out, err = run_fish_cmd('set -L')
|
||||
|
||||
# Put all the variables into a dictionary
|
||||
vars = {}
|
||||
for line in out.split('\n'):
|
||||
comps = line.split(' ', 1)
|
||||
if len(comps) < 2: continue
|
||||
fish_var = FishVar(comps[0], comps[1])
|
||||
vars[fish_var.name] = fish_var
|
||||
|
||||
# Mark universal variables. L means don't abbreviate.
|
||||
for name in self.do_get_variable_names('set -nUL'):
|
||||
if name in vars: vars[name].universal = True
|
||||
# Mark exported variables. L means don't abbreviate.
|
||||
for name in self.do_get_variable_names('set -nxL'):
|
||||
if name in vars: vars[name].exported = True
|
||||
|
||||
return [vars[key].get_json_obj() for key in sorted(vars.keys(), key=str.lower)]
|
||||
|
||||
def do_get_history(self):
|
||||
# Use \x1e ("record separator") to distinguish between history items. The first
|
||||
# backslash is so Python passes one backslash to fish
|
||||
out, err = run_fish_cmd('for val in $history; echo -n $val \\x1e; end')
|
||||
result = out.split('\x1e')
|
||||
if result: result.pop()
|
||||
return result
|
||||
|
||||
def do_get_colors(self):
|
||||
# Looks for fish_color_*.
|
||||
# Returns an array of lists [color_name, color_description, color_value]
|
||||
result = []
|
||||
|
||||
# Make sure we return at least these
|
||||
remaining = set(['normal',
|
||||
'error',
|
||||
'command',
|
||||
'end',
|
||||
'param',
|
||||
'comment',
|
||||
'match',
|
||||
'search_match',
|
||||
'operator',
|
||||
'escape',
|
||||
'quote',
|
||||
'redirection',
|
||||
'valid_path',
|
||||
'autosuggestion'
|
||||
])
|
||||
|
||||
# Here are our color descriptions
|
||||
descriptions = {
|
||||
'normal': 'Default text',
|
||||
'command': 'Ordinary commands',
|
||||
'quote': 'Text within quotes',
|
||||
'redirection': 'Like | and >',
|
||||
'end': 'Like ; and &',
|
||||
'error': 'Potential errors',
|
||||
'param': 'Command parameters',
|
||||
'comment': 'Comments start with #',
|
||||
'match': 'Matching parenthesis',
|
||||
'search_match': 'History searching',
|
||||
'history_current': 'Directory history',
|
||||
'operator': 'Like * and ~',
|
||||
'escape': 'Escapes like \\n',
|
||||
'cwd': 'Current directory',
|
||||
'cwd_root': 'cwd for root user',
|
||||
'valid_path': 'Valid paths',
|
||||
'autosuggestion': 'Suggested completion'
|
||||
}
|
||||
|
||||
out, err = run_fish_cmd('set -L')
|
||||
for line in out.split('\n'):
|
||||
for match in re.finditer(r"^fish_color_(\S+) ?(.*)", line):
|
||||
color_name, color_value = [x.strip() for x in match.group(1, 2)]
|
||||
color_desc = descriptions.get(color_name, '')
|
||||
result.append([color_name, color_desc, parse_color(color_value)])
|
||||
remaining.discard(color_name)
|
||||
|
||||
# Ensure that we have all the color names we know about, so that if the
|
||||
# user deletes one he can still set it again via the web interface
|
||||
for color_name in remaining:
|
||||
color_desc = descriptions.get(color_name, '')
|
||||
result.append([color_name, color_desc, parse_color('')])
|
||||
|
||||
# Sort our result (by their keys)
|
||||
result.sort()
|
||||
|
||||
return result
|
||||
|
||||
def do_get_functions(self):
|
||||
out, err = run_fish_cmd('functions')
|
||||
out = out.strip()
|
||||
|
||||
# Not sure why fish sometimes returns this with newlines
|
||||
if "\n" in out:
|
||||
return out.split('\n')
|
||||
else:
|
||||
return out.strip().split(', ')
|
||||
|
||||
def do_get_variable_names(self, cmd):
|
||||
" Given a command like 'set -U' return all the variable names "
|
||||
out, err = run_fish_cmd(cmd)
|
||||
return out.split('\n')
|
||||
|
||||
def do_get_variables(self):
|
||||
out, err = run_fish_cmd('set -L')
|
||||
|
||||
# Put all the variables into a dictionary
|
||||
vars = {}
|
||||
for line in out.split('\n'):
|
||||
comps = line.split(' ', 1)
|
||||
if len(comps) < 2: continue
|
||||
fish_var = FishVar(comps[0], comps[1])
|
||||
vars[fish_var.name] = fish_var
|
||||
|
||||
# Mark universal variables. L means don't abbreviate.
|
||||
for name in self.do_get_variable_names('set -nUL'):
|
||||
if name in vars: vars[name].universal = True
|
||||
# Mark exported variables. L means don't abbreviate.
|
||||
for name in self.do_get_variable_names('set -nxL'):
|
||||
if name in vars: vars[name].exported = True
|
||||
|
||||
return [vars[key].get_json_obj() for key in sorted(vars.keys(), key=str.lower)]
|
||||
|
||||
def do_get_history(self):
|
||||
# Use \x1e ("record separator") to distinguish between history items. The first
|
||||
# backslash is so Python passes one backslash to fish
|
||||
out, err = run_fish_cmd('for val in $history; echo -n $val \\x1e; end')
|
||||
result = out.split('\x1e')
|
||||
if result: result.pop()
|
||||
return result
|
||||
|
||||
|
||||
def do_get_color_for_variable(self, name):
|
||||
"Return the color with the given name, or the empty string if there is none"
|
||||
out, err = run_fish_cmd("echo -n $" + name)
|
||||
return out
|
||||
|
||||
def do_set_color_for_variable(self, name, color, background_color, bold, underline):
|
||||
if not color: color = 'normal'
|
||||
"Sets a color for a fish color name, like 'autosuggestion'"
|
||||
command = 'set -U fish_color_' + name
|
||||
if color: command += ' ' + color
|
||||
if background_color: command += ' --background=' + background_color
|
||||
if bold: command += ' --bold'
|
||||
if underline: command += ' --underline'
|
||||
|
||||
out, err = run_fish_cmd(command)
|
||||
return out
|
||||
|
||||
def do_get_function(self, func_name):
|
||||
out, err = run_fish_cmd('functions ' + func_name)
|
||||
return out
|
||||
|
||||
def do_GET(self):
|
||||
p = self.path
|
||||
if p == '/colors/':
|
||||
output = self.do_get_colors()
|
||||
elif p == '/functions/':
|
||||
output = self.do_get_functions()
|
||||
elif p == '/variables/':
|
||||
output = self.do_get_variables()
|
||||
elif p == '/history/':
|
||||
output = self.do_get_history()
|
||||
elif re.match(r"/color/(\w+)/", p):
|
||||
name = re.match(r"/color/(\w+)/", p).group(1)
|
||||
output = self.do_get_color_for_variable(name)
|
||||
else:
|
||||
return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
|
||||
|
||||
# Return valid output
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type','text/html')
|
||||
self.wfile.write('\n')
|
||||
|
||||
# Output JSON
|
||||
json.dump(output, self.wfile)
|
||||
|
||||
def do_POST(self):
|
||||
p = self.path
|
||||
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
|
||||
if ctype == 'multipart/form-data':
|
||||
postvars = cgi.parse_multipart(self.rfile, pdict)
|
||||
elif ctype == 'application/x-www-form-urlencoded':
|
||||
length = int(self.headers.getheader('content-length'))
|
||||
postvars = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
|
||||
else:
|
||||
postvars = {}
|
||||
|
||||
if p == '/set_color/':
|
||||
what = postvars.get('what')
|
||||
color = postvars.get('color')
|
||||
background_color = postvars.get('background_color')
|
||||
bold = postvars.get('bold')
|
||||
underline = postvars.get('underline')
|
||||
if what:
|
||||
# Not sure why we get lists here?
|
||||
output = self.do_set_color_for_variable(what[0], color[0], background_color[0], parse_bool(bold[0]), parse_bool(underline[0]))
|
||||
else:
|
||||
output = 'Bad request'
|
||||
elif p == '/get_function/':
|
||||
what = postvars.get('what')
|
||||
output = [self.do_get_function(what[0])]
|
||||
else:
|
||||
return SimpleHTTPServer.SimpleHTTPRequestHandler.do_POST(self)
|
||||
|
||||
# Return valid output
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type','text/html')
|
||||
self.wfile.write('\n')
|
||||
|
||||
# Output JSON
|
||||
json.dump(output, self.wfile)
|
||||
def do_get_color_for_variable(self, name):
|
||||
"Return the color with the given name, or the empty string if there is none"
|
||||
out, err = run_fish_cmd("echo -n $" + name)
|
||||
return out
|
||||
|
||||
def do_set_color_for_variable(self, name, color, background_color, bold, underline):
|
||||
if not color: color = 'normal'
|
||||
"Sets a color for a fish color name, like 'autosuggestion'"
|
||||
command = 'set -U fish_color_' + name
|
||||
if color: command += ' ' + color
|
||||
if background_color: command += ' --background=' + background_color
|
||||
if bold: command += ' --bold'
|
||||
if underline: command += ' --underline'
|
||||
|
||||
out, err = run_fish_cmd(command)
|
||||
return out
|
||||
|
||||
def do_get_function(self, func_name):
|
||||
out, err = run_fish_cmd('functions ' + func_name)
|
||||
return out
|
||||
|
||||
def do_GET(self):
|
||||
p = self.path
|
||||
if p == '/colors/':
|
||||
output = self.do_get_colors()
|
||||
elif p == '/functions/':
|
||||
output = self.do_get_functions()
|
||||
elif p == '/variables/':
|
||||
output = self.do_get_variables()
|
||||
elif p == '/history/':
|
||||
output = self.do_get_history()
|
||||
elif re.match(r"/color/(\w+)/", p):
|
||||
name = re.match(r"/color/(\w+)/", p).group(1)
|
||||
output = self.do_get_color_for_variable(name)
|
||||
else:
|
||||
return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
|
||||
|
||||
# Return valid output
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type','text/html')
|
||||
self.wfile.write('\n')
|
||||
|
||||
# Output JSON
|
||||
json.dump(output, self.wfile)
|
||||
|
||||
def do_POST(self):
|
||||
p = self.path
|
||||
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
|
||||
if ctype == 'multipart/form-data':
|
||||
postvars = cgi.parse_multipart(self.rfile, pdict)
|
||||
elif ctype == 'application/x-www-form-urlencoded':
|
||||
length = int(self.headers.getheader('content-length'))
|
||||
postvars = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
|
||||
else:
|
||||
postvars = {}
|
||||
|
||||
if p == '/set_color/':
|
||||
what = postvars.get('what')
|
||||
color = postvars.get('color')
|
||||
background_color = postvars.get('background_color')
|
||||
bold = postvars.get('bold')
|
||||
underline = postvars.get('underline')
|
||||
if what:
|
||||
# Not sure why we get lists here?
|
||||
output = self.do_set_color_for_variable(what[0], color[0], background_color[0], parse_bool(bold[0]), parse_bool(underline[0]))
|
||||
else:
|
||||
output = 'Bad request'
|
||||
elif p == '/get_function/':
|
||||
what = postvars.get('what')
|
||||
output = [self.do_get_function(what[0])]
|
||||
else:
|
||||
return SimpleHTTPServer.SimpleHTTPRequestHandler.do_POST(self)
|
||||
|
||||
# Return valid output
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type','text/html')
|
||||
self.wfile.write('\n')
|
||||
|
||||
# Output JSON
|
||||
json.dump(output, self.wfile)
|
||||
|
||||
def log_request(self, code='-', size='-'):
|
||||
""" Disable request logging """
|
||||
pass
|
||||
def log_request(self, code='-', size='-'):
|
||||
""" Disable request logging """
|
||||
pass
|
||||
|
||||
# Make sure that the working directory is the one that contains the script server file,
|
||||
# because the document root is the working directory
|
||||
|
@ -258,23 +284,23 @@ os.chdir(where)
|
|||
# Try to find a suitable port
|
||||
PORT = 8000
|
||||
while PORT <= 9000:
|
||||
try:
|
||||
Handler = FishConfigHTTPRequestHandler
|
||||
httpd = SocketServer.TCPServer(("", PORT), Handler)
|
||||
# Success
|
||||
break;
|
||||
except socket.error:
|
||||
type, value = sys.exc_info()[:2]
|
||||
if 'Address already in use' not in value:
|
||||
break
|
||||
PORT += 1
|
||||
try:
|
||||
Handler = FishConfigHTTPRequestHandler
|
||||
httpd = SocketServer.TCPServer(("", PORT), Handler)
|
||||
# Success
|
||||
break;
|
||||
except socket.error:
|
||||
type, value = sys.exc_info()[:2]
|
||||
if 'Address already in use' not in value:
|
||||
break
|
||||
PORT += 1
|
||||
|
||||
if PORT > 9000:
|
||||
# Nobody say it
|
||||
print "Unable to find an open port between 8000 and 9000"
|
||||
sys.exit(-1)
|
||||
# Nobody say it
|
||||
print "Unable to find an open port between 8000 and 9000"
|
||||
sys.exit(-1)
|
||||
|
||||
|
||||
|
||||
url = 'http://localhost:%d' % PORT
|
||||
|
||||
print "Web config started at '%s'. Hit enter to stop." % url
|
||||
|
@ -283,11 +309,11 @@ webbrowser.open(url)
|
|||
# Select on stdin and httpd
|
||||
stdin_no = sys.stdin.fileno()
|
||||
while True:
|
||||
ready_read, _, _ = select.select([sys.stdin.fileno(), httpd.fileno()], [], [])
|
||||
if stdin_no in ready_read:
|
||||
print "Shutting down."
|
||||
# Consume the newline so it doesn't get printed by the caller
|
||||
sys.stdin.readline()
|
||||
break
|
||||
else:
|
||||
httpd.handle_request()
|
||||
ready_read, _, _ = select.select([sys.stdin.fileno(), httpd.fileno()], [], [])
|
||||
if stdin_no in ready_read:
|
||||
print "Shutting down."
|
||||
# Consume the newline so it doesn't get printed by the caller
|
||||
sys.stdin.readline()
|
||||
break
|
||||
else:
|
||||
httpd.handle_request()
|
||||
|
|
Loading…
Reference in a new issue