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.

drh 2025-03-16 19:15 trunk
Commit fc60e44417e8437ce3f07a7ffdae72bbdd6ab3c9af80a231a5b84e1c38c9e819
1 file changed +62 -17
+62 -17
--- src/util.c
+++ src/util.c
@@ -670,28 +670,32 @@
670670
** Search algorithm:
671671
** (1) The local "editor" setting
672672
** (2) The global "editor" setting
673673
** (3) The VISUAL environment variable
674674
** (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,
676677
*/
677678
const char *fossil_text_editor(void){
678679
const char *zEditor = db_get("editor", 0);
680
+ const char *azStdEd[] = {
681
+ "notepad", "nano", "pico", "edit", "vi", "vim", "ed"
682
+ };
683
+ int i = 0;
679684
if( zEditor==0 ){
680685
zEditor = fossil_getenv("VISUAL");
681686
}
682687
if( zEditor==0 ){
683688
zEditor = fossil_getenv("EDITOR");
684689
}
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
+ }
693697
return zEditor;
694698
}
695699
696700
/*
697701
** Construct a temporary filename.
@@ -895,35 +899,76 @@
895899
return n< 10 ? 1 : n< 100 ? 2 : n< 1000 ? 3
896900
: n< 10000 ? 4 : n< 100000 ? 5 : n< 1000000 ? 6
897901
: n<10000000 ? 7 : n<100000000 ? 8 : n<1000000000 ? 9 : 10;
898902
}
899903
900
-#if !defined(_WIN32)
901
-#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
902904
/*
903905
** Search for an executable on the PATH environment variable.
904906
** 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.
905910
*/
906
-static int binaryOnPath(const char *zBinary){
911
+int fossil_app_on_path(const char *zBinary, int ePrint){
907912
const char *zPath = fossil_getenv("PATH");
908913
char *zFull;
909914
int i;
910915
int bExists;
916
+ int bFound = 0;
911917
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
912929
while( zPath[0]==':' ) zPath++;
913930
for(i=0; zPath[i] && zPath[i]!=':'; i++){}
914931
zFull = mprintf("%.*s/%s", i, zPath, zBinary);
915932
bExists = file_access(zFull, X_OK);
933
+#endif
934
+ if( bExists==0 && ePrint ){
935
+ fossil_print("%s\n", zFull);
936
+ }
916937
fossil_free(zFull);
917
- if( bExists==0 ) return 1;
938
+ if( bExists==0 ){
939
+ if( ePrint<2 ) return 1;
940
+ bFound = 1;
941
+ }
918942
zPath += i;
919943
}
920
- return 0;
944
+ return bFound;
921945
}
922
-#endif
923
-#endif
924946
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
+}
925970
926971
/*
927972
** Return the name of a command that will launch a web-browser.
928973
*/
929974
const char *fossil_web_browser(void){
@@ -938,11 +983,11 @@
938983
static const char *const azBrowserProg[] =
939984
{ "xdg-open", "gnome-open", "firefox", "google-chrome" };
940985
int i;
941986
zBrowser = "echo";
942987
for(i=0; i<count(azBrowserProg); i++){
943
- if( binaryOnPath(azBrowserProg[i]) ){
988
+ if( fossil_app_on_path(azBrowserProg[i],0) ){
944989
zBrowser = azBrowserProg[i];
945990
break;
946991
}
947992
}
948993
zBrowser = mprintf("%s 2>/dev/null", zBrowser);
949994
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button