mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-26 03:35:17 +00:00
fix webconfig.py lint issues
This commit is contained in:
parent
47a9f99523
commit
20bcbcc252
1 changed files with 241 additions and 134 deletions
|
@ -1,19 +1,28 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
# Whether we're Python 2
|
import binascii
|
||||||
import sys
|
import cgi
|
||||||
|
import glob
|
||||||
import multiprocessing.pool
|
import multiprocessing.pool
|
||||||
import os
|
|
||||||
import operator
|
import operator
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import re
|
||||||
|
import select
|
||||||
import socket
|
import socket
|
||||||
|
import string
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
|
FISH_BIN_PATH = False # will be set later
|
||||||
IS_PY2 = sys.version_info[0] == 2
|
IS_PY2 = sys.version_info[0] == 2
|
||||||
|
|
||||||
if IS_PY2:
|
if IS_PY2:
|
||||||
import SimpleHTTPServer
|
import SimpleHTTPServer
|
||||||
import SocketServer
|
import SocketServer
|
||||||
from urlparse import parse_qs
|
from urlparse import parse_qs
|
||||||
|
|
||||||
else:
|
else:
|
||||||
import http.server as SimpleHTTPServer
|
import http.server as SimpleHTTPServer
|
||||||
import socketserver as SocketServer
|
import socketserver as SocketServer
|
||||||
|
@ -21,22 +30,20 @@ else:
|
||||||
|
|
||||||
# Disable CLI web browsers
|
# Disable CLI web browsers
|
||||||
term = os.environ.pop('TERM', None)
|
term = os.environ.pop('TERM', None)
|
||||||
import webbrowser
|
|
||||||
if term:
|
if term:
|
||||||
os.environ['TERM'] = term
|
os.environ['TERM'] = term
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import re, cgi, select, time, glob, random, string, binascii
|
|
||||||
try:
|
try:
|
||||||
import json
|
import json
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import simplejson as json
|
import simplejson as json
|
||||||
|
|
||||||
FISH_BIN_PATH = False # will be set later
|
|
||||||
def run_fish_cmd(text):
|
def run_fish_cmd(text):
|
||||||
from subprocess import PIPE
|
from subprocess import PIPE
|
||||||
# ensure that fish is using UTF-8
|
# Ensure that fish is using UTF-8.
|
||||||
ctype = os.environ.get("LC_ALL", os.environ.get("LC_CTYPE", os.environ.get("LANG")))
|
ctype = os.environ.get("LC_ALL", os.environ.get("LC_CTYPE",
|
||||||
|
os.environ.get("LANG")))
|
||||||
env = None
|
env = None
|
||||||
if ctype is None or re.search(r"\.utf-?8$", ctype, flags=re.I) is None:
|
if ctype is None or re.search(r"\.utf-?8$", ctype, flags=re.I) is None:
|
||||||
# override LC_CTYPE with en_US.UTF-8
|
# override LC_CTYPE with en_US.UTF-8
|
||||||
|
@ -44,68 +51,66 @@ def run_fish_cmd(text):
|
||||||
# Fish makes the same assumption in config.fish
|
# Fish makes the same assumption in config.fish
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env.update(LC_CTYPE="en_US.UTF-8", LANG="en_US.UTF-8")
|
env.update(LC_CTYPE="en_US.UTF-8", LANG="en_US.UTF-8")
|
||||||
p = subprocess.Popen([FISH_BIN_PATH], stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env)
|
p = subprocess.Popen([FISH_BIN_PATH], stdin=PIPE, stdout=PIPE, stderr=PIPE,
|
||||||
|
env=env)
|
||||||
out, err = p.communicate(text.encode('utf-8'))
|
out, err = p.communicate(text.encode('utf-8'))
|
||||||
out = out.decode('utf-8', 'replace')
|
out = out.decode('utf-8', 'replace')
|
||||||
err = err.decode('utf-8', 'replace')
|
err = err.decode('utf-8', 'replace')
|
||||||
return(out, err)
|
return(out, err)
|
||||||
|
|
||||||
|
|
||||||
def escape_fish_cmd(text):
|
def escape_fish_cmd(text):
|
||||||
# Replace one backslash with two, and single quotes with backslash-quote
|
# Replace one backslash with two, and single quotes with backslash-quote
|
||||||
escaped = text.replace('\\', '\\\\').replace("'", "\\'")
|
escaped = text.replace('\\', '\\\\').replace("'", "\\'")
|
||||||
return "'" + escaped + "'"
|
return "'" + escaped + "'"
|
||||||
|
|
||||||
named_colors = {
|
named_colors = {
|
||||||
'black' : '000000',
|
'black': '000000', 'red': '800000', 'green': '008000', 'brown': '725000',
|
||||||
'red' : '800000',
|
'yellow': '808000', 'blue': '000080', 'magenta': '800080',
|
||||||
'green' : '008000',
|
'purple': '800080', 'cyan': '008080', 'grey': 'e5e5e5', 'brgrey': '555555',
|
||||||
'brown' : '725000',
|
'white': 'c0c0c0', 'brblack': '808080', 'brred': 'ff0000',
|
||||||
'yellow' : '808000',
|
'brgreen': '00ff00', 'brbrown': 'ffff00', 'bryellow': 'ffff00',
|
||||||
'blue' : '000080',
|
'brblue': '0000ff', 'brmagenta': 'ff00ff', 'brpurple': 'ff00ff',
|
||||||
'magenta' : '800080',
|
'brcyan': '00ffff', 'brwhite': 'ffffff'
|
||||||
'purple' : '800080',
|
|
||||||
'cyan' : '008080',
|
|
||||||
'grey' : 'e5e5e5',
|
|
||||||
'brgrey' : '555555',
|
|
||||||
'white' : 'c0c0c0',
|
|
||||||
'brblack' : '808080',
|
|
||||||
'brred' : 'ff0000',
|
|
||||||
'brgreen' : '00ff00',
|
|
||||||
'brbrown' : 'ffff00',
|
|
||||||
'bryellow' : 'ffff00',
|
|
||||||
'brblue' : '0000ff',
|
|
||||||
'brmagenta' : 'ff00ff',
|
|
||||||
'brpurple' : 'ff00ff',
|
|
||||||
'brcyan' : '00ffff',
|
|
||||||
'brwhite' : 'ffffff'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bindings_blacklist = set(["self-insert", "'begin;end'"])
|
bindings_blacklist = set(["self-insert", "'begin;end'"])
|
||||||
|
|
||||||
|
|
||||||
def parse_one_color(comp):
|
def parse_one_color(comp):
|
||||||
""" A basic function to parse a single color value like 'FFA000' """
|
""" A basic function to parse a single color value like 'FFA000' """
|
||||||
if comp in named_colors:
|
if comp in named_colors:
|
||||||
# Named color
|
# Named color
|
||||||
return named_colors[comp]
|
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:
|
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
|
# Hex color
|
||||||
return comp
|
return comp
|
||||||
else:
|
else:
|
||||||
# Unknown
|
# Unknown
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
def better_color(c1, c2):
|
def better_color(c1, c2):
|
||||||
""" Indicate which color is "better", i.e. prefer term256 colors """
|
""" Indicate which color is "better", i.e. prefer term256 colors """
|
||||||
if not c2: return c1
|
if not c2:
|
||||||
if not c1: return c2
|
return c1
|
||||||
if c1 == 'normal': return c2
|
if not c1:
|
||||||
if c2 == 'normal': return c1
|
return c2
|
||||||
if c2 in named_colors: return c1
|
if c1 == 'normal':
|
||||||
if c1 in named_colors: return c2
|
return c2
|
||||||
|
if c2 == 'normal':
|
||||||
|
return c1
|
||||||
|
if c2 in named_colors:
|
||||||
|
return c1
|
||||||
|
if c1 in named_colors:
|
||||||
|
return c2
|
||||||
return c1
|
return c1
|
||||||
|
|
||||||
|
|
||||||
def parse_color(color_str):
|
def parse_color(color_str):
|
||||||
""" A basic function to parse a color string, for example, 'red' '--bold' """
|
""" A basic function to parse a color string, for example, 'red' '--bold'.
|
||||||
|
"""
|
||||||
comps = color_str.split(' ')
|
comps = color_str.split(' ')
|
||||||
color = 'normal'
|
color = 'normal'
|
||||||
background_color = ''
|
background_color = ''
|
||||||
|
@ -119,21 +124,69 @@ def parse_color(color_str):
|
||||||
underline = True
|
underline = True
|
||||||
elif comp.startswith('--background='):
|
elif comp.startswith('--background='):
|
||||||
# Background color
|
# Background color
|
||||||
background_color = better_color(background_color, parse_one_color(comp[len('--background='):]))
|
background_color = better_color(
|
||||||
|
background_color, parse_one_color(comp[len('--background='):]))
|
||||||
else:
|
else:
|
||||||
# Regular color
|
# Regular color
|
||||||
color = better_color(color, parse_one_color(comp))
|
color = better_color(color, parse_one_color(comp))
|
||||||
|
|
||||||
return {"color": color, "background": background_color, "bold": bold, "underline": underline}
|
return {"color": color, "background": background_color, "bold": bold,
|
||||||
|
"underline": underline}
|
||||||
|
|
||||||
|
|
||||||
def parse_bool(val):
|
def parse_bool(val):
|
||||||
val = val.lower()
|
val = val.lower()
|
||||||
if val.startswith('f') or val.startswith('0'): return False
|
if val.startswith('f') or val.startswith('0'):
|
||||||
if val.startswith('t') or val.startswith('1'): return True
|
return False
|
||||||
|
if val.startswith('t') or val.startswith('1'):
|
||||||
|
return True
|
||||||
return bool(val)
|
return bool(val)
|
||||||
|
|
||||||
|
|
||||||
def html_color_for_ansi_color_index(val):
|
def html_color_for_ansi_color_index(val):
|
||||||
arr = ['black', '#AA0000', '#00AA00', '#AA5500', '#0000AA', '#AA00AA', '#00AAAA', '#AAAAAA', '#555555', '#FF5555', '#55FF55', '#FFFF55', '#5555FF', '#FF55FF', '#55FFFF', 'white', '#000000', '#00005f', '#000087', '#0000af', '#0000d7', '#0000ff', '#005f00', '#005f5f', '#005f87', '#005faf', '#005fd7', '#005fff', '#008700', '#00875f', '#008787', '#0087af', '#0087d7', '#0087ff', '#00af00', '#00af5f', '#00af87', '#00afaf', '#00afd7', '#00afff', '#00d700', '#00d75f', '#00d787', '#00d7af', '#00d7d7', '#00d7ff', '#00ff00', '#00ff5f', '#00ff87', '#00ffaf', '#00ffd7', '#00ffff', '#5f0000', '#5f005f', '#5f0087', '#5f00af', '#5f00d7', '#5f00ff', '#5f5f00', '#5f5f5f', '#5f5f87', '#5f5faf', '#5f5fd7', '#5f5fff', '#5f8700', '#5f875f', '#5f8787', '#5f87af', '#5f87d7', '#5f87ff', '#5faf00', '#5faf5f', '#5faf87', '#5fafaf', '#5fafd7', '#5fafff', '#5fd700', '#5fd75f', '#5fd787', '#5fd7af', '#5fd7d7', '#5fd7ff', '#5fff00', '#5fff5f', '#5fff87', '#5fffaf', '#5fffd7', '#5fffff', '#870000', '#87005f', '#870087', '#8700af', '#8700d7', '#8700ff', '#875f00', '#875f5f', '#875f87', '#875faf', '#875fd7', '#875fff', '#878700', '#87875f', '#878787', '#8787af', '#8787d7', '#8787ff', '#87af00', '#87af5f', '#87af87', '#87afaf', '#87afd7', '#87afff', '#87d700', '#87d75f', '#87d787', '#87d7af', '#87d7d7', '#87d7ff', '#87ff00', '#87ff5f', '#87ff87', '#87ffaf', '#87ffd7', '#87ffff', '#af0000', '#af005f', '#af0087', '#af00af', '#af00d7', '#af00ff', '#af5f00', '#af5f5f', '#af5f87', '#af5faf', '#af5fd7', '#af5fff', '#af8700', '#af875f', '#af8787', '#af87af', '#af87d7', '#af87ff', '#afaf00', '#afaf5f', '#afaf87', '#afafaf', '#afafd7', '#afafff', '#afd700', '#afd75f', '#afd787', '#afd7af', '#afd7d7', '#afd7ff', '#afff00', '#afff5f', '#afff87', '#afffaf', '#afffd7', '#afffff', '#d70000', '#d7005f', '#d70087', '#d700af', '#d700d7', '#d700ff', '#d75f00', '#d75f5f', '#d75f87', '#d75faf', '#d75fd7', '#d75fff', '#d78700', '#d7875f', '#d78787', '#d787af', '#d787d7', '#d787ff', '#d7af00', '#d7af5f', '#d7af87', '#d7afaf', '#d7afd7', '#d7afff', '#d7d700', '#d7d75f', '#d7d787', '#d7d7af', '#d7d7d7', '#d7d7ff', '#d7ff00', '#d7ff5f', '#d7ff87', '#d7ffaf', '#d7ffd7', '#d7ffff', '#ff0000', '#ff005f', '#ff0087', '#ff00af', '#ff00d7', '#ff00ff', '#ff5f00', '#ff5f5f', '#ff5f87', '#ff5faf', '#ff5fd7', '#ff5fff', '#ff8700', '#ff875f', '#ff8787', '#ff87af', '#ff87d7', '#ff87ff', '#ffaf00', '#ffaf5f', '#ffaf87', '#ffafaf', '#ffafd7', '#ffafff', '#ffd700', '#ffd75f', '#ffd787', '#ffd7af', '#ffd7d7', '#ffd7ff', '#ffff00', '#ffff5f', '#ffff87', '#ffffaf', '#ffffd7', '#ffffff', '#080808', '#121212', '#1c1c1c', '#262626', '#303030', '#3a3a3a', '#444444', '#4e4e4e', '#585858', '#626262', '#6c6c6c', '#767676', '#808080', '#8a8a8a', '#949494', '#9e9e9e', '#a8a8a8', '#b2b2b2', '#bcbcbc', '#c6c6c6', '#d0d0d0', '#dadada', '#e4e4e4', '#eeeeee']
|
arr = ['black', '#AA0000', '#00AA00', '#AA5500', '#0000AA', '#AA00AA',
|
||||||
|
'#00AAAA', '#AAAAAA', '#555555', '#FF5555', '#55FF55', '#FFFF55',
|
||||||
|
'#5555FF', '#FF55FF', '#55FFFF', 'white', '#000000', '#00005f',
|
||||||
|
'#000087', '#0000af', '#0000d7', '#0000ff', '#005f00', '#005f5f',
|
||||||
|
'#005f87', '#005faf', '#005fd7', '#005fff', '#008700', '#00875f',
|
||||||
|
'#008787', '#0087af', '#0087d7', '#0087ff', '#00af00', '#00af5f',
|
||||||
|
'#00af87', '#00afaf', '#00afd7', '#00afff', '#00d700', '#00d75f',
|
||||||
|
'#00d787', '#00d7af', '#00d7d7', '#00d7ff', '#00ff00', '#00ff5f',
|
||||||
|
'#00ff87', '#00ffaf', '#00ffd7', '#00ffff', '#5f0000', '#5f005f',
|
||||||
|
'#5f0087', '#5f00af', '#5f00d7', '#5f00ff', '#5f5f00', '#5f5f5f',
|
||||||
|
'#5f5f87', '#5f5faf', '#5f5fd7', '#5f5fff', '#5f8700', '#5f875f',
|
||||||
|
'#5f8787', '#5f87af', '#5f87d7', '#5f87ff', '#5faf00', '#5faf5f',
|
||||||
|
'#5faf87', '#5fafaf', '#5fafd7', '#5fafff', '#5fd700', '#5fd75f',
|
||||||
|
'#5fd787', '#5fd7af', '#5fd7d7', '#5fd7ff', '#5fff00', '#5fff5f',
|
||||||
|
'#5fff87', '#5fffaf', '#5fffd7', '#5fffff', '#870000', '#87005f',
|
||||||
|
'#870087', '#8700af', '#8700d7', '#8700ff', '#875f00', '#875f5f',
|
||||||
|
'#875f87', '#875faf', '#875fd7', '#875fff', '#878700', '#87875f',
|
||||||
|
'#878787', '#8787af', '#8787d7', '#8787ff', '#87af00', '#87af5f',
|
||||||
|
'#87af87', '#87afaf', '#87afd7', '#87afff', '#87d700', '#87d75f',
|
||||||
|
'#87d787', '#87d7af', '#87d7d7', '#87d7ff', '#87ff00', '#87ff5f',
|
||||||
|
'#87ff87', '#87ffaf', '#87ffd7', '#87ffff', '#af0000', '#af005f',
|
||||||
|
'#af0087', '#af00af', '#af00d7', '#af00ff', '#af5f00', '#af5f5f',
|
||||||
|
'#af5f87', '#af5faf', '#af5fd7', '#af5fff', '#af8700', '#af875f',
|
||||||
|
'#af8787', '#af87af', '#af87d7', '#af87ff', '#afaf00', '#afaf5f',
|
||||||
|
'#afaf87', '#afafaf', '#afafd7', '#afafff', '#afd700', '#afd75f',
|
||||||
|
'#afd787', '#afd7af', '#afd7d7', '#afd7ff', '#afff00', '#afff5f',
|
||||||
|
'#afff87', '#afffaf', '#afffd7', '#afffff', '#d70000', '#d7005f',
|
||||||
|
'#d70087', '#d700af', '#d700d7', '#d700ff', '#d75f00', '#d75f5f',
|
||||||
|
'#d75f87', '#d75faf', '#d75fd7', '#d75fff', '#d78700', '#d7875f',
|
||||||
|
'#d78787', '#d787af', '#d787d7', '#d787ff', '#d7af00', '#d7af5f',
|
||||||
|
'#d7af87', '#d7afaf', '#d7afd7', '#d7afff', '#d7d700', '#d7d75f',
|
||||||
|
'#d7d787', '#d7d7af', '#d7d7d7', '#d7d7ff', '#d7ff00', '#d7ff5f',
|
||||||
|
'#d7ff87', '#d7ffaf', '#d7ffd7', '#d7ffff', '#ff0000', '#ff005f',
|
||||||
|
'#ff0087', '#ff00af', '#ff00d7', '#ff00ff', '#ff5f00', '#ff5f5f',
|
||||||
|
'#ff5f87', '#ff5faf', '#ff5fd7', '#ff5fff', '#ff8700', '#ff875f',
|
||||||
|
'#ff8787', '#ff87af', '#ff87d7', '#ff87ff', '#ffaf00', '#ffaf5f',
|
||||||
|
'#ffaf87', '#ffafaf', '#ffafd7', '#ffafff', '#ffd700', '#ffd75f',
|
||||||
|
'#ffd787', '#ffd7af', '#ffd7d7', '#ffd7ff', '#ffff00', '#ffff5f',
|
||||||
|
'#ffff87', '#ffffaf', '#ffffd7', '#ffffff', '#080808', '#121212',
|
||||||
|
'#1c1c1c', '#262626', '#303030', '#3a3a3a', '#444444', '#4e4e4e',
|
||||||
|
'#585858', '#626262', '#6c6c6c', '#767676', '#808080', '#8a8a8a',
|
||||||
|
'#949494', '#9e9e9e', '#a8a8a8', '#b2b2b2', '#bcbcbc', '#c6c6c6',
|
||||||
|
'#d0d0d0', '#dadada', '#e4e4e4', '#eeeeee']
|
||||||
if val < 0 or val >= len(arr):
|
if val < 0 or val >= len(arr):
|
||||||
return ''
|
return ''
|
||||||
else:
|
else:
|
||||||
|
@ -141,6 +194,8 @@ def html_color_for_ansi_color_index(val):
|
||||||
|
|
||||||
# Function to return special ANSI escapes like exit_attribute_mode
|
# Function to return special ANSI escapes like exit_attribute_mode
|
||||||
g_special_escapes_dict = None
|
g_special_escapes_dict = None
|
||||||
|
|
||||||
|
|
||||||
def get_special_ansi_escapes():
|
def get_special_ansi_escapes():
|
||||||
global g_special_escapes_dict
|
global g_special_escapes_dict
|
||||||
if g_special_escapes_dict is None:
|
if g_special_escapes_dict is None:
|
||||||
|
@ -152,8 +207,10 @@ def get_special_ansi_escapes():
|
||||||
def get_tparm(key):
|
def get_tparm(key):
|
||||||
val = None
|
val = None
|
||||||
key = curses.tigetstr("sgr0")
|
key = curses.tigetstr("sgr0")
|
||||||
if key: val = curses.tparm(key)
|
if key:
|
||||||
if val: val = val.decode('utf-8')
|
val = curses.tparm(key)
|
||||||
|
if val:
|
||||||
|
val = val.decode('utf-8')
|
||||||
return val
|
return val
|
||||||
|
|
||||||
# Just a few for now
|
# Just a few for now
|
||||||
|
@ -165,6 +222,8 @@ def get_special_ansi_escapes():
|
||||||
|
|
||||||
# Given a known ANSI escape sequence, convert it to HTML and append to the list
|
# Given a known ANSI escape sequence, convert it to HTML and append to the list
|
||||||
# Returns whether we have an open <span>
|
# Returns whether we have an open <span>
|
||||||
|
|
||||||
|
|
||||||
def append_html_for_ansi_escape(full_val, result, span_open):
|
def append_html_for_ansi_escape(full_val, result, span_open):
|
||||||
|
|
||||||
# Strip off the initial \x1b[ and terminating m
|
# Strip off the initial \x1b[ and terminating m
|
||||||
|
@ -179,16 +238,16 @@ def append_html_for_ansi_escape(full_val, result, span_open):
|
||||||
match = re.match('38;5;(\d+)', val)
|
match = re.match('38;5;(\d+)', val)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
close_span()
|
close_span()
|
||||||
html_color = html_color_for_ansi_color_index(int(match.group(1)))
|
html_color = html_color_for_ansi_color_index(int(match.group(1)))
|
||||||
result.append('<span style="color: ' + html_color + '">')
|
result.append('<span style="color: ' + html_color + '">')
|
||||||
return True # span now open
|
return True # span now open
|
||||||
|
|
||||||
# term8 foreground color
|
# term8 foreground color
|
||||||
if val in [str(x) for x in range(30, 38)]:
|
if val in [str(x) for x in range(30, 38)]:
|
||||||
close_span()
|
close_span()
|
||||||
html_color = html_color_for_ansi_color_index(int(val) - 30)
|
html_color = html_color_for_ansi_color_index(int(val) - 30)
|
||||||
result.append('<span style="color: ' + html_color + '">')
|
result.append('<span style="color: ' + html_color + '">')
|
||||||
return True # span now open
|
return True # span now open
|
||||||
|
|
||||||
# Try special escapes
|
# Try special escapes
|
||||||
special_escapes = get_special_ansi_escapes()
|
special_escapes = get_special_ansi_escapes()
|
||||||
|
@ -201,15 +260,17 @@ def append_html_for_ansi_escape(full_val, result, span_open):
|
||||||
# Do nothing on failure
|
# Do nothing on failure
|
||||||
return span_open
|
return span_open
|
||||||
|
|
||||||
|
|
||||||
def strip_ansi(val):
|
def strip_ansi(val):
|
||||||
# Make a half-assed effort to strip ANSI control sequences
|
# Make a half-assed effort to strip ANSI control sequences
|
||||||
# We assume that all such sequences start with 0x1b and end with m,
|
# We assume that all such sequences start with 0x1b and end with m,
|
||||||
# which catches most cases
|
# which catches most cases
|
||||||
return re.sub("\x1b[^m]*m", '', val)
|
return re.sub("\x1b[^m]*m", '', val)
|
||||||
|
|
||||||
|
|
||||||
def ansi_prompt_line_width(val):
|
def ansi_prompt_line_width(val):
|
||||||
# Given an ANSI prompt, return the length of its longest line, as in the number of characters it takes up
|
# Given an ANSI prompt, return the length of its longest line, as in the
|
||||||
# Start by stripping off ANSI
|
# number of characters it takes up. Start by stripping off ANSI.
|
||||||
stripped_val = strip_ansi(val)
|
stripped_val = strip_ansi(val)
|
||||||
|
|
||||||
# Now count the longest line
|
# Now count the longest line
|
||||||
|
@ -217,10 +278,10 @@ def ansi_prompt_line_width(val):
|
||||||
|
|
||||||
|
|
||||||
def ansi_to_html(val):
|
def ansi_to_html(val):
|
||||||
# Split us up by ANSI escape sequences
|
# Split us up by ANSI escape sequences. We want to catch not only the
|
||||||
# We want to catch not only the standard color codes, but also things like sgr0
|
# standard color codes, but also things like sgr0. Hence this lame check.
|
||||||
# Hence this lame check
|
# Note that Python 2.6 doesn't have a flag param to re.split, so we have to
|
||||||
# Note that Python 2.6 doesn't have a flag param to re.split, so we have to compile it first
|
# compile it first.
|
||||||
reg = re.compile("""
|
reg = re.compile("""
|
||||||
( # Capture
|
( # Capture
|
||||||
\x1b # Escape
|
\x1b # Escape
|
||||||
|
@ -245,10 +306,12 @@ def ansi_to_html(val):
|
||||||
result.append(cgi.escape(strip_ansi(component)))
|
result.append(cgi.escape(strip_ansi(component)))
|
||||||
else:
|
else:
|
||||||
# It's an escape sequence. Close the previous escape.
|
# It's an escape sequence. Close the previous escape.
|
||||||
span_open = append_html_for_ansi_escape(component, result, span_open)
|
span_open = append_html_for_ansi_escape(component, result,
|
||||||
|
span_open)
|
||||||
|
|
||||||
# Close final escape
|
# Close final escape
|
||||||
if span_open: result.append('</span>')
|
if span_open:
|
||||||
|
result.append('</span>')
|
||||||
|
|
||||||
# Remove empty elements
|
# Remove empty elements
|
||||||
result = [x for x in result if x]
|
result = [x for x in result if x]
|
||||||
|
@ -264,6 +327,7 @@ def ansi_to_html(val):
|
||||||
|
|
||||||
return ''.join(result)
|
return ''.join(result)
|
||||||
|
|
||||||
|
|
||||||
class FishVar:
|
class FishVar:
|
||||||
""" A class that represents a variable """
|
""" A class that represents a variable """
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
|
@ -275,15 +339,20 @@ class FishVar:
|
||||||
def get_json_obj(self):
|
def get_json_obj(self):
|
||||||
# Return an array(3): name, value, flags
|
# Return an array(3): name, value, flags
|
||||||
flags = []
|
flags = []
|
||||||
if self.universal: flags.append('universal')
|
if self.universal:
|
||||||
if self.exported: flags.append('exported')
|
flags.append('universal')
|
||||||
return {"name": self.name, "value": self.value, "Flags": ', '.join(flags)}
|
if self.exported:
|
||||||
|
flags.append('exported')
|
||||||
|
return {"name": self.name, "value": self.value,
|
||||||
|
"Flags": ', '.join(flags)}
|
||||||
|
|
||||||
|
|
||||||
class FishBinding:
|
class FishBinding:
|
||||||
"""A class that represents keyboard binding """
|
"""A class that represents keyboard binding """
|
||||||
|
|
||||||
def __init__(self, command, raw_binding, readable_binding, description=None):
|
def __init__(self, command, raw_binding, readable_binding,
|
||||||
self.command = command
|
description=None):
|
||||||
|
self.command = command
|
||||||
self.bindings = []
|
self.bindings = []
|
||||||
self.description = description
|
self.description = description
|
||||||
self.add_binding(raw_binding, readable_binding)
|
self.add_binding(raw_binding, readable_binding)
|
||||||
|
@ -294,23 +363,24 @@ class FishBinding:
|
||||||
i['raw_bindings'].append(raw_binding)
|
i['raw_bindings'].append(raw_binding)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.bindings.append({'readable_binding':readable_binding, 'raw_bindings':[raw_binding]})
|
self.bindings.append({'readable_binding': readable_binding,
|
||||||
|
'raw_bindings': [raw_binding]})
|
||||||
|
|
||||||
def get_json_obj(self):
|
def get_json_obj(self):
|
||||||
return {"command" : self.command, "bindings": self.bindings, "description": self.description}
|
return {"command": self.command, "bindings": self.bindings,
|
||||||
|
"description": self.description}
|
||||||
|
|
||||||
|
|
||||||
class BindingParser:
|
class BindingParser:
|
||||||
""" Class to parse codes for bind command """
|
""" Class to parse codes for bind command """
|
||||||
|
|
||||||
#TODO: What does snext and sprevious mean ?
|
# TODO: What does snext and sprevious mean ?
|
||||||
readable_keys= { "dc":"Delete", "npage": "Page Up", "ppage":"Page Down",
|
readable_keys = {"dc": "Delete", "npage": "Page Up", "ppage": "Page Down",
|
||||||
"sdc": "Shift Delete", "shome": "Shift Home",
|
"sdc": "Shift Delete", "shome": "Shift Home",
|
||||||
"left": "Left Arrow", "right": "Right Arrow",
|
"left": "Left Arrow", "right": "Right Arrow",
|
||||||
"up": "Up Arrow", "down": "Down Arrow",
|
"up": "Up Arrow", "down": "Down Arrow",
|
||||||
"sleft": "Shift Left", "sright": "Shift Right",
|
"sleft": "Shift Left", "sright": "Shift Right",
|
||||||
"btab": "Shift Tab"
|
"btab": "Shift Tab"}
|
||||||
}
|
|
||||||
|
|
||||||
def set_buffer(self, buffer):
|
def set_buffer(self, buffer):
|
||||||
""" Sets code to parse """
|
""" Sets code to parse """
|
||||||
|
@ -348,7 +418,8 @@ class BindingParser:
|
||||||
|
|
||||||
# \[1\; is start of control sequence
|
# \[1\; is start of control sequence
|
||||||
if c == '1':
|
if c == '1':
|
||||||
b = self.get_char(); c = self.get_char()
|
b = self.get_char()
|
||||||
|
c = self.get_char()
|
||||||
if b == '\\' and c == '~':
|
if b == '\\' and c == '~':
|
||||||
result += "Home"
|
result += "Home"
|
||||||
elif c == ";":
|
elif c == ";":
|
||||||
|
@ -361,7 +432,8 @@ class BindingParser:
|
||||||
|
|
||||||
# \[4\~ is End
|
# \[4\~ is End
|
||||||
if c == '4':
|
if c == '4':
|
||||||
b = self.get_char(); c = self.get_char()
|
b = self.get_char()
|
||||||
|
c = self.get_char()
|
||||||
if b == '\\' and c == '~':
|
if b == '\\' and c == '~':
|
||||||
result += "End"
|
result += "End"
|
||||||
|
|
||||||
|
@ -518,7 +590,7 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
for match in re.finditer(r"^fish_color_(\S+) ?(.*)", line):
|
for match in re.finditer(r"^fish_color_(\S+) ?(.*)", line):
|
||||||
color_name, color_value = [x.strip() for x in match.group(1, 2)]
|
color_name, color_value = [x.strip() for x in match.group(1, 2)]
|
||||||
color_desc = descriptions.get(color_name, '')
|
color_desc = descriptions.get(color_name, '')
|
||||||
data = { "name": color_name, "description" : color_desc }
|
data = {"name": color_name, "description": color_desc}
|
||||||
data.update(parse_color(color_value))
|
data.update(parse_color(color_value))
|
||||||
result.append(data)
|
result.append(data)
|
||||||
remaining.discard(color_name)
|
remaining.discard(color_name)
|
||||||
|
@ -556,18 +628,22 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
vars = {}
|
vars = {}
|
||||||
for line in out.split('\n'):
|
for line in out.split('\n'):
|
||||||
comps = line.split(' ', 1)
|
comps = line.split(' ', 1)
|
||||||
if len(comps) < 2: continue
|
if len(comps) < 2:
|
||||||
|
continue
|
||||||
fish_var = FishVar(comps[0], comps[1])
|
fish_var = FishVar(comps[0], comps[1])
|
||||||
vars[fish_var.name] = fish_var
|
vars[fish_var.name] = fish_var
|
||||||
|
|
||||||
# Mark universal variables. L means don't abbreviate.
|
# Mark universal variables. L means don't abbreviate.
|
||||||
for name in self.do_get_variable_names('set -nUL'):
|
for name in self.do_get_variable_names('set -nUL'):
|
||||||
if name in vars: vars[name].universal = True
|
if name in vars:
|
||||||
|
vars[name].universal = True
|
||||||
# Mark exported variables. L means don't abbreviate.
|
# Mark exported variables. L means don't abbreviate.
|
||||||
for name in self.do_get_variable_names('set -nxL'):
|
for name in self.do_get_variable_names('set -nxL'):
|
||||||
if name in vars: vars[name].exported = True
|
if name in vars:
|
||||||
|
vars[name].exported = True
|
||||||
|
|
||||||
return [vars[key].get_json_obj() for key in sorted(vars.keys(), key=lambda x: x.lower())]
|
return [vars[key].get_json_obj() for key
|
||||||
|
in sorted(vars.keys(), key=lambda x: x.lower())]
|
||||||
|
|
||||||
def do_get_bindings(self):
|
def do_get_bindings(self):
|
||||||
""" Get key bindings """
|
""" Get key bindings """
|
||||||
|
@ -613,29 +689,37 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
bindings.append(fish_binding)
|
bindings.append(fish_binding)
|
||||||
command_to_binding[command] = fish_binding
|
command_to_binding[command] = fish_binding
|
||||||
|
|
||||||
return [ binding.get_json_obj() for binding in bindings ]
|
return [binding.get_json_obj() for binding in bindings]
|
||||||
|
|
||||||
def do_get_history(self):
|
def do_get_history(self):
|
||||||
# Use \x1e ("record separator") to distinguish between history items. The first
|
# Use \x1e ("record separator") to distinguish between history items.
|
||||||
# backslash is so Python passes one backslash to fish
|
# 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')
|
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() # Trim off the trailing element
|
if result:
|
||||||
|
result.pop() # trim off the trailing element
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def do_get_color_for_variable(self, name):
|
def do_get_color_for_variable(self, name):
|
||||||
"Return the color with the given name, or the empty string if there is none"
|
# Return the color with the given name, or the empty string if there is
|
||||||
|
# none.
|
||||||
out, err = run_fish_cmd("echo -n $" + name)
|
out, err = run_fish_cmd("echo -n $" + name)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def do_set_color_for_variable(self, name, color, background_color, bold, underline):
|
def do_set_color_for_variable(self, name, color, background_color, bold,
|
||||||
if not color: color = 'normal'
|
underline):
|
||||||
|
if not color:
|
||||||
|
color = 'normal'
|
||||||
"Sets a color for a fish color name, like 'autosuggestion'"
|
"Sets a color for a fish color name, like 'autosuggestion'"
|
||||||
command = 'set -U fish_color_' + name
|
command = 'set -U fish_color_' + name
|
||||||
if color: command += ' ' + color
|
if color:
|
||||||
if background_color: command += ' --background=' + background_color
|
command += ' ' + color
|
||||||
if bold: command += ' --bold'
|
if background_color:
|
||||||
if underline: command += ' --underline'
|
command += ' --background=' + background_color
|
||||||
|
if bold:
|
||||||
|
command += ' --bold'
|
||||||
|
if underline:
|
||||||
|
command += ' --underline'
|
||||||
|
|
||||||
out, err = run_fish_cmd(command)
|
out, err = run_fish_cmd(command)
|
||||||
return out
|
return out
|
||||||
|
@ -647,7 +731,7 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
def do_delete_history_item(self, history_item_text):
|
def do_delete_history_item(self, history_item_text):
|
||||||
# It's really lame that we always return success here
|
# It's really lame that we always return success here
|
||||||
cmd = ('builtin history delete --exact -- %s; builtin history save' %
|
cmd = ('builtin history delete --exact -- %s; builtin history save' %
|
||||||
escape_fish_cmd(history_item_text))
|
escape_fish_cmd(history_item_text))
|
||||||
out, err = run_fish_cmd(cmd)
|
out, err = run_fish_cmd(cmd)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -661,29 +745,35 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
prompt_demo_ansi, err = run_fish_cmd(command_to_run)
|
prompt_demo_ansi, err = run_fish_cmd(command_to_run)
|
||||||
prompt_demo_html = ansi_to_html(prompt_demo_ansi)
|
prompt_demo_html = ansi_to_html(prompt_demo_ansi)
|
||||||
prompt_demo_font_size = self.font_size_for_ansi_prompt(prompt_demo_ansi)
|
prompt_demo_font_size = self.font_size_for_ansi_prompt(prompt_demo_ansi)
|
||||||
result = {'function': prompt_function_text, 'demo': prompt_demo_html, 'font_size': prompt_demo_font_size }
|
result = {'function': prompt_function_text, 'demo': prompt_demo_html,
|
||||||
|
'font_size': prompt_demo_font_size}
|
||||||
if extras_dict:
|
if extras_dict:
|
||||||
result.update(extras_dict)
|
result.update(extras_dict)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def do_get_current_prompt(self):
|
def do_get_current_prompt(self):
|
||||||
# Return the current prompt
|
# Return the current prompt. We run 'false' to demonstrate how the
|
||||||
# We run 'false' to demonstrate how the prompt shows the command status (#1624)
|
# prompt shows the command status (#1624).
|
||||||
prompt_func, err = run_fish_cmd('functions fish_prompt')
|
prompt_func, err = run_fish_cmd('functions fish_prompt')
|
||||||
result = self.do_get_prompt('builtin cd "' + initial_wd + '" ; false ; fish_prompt', prompt_func.strip(), {'name': 'Current'})
|
result = self.do_get_prompt(
|
||||||
|
'builtin cd "' + initial_wd + '" ; false ; fish_prompt',
|
||||||
|
prompt_func.strip(), {'name': 'Current'})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def do_get_sample_prompt(self, text, extras_dict):
|
def do_get_sample_prompt(self, text, extras_dict):
|
||||||
# Return the prompt you get from the given text
|
# Return the prompt you get from the given text. Extras_dict is a
|
||||||
# extras_dict is a dictionary whose values get merged in
|
# dictionary whose values get merged in. We run 'false' to demonstrate
|
||||||
# We run 'false' to demonstrate how the prompt shows the command status (#1624)
|
# how the prompt shows the command status (#1624)
|
||||||
cmd = text + "\n builtin cd \"" + initial_wd + "\" \n false \n fish_prompt\n"
|
cmd = (text + "\n builtin cd \"" + initial_wd +
|
||||||
|
"\" \n false \n fish_prompt\n")
|
||||||
return self.do_get_prompt(cmd, text.strip(), extras_dict)
|
return self.do_get_prompt(cmd, text.strip(), extras_dict)
|
||||||
|
|
||||||
def parse_one_sample_prompt_hash(self, line, result_dict):
|
def parse_one_sample_prompt_hash(self, line, result_dict):
|
||||||
# Allow us to skip whitespace, etc.
|
# Allow us to skip whitespace, etc.
|
||||||
if not line: return True
|
if not line:
|
||||||
if line.isspace(): return True
|
return True
|
||||||
|
if line.isspace():
|
||||||
|
return True
|
||||||
|
|
||||||
# Parse a comment hash like '# name: Classic'
|
# Parse a comment hash like '# name: Classic'
|
||||||
match = re.match(r"#\s*(\w+?): (.+)", line, re.IGNORECASE)
|
match = re.match(r"#\s*(\w+?): (.+)", line, re.IGNORECASE)
|
||||||
|
@ -695,7 +785,6 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
# Skip other hash comments
|
# Skip other hash comments
|
||||||
return line.startswith('#')
|
return line.startswith('#')
|
||||||
|
|
||||||
|
|
||||||
def read_one_sample_prompt(self, path):
|
def read_one_sample_prompt(self, path):
|
||||||
try:
|
try:
|
||||||
with open(path, 'rb') as fd:
|
with open(path, 'rb') as fd:
|
||||||
|
@ -705,10 +794,13 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
parsing_hashes = True
|
parsing_hashes = True
|
||||||
unicode_lines = (line.decode('utf-8') for line in fd)
|
unicode_lines = (line.decode('utf-8') for line in fd)
|
||||||
for line in unicode_lines:
|
for line in unicode_lines:
|
||||||
# Parse hashes until parse_one_sample_prompt_hash return False
|
# Parse hashes until parse_one_sample_prompt_hash return
|
||||||
|
# False.
|
||||||
if parsing_hashes:
|
if parsing_hashes:
|
||||||
parsing_hashes = self.parse_one_sample_prompt_hash(line, extras_dict)
|
parsing_hashes = self.parse_one_sample_prompt_hash(
|
||||||
# Maybe not we're not parsing hashes, or maybe we already were not
|
line, extras_dict)
|
||||||
|
# Maybe not we're not parsing hashes, or maybe we already
|
||||||
|
# were not.
|
||||||
if not parsing_hashes:
|
if not parsing_hashes:
|
||||||
function_lines.append(line)
|
function_lines.append(line)
|
||||||
func = ''.join(function_lines).strip()
|
func = ''.join(function_lines).strip()
|
||||||
|
@ -750,7 +842,8 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def do_save_abbreviation(self, abbreviation):
|
def do_save_abbreviation(self, abbreviation):
|
||||||
out, err = run_fish_cmd('abbr --add \'%s %s\'' % (abbreviation['word'], abbreviation['phrase']))
|
out, err = run_fish_cmd('abbr --add \'%s %s\'' % (
|
||||||
|
abbreviation['word'], abbreviation['phrase']))
|
||||||
if err:
|
if err:
|
||||||
return err
|
return err
|
||||||
else:
|
else:
|
||||||
|
@ -760,21 +853,29 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
if len(haystack) < len(needle):
|
if len(haystack) < len(needle):
|
||||||
return False
|
return False
|
||||||
bits = 0
|
bits = 0
|
||||||
for x,y in zip(haystack, needle):
|
for x, y in zip(haystack, needle):
|
||||||
bits |= ord(x) ^ ord(y)
|
bits |= ord(x) ^ ord(y)
|
||||||
return bits == 0
|
return bits == 0
|
||||||
|
|
||||||
def font_size_for_ansi_prompt(self, prompt_demo_ansi):
|
def font_size_for_ansi_prompt(self, prompt_demo_ansi):
|
||||||
width = ansi_prompt_line_width(prompt_demo_ansi)
|
width = ansi_prompt_line_width(prompt_demo_ansi)
|
||||||
# Pick a font size
|
# Pick a font size
|
||||||
if width >= 70: font_size = '8pt'
|
if width >= 70:
|
||||||
if width >= 60: font_size = '10pt'
|
font_size = '8pt'
|
||||||
elif width >= 50: font_size = '11pt'
|
if width >= 60:
|
||||||
elif width >= 40: font_size = '13pt'
|
font_size = '10pt'
|
||||||
elif width >= 30: font_size = '15pt'
|
elif width >= 50:
|
||||||
elif width >= 25: font_size = '16pt'
|
font_size = '11pt'
|
||||||
elif width >= 20: font_size = '17pt'
|
elif width >= 40:
|
||||||
else: font_size = '18pt'
|
font_size = '13pt'
|
||||||
|
elif width >= 30:
|
||||||
|
font_size = '15pt'
|
||||||
|
elif width >= 25:
|
||||||
|
font_size = '16pt'
|
||||||
|
elif width >= 20:
|
||||||
|
font_size = '17pt'
|
||||||
|
else:
|
||||||
|
font_size = '18pt'
|
||||||
return font_size
|
return font_size
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
|
@ -812,7 +913,7 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
|
|
||||||
# Return valid output
|
# Return valid output
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header('Content-type','application/json')
|
self.send_header('Content-type', 'application/json')
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.write_to_wfile('\n')
|
self.write_to_wfile('\n')
|
||||||
|
|
||||||
|
@ -853,7 +954,9 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
|
|
||||||
if what:
|
if what:
|
||||||
# Not sure why we get lists here?
|
# 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]))
|
output = self.do_set_color_for_variable(
|
||||||
|
what[0], color[0], background_color[0],
|
||||||
|
parse_bool(bold[0]), parse_bool(underline[0]))
|
||||||
else:
|
else:
|
||||||
output = 'Bad request'
|
output = 'Bad request'
|
||||||
elif p == '/get_function/':
|
elif p == '/get_function/':
|
||||||
|
@ -873,13 +976,13 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
output = ["Unable to set prompt"]
|
output = ["Unable to set prompt"]
|
||||||
elif p == '/save_abbreviation/':
|
elif p == '/save_abbreviation/':
|
||||||
r = self.do_save_abbreviation(postvars)
|
r = self.do_save_abbreviation(postvars)
|
||||||
if r == True:
|
if r:
|
||||||
output = ["OK"]
|
output = ["OK"]
|
||||||
else:
|
else:
|
||||||
output = [r]
|
output = [r]
|
||||||
elif p == '/remove_abbreviation/':
|
elif p == '/remove_abbreviation/':
|
||||||
r = self.do_remove_abbreviation(postvars)
|
r = self.do_remove_abbreviation(postvars)
|
||||||
if r == True:
|
if r:
|
||||||
output = ["OK"]
|
output = ["OK"]
|
||||||
else:
|
else:
|
||||||
output = [r]
|
output = [r]
|
||||||
|
@ -888,7 +991,7 @@ class FishConfigHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
|
|
||||||
# Return valid output
|
# Return valid output
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.send_header('Content-type','application/json')
|
self.send_header('Content-type', 'application/json')
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.write_to_wfile('\n')
|
self.write_to_wfile('\n')
|
||||||
|
|
||||||
|
@ -924,7 +1027,8 @@ redirect_template_html = """
|
||||||
fish_bin_dir = os.environ.get('__fish_bin_dir')
|
fish_bin_dir = os.environ.get('__fish_bin_dir')
|
||||||
fish_bin_path = None
|
fish_bin_path = None
|
||||||
if not fish_bin_dir:
|
if not fish_bin_dir:
|
||||||
print('The __fish_bin_dir environment variable is not set. Looking in $PATH...')
|
print('The __fish_bin_dir environment variable is not set. '
|
||||||
|
'Looking in $PATH...')
|
||||||
# distutils.spawn is terribly broken, because it looks in wd before PATH,
|
# distutils.spawn is terribly broken, because it looks in wd before PATH,
|
||||||
# and doesn't actually validate that the file is even executable
|
# and doesn't actually validate that the file is even executable
|
||||||
for p in os.environ['PATH'].split(os.pathsep):
|
for p in os.environ['PATH'].split(os.pathsep):
|
||||||
|
@ -942,7 +1046,8 @@ else:
|
||||||
fish_bin_path = os.path.join(fish_bin_dir, 'fish')
|
fish_bin_path = os.path.join(fish_bin_dir, 'fish')
|
||||||
|
|
||||||
if not os.access(fish_bin_path, os.X_OK):
|
if not os.access(fish_bin_path, os.X_OK):
|
||||||
print("fish could not be executed at path '%s'. Is fish installed correctly?" % fish_bin_path)
|
print("fish could not be executed at path '%s'. "
|
||||||
|
"Is fish installed correctly?" % fish_bin_path)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
FISH_BIN_PATH = fish_bin_path
|
FISH_BIN_PATH = fish_bin_path
|
||||||
|
|
||||||
|
@ -950,8 +1055,8 @@ FISH_BIN_PATH = fish_bin_path
|
||||||
# so get the current working directory
|
# so get the current working directory
|
||||||
initial_wd = os.getcwd()
|
initial_wd = os.getcwd()
|
||||||
|
|
||||||
# Make sure that the working directory is the one that contains the script server file,
|
# Make sure that the working directory is the one that contains the script
|
||||||
# because the document root is the working directory
|
# server file, because the document root is the working directory.
|
||||||
where = os.path.dirname(sys.argv[0])
|
where = os.path.dirname(sys.argv[0])
|
||||||
os.chdir(where)
|
os.chdir(where)
|
||||||
|
|
||||||
|
@ -984,16 +1089,17 @@ if PORT > 9000:
|
||||||
# Just look at the first letter
|
# Just look at the first letter
|
||||||
initial_tab = ''
|
initial_tab = ''
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
for tab in ['functions', 'prompt', 'colors', 'variables', 'history', 'bindings', 'abbreviations']:
|
for tab in ['functions', 'prompt', 'colors', 'variables', 'history',
|
||||||
|
'bindings', 'abbreviations']:
|
||||||
if tab.startswith(sys.argv[1]):
|
if tab.startswith(sys.argv[1]):
|
||||||
initial_tab = '#' + tab
|
initial_tab = '#' + tab
|
||||||
break
|
break
|
||||||
|
|
||||||
url = 'http://localhost:%d/%s/%s' % (PORT, authkey, initial_tab)
|
url = 'http://localhost:%d/%s/%s' % (PORT, authkey, initial_tab)
|
||||||
|
|
||||||
# Create temporary file to hold redirect to real server
|
# Create temporary file to hold redirect to real server. This prevents exposing
|
||||||
# This prevents exposing the URL containing the authentication key on the command line
|
# the URL containing the authentication key on the command line (see
|
||||||
# (see CVE-2014-2914 or https://github.com/fish-shell/fish-shell/issues/1438)
|
# CVE-2014-2914 or https://github.com/fish-shell/fish-shell/issues/1438).
|
||||||
if 'XDG_CACHE_HOME' in os.environ:
|
if 'XDG_CACHE_HOME' in os.environ:
|
||||||
dirname = os.path.expanduser(os.path.expandvars('$XDG_CACHE_HOME/fish/'))
|
dirname = os.path.expanduser(os.path.expandvars('$XDG_CACHE_HOME/fish/'))
|
||||||
else:
|
else:
|
||||||
|
@ -1004,11 +1110,12 @@ try:
|
||||||
os.makedirs(dirname, 0o0700)
|
os.makedirs(dirname, 0o0700)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == 17:
|
if e.errno == 17:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
randtoken = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
|
randtoken = ''.join(random.choice(string.ascii_uppercase + string.digits)
|
||||||
|
for _ in range(6))
|
||||||
filename = dirname + 'web_config-%s.html' % randtoken
|
filename = dirname + 'web_config-%s.html' % randtoken
|
||||||
|
|
||||||
f = open(filename, 'w')
|
f = open(filename, 'w')
|
||||||
|
|
Loading…
Reference in a new issue