Commit e0ae921f authored by Glen Mével's avatar Glen Mével
Browse files

first commit

parents
#!/bin/sh
# Save the bell settings and activate it if needed.
settings=$(xset -q |grep bell |grep -o '[0-9]*')
xset b ${settings/#0/50}
# Ring the bell.
echo -ne '\a'
# Restore the bell settings.
xset b $settings
#!/bin/sh
# Colorize diff’s output (unified style).
#
# Note that ‘diff’ already supports colors but that, for some reason, it doesn’t
# colorize all lines (only the first line of each difference).
color="auto"
args=()
for arg in "$@" ; do
if [ "$arg" == "--color=never" ] ; then
color="never"
elif [ "$arg" == "--color=always" ] ; then
color="always"
elif [ "$arg" == "--color=auto" ] ; then
color="auto"
else
args+=( "$arg" )
fi
done
if [ "$color" == "always" -o '(' "$color" == "auto" -a -t 1 ')' ] ; then
/usr/bin/diff -u --color=never "${args[@]}" \
|sed 's/^Only in/\x1B[43;1;30mOnly in/;
s/^Files/\x1B[45;1mFiles/;
s/^diff/\x1B[1;30mdiff/;
s/^--- /\x1B[1;31m--- /;
s/^+++ /\x1B[1;32m+++ /;
s/^@@/\x1b[34m@@/;
s/^-/-\x1b[41m/;
s/^+/+\x1b[42m/;
s/^ / \x1B[30m/;
s/$/\x1b[0m/'
else
/usr/bin/diff -u --color=never "${args[@]}"
fi
#!/usr/bin/ocaml
(*
* Reads an UTF-8 text and writes it on standard output. Invalid codes are
* regarded as CP1252-encoded characters and are converted to UTF-8.
*)
let substitute = "�"
let buf = object (self)
val buf = Bytes.make 4 '\x00'
val mutable first = 0
val mutable cur = 0
val mutable last = 0
method input () =
Char.code @@
if cur < last then
let b = Bytes.get buf (cur mod 4) in
cur <- cur + 1 ;
b
else
let b = input_char stdin in
Bytes.set buf (cur mod 4) b ;
cur <- cur + 1 ;
last <- cur ;
assert (first <= last && last <= first + 4) ;
b
method rewind () =
cur <- first
method discard () =
first <- cur
method consume ?(keep=0) f =
self#rewind () ;
while cur < last - keep do
f (self#input ())
done ;
self#discard ()
end
exception Invalid_code of int
let unicode_of_cp1252 =
let mapping =
[|
(* codes from 0x80 to 0x8F: *)
0x20AC ; 0 ; 0x201A ; 0x0192 ; 0x201E ; 0x2026 ; 0x2020 ; 0x2021 ;
0x02C6 ; 0x2030 ; 0x0160 ; 0x2039 ; 0x0152 ; 0 ; 0x017D ; 0 ;
(* codes from 0x90 to 0x9F: *)
0 ; 0x2018 ; 0x2019 ; 0x201C ; 0x201D ; 0x2022 ; 0x2013 ; 0x2014 ;
0x02DC ; 0x2122 ; 0x0161 ; 0x203A ; 0x0153 ; 0 ; 0x017E ; 0x0178 ;
|]
in fun code ->
if 0x80 <= code && code < 0xA0 then
let ucode = mapping.(code-0x80) in
if ucode = 0 then raise (Invalid_code code) else ucode
else
code
let utf8_of_unicode ucode =
assert (ucode < 0b1000000000000000000000) ;
if ucode < 0x80 then
[ ucode ]
else if ucode < 0b100000000000 then
let b1 = 0b10_000000 lor (ucode land 0b111111) in
let b0 = 0b110_00000 lor (ucode lsr 6) in
[ b0 ; b1 ]
else if ucode < 0b10000000000000000 then
let b2 = 0b10_000000 lor ( ucode land 0b111111) in
let b1 = 0b10_000000 lor ((ucode lsr 6 ) land 0b111111) in
let b0 = 0b1110_0000 lor ((ucode lsr 12) ) in
[ b0 ; b1 ; b2 ]
else
let b3 = 0b10_000000 lor (ucode land 0b111111) in
let b2 = 0b10_000000 lor ((ucode lsr 6 ) land 0b111111) in
let b1 = 0b10_000000 lor ((ucode lsr 12) land 0b111111) in
let b0 = 0b11110_000 lor ((ucode lsr 18) ) in
[ b0 ; b1 ; b2 ; b3 ]
let output_utf8_byte =
output_byte stdout
let output_cp1252_as_utf8 code =
try
List.iter output_utf8_byte (utf8_of_unicode (unicode_of_cp1252 code))
with Invalid_code _ ->
Printf.eprintf "unknown code %02X ; inserting “%s” instead\n" code substitute ;
output_string stdout substitute
let rec read state =
match buf#input () with
| b when b < 0x80 && state = 0 ->
buf#discard () ;
output_utf8_byte b ;
read 0
| b when b lsr 6 = 0b10 && state > 0 ->
if state = 1 then
buf#consume output_utf8_byte ;
read (state - 1)
| b when b lsr 5 = 0b110 && state = 0 -> read 1
| b when b lsr 4 = 0b1110 && state = 0 -> read 2
| b when b lsr 3 = 0b11110 && state = 0 -> read 3
| _ ->
buf#consume ~keep:1 output_cp1252_as_utf8 ;
read 0
| exception End_of_file when state > 0 ->
buf#consume ~keep:1 output_cp1252_as_utf8 ;
read 0
| exception End_of_file -> ()
let () =
read 0
#!/bin/sh
# Launches a command out of the terminal.
# If coming from or going to a terminal, input and/or output are discarded.
#
# Usage:
# launch CMD …
# If the command is not available, exit with a detailed error message.
command -v "$1" >&- || "$1"
# Close file descriptors if needed.
if [ -t 0 ]; then
exec 0<&-
fi
if [ -t 1 ]; then
exec 1>&-
fi
# This one simply hides the messages from nohup (as nohup already
# redirects the stderr of the called program to its stdout):
exec 2>&-
# Launch the command.
nohup "$@" &
#!/bin/sh
# Merge recursively a directory into another.
# mvmerge SRCDIR TARGETDIR
# It moves recursively every file from the source directory to the target
# directory (asking for confirmation before overwriting) and preserves
# directory structure. Symbolic links are treated as regular files.
# Note: to copy instead of moving, one can simply run:
# cp -Triv SRCDIR TARGETDIR
if [ -n "$1" -a -n "$2" ] ; then
SOURCE_DIR="$1"
TARGET_DIR="$2"
else
echo "Usage: $0 src dest"
exit
fi
export SOURCE_DIR
export TARGET_DIR
export mvmerge="$(basename "$0")"
# Test whether the given name exists and is really a directory (not a symlink).
function is_true_dir() {
[ -d "$1" -a ! -L "$1" ]
}
# Test whether both the source and the target exist and are directories.
function test_dirs() {
src="$1"
dst="${src/$SOURCE_DIR/$TARGET_DIR}"
#[ -d "$src" -a -d "$dst" ] && [ ! -L "$src" -a ! -L "$dst" ]
is_true_dir "$src" && is_true_dir "$dst"
}
# Rename the source to the target, with interactive overwriting (and verbose
# output) that works even if both files are of different kind (ie. directory or
# non-directory).
function mv_overwrite() {
src="$1"
dst="${src/$SOURCE_DIR/$TARGET_DIR}"
# Here, we know that $src exists, and that $src and $dst can not be both
# directories.
if [ -e "$dst" ]; then
# If $dst exists and is not of the same kind than $src, then ‘mv’ will
# fail to overwrite it. Thus we remove it first.
if is_true_dir "$src"; then
echo -n "$mvmerge: replace the non-directory “$dst” by a directory? " >&2
rm -iv -- "$dst" 2>&-
[ -e "$dst" ] && return # if the user declined
elif is_true_dir "$dst"; then
echo -n "$mvmerge: replace the directory “$dst” by a non-directory? " >&2
rm -rIv -- "$dst" 2>&-
[ -e "$dst" ] && return # if the user declined
fi
fi
mv -Tiv -- "$src" "$dst"
}
export -f is_true_dir
export -f test_dirs
export -f mv_overwrite
# Move every file recursively; if the target exists and both source and target
# are directories, do nothing and let ‘find’ explore them recursively;
# otherwise, move the source to the target and stop the recursion (‘-prune’):
find -- "$SOURCE_DIR" \
-exec sh -c 'test_dirs "$0"' {} \; \
-o -prune -exec sh -c 'mv_overwrite "$0"' {} \;
# Remove remaining directories, but keep the non-directory files, which come the
# user refusing an overwrite (‘-delete’ do not remove a non-empty directory):
[ -e "$SOURCE_DIR" ] && find -- "$SOURCE_DIR" -type d -delete
#!/bin/sh
# Print the current public IP adress to standard output
# with ‘wget’, from package wget:
#wget -qO- http://www.wgetip.com
# with ‘dig’, from package bind-utils:
dig +short myip.opendns.com @resolver1.opendns.com
#!/usr/bin/ocaml
(* guyslain nave, teaching / prog fonctionnelle / tp 8 (parseurs) *)
(**
** a small json parser
**
** reads json code on stdin and reformat it on stdout
**)
let ( %> ) f g x = g (f x)
let some x = Some x
(* json expressions: *)
type value =
| Base of base_value
| List of value list
| Record of record_field list
and base_value =
| Null
| Bool of bool
| Int of int64
| Float of float
| String of string
and record_field =
{ name : base_value;
value : value; }
class virtual stream =
object
method virtual get : char
method virtual unget : char -> unit
end
class file_stream file =
object
inherit stream
val mutable buf = []
method get =
match buf with
| c::buf' -> buf <- buf'; c
| [] -> input_char file
method unget c =
buf <- c :: buf
end
class string_stream s =
object
inherit stream
val len = String.length s
val mutable i = 0
method get =
i <- i + 1 ;
if i > len then
raise End_of_file ;
s.[i-1]
method unget c =
i <- i - 1 ;
assert (i >= 0 && c = s.[i])
end
let is_blank = function
| ' ' | '\t' | '\r' | '\n' -> true
| _ -> false
let is_ident = function
| 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' | '-' | '.' -> true
| _ -> false
let parse_json stream =
(* as stream#get, returns the first character, but ignores blanks;
* raises EOF under analogous conditions: *)
let rec get_nonblank () =
let c = stream#get in
if is_blank c then get_nonblank () else c
in
(* raises EOF only if input is empty (modulo blanks): *)
let rec parse_value () : value =
begin match get_nonblank () with
| '[' ->
parse_list ()
| '{' ->
parse_record ()
| c when is_ident c ->
let buf = Buffer.create 32 in
begin try
let c = ref c in
while is_ident !c do
Buffer.add_char buf !c;
c := stream#get
done;
stream#unget !c
with End_of_file ->
()
end;
begin match Buffer.contents buf with
| "null" -> Base Null
| "false" -> Base (Bool false)
| "true" -> Base (Bool true)
| s ->
begin try
Base (Int (Int64.of_string s))
with Failure "Int64.of_string" ->
begin try
Base (Float (float_of_string s))
with Failure "float_of_string" ->
failwith @@ "unrecognized token: " ^ s
end
end
end
| '"' ->
let buf = Buffer.create 1024 in
begin try
let c = ref '\000' in
while c := stream#get; !c <> '"' do
if !c = '\\' then
c := stream#get;
Buffer.add_char buf !c
done;
with End_of_file ->
failwith "unterminated quoted string"
end;
Base (String (Buffer.contents buf))
| _ ->
failwith "syntax error: identifier, string, list or record expected"
end
(* raises EOF only if input is empty: *)
and parse_record_field () : record_field =
begin match parse_value () with
| Base name ->
begin try
begin match get_nonblank () with
| ':' ->
let value = parse_value () in
{ name; value }
| _ ->
failwith "syntax error: ‘:’ expected after a field name"
end
with End_of_file ->
failwith "unterminated record field"
end
| _ ->
failwith "forbidden expression as a field name"
end
(* never raise EOF: *)
and parse_record_aux () : record_field list =
begin match get_nonblank () with
| '}' ->
[]
| c ->
stream#unget c;
let field = parse_record_field () in
begin match get_nonblank () with
| '}' ->
[field]
| ',' ->
field :: parse_record_aux ()
| _ ->
failwith "syntax error: ‘,’ or ‘}’ expected after a record field"
| exception End_of_file ->
failwith "unterminated record"
end
| exception End_of_file ->
failwith "unterminated record"
end
and parse_record () : value =
Record (parse_record_aux ())
(* never raise EOF: *)
and parse_list_aux () : value list =
begin match get_nonblank () with
| ']' ->
[]
| c ->
stream#unget c;
let elem = parse_value () in
begin match get_nonblank () with
| ']' ->
[elem]
| ',' ->
elem :: parse_list_aux ()
| _ ->
failwith "syntax error: ‘,’ or ‘]’ expected after a list element"
| exception End_of_file ->
failwith "unterminated list"
end
| exception End_of_file ->
failwith "unterminated list"
end
and parse_list () : value =
List (parse_list_aux ())
in
begin match parse_value () with
| json ->
begin match get_nonblank () with
| exception End_of_file ->
json
| _ ->
failwith "extra input"
end
| exception End_of_file ->
failwith "empty input"
end
let parse_json_file in_file =
parse_json (new file_stream in_file)
let parse_json_string s =
parse_json (new string_stream s)
let print_indent out_file level =
for _ = 1 to level do
output_char out_file '\t'
done
let print_quoted out_file str =
String.iter (fun c ->
if c = '"' || c = '\\' then
output_char out_file '\\';
output_char out_file c
)
str
let print_json out_file json =
let rec print level = function
| Base Null ->
output_string out_file "null"
| Base (Bool b) ->
output_string out_file (string_of_bool b)
| Base (Int i) ->
output_string out_file (Int64.to_string i)
| Base (Float f) ->
output_string out_file (string_of_float f)
| Base (String str) ->
(*Printf.fprintf out_file "%S" str*)
(*output_string out_file @@ "\"" ^ String.escaped str ^ "\""*)
output_char out_file '"';
print_quoted out_file str;
output_char out_file '"'
| List values ->
output_string out_file "[\n";
let level' = level+1 in
List.iter (fun value ->
print_indent out_file level';
print level' value;
output_string out_file ",\n"
)
values;
(*List.iter
(Printf.fprintf out_file "%a%a,\n" print_indent level' (print level'))
values;*)
Printf.fprintf out_file "%a]" print_indent level
| Record fields ->
output_string out_file "{\n";
let level' = level+1 in
List.iter (fun { name; value } ->
print_indent out_file level';
print level' (Base name);
output_char out_file ':';
print level' value;
output_string out_file ",\n";
(*Printf.fprintf out_file "%a%a:%a,\n"
print_indent level'
(print level') (Base name)
(print level') value*)
)
fields;
print_indent out_file level;
output_char out_file '}'
(*Printf.fprintf out_file "%a]" print_indent level*)
in
print 0 json
(*
* the simple json reformater
*)
(*
let () =
stdin
|> parse_json_file
|> print_json stdout
*)
(*
* a more specific use case
*)
let has_field record name' =
record
|> List.exists (fun { name; _ } -> name = String name')
let get_field record name =
record
|> List.map (fun { name; value } -> name, value)
|> List.assoc (String name)
let get_default record name f ~default =
try
get_field record name |> f
with Not_found ->
default
let as_bool = function
| Base (Bool b) -> b
let as_int = function
| Base (Int i) -> Int64.to_int i
let as_string = function
| Base (String str) -> str
let as_list = function
| List li -> li
| Base Null -> []
let as_record = function
| Record r -> r
| Base Null -> []
let ( |? ) = has_field
let ( |. ) = get_field
type tab = {
url : string ;
title : string ;
(*pinned : bool ;
hidden : bool ;*)
}
let () =
let tabgroup_titles = ref []
and tabgroups = Hashtbl.create 10 in
let add_to_group group_id tab =
let old =
begin try
Hashtbl.find tabgroups group_id
with Not_found ->
[]
end
in
Hashtbl.replace tabgroups group_id (tab :: old)
in
parse_json_file stdin |> as_record |. "windows" |> as_list
|> List.iter (fun window ->
window |> as_record |. "tabs" |> as_list
|> List.iter (fun tab ->
let tab = tab |> as_record in
(*let pinned = get_default tab "pinned" as_bool ~default:false
and hidden = get_default tab "hidden" as_bool ~default:false in*)
let entries = tab |. "entries" |> as_list in
let index = get_default tab "index" as_int ~default:(List.length entries) in
let entry = List.nth entries (index-1) |> as_record in
let url = get_default entry "url" as_string ~default:"[no url]"
and title = get_default entry "title" as_string ~default:"[no title]" in
let group_id =
get_default tab "extData" (as_record %> fun extdata ->
get_default extdata "tabview-tab" (as_string %> parse_json_string %> as_record %> fun tabview ->
get_default tabview "groupID" (as_int %> some) ~default:None
)
~default:None
)
~default:None
in
let tab = { url ; title (*pinned ; hidden*) } in
add_to_group group_id tab
) ;
window |> as_record |. "extData" |> as_record |. "tabview-group" |> as_string |> parse_json_string |> as_record
|> List.iter (fun field ->
let id = Base field.name |> as_string |> int_of_string
and title = field.value |> as_record |. "title" |> as_string in
tabgroup_titles := (id, title) :: !tabgroup_titles
)
) ;
Hashtbl.iter (fun group_id tabs ->
begin match group_id with
| None -> Printf.printf "\n-- pinned\n\n"
| Some id -> Printf.printf "\n-- group %i: %s\n\n" id (List.assoc id !tabgroup_titles)
end ;
let tabs = List.rev tabs in
List.iter (fun tab ->