Fossil SCM
Add the "fossil which" command, which even works on Windows. Enhance the fossil_text_editor() function so that it looks for common text editor names if it does not find a user-specified preference.
Commit
fc60e44417e8437ce3f07a7ffdae72bbdd6ab3c9af80a231a5b84e1c38c9e819
Parent
19fc9713fccfed7…
1 file changed
+62
-17
+62
-17
| --- src/util.c | ||
| +++ src/util.c | ||
| @@ -670,28 +670,32 @@ | ||
| 670 | 670 | ** Search algorithm: |
| 671 | 671 | ** (1) The local "editor" setting |
| 672 | 672 | ** (2) The global "editor" setting |
| 673 | 673 | ** (3) The VISUAL environment variable |
| 674 | 674 | ** (4) The EDITOR environment variable |
| 675 | -** (5) (Windows only:) "notepad.exe" | |
| 675 | +** (5) Any of the following programs that are available: | |
| 676 | +** notepad, nano, pico, edit, vi, vim, ed, | |
| 676 | 677 | */ |
| 677 | 678 | const char *fossil_text_editor(void){ |
| 678 | 679 | const char *zEditor = db_get("editor", 0); |
| 680 | + const char *azStdEd[] = { | |
| 681 | + "notepad", "nano", "pico", "edit", "vi", "vim", "ed" | |
| 682 | + }; | |
| 683 | + int i = 0; | |
| 679 | 684 | if( zEditor==0 ){ |
| 680 | 685 | zEditor = fossil_getenv("VISUAL"); |
| 681 | 686 | } |
| 682 | 687 | if( zEditor==0 ){ |
| 683 | 688 | zEditor = fossil_getenv("EDITOR"); |
| 684 | 689 | } |
| 685 | -#if defined(_WIN32) || defined(__CYGWIN__) | |
| 686 | - if( zEditor==0 ){ | |
| 687 | - zEditor = mprintf("%s\\notepad.exe", fossil_getenv("SYSTEMROOT")); | |
| 688 | -#if defined(__CYGWIN__) | |
| 689 | - zEditor = fossil_utf8_to_path(zEditor, 0); | |
| 690 | -#endif | |
| 691 | - } | |
| 692 | -#endif | |
| 690 | + while( zEditor==0 && i<count(azStdEd) ){ | |
| 691 | + if( fossil_app_on_path(azStdEd[i],0) ){ | |
| 692 | + zEditor = azStdEd[i]; | |
| 693 | + }else{ | |
| 694 | + i++; | |
| 695 | + } | |
| 696 | + } | |
| 693 | 697 | return zEditor; |
| 694 | 698 | } |
| 695 | 699 | |
| 696 | 700 | /* |
| 697 | 701 | ** Construct a temporary filename. |
| @@ -895,35 +899,76 @@ | ||
| 895 | 899 | return n< 10 ? 1 : n< 100 ? 2 : n< 1000 ? 3 |
| 896 | 900 | : n< 10000 ? 4 : n< 100000 ? 5 : n< 1000000 ? 6 |
| 897 | 901 | : n<10000000 ? 7 : n<100000000 ? 8 : n<1000000000 ? 9 : 10; |
| 898 | 902 | } |
| 899 | 903 | |
| 900 | -#if !defined(_WIN32) | |
| 901 | -#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__) | |
| 902 | 904 | /* |
| 903 | 905 | ** Search for an executable on the PATH environment variable. |
| 904 | 906 | ** Return true (1) if found and false (0) if not found. |
| 907 | +** | |
| 908 | +** Print the full pathname of the first location if ePrint==1. Print | |
| 909 | +** all pathnames for the executable if ePrint==2 or more. | |
| 905 | 910 | */ |
| 906 | -static int binaryOnPath(const char *zBinary){ | |
| 911 | +int fossil_app_on_path(const char *zBinary, int ePrint){ | |
| 907 | 912 | const char *zPath = fossil_getenv("PATH"); |
| 908 | 913 | char *zFull; |
| 909 | 914 | int i; |
| 910 | 915 | int bExists; |
| 916 | + int bFound = 0; | |
| 911 | 917 | while( zPath && zPath[0] ){ |
| 918 | +#ifdef _WIN32 | |
| 919 | + while( zPath[0]==';' ) zPath++; | |
| 920 | + for(i=0; zPath[i] && zPath[i]!=';'; i++){} | |
| 921 | + zFull = mprintf("%.*s\\%s.exe", i, zPath, zBinary); | |
| 922 | + bExists = file_access(zFull, R_OK); | |
| 923 | + if( bExists!=0 ){ | |
| 924 | + fossil_free(zFull); | |
| 925 | + zFull = mprintf("%.*s\\%s.bat", i, zPath, zBinary); | |
| 926 | + bExists = file_access(zFull, R_OK); | |
| 927 | + } | |
| 928 | +#else | |
| 912 | 929 | while( zPath[0]==':' ) zPath++; |
| 913 | 930 | for(i=0; zPath[i] && zPath[i]!=':'; i++){} |
| 914 | 931 | zFull = mprintf("%.*s/%s", i, zPath, zBinary); |
| 915 | 932 | bExists = file_access(zFull, X_OK); |
| 933 | +#endif | |
| 934 | + if( bExists==0 && ePrint ){ | |
| 935 | + fossil_print("%s\n", zFull); | |
| 936 | + } | |
| 916 | 937 | fossil_free(zFull); |
| 917 | - if( bExists==0 ) return 1; | |
| 938 | + if( bExists==0 ){ | |
| 939 | + if( ePrint<2 ) return 1; | |
| 940 | + bFound = 1; | |
| 941 | + } | |
| 918 | 942 | zPath += i; |
| 919 | 943 | } |
| 920 | - return 0; | |
| 944 | + return bFound; | |
| 921 | 945 | } |
| 922 | -#endif | |
| 923 | -#endif | |
| 924 | 946 | |
| 947 | +/* | |
| 948 | +** COMMAND: which* | |
| 949 | +** | |
| 950 | +** Usage: fossil which [-a] NAME ... | |
| 951 | +** | |
| 952 | +** For each NAME mentioned as an argument, print the first location on the | |
| 953 | +** on PATH of the executable with that name. Or, show all locations on PATH | |
| 954 | +** for each argument if the -a option is used. | |
| 955 | +** | |
| 956 | +** This command is a substitute for the unix "which" command, which is not | |
| 957 | +** always available, especially on Windows. | |
| 958 | +*/ | |
| 959 | +void test_app_on_path(void){ | |
| 960 | + int i; | |
| 961 | + int ePrint = 1; | |
| 962 | + if( find_option("all","a",0)!=0 ) ePrint = 2; | |
| 963 | + verify_all_options(); | |
| 964 | + for(i=2; i<g.argc; i++){ | |
| 965 | + if( fossil_app_on_path(g.argv[i], ePrint)==0 ){ | |
| 966 | + fossil_print("NOT FOUND: %s\n", g.argv[i]); | |
| 967 | + } | |
| 968 | + } | |
| 969 | +} | |
| 925 | 970 | |
| 926 | 971 | /* |
| 927 | 972 | ** Return the name of a command that will launch a web-browser. |
| 928 | 973 | */ |
| 929 | 974 | const char *fossil_web_browser(void){ |
| @@ -938,11 +983,11 @@ | ||
| 938 | 983 | static const char *const azBrowserProg[] = |
| 939 | 984 | { "xdg-open", "gnome-open", "firefox", "google-chrome" }; |
| 940 | 985 | int i; |
| 941 | 986 | zBrowser = "echo"; |
| 942 | 987 | for(i=0; i<count(azBrowserProg); i++){ |
| 943 | - if( binaryOnPath(azBrowserProg[i]) ){ | |
| 988 | + if( fossil_app_on_path(azBrowserProg[i],0) ){ | |
| 944 | 989 | zBrowser = azBrowserProg[i]; |
| 945 | 990 | break; |
| 946 | 991 | } |
| 947 | 992 | } |
| 948 | 993 | zBrowser = mprintf("%s 2>/dev/null", zBrowser); |
| 949 | 994 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -670,28 +670,32 @@ | |
| 670 | ** Search algorithm: |
| 671 | ** (1) The local "editor" setting |
| 672 | ** (2) The global "editor" setting |
| 673 | ** (3) The VISUAL environment variable |
| 674 | ** (4) The EDITOR environment variable |
| 675 | ** (5) (Windows only:) "notepad.exe" |
| 676 | */ |
| 677 | const char *fossil_text_editor(void){ |
| 678 | const char *zEditor = db_get("editor", 0); |
| 679 | if( zEditor==0 ){ |
| 680 | zEditor = fossil_getenv("VISUAL"); |
| 681 | } |
| 682 | if( zEditor==0 ){ |
| 683 | zEditor = fossil_getenv("EDITOR"); |
| 684 | } |
| 685 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 686 | if( zEditor==0 ){ |
| 687 | zEditor = mprintf("%s\\notepad.exe", fossil_getenv("SYSTEMROOT")); |
| 688 | #if defined(__CYGWIN__) |
| 689 | zEditor = fossil_utf8_to_path(zEditor, 0); |
| 690 | #endif |
| 691 | } |
| 692 | #endif |
| 693 | return zEditor; |
| 694 | } |
| 695 | |
| 696 | /* |
| 697 | ** Construct a temporary filename. |
| @@ -895,35 +899,76 @@ | |
| 895 | return n< 10 ? 1 : n< 100 ? 2 : n< 1000 ? 3 |
| 896 | : n< 10000 ? 4 : n< 100000 ? 5 : n< 1000000 ? 6 |
| 897 | : n<10000000 ? 7 : n<100000000 ? 8 : n<1000000000 ? 9 : 10; |
| 898 | } |
| 899 | |
| 900 | #if !defined(_WIN32) |
| 901 | #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__) |
| 902 | /* |
| 903 | ** Search for an executable on the PATH environment variable. |
| 904 | ** Return true (1) if found and false (0) if not found. |
| 905 | */ |
| 906 | static int binaryOnPath(const char *zBinary){ |
| 907 | const char *zPath = fossil_getenv("PATH"); |
| 908 | char *zFull; |
| 909 | int i; |
| 910 | int bExists; |
| 911 | while( zPath && zPath[0] ){ |
| 912 | while( zPath[0]==':' ) zPath++; |
| 913 | for(i=0; zPath[i] && zPath[i]!=':'; i++){} |
| 914 | zFull = mprintf("%.*s/%s", i, zPath, zBinary); |
| 915 | bExists = file_access(zFull, X_OK); |
| 916 | fossil_free(zFull); |
| 917 | if( bExists==0 ) return 1; |
| 918 | zPath += i; |
| 919 | } |
| 920 | return 0; |
| 921 | } |
| 922 | #endif |
| 923 | #endif |
| 924 | |
| 925 | |
| 926 | /* |
| 927 | ** Return the name of a command that will launch a web-browser. |
| 928 | */ |
| 929 | const char *fossil_web_browser(void){ |
| @@ -938,11 +983,11 @@ | |
| 938 | static const char *const azBrowserProg[] = |
| 939 | { "xdg-open", "gnome-open", "firefox", "google-chrome" }; |
| 940 | int i; |
| 941 | zBrowser = "echo"; |
| 942 | for(i=0; i<count(azBrowserProg); i++){ |
| 943 | if( binaryOnPath(azBrowserProg[i]) ){ |
| 944 | zBrowser = azBrowserProg[i]; |
| 945 | break; |
| 946 | } |
| 947 | } |
| 948 | zBrowser = mprintf("%s 2>/dev/null", zBrowser); |
| 949 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -670,28 +670,32 @@ | |
| 670 | ** Search algorithm: |
| 671 | ** (1) The local "editor" setting |
| 672 | ** (2) The global "editor" setting |
| 673 | ** (3) The VISUAL environment variable |
| 674 | ** (4) The EDITOR environment variable |
| 675 | ** (5) Any of the following programs that are available: |
| 676 | ** notepad, nano, pico, edit, vi, vim, ed, |
| 677 | */ |
| 678 | const char *fossil_text_editor(void){ |
| 679 | const char *zEditor = db_get("editor", 0); |
| 680 | const char *azStdEd[] = { |
| 681 | "notepad", "nano", "pico", "edit", "vi", "vim", "ed" |
| 682 | }; |
| 683 | int i = 0; |
| 684 | if( zEditor==0 ){ |
| 685 | zEditor = fossil_getenv("VISUAL"); |
| 686 | } |
| 687 | if( zEditor==0 ){ |
| 688 | zEditor = fossil_getenv("EDITOR"); |
| 689 | } |
| 690 | while( zEditor==0 && i<count(azStdEd) ){ |
| 691 | if( fossil_app_on_path(azStdEd[i],0) ){ |
| 692 | zEditor = azStdEd[i]; |
| 693 | }else{ |
| 694 | i++; |
| 695 | } |
| 696 | } |
| 697 | return zEditor; |
| 698 | } |
| 699 | |
| 700 | /* |
| 701 | ** Construct a temporary filename. |
| @@ -895,35 +899,76 @@ | |
| 899 | return n< 10 ? 1 : n< 100 ? 2 : n< 1000 ? 3 |
| 900 | : n< 10000 ? 4 : n< 100000 ? 5 : n< 1000000 ? 6 |
| 901 | : n<10000000 ? 7 : n<100000000 ? 8 : n<1000000000 ? 9 : 10; |
| 902 | } |
| 903 | |
| 904 | /* |
| 905 | ** Search for an executable on the PATH environment variable. |
| 906 | ** Return true (1) if found and false (0) if not found. |
| 907 | ** |
| 908 | ** Print the full pathname of the first location if ePrint==1. Print |
| 909 | ** all pathnames for the executable if ePrint==2 or more. |
| 910 | */ |
| 911 | int fossil_app_on_path(const char *zBinary, int ePrint){ |
| 912 | const char *zPath = fossil_getenv("PATH"); |
| 913 | char *zFull; |
| 914 | int i; |
| 915 | int bExists; |
| 916 | int bFound = 0; |
| 917 | while( zPath && zPath[0] ){ |
| 918 | #ifdef _WIN32 |
| 919 | while( zPath[0]==';' ) zPath++; |
| 920 | for(i=0; zPath[i] && zPath[i]!=';'; i++){} |
| 921 | zFull = mprintf("%.*s\\%s.exe", i, zPath, zBinary); |
| 922 | bExists = file_access(zFull, R_OK); |
| 923 | if( bExists!=0 ){ |
| 924 | fossil_free(zFull); |
| 925 | zFull = mprintf("%.*s\\%s.bat", i, zPath, zBinary); |
| 926 | bExists = file_access(zFull, R_OK); |
| 927 | } |
| 928 | #else |
| 929 | while( zPath[0]==':' ) zPath++; |
| 930 | for(i=0; zPath[i] && zPath[i]!=':'; i++){} |
| 931 | zFull = mprintf("%.*s/%s", i, zPath, zBinary); |
| 932 | bExists = file_access(zFull, X_OK); |
| 933 | #endif |
| 934 | if( bExists==0 && ePrint ){ |
| 935 | fossil_print("%s\n", zFull); |
| 936 | } |
| 937 | fossil_free(zFull); |
| 938 | if( bExists==0 ){ |
| 939 | if( ePrint<2 ) return 1; |
| 940 | bFound = 1; |
| 941 | } |
| 942 | zPath += i; |
| 943 | } |
| 944 | return bFound; |
| 945 | } |
| 946 | |
| 947 | /* |
| 948 | ** COMMAND: which* |
| 949 | ** |
| 950 | ** Usage: fossil which [-a] NAME ... |
| 951 | ** |
| 952 | ** For each NAME mentioned as an argument, print the first location on the |
| 953 | ** on PATH of the executable with that name. Or, show all locations on PATH |
| 954 | ** for each argument if the -a option is used. |
| 955 | ** |
| 956 | ** This command is a substitute for the unix "which" command, which is not |
| 957 | ** always available, especially on Windows. |
| 958 | */ |
| 959 | void test_app_on_path(void){ |
| 960 | int i; |
| 961 | int ePrint = 1; |
| 962 | if( find_option("all","a",0)!=0 ) ePrint = 2; |
| 963 | verify_all_options(); |
| 964 | for(i=2; i<g.argc; i++){ |
| 965 | if( fossil_app_on_path(g.argv[i], ePrint)==0 ){ |
| 966 | fossil_print("NOT FOUND: %s\n", g.argv[i]); |
| 967 | } |
| 968 | } |
| 969 | } |
| 970 | |
| 971 | /* |
| 972 | ** Return the name of a command that will launch a web-browser. |
| 973 | */ |
| 974 | const char *fossil_web_browser(void){ |
| @@ -938,11 +983,11 @@ | |
| 983 | static const char *const azBrowserProg[] = |
| 984 | { "xdg-open", "gnome-open", "firefox", "google-chrome" }; |
| 985 | int i; |
| 986 | zBrowser = "echo"; |
| 987 | for(i=0; i<count(azBrowserProg); i++){ |
| 988 | if( fossil_app_on_path(azBrowserProg[i],0) ){ |
| 989 | zBrowser = azBrowserProg[i]; |
| 990 | break; |
| 991 | } |
| 992 | } |
| 993 | zBrowser = mprintf("%s 2>/dev/null", zBrowser); |
| 994 |