diff --git a/cmake/Modules/Tools.cmake b/cmake/Modules/Tools.cmake index d033681c79..efb3876468 100644 --- a/cmake/Modules/Tools.cmake +++ b/cmake/Modules/Tools.cmake @@ -34,13 +34,24 @@ if(BUILD_LAMMPS_SHELL) if(NOT LAMMPS_EXCEPTIONS) message(WARNING "The LAMMPS shell needs LAMMPS_EXCEPTIONS enabled for full functionality") endif() - add_executable(lammps-shell ${LAMMPS_TOOLS_DIR}/lammps-shell/lammps-shell.cpp) + + # include resource compiler to embed icons into the executable on Windows + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + enable_language(RC) + set(ICON_RC_FILE ${LAMMPS_TOOLS_DIR}/lammps-shell/lmpicons.rc) + endif() + + add_executable(lammps-shell ${LAMMPS_TOOLS_DIR}/lammps-shell/lammps-shell.cpp ${ICON_RC_FILE}) + target_include_directories(lammps-shell PRIVATE ${LAMMPS_TOOLS_DIR}/lammps-shell) + # workaround for broken readline pkg-config file on FreeBSD if(CMAKE_SYSTEM_NAME STREQUAL FreeBSD) target_include_directories(lammps-shell PRIVATE /usr/local/include) endif() target_link_libraries(lammps-shell PRIVATE lammps PkgConfig::READLINE) install(TARGETS lammps-shell EXPORT LAMMPS_Targets DESTINATION ${CMAKE_INSTALL_BINDIR}) + install(DIRECTORY icons DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/) + install(FILES lammps-shell.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/) endif() diff --git a/src/utils.cpp b/src/utils.cpp index 40fc87ca01..5ae76ed00d 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -772,6 +772,22 @@ std::string utils::path_basename(const std::string &path) { return path.substr(start); } +/* ---------------------------------------------------------------------- + Return only the leading part of a path, return just the directory +------------------------------------------------------------------------- */ + +std::string utils::path_dirname(const std::string &path) { +#if defined(_WIN32) + size_t start = path.find_last_of("/\\"); +#else + size_t start = path.find_last_of("/"); +#endif + + if (start == std::string::npos) return "."; + + return path.substr(0,start); +} + /* ---------------------------------------------------------------------- join two paths ------------------------------------------------------------------------- */ diff --git a/src/utils.h b/src/utils.h index 7515f1f21b..52f7933caf 100644 --- a/src/utils.h +++ b/src/utils.h @@ -291,6 +291,13 @@ namespace LAMMPS_NS { std::string path_basename(const std::string &path); + /** Return the directory part of a path. Return "." if empty + * + * \param path file path + * \return directory name */ + + std::string path_dirname(const std::string &path); + /** Join two pathname segments * * This uses the forward slash '/' character unless LAMMPS is compiled diff --git a/tools/lammps-shell/README b/tools/lammps-shell/README index 549f8a3343..d5d050c417 100644 --- a/tools/lammps-shell/README +++ b/tools/lammps-shell/README @@ -162,14 +162,14 @@ is. File extension association """""""""""""""""""""""""" -Since the LAMMPS shell (unlike the regular LAMMPS executable) does not -exit when an input file is passed on the command line with the "-in" or -"-i" flag (the behavior is like for "python -i "), it makes -the LAMMPS shell suitable for associating it with input files based on -their filename extension (e.g. ".lmp"). Since "lammps-shell" is a -console application, you have to run it inside a terminal program with a -command line like this: - - xterm -title "LAMMPS Shell" -e /path/to/lammps-shell -i in.file.lmp +The LAMMPS shell (unlike the regular LAMMPS executable) does not +exit when an input file is passed on the command line, which can be +either with the "-in" or "-i" flag (the behavior is like for +"python -i ") or as the first argument without a flag. +Thus the LAMMPS shell is suitable for associating it with input files +based on their filename extension (e.g. ".lmp"). Since "lammps-shell" +is a console application, you have to run it inside a terminal program. +A "lammps-shell.desktop" and suitable icon files are provided, so that +it can be integrated into compatible desktop environments. diff --git a/tools/lammps-shell/icons/hicolor/128x128/apps/lammps.png b/tools/lammps-shell/icons/hicolor/128x128/apps/lammps.png new file mode 100644 index 0000000000..bfbeb47978 Binary files /dev/null and b/tools/lammps-shell/icons/hicolor/128x128/apps/lammps.png differ diff --git a/tools/lammps-shell/icons/hicolor/16x16/apps/lammps.png b/tools/lammps-shell/icons/hicolor/16x16/apps/lammps.png new file mode 100644 index 0000000000..b48ea6d6a9 Binary files /dev/null and b/tools/lammps-shell/icons/hicolor/16x16/apps/lammps.png differ diff --git a/tools/lammps-shell/icons/hicolor/22x22/apps/lammps.png b/tools/lammps-shell/icons/hicolor/22x22/apps/lammps.png new file mode 100644 index 0000000000..5f15c747d1 Binary files /dev/null and b/tools/lammps-shell/icons/hicolor/22x22/apps/lammps.png differ diff --git a/tools/lammps-shell/icons/hicolor/32x32/apps/lammps.png b/tools/lammps-shell/icons/hicolor/32x32/apps/lammps.png new file mode 100644 index 0000000000..4609d8a411 Binary files /dev/null and b/tools/lammps-shell/icons/hicolor/32x32/apps/lammps.png differ diff --git a/tools/lammps-shell/icons/hicolor/48x48/apps/lammps.png b/tools/lammps-shell/icons/hicolor/48x48/apps/lammps.png new file mode 100644 index 0000000000..bf578d74da Binary files /dev/null and b/tools/lammps-shell/icons/hicolor/48x48/apps/lammps.png differ diff --git a/tools/lammps-shell/icons/hicolor/64x64/apps/lammps.png b/tools/lammps-shell/icons/hicolor/64x64/apps/lammps.png new file mode 100644 index 0000000000..47fb998982 Binary files /dev/null and b/tools/lammps-shell/icons/hicolor/64x64/apps/lammps.png differ diff --git a/tools/lammps-shell/icons/lammps.ico b/tools/lammps-shell/icons/lammps.ico new file mode 100644 index 0000000000..cce156bf79 Binary files /dev/null and b/tools/lammps-shell/icons/lammps.ico differ diff --git a/tools/lammps-shell/icons/lmpfile.ico b/tools/lammps-shell/icons/lmpfile.ico new file mode 100644 index 0000000000..7e1636584f Binary files /dev/null and b/tools/lammps-shell/icons/lmpfile.ico differ diff --git a/tools/lammps-shell/lammps-shell.cpp b/tools/lammps-shell/lammps-shell.cpp index b2c8137aba..7ace6d6819 100644 --- a/tools/lammps-shell/lammps-shell.cpp +++ b/tools/lammps-shell/lammps-shell.cpp @@ -563,7 +563,7 @@ static int help_cmd() "in the current working directory and - if present - this file will be\n" "read at the beginning of the next session of the LAMMPS shell.\n\n" "Additional information is at https://packages.lammps.org/lammps-shell.html\n\n"; - return 0; + return 0; } static int shell_end() @@ -681,7 +681,7 @@ int main(int argc, char **argv) // switch to the user's documents directory. Avoid buffer overflow // and skip this step if the path is too long for our buffer. if (getcwd(buf, buflen)) { - if ((strstr(buf, "System32") || strstr(buf, "system32"))) { + if ((strstr(buf, "System32") || strstr(buf, "system32"))) { char *drive = getenv("HOMEDRIVE"); char *path = getenv("HOMEPATH"); buf[0] = '\0'; @@ -719,11 +719,14 @@ int main(int argc, char **argv) // handle the special case where the first argument is not a flag but a file // this happens for example when using file type associations on Windows. // in this case we save the pointer and remove it from argv. - char *input_file = nullptr; + // we also get the directory name and switch to that folder + std::string input_file; if ((argc > 1) && (argv[1][0] != '-')) { --argc; - input_file = argv[1]; - for (int i = 1; i < argc; ++i) argv[i] = argv[i+1]; + input_file = utils::path_basename(argv[1]); + chdir(utils::path_dirname(input_file).c_str()); + for (int i = 1; i < argc; ++i) + argv[i] = argv[i + 1]; } lmp = lammps_open_no_mpi(argc, argv, nullptr); @@ -733,8 +736,8 @@ int main(int argc, char **argv) init_commands(); // pre-load an input file that was provided on the command line - if (input_file) { - lammps_file(lmp, input_file); + if (!input_file.empty()) { + lammps_file(lmp, input_file.c_str()); } else { for (int i = 0; i < argc; ++i) { if ((strcmp(argv[i], "-in") == 0) || (strcmp(argv[i], "-i") == 0)) { diff --git a/tools/lammps-shell/lammps-shell.desktop b/tools/lammps-shell/lammps-shell.desktop new file mode 100644 index 0000000000..67675c8f22 --- /dev/null +++ b/tools/lammps-shell/lammps-shell.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Categories=Science;Engineering; +Exec=/bin/sh -c "echo -e -n \"\033]0;The LAMMPS Shell\007\"; LC_ALL=C lammps-shell %f" +Name=The LAMMPS Shell +Terminal=true +GenericName=MD Simulator +Keywords=MD Simulation;LAMMPS;Molecular Dynamics;N-Body +Icon=lammps diff --git a/tools/lammps-shell/lmpicons.rc b/tools/lammps-shell/lmpicons.rc new file mode 100644 index 0000000000..a9da9eea17 --- /dev/null +++ b/tools/lammps-shell/lmpicons.rc @@ -0,0 +1,2 @@ +id1 ICON icons/lammps.ico +id2 ICON icons/lmpfile.ico diff --git a/unittest/utils/test_utils.cpp b/unittest/utils/test_utils.cpp index 796ce0f8c7..2c3da7b9df 100644 --- a/unittest/utils/test_utils.cpp +++ b/unittest/utils/test_utils.cpp @@ -525,11 +525,26 @@ TEST(Utils, path_basename) { #if defined(_WIN32) ASSERT_THAT(utils::path_basename("c:\\parent\\folder\\filename"), Eq("filename")); + ASSERT_THAT(utils::path_basename("folder\\"), Eq("")); + ASSERT_THAT(utils::path_basename("c:/parent/folder/filename"), Eq("filename")); #else ASSERT_THAT(utils::path_basename("/parent/folder/filename"), Eq("filename")); + ASSERT_THAT(utils::path_basename("/parent/folder/"), Eq("")); #endif } +TEST(Utils, path_dirname) +{ +#if defined(_WIN32) + ASSERT_THAT(utils::path_dirname("c:/parent/folder/filename"), Eq("c:/parent/folder")); + ASSERT_THAT(utils::path_dirname("c:\\parent\\folder\\filename"), Eq("c:\\parent\\folder")); + ASSERT_THAT(utils::path_dirname("c:filename"), Eq(".")); +#else + ASSERT_THAT(utils::path_dirname("/parent/folder/filename"), Eq("/parent/folder")); +#endif + ASSERT_THAT(utils::path_dirname("filename"), Eq(".")); +} + TEST(Utils, getsyserror) { #if defined(__linux__)