Permalink
Browse files

[list/search] improve the behavior of list search

Now:
    $ opam list foo

will return the package foo only, and not all the packages whose name contains foo.

Also:
    $ opam search foo

will return all the packages whose name or description contain foo.
  • Loading branch information...
1 parent a12239d commit be2811333fbea0ebca910ce1e71418dc90ab14f3 @samoht samoht committed Sep 10, 2012
Showing with 63 additions and 41 deletions.
  1. +28 −28 src/client.ml
  2. +3 −3 src/client.mli
  3. +22 −10 src/opam.ml
  4. +10 −0 src/utils.ml
View
@@ -728,28 +728,30 @@ let indent_right s nb =
let s_not_installed = "--"
-let list ~print_short ~installed_only ~name_only pkg_str =
+let list ~print_short ~installed_only ~name_only res =
log "list";
let t = load_state () in
- let re =
- try Re.compile (Re_glob.globx pkg_str)
- with Re_glob.Parse_error ->
- Globals.error_and_exit "\"%s\" is not a valid package descriptor" pkg_str
- in
+ let res =
+ Utils.filter_map (fun re ->
+ try Some (Re.compile (Re_glob.globx re))
+ with Re_glob.Parse_error ->
+ Globals.error "\"%s\" is not a valid package descriptor" re;
+ None
+ ) res in
+ let exact_match str =
+ List.exists (fun re -> Utils.exact_match re str) res in
+ let partial_match str =
+ List.exists (fun re -> Re.execp re str) res in
(* Get all the installed packages *)
let installed = File.Installed.read (Path.C.installed t.compiler) in
let map, max_n, max_v =
NV.Set.fold
(fun nv (map, max_n, max_v) ->
let name = NV.name nv in
let version = NV.version nv in
- if
- N.Map.mem name map (* If the packet has been processed yet *)
- &&
- fst (N.Map.find name map) <> None
- (* If moreover the version processed was the version that is installed.
- NB at the time of writing there is at most only 1 [version]
- installed for a given [name]. *)
+ if N.Map.mem name map (* If the packet has been processed yet *)
+ (* And the version processed was the installed version. *)
+ && fst (N.Map.find name map) <> None
then
map, max_n, max_v
else
@@ -761,29 +763,27 @@ let list ~print_short ~installed_only ~name_only pkg_str =
let max_v = if is_installed then max max_v (String.length (V.to_string version)) else max_v in
map, max_n, max_v)
t.available
- (N.Map.empty, min_int, String.length s_not_installed)
- in
+ (N.Map.empty, min_int, String.length s_not_installed) in
+ let map =
+ N.Map.filter (fun name (version, descr) ->
+ (* installp *) (not installed_only || version <> None)
+ (* allp *) && (res = []
+ (* namep *) || name_only && exact_match (N.to_string name)
+ (* descrp *) || not name_only && (partial_match (N.to_string name) || partial_match descr))
+ ) map in
N.Map.iter (
if print_short then
- fun name (version, _) ->
- let version = match version with
- | None -> s_not_installed
- | Some v -> V.to_string v in
- let name = N.to_string name in
- (if Re.execp re name && (not installed_only || version <> s_not_installed)
- then Globals.msg "%s " name)
+ fun name _ -> Globals.msg "%s " (N.to_string name)
else
fun name (version, description) ->
let name = N.to_string name in
let version = match version with
| None -> s_not_installed
| Some v -> V.to_string v in
- (if (Re.execp re name || (not name_only && Re.execp re description))
- && (not installed_only || version <> s_not_installed) then
- Globals.msg "%s %s %s\n"
- (indent_left name max_n)
- (indent_right version max_v)
- description)
+ Globals.msg "%s %s %s\n"
+ (indent_left name max_n)
+ (indent_right version max_v)
+ description
) map
let info package =
View
@@ -25,9 +25,9 @@ open Types
- [cores] is the number of cores *)
val init : repository -> OCaml_V.t option -> int -> unit
-(** Displays all available packages that matches [string]. *)
-val list : print_short:bool -> installed_only:bool -> name_only:bool
- -> string -> unit
+(** Displays all available packages that matches any of the regexps. *)
+val list : print_short:bool -> installed_only:bool -> name_only:bool
+ -> string list -> unit
(** Displays a general summary of a package. *)
val info : N.t -> unit
View
@@ -112,33 +112,45 @@ let list =
let installed = ref false in
{
name = "list";
- usage = "[package-regexp]*";
+ usage = "<package-regexp>*";
synopsis = "Display the list of available packages";
help = "";
specs = [
- ("-short", Arg.Set short, " Minimize the output by displaying only package name (installed and not installed)");
+ ("-short" , Arg.Set short , " Minimize the output by displaying only package name");
("-installed", Arg.Set installed, " Display only the list of installed packages");
];
anon;
main =
- parse_args (function
- | [] -> Client.list !short !installed true ""
- | l -> List.iter (fun name -> Client.list !short !installed true name) l)
+ parse_args (function args ->
+ let print_short = !short in
+ let installed_only = !installed in
+ let name_only = true in
+ Client.list ~print_short ~installed_only ~name_only args
+ )
}
(* opam search [PACKAGE_REGEXP]* *)
-let search =
+let search =
+ let short = ref false in
+ let installed = ref false in
{
name = "search";
usage = "<package-regexp>*";
synopsis = "Search into the package list";
help = "";
- specs = [];
+ specs = [
+ ("-short" , Arg.Set short , " Minimize the output by displaying only package name");
+ ("-installed", Arg.Set installed, " Display only the list of installed packages");
+ ];
+
anon;
main =
- parse_args (function
- | [] -> Client.list false false false ""
- | l -> List.iter (fun name -> Client.list false false false name) l)
+ parse_args (function args ->
+ let print_short = !short in
+ let installed_only = !installed in
+ let name_only = false in
+ Client.list ~print_short ~installed_only ~name_only args
+ )
}
(* opam info [PACKAGE] *)
View
@@ -107,3 +107,13 @@ let rsync_trim = function
match List.rev t with
| _ :: _ :: _ :: l -> List.filter ((<>) "./") l
| _ -> []
+
+let exact_match re s =
+ try
+ let subs = Re.exec re s in
+ let subs = Array.to_list (Re.get_all_ofs subs) in
+ let n = String.length s in
+ let subs = List.filter (fun (s,e) -> s=0 && e=n) subs in
+ List.length subs > 0
+ with Not_found ->
+ false

0 comments on commit be28113

Please sign in to comment.