diff --git a/coding-style/index.html b/coding-style/index.html index 5665514..22ccbc6 100644 --- a/coding-style/index.html +++ b/coding-style/index.html @@ -1113,7 +1113,7 @@ $ alias cl Copyright © 2025 Yury V. Zaytsev • - Revision: g6ad233e62 + Revision: g5b891d773 • Yury V. Zaytsev • - Revision: g6ad233e62 + Revision: g5b891d773 • + + +
Midnight Commander supports theming! Check out the skins that come with the distribution or develop your own:
+This website is the new home of Midnight Commander.
The main project forge has been moved from Savannah and later Trac to a new forge hosted by GitHub.
We used to run a self-hosted Trac instance for over a decade to serve as our home page, wiki, source browser, and issue tracker. With the retirement of Trac, most of these items have been moved to GitHub.
-A third party has developed an online skin editor for Midnight Commander that can be accessed through a browser without installation:
-The old server is still available at https://old.midnight-commander.org until it is decommissioned. Please let us know if there is any content you would like to secure!
mc) is a visual, dual-pane file manager. It is released under the GNU General Public License and therefore qualifies as Free Software. Midnight Commander is a feature-rich, full-screen, text-mode application that allows you to copy, move, and delete files and entire directory trees, search for files, and execute commands in the subshell. Internal viewer, editor and diff viewer are included.
mc uses versatile text interface libraries such as ncurses or S-Lang, which allows it to work on a regular console, inside an X Window terminal, over ssh connections, and in all kinds of remote shells.
The easiest way to install mc is to use your system package manager:
# apt-get install mc\n # dnf install mc\n # pkg install mc\n % brew install midnight-commander\n Our source releases are kindly mirrored by OSU OSL. Our canonical repository is hosted on GitHub. See the Source code page for details.
"},{"location":"#documentation","title":"Documentation","text":"The primary way to learn about mc is to use the context-sensitive online help available via F1.
We also have extensive manual pages, which are the primary source of official documentation:
mcmceditmcviewmcdiff$ man mc\n ... or read the latest development version online.
$ man mcedit\n ... or read the latest development version online.
$ man mcview\n ... or read the latest development version online.
$ man mcdiff\n ... or read the latest development version online.
"},{"location":"#contributing-support","title":"Contributing & support","text":"mc, proceed to the \"Development\" section.We loosely follow the GNU Coding Standards with some local deviations. Whether you agree with them or not, do check it out\u2014it is an educational read. In a nutshell:
Use the clang-format to format the code:
$ make indent\n To avoid formatting differences between clang-format versions, we currently use clang-format-19. The clang-format Python distribution provides precompiled binaries for all major platforms:
$ uv tool install 'clang-format==19.*'\n$ alias clang-format='uvx clang-format'\n"},{"location":"coding-style/#readable-code","title":"Readable code","text":"Use your best judgment and choose the more readable option. Remember that many other people will be reading it:
Rightbytes = read (fd, &routine.pointer, sizeof (routine));\nif (bytes == -1 || (size_t) bytes < sizeof (routine))\n ...\n Wrongif ((bytes = read (fd, &routine.pointer, sizeof (routine))) == -1 || (size_t) bytes < sizeof (routine))\n ...\n Do not put more than one statement on a line:
Righta = 0;\nb = 2;\n\na = f ();\nif (a == 2)\n b = 5;\n Wronga = 0; b = 2;\n\nif ((a = f()) == 2)\n b = 5;\n\nif (a == 2) b = 5;\n Use explicit comparison in equality operators:
void *p1, *p2;\nint i1, i2;\nchar c1, c2;\n Rightif (p1 != NULL)\nif (p2 == NULL)\n\nif (i1 != 0)\nif (i2 == 0)\n\nif (c1 != '\\0')\nif (c2 == '\\0')\n Wrongif (p1)\nif (!p2)\n\nif (i1)\nif (!i2)\n\nif (c1)\nif (!c2)\n Do not check boolean values for equality:
gboolean b1, b2;\n Rightif (b1)\nif (!b2)\n Wrongif (b1 == TRUE)\nif (b2 == FALSE)\n"},{"location":"coding-style/#comments","title":"Comments","text":"Precede comments with a blank line. If the comment belongs directly to the following code, there should not be a blank line after the comment, unless the comment contains a summary of several blocks of following code.
Right/*\n * This is a multiline comment\n *\n * Note that edit_delete() will not corrupt anything if it is called \n * while the cursor position is EOF.\n */\n(void) edit_delete (edit);\n\n// This is a one-line comment. Allocate additional memory.\nmem = (char *) malloc (memneed);\n\n/**\n * @brief This is a Doxygen comment\n *\n * This is a more detailed explanation of\n * this simple function.\n *\n * @param[in] param1 The parameter value of the function\n * @param[out] result1 The result value of the function\n * @return 0 on success and -1 on error\n */\nint example (int param1, int *result1);\n Wrong//This is a one-line comment.\nmem = (char *) malloc (memneed);// No space before comment\n\n/* This is a multiline comment,\n with some more words...*/\n"},{"location":"coding-style/#conditionals","title":"Conditionals","text":"Always follow an if keyword with a space, but do not include additional spaces before or after the parentheses in the conditional:
if (i == 0)\n\u2800\n Wrongif ( i == 0 )\nif (0 == i)\n"},{"location":"coding-style/#function-calls","title":"Function calls","text":"Always include a space between the name and the left parentheses when calling functions:
Rightdo_example (int param1, int *result1);\n Wrongdo_example(int param1, int *result1);\n"},{"location":"coding-style/#braces","title":"Braces","text":"Braces for blocks of code associated with for, if, switch, while, do .. while, etc. should start on the next line after the statement keyword and end on a separate line.
If the length of the opening statement requires it to span multiple lines, the opening brace should be on a separate line.
Do not use braces unnecessarily when a single statement will do.
Rightif (xterm_flag && xterm_title)\n{\n path = strip_home_and_password (current_panel->cwd);\n ...\n}\n\nfor (k = 0; k < 10; k++)\n for (j = 0; j < 10; j++)\n for (i = 0; str_options[i].opt_name != NULL; i++)\n g_free (*str_options[i].opt_addr);\n Wrongif (xterm_flag && xterm_title) {\n path = strip_home_and_password (current_panel->cwd);\n ...\n}\n\nif (xterm_flag && xterm_title)\n{\n path = strip_home_and_password (current_panel->cwd); }\n"},{"location":"coding-style/#goto","title":"Goto","text":"Use goto only when necessary; it is evil, but can greatly improve readability and reduce memory leaks when used as the only exit point from a function.
{\n if (link_type == LINK_HARDLINK)\n {\n src = g_strdup_printf (_ (\"Link %s to:\"), str_trunc (fname, 46));\n dest = input_expand_dialog (_ (\"Link\"), src, MC_HISTORY_FM_LINK, \"\");\n\n if (dest == NULL || *dest == '\\0')\n goto cleanup;\n ...\n ...\n }\n ...\n ...\n\ncleanup:\n g_free (src);\n g_free (dest);\n\n}\n"},{"location":"coding-style/#variables","title":"Variables","text":"Do not mix variable declarations and code; declare variables only at the beginning of the appropriate block.
Reduce variable scope as much as possible: declare local variables in the block where they are used.
Separate variable declaration and code with an empty line.
Right{\n while (TRUE) {\n int foo = 0;\n\n do_bar (foo);\n }\n}\n Wrong{\n int foo = 0;\n while (TRUE) {\n do_bar (foo);\n }\n}\n\u2800\n If a variable is introduced only to store an intermediate value, declare it at the place of use, join declaration and initialization, and mark it as a constant:
Rightconst ssize_t len = mc_readlink ( ... );\n\u2800\n\u2800\n Wrongssize_t len;\n\nlen = mc_readlink ( ... );\n Avoid having initialized and uninitialized variables in the same declaration:
Rightint a;\nint b = 0;\n Wrongint a, b = 0;\n\u2800\n Avoid multiple non-trivial variable initializations in a declaration:
Rightint a = 2 + 5;\nint b = 4 * 3 - 1;\n Wrongint a = 2 + 5, b = 4 * 3 - 1;\n\u2800\n Mark unused variables with the MC_UNUSED macro:
int\nprogress_button_callback (MC_UNUSED WButton *button, MC_UNUSED int action)\n{\n return 0;\n}\n Wrongint\nprogress_button_callback (WButton *button, int action)\n{\n (void) button;\n (void) action;\n\n return 0;\n}\n Try to avoid passing function calls as function parameters in new code. Not doing so makes the code much easier to read, and it is also easier to use the step command in gdb.
void\ndirsizes_cmd (void)\n{\n const ComputeDirSizeUI *ui = compute_dir_size_create_ui ();\n compute_dir_size_destroy_ui (ui);\n}\n Wrongvoid\ndirsizes_cmd (void)\n{\n compute_dir_size_destroy_ui (compute_dir_size_create_ui ());\n}\n Avoid abusing non-const function parameters as local variables:
void\nfoo (const int iterations)\n{\n int result;\n\n result = do_one_thing (iterations);\n do_something (&result);\n ...\n}\n Wrongvoid\nfoo (int iterations)\n{\n iterations = do_one_thing (iterations);\n do_something (&iterations);\n ...\n}\n"},{"location":"coding-style/#loops","title":"Loops","text":"Declare loop variables within the loop to limit its scope and avoid unwanted reuse of the last value set.
Right\u2800\nfor (int i = 0; i < 5; i++)\n{\n do_something (i);\n}\n\u2800\n Wrongint i;\n\nfor (i = 0; i < 5; i++)\n{\n do_something (i);\n}\n"},{"location":"coding-style/#headers","title":"Headers","text":"Do not mix headers:
Right#include <errno.h>\n#include <stdio.h>\n#include <string.h>\n\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#include \"lib/global.h\"\n#include \"lib/tty/tty.h\" // LINES, tty_touch_screen()\n#include \"lib/tty/win.h\" // do_enter_ca_mode()\n\n#include \"src/subshell.h\" // use_subshell\n#include \"src/help.h\" // interactive_display()\n#include \"src/setup.h\"\n Wrong#include <errno.h>\n#include <sys/types.h>\n#include <stdio.h>\n#include <string.h>\n\n#include <sys/stat.h>\n\n#include \"src/subshell.h\" // use_subshell\n#include \"src/help.h\" // interactive_display()\n\n#include \"lib/tty/tty.h\" // LINES, tty_touch_screen()\n#include \"lib/tty/win.h\" // do_enter_ca_mode()\n\n#include \"src/setup.h\"\n#include \"lib/global.h\"\n Use short comment for header file:
Right#include \"lib/tty/tty.h\" // LINES, tty_touch_screen()\n#include \"lib/tty/win.h\" // do_enter_ca_mode()\n#include \"src/subshell.h\" // use_subshell\n#include \"src/help.h\" // interactive_display()\n This is not to please folks with low-resolution screens, but rather because sticking to 100 columns prevents you from easily nesting more than one level of if statements or other code blocks.\u00a0\u21a9
Communication, discussion, and decision-making within the Midnight Commander project is primarily done through mailing list conversations.
Alternatively, we have opened up GitHub Discussions for those who prefer a more forum-like experience.
To report an issue or file a feature request please use our issue tracker on GitHub.
Warning
Please keep in mind that the project is maintained by volunteers who code and communicate in their spare time for the fun of it. There is no entitlement to commercial-grade support, service level agreements, or any kind of warranties.
For best results, follow \"The Core Rules of Netiquette\" by Virginia Shea, which has not lost its relevance since 1994. In short, be pleasant and polite... and have fun!
"},{"location":"communication/#mailing-lists","title":"Mailing lists","text":""},{"location":"communication/#users","title":"Users","text":"The Midnight Commander project was founded around 1994 by Miguel de Icaza and is currently maintained as a team effort. We would like to thank all our contributors, past and present, including translators.
"},{"location":"maintainers/#current-team","title":"Current team","text":"Andrew Borodin \u00b7 aborodin / mc-worker
Yury V. Zaytsev \u00b7 zyv \u00b7
Listed alphabetically by last name:
Listed in reverse chronological order:
Slava relaunched Midnight Commander as a collaborative project in 2009 and became the release manager until he stepped down for personal reasons in 2015.\u00a0\u21a9
This website is the new home of Midnight Commander.
The main project forge has been moved from Savannah and later Trac to a new forge hosted by GitHub.
We used to run a self-hosted Trac instance for over a decade to serve as our home page, wiki, source browser, and issue tracker. With the retirement of Trac, most of these items have been moved to GitHub.
"},{"location":"other/#skin-editor","title":"Skin editor","text":"A third party has developed an online skin editor for Midnight Commander that can be accessed through a browser without installation:
The old server is still available at https://old.midnight-commander.org until it is decommissioned. Please let us know if there is any content you would like to secure!
Warning
The projects below may be of interest to you. Please note that we are not associated with these projects and cannot offer any support!
"},{"location":"other/#microsoft-windows","title":"Microsoft Windows","text":"This fork appears to be actively developed. Please contact the author for status and support.
This fork is based on mc-4.8.17 (released in 2016) and unfortunately has not been updated since.
4.8.XX)yum build-dep mc\nyum install git-core fakeroot check-devel po4a libX11-devel\ngit: git config --global user.name \"Yury V. Zaytsev\"\ngit config --global user.email \"yury@shurup.com\"\nSet up Transifex to be able to work with translations.
"},{"location":"release-process/#release-process_1","title":"Release process","text":"Copy and paste the following list into the Prepare for release mc-4.8.XX issue on GitHub:
git clone git@github.com:MidnightCommander/mc.git\ngit fetch\ngit checkout master\ngit reset --hard origin/master\ngit clean -dfx\n./autogen.sh\nmkdir dist; cd dist; ../configure; cd ..\n./maint/sync-transifex/po-from-transifex.py\ngit: make -C dist/po update-po\ngit add po/*.po\ngit commit -s -m 'maint: update PO translations from Transifex'\ngit push origin master\n./maint/sync-transifex/hints-from-transifex.py\ngit: git add doc/hints/l10n/mc.hint.*\ngit commit -s -m 'maint: update hints translations from Transifex'\ngit push origin master\nNEWS-4.8.YY wiki page for the next version with an empty template. The template can be copied from the current NEWS wiki page (without the list of tasks and bug reports).NEWS wiki page to the doc/NEWS file in the git repo: git add doc/NEWS\ngit commit -s -m 'maint: update doc/NEWS file'\ngit push origin master\nver: 4.8.XX)4.8.YY)git tag: git tag -s 4.8.XX # \"Release\" or \"RCn\"\n*.tar.(bz2|xz) distribution archives: cd dist; fakeroot make dist-bzip2 && fakeroot make dist-xz\n\n# https://bugzilla.redhat.com/show_bug.cgi?id=2338285\ncat mc-4.8.33.tar | XZ_OPT=${XZ_OPT--e} xz -c >mc-4.8.33.tar.xz\nsha256sum mc-*tar.* > mc-4.8.XX.sha256\n./configure --prefix=$(pwd)/install\nmake install\nmake check\ngit push origin 4.8.XX\nscp mc-4.8.XX.* midnightcommander@ftp-osl.osuosl.org:/home/midnightcommander/data\nssh midnightcommander@ftp-osl.osuosl.org 'ls -als /home/midnightcommander/data/' | grep 4.8.3\nssh midnightcommander@ftp-osl.osuosl.org '/home/midnightcommander/trigger-midnightcommander'\n0644) if necessaryPrepare for release mc-4.8.YY (type: Task, label: area: adm) for the next releaseLabels and milestones are managed via Pulumi\u00a0\u21a9\u21a9\u21a9
To compile from source, refer to the installation instructions.
"},{"location":"source-code/#contributing","title":"Contributing","text":"We require an issue (or pull request) and code review for any code contribution, except for the following, which can be committed directly to the development branch:
.github)The commit message for the first patch in the series should begin with the following header:
Ticket #<github_issue_number>: brief summary of the changes\n"},{"location":"source-code/#version-control","title":"Version control","text":"master4632_shift_fx)-i --autosquash before merging to preserve linear history--no-ff) merges to track commit originNote
DCO sign-off is different to \"commit signing\" using something like PGP or gitsign!
All contributors must acknowledge that they own the rights to the code they contribute by signing their commits with git commit --amend -s (adding a Signed-off-by: line to the commit message). This signifies that they abide by the Developer Certificate of Origin, Version 1.1, which is also used by the Linux kernel.
Tip
Do not forget to update the changelog as tracked on the current NEWS-4.8.XX wiki page!
state: in review@mention the reviewersgit commit --fixupstate: approved labelgit rebase -i --autosquashgit commit --fixup/rebaseTip
To substantially increase the likelihood that your changes will be accepted, be sure to add tests for the code you touch.
Contributions should be reviewed according to the following criteria:
Motivation It should be clear what the purpose of the proposed changes is. Tests Changes should be accompanied by tests that document that the desired goals have been achieved. Code quality (see Coding style)Note
A lot of great (and sometimes not so great) literature has been written about code review over the decades. We do not intend to cover code review in detail here, just highlight the points that are most relevant to our process.
A good place to start learning about code review in general is Your code sucks, and I hate you by Jonathan Lange.
"},{"location":"source-code/#cleanup-branch","title":"Cleanup branch","text":"For every release, we create a cleanup branch like 4633_cleanup to aggregate small code changes, connected to the corresponding release ticket (e.g. #4633).
Sometimes your patches might end up there. Do not worry, everything will be fine.
"},{"location":"source-code/#source-tour","title":"Source tour","text":"A cross-referenced source code tour of the development branch is available at the following URL:
We use Transifex to crowdsource translations.
Transifex allows us to centralize translation activities and enables translators without much previous experience to edit our localization files via the web interface. Translators who want to work directly with PO files can download the latest versions from Transifex, make their changes using familiar tools, and upload them back.
"},{"location":"translations/#contributing","title":"Contributing","text":"To join our project, go to our project page and click on the \"Join this project\" button. Join requests for new contributors are processed by the maintainers as time permits.
Note
At the moment it is only possible to translate the interface and hint files!
Translation of the manual pages from which the online help accessible via F1 is generated has been disabled to protect our translators. Unfortunately, the resources were manually uploaded to Transifex by a former member of the development team, but the corresponding sync code for the manual pages was never developed.
Will you be the hero to merge the translations we currently have and fix the sync code to properly handle the manual pages?
"},{"location":"translations/#synchronization","title":"Synchronization","text":"The updated POT file is automatically fetched by Transifex from the master branch of our GitHub repository.
Updated PO files with translations are merged back into the repository during the release process.
"},{"location":"translations/#transifex-client","title":"Transifex client","text":"As of 2025, Fedora 41 unfortunately only ships the old client (transifex-client), which is no longer useful. The new client is available in binary form from GitHub (download, unpack and copy to ~/bin). To complete the configuration, fill in your API token:
[https://www.transifex.com]\nrest_hostname = https://rest.api.transifex.com\ntoken = 1/***\n To make sure that Transifex client is installed correctly, try to run it with the following command:
$ tx --help\n"},{"location":"translations/#trying-it-out","title":"Trying it out","text":"To check updated translations locally, you need to build mc from source. Check out the repository and run the following command to fetch the translations from Transifex:
$ ./maint/sync-transifex/po-from-transifex.py\n Then build and install as usual.
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Welcome to Midnight Commander","text":"GNU Midnight Commander (or mc) is a visual, dual-pane file manager. It is released under the GNU General Public License and therefore qualifies as Free Software.
Midnight Commander is a feature-rich, full-screen, text-mode application that allows you to copy, move, and delete files and entire directory trees, search for files, and execute commands in the subshell. Internal viewer, editor and diff viewer are included.
mc uses versatile text interface libraries such as ncurses or S-Lang, which allows it to work on a regular console, inside an X Window terminal, over ssh connections, and in all kinds of remote shells.
The easiest way to install mc is to use your system package manager:
# apt-get install mc\n # dnf install mc\n # pkg install mc\n % brew install midnight-commander\n Our source releases are kindly mirrored by OSU OSL. Our canonical repository is hosted on GitHub. See the Source code page for details.
"},{"location":"#documentation","title":"Documentation","text":"The primary way to learn about mc is to use the context-sensitive online help available via F1.
We also have extensive manual pages, which are the primary source of official documentation:
mcmceditmcviewmcdiff$ man mc\n ... or read the latest development version online.
$ man mcedit\n ... or read the latest development version online.
$ man mcview\n ... or read the latest development version online.
$ man mcdiff\n ... or read the latest development version online.
"},{"location":"#color-schemes","title":"Color schemes","text":"Midnight Commander supports theming! Check out the skins that come with the distribution or develop your own:
mc, proceed to the \"Development\" section.We loosely follow the GNU Coding Standards with some local deviations. Whether you agree with them or not, do check it out\u2014it is an educational read. In a nutshell:
Use the clang-format to format the code:
$ make indent\n To avoid formatting differences between clang-format versions, we currently use clang-format-19. The clang-format Python distribution provides precompiled binaries for all major platforms:
$ uv tool install 'clang-format==19.*'\n$ alias clang-format='uvx clang-format'\n"},{"location":"coding-style/#readable-code","title":"Readable code","text":"Use your best judgment and choose the more readable option. Remember that many other people will be reading it:
Rightbytes = read (fd, &routine.pointer, sizeof (routine));\nif (bytes == -1 || (size_t) bytes < sizeof (routine))\n ...\n Wrongif ((bytes = read (fd, &routine.pointer, sizeof (routine))) == -1 || (size_t) bytes < sizeof (routine))\n ...\n Do not put more than one statement on a line:
Righta = 0;\nb = 2;\n\na = f ();\nif (a == 2)\n b = 5;\n Wronga = 0; b = 2;\n\nif ((a = f()) == 2)\n b = 5;\n\nif (a == 2) b = 5;\n Use explicit comparison in equality operators:
void *p1, *p2;\nint i1, i2;\nchar c1, c2;\n Rightif (p1 != NULL)\nif (p2 == NULL)\n\nif (i1 != 0)\nif (i2 == 0)\n\nif (c1 != '\\0')\nif (c2 == '\\0')\n Wrongif (p1)\nif (!p2)\n\nif (i1)\nif (!i2)\n\nif (c1)\nif (!c2)\n Do not check boolean values for equality:
gboolean b1, b2;\n Rightif (b1)\nif (!b2)\n Wrongif (b1 == TRUE)\nif (b2 == FALSE)\n"},{"location":"coding-style/#comments","title":"Comments","text":"Precede comments with a blank line. If the comment belongs directly to the following code, there should not be a blank line after the comment, unless the comment contains a summary of several blocks of following code.
Right/*\n * This is a multiline comment\n *\n * Note that edit_delete() will not corrupt anything if it is called \n * while the cursor position is EOF.\n */\n(void) edit_delete (edit);\n\n// This is a one-line comment. Allocate additional memory.\nmem = (char *) malloc (memneed);\n\n/**\n * @brief This is a Doxygen comment\n *\n * This is a more detailed explanation of\n * this simple function.\n *\n * @param[in] param1 The parameter value of the function\n * @param[out] result1 The result value of the function\n * @return 0 on success and -1 on error\n */\nint example (int param1, int *result1);\n Wrong//This is a one-line comment.\nmem = (char *) malloc (memneed);// No space before comment\n\n/* This is a multiline comment,\n with some more words...*/\n"},{"location":"coding-style/#conditionals","title":"Conditionals","text":"Always follow an if keyword with a space, but do not include additional spaces before or after the parentheses in the conditional:
if (i == 0)\n\u2800\n Wrongif ( i == 0 )\nif (0 == i)\n"},{"location":"coding-style/#function-calls","title":"Function calls","text":"Always include a space between the name and the left parentheses when calling functions:
Rightdo_example (int param1, int *result1);\n Wrongdo_example(int param1, int *result1);\n"},{"location":"coding-style/#braces","title":"Braces","text":"Braces for blocks of code associated with for, if, switch, while, do .. while, etc. should start on the next line after the statement keyword and end on a separate line.
If the length of the opening statement requires it to span multiple lines, the opening brace should be on a separate line.
Do not use braces unnecessarily when a single statement will do.
Rightif (xterm_flag && xterm_title)\n{\n path = strip_home_and_password (current_panel->cwd);\n ...\n}\n\nfor (k = 0; k < 10; k++)\n for (j = 0; j < 10; j++)\n for (i = 0; str_options[i].opt_name != NULL; i++)\n g_free (*str_options[i].opt_addr);\n Wrongif (xterm_flag && xterm_title) {\n path = strip_home_and_password (current_panel->cwd);\n ...\n}\n\nif (xterm_flag && xterm_title)\n{\n path = strip_home_and_password (current_panel->cwd); }\n"},{"location":"coding-style/#goto","title":"Goto","text":"Use goto only when necessary; it is evil, but can greatly improve readability and reduce memory leaks when used as the only exit point from a function.
{\n if (link_type == LINK_HARDLINK)\n {\n src = g_strdup_printf (_ (\"Link %s to:\"), str_trunc (fname, 46));\n dest = input_expand_dialog (_ (\"Link\"), src, MC_HISTORY_FM_LINK, \"\");\n\n if (dest == NULL || *dest == '\\0')\n goto cleanup;\n ...\n ...\n }\n ...\n ...\n\ncleanup:\n g_free (src);\n g_free (dest);\n\n}\n"},{"location":"coding-style/#variables","title":"Variables","text":"Do not mix variable declarations and code; declare variables only at the beginning of the appropriate block.
Reduce variable scope as much as possible: declare local variables in the block where they are used.
Separate variable declaration and code with an empty line.
Right{\n while (TRUE) {\n int foo = 0;\n\n do_bar (foo);\n }\n}\n Wrong{\n int foo = 0;\n while (TRUE) {\n do_bar (foo);\n }\n}\n\u2800\n If a variable is introduced only to store an intermediate value, declare it at the place of use, join declaration and initialization, and mark it as a constant:
Rightconst ssize_t len = mc_readlink ( ... );\n\u2800\n\u2800\n Wrongssize_t len;\n\nlen = mc_readlink ( ... );\n Avoid having initialized and uninitialized variables in the same declaration:
Rightint a;\nint b = 0;\n Wrongint a, b = 0;\n\u2800\n Avoid multiple non-trivial variable initializations in a declaration:
Rightint a = 2 + 5;\nint b = 4 * 3 - 1;\n Wrongint a = 2 + 5, b = 4 * 3 - 1;\n\u2800\n Mark unused variables with the MC_UNUSED macro:
int\nprogress_button_callback (MC_UNUSED WButton *button, MC_UNUSED int action)\n{\n return 0;\n}\n Wrongint\nprogress_button_callback (WButton *button, int action)\n{\n (void) button;\n (void) action;\n\n return 0;\n}\n Try to avoid passing function calls as function parameters in new code. Not doing so makes the code much easier to read, and it is also easier to use the step command in gdb.
void\ndirsizes_cmd (void)\n{\n const ComputeDirSizeUI *ui = compute_dir_size_create_ui ();\n compute_dir_size_destroy_ui (ui);\n}\n Wrongvoid\ndirsizes_cmd (void)\n{\n compute_dir_size_destroy_ui (compute_dir_size_create_ui ());\n}\n Avoid abusing non-const function parameters as local variables:
void\nfoo (const int iterations)\n{\n int result;\n\n result = do_one_thing (iterations);\n do_something (&result);\n ...\n}\n Wrongvoid\nfoo (int iterations)\n{\n iterations = do_one_thing (iterations);\n do_something (&iterations);\n ...\n}\n"},{"location":"coding-style/#loops","title":"Loops","text":"Declare loop variables within the loop to limit its scope and avoid unwanted reuse of the last value set.
Right\u2800\nfor (int i = 0; i < 5; i++)\n{\n do_something (i);\n}\n\u2800\n Wrongint i;\n\nfor (i = 0; i < 5; i++)\n{\n do_something (i);\n}\n"},{"location":"coding-style/#headers","title":"Headers","text":"Do not mix headers:
Right#include <errno.h>\n#include <stdio.h>\n#include <string.h>\n\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#include \"lib/global.h\"\n#include \"lib/tty/tty.h\" // LINES, tty_touch_screen()\n#include \"lib/tty/win.h\" // do_enter_ca_mode()\n\n#include \"src/subshell.h\" // use_subshell\n#include \"src/help.h\" // interactive_display()\n#include \"src/setup.h\"\n Wrong#include <errno.h>\n#include <sys/types.h>\n#include <stdio.h>\n#include <string.h>\n\n#include <sys/stat.h>\n\n#include \"src/subshell.h\" // use_subshell\n#include \"src/help.h\" // interactive_display()\n\n#include \"lib/tty/tty.h\" // LINES, tty_touch_screen()\n#include \"lib/tty/win.h\" // do_enter_ca_mode()\n\n#include \"src/setup.h\"\n#include \"lib/global.h\"\n Use short comment for header file:
Right#include \"lib/tty/tty.h\" // LINES, tty_touch_screen()\n#include \"lib/tty/win.h\" // do_enter_ca_mode()\n#include \"src/subshell.h\" // use_subshell\n#include \"src/help.h\" // interactive_display()\n This is not to please folks with low-resolution screens, but rather because sticking to 100 columns prevents you from easily nesting more than one level of if statements or other code blocks.\u00a0\u21a9
Communication, discussion, and decision-making within the Midnight Commander project is primarily done through mailing list conversations.
Alternatively, we have opened up GitHub Discussions for those who prefer a more forum-like experience.
To report an issue or file a feature request please use our issue tracker on GitHub.
Warning
Please keep in mind that the project is maintained by volunteers who code and communicate in their spare time for the fun of it. There is no entitlement to commercial-grade support, service level agreements, or any kind of warranties.
For best results, follow \"The Core Rules of Netiquette\" by Virginia Shea, which has not lost its relevance since 1994. In short, be pleasant and polite... and have fun!
"},{"location":"communication/#mailing-lists","title":"Mailing lists","text":""},{"location":"communication/#users","title":"Users","text":"The Midnight Commander project was founded around 1994 by Miguel de Icaza and is currently maintained as a team effort. We would like to thank all our contributors, past and present, including translators.
"},{"location":"maintainers/#current-team","title":"Current team","text":"Andrew Borodin \u00b7 aborodin / mc-worker
Yury V. Zaytsev \u00b7 zyv \u00b7
Listed alphabetically by last name:
Listed in reverse chronological order:
Slava relaunched Midnight Commander as a collaborative project in 2009 and became the release manager until he stepped down for personal reasons in 2015.\u00a0\u21a9
This website is the new home of Midnight Commander.
The main project forge has been moved from Savannah and later Trac to a new forge hosted by GitHub.
We used to run a self-hosted Trac instance for over a decade to serve as our home page, wiki, source browser, and issue tracker. With the retirement of Trac, most of these items have been moved to GitHub.
"},{"location":"other/#trac-archives","title":"Trac archives","text":"The old server is still available at https://old.midnight-commander.org until it is decommissioned. Please let us know if there is any content you would like to secure!
Warning
The projects below may be of interest to you. Please note that we are not associated with these projects and cannot offer any support!
"},{"location":"other/#microsoft-windows","title":"Microsoft Windows","text":"This fork appears to be actively developed. Please contact the author for status and support.
This fork is based on mc-4.8.17 (released in 2016) and unfortunately has not been updated since.
4.8.XX)yum build-dep mc\nyum install git-core fakeroot check-devel po4a libX11-devel\ngit: git config --global user.name \"Yury V. Zaytsev\"\ngit config --global user.email \"yury@shurup.com\"\nSet up Transifex to be able to work with translations.
"},{"location":"release-process/#release-process_1","title":"Release process","text":"Copy and paste the following list into the Prepare for release mc-4.8.XX issue on GitHub:
git clone git@github.com:MidnightCommander/mc.git\ngit fetch\ngit checkout master\ngit reset --hard origin/master\ngit clean -dfx\n./autogen.sh\nmkdir dist; cd dist; ../configure; cd ..\n./maint/sync-transifex/po-from-transifex.py\ngit: make -C dist/po update-po\ngit add po/*.po\ngit commit -s -m 'maint: update PO translations from Transifex'\ngit push origin master\n./maint/sync-transifex/hints-from-transifex.py\ngit: git add doc/hints/l10n/mc.hint.*\ngit commit -s -m 'maint: update hints translations from Transifex'\ngit push origin master\nNEWS-4.8.YY wiki page for the next version with an empty template. The template can be copied from the current NEWS wiki page (without the list of tasks and bug reports).NEWS wiki page to the doc/NEWS file in the git repo: git add doc/NEWS\ngit commit -s -m 'maint: update doc/NEWS file'\ngit push origin master\nver: 4.8.XX)4.8.YY)git tag: git tag -s 4.8.XX # \"Release\" or \"RCn\"\n*.tar.(bz2|xz) distribution archives: cd dist; fakeroot make dist-bzip2 && fakeroot make dist-xz\n\n# https://bugzilla.redhat.com/show_bug.cgi?id=2338285\ncat mc-4.8.33.tar | XZ_OPT=${XZ_OPT--e} xz -c >mc-4.8.33.tar.xz\nsha256sum mc-*tar.* > mc-4.8.XX.sha256\n./configure --prefix=$(pwd)/install\nmake install\nmake check\ngit push origin 4.8.XX\nscp mc-4.8.XX.* midnightcommander@ftp-osl.osuosl.org:/home/midnightcommander/data\nssh midnightcommander@ftp-osl.osuosl.org 'ls -als /home/midnightcommander/data/' | grep 4.8.3\nssh midnightcommander@ftp-osl.osuosl.org '/home/midnightcommander/trigger-midnightcommander'\n0644) if necessaryPrepare for release mc-4.8.YY (type: Task, label: area: adm) for the next releaseLabels and milestones are managed via Pulumi\u00a0\u21a9\u21a9\u21a9
To compile from source, refer to the installation instructions.
"},{"location":"source-code/#contributing","title":"Contributing","text":"We require an issue (or pull request) and code review for any code contribution, except for the following, which can be committed directly to the development branch:
.github)The commit message for the first patch in the series should begin with the following header:
Ticket #<github_issue_number>: brief summary of the changes\n"},{"location":"source-code/#version-control","title":"Version control","text":"master4632_shift_fx)-i --autosquash before merging to preserve linear history--no-ff) merges to track commit originNote
DCO sign-off is different to \"commit signing\" using something like PGP or gitsign!
All contributors must acknowledge that they own the rights to the code they contribute by signing their commits with git commit --amend -s (adding a Signed-off-by: line to the commit message). This signifies that they abide by the Developer Certificate of Origin, Version 1.1, which is also used by the Linux kernel.
Tip
Do not forget to update the changelog as tracked on the current NEWS-4.8.XX wiki page!
state: in review@mention the reviewersgit commit --fixupstate: approved labelgit rebase -i --autosquashgit commit --fixup/rebaseTip
To substantially increase the likelihood that your changes will be accepted, be sure to add tests for the code you touch.
Contributions should be reviewed according to the following criteria:
Motivation It should be clear what the purpose of the proposed changes is. Tests Changes should be accompanied by tests that document that the desired goals have been achieved. Code quality (see Coding style)Note
A lot of great (and sometimes not so great) literature has been written about code review over the decades. We do not intend to cover code review in detail here, just highlight the points that are most relevant to our process.
A good place to start learning about code review in general is Your code sucks, and I hate you by Jonathan Lange.
"},{"location":"source-code/#cleanup-branch","title":"Cleanup branch","text":"For every release, we create a cleanup branch like 4633_cleanup to aggregate small code changes, connected to the corresponding release ticket (e.g. #4633).
Sometimes your patches might end up there. Do not worry, everything will be fine.
"},{"location":"source-code/#source-tour","title":"Source tour","text":"A cross-referenced source code tour of the development branch is available at the following URL:
We use Transifex to crowdsource translations.
Transifex allows us to centralize translation activities and enables translators without much previous experience to edit our localization files via the web interface. Translators who want to work directly with PO files can download the latest versions from Transifex, make their changes using familiar tools, and upload them back.
"},{"location":"translations/#contributing","title":"Contributing","text":"To join our project, go to our project page and click on the \"Join this project\" button. Join requests for new contributors are processed by the maintainers as time permits.
Note
At the moment it is only possible to translate the interface and hint files!
Translation of the manual pages from which the online help accessible via F1 is generated has been disabled to protect our translators. Unfortunately, the resources were manually uploaded to Transifex by a former member of the development team, but the corresponding sync code for the manual pages was never developed.
Will you be the hero to merge the translations we currently have and fix the sync code to properly handle the manual pages?
"},{"location":"translations/#synchronization","title":"Synchronization","text":"The updated POT file is automatically fetched by Transifex from the master branch of our GitHub repository.
Updated PO files with translations are merged back into the repository during the release process.
"},{"location":"translations/#transifex-client","title":"Transifex client","text":"As of 2025, Fedora 41 unfortunately only ships the old client (transifex-client), which is no longer useful. The new client is available in binary form from GitHub (download, unpack and copy to ~/bin). To complete the configuration, fill in your API token:
[https://www.transifex.com]\nrest_hostname = https://rest.api.transifex.com\ntoken = 1/***\n To make sure that Transifex client is installed correctly, try to run it with the following command:
$ tx --help\n"},{"location":"translations/#trying-it-out","title":"Trying it out","text":"To check updated translations locally, you need to build mc from source. Check out the repository and run the following command to fetch the translations from Transifex:
$ ./maint/sync-transifex/po-from-transifex.py\n Then build and install as usual.
"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 09adcb1..8fae0d9 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,34 +2,34 @@