Python Readline on macOS behaves differently than on Linux/Windows - python

A project I'm working on uses a custom CLI handler instead of Python's cmd.Cmd class. Without getting too much in detail, the handler features TAB-key completion to assist the operator with command usage. The feature works as expected on Windows (using pyreadline) and Linux (using GNU's readline).
Here is an example of the expected behavior (assume "cmd > " is the prompt and that [TAB] is a push of the TAB key):
cmd > [TAB]
cd exit load save # all the available commands
cmd > c[TAB] # autocompletes to 'cd'
cmd > cd [TAB]
cd ./folder1 cd ./folder2 cd ./folder3 # folders in the cwd
cmd > cd C:\[TAB]
cd C:\Users cd C:\Windows... # enumerates folders in C:\ (on windows)
cmd > cd /[TAB]
cd /bin cd /opt cd /usr... # enumerates folders from root (on linux)
The custom class defines the following tab completion method, which is set using readline.set_completer():
def tab_completer(self, text, state):
# rl delims set to "" so we get the whole line as a single string
words = re.split(r'[\s\t\n]+', text)
# find_subcompleter populates a list of possible matches or next words
# each command implements its own completer_stub depending on the function (ex: cd will complete directory names)
retval = self.find_subcompleter(words.pop())
try:
return retval[state]
except IndexError:
return None
The function works as expected on Windows (10, Python 3.6.6) and Linux (CentOS 7, Python 3.6.8), but something strange happens on macOS (10.15.7, Python 3.8.2 via xcode on zsh terminal):
cmd > [TAB]
cd exit load save # this is good
cmd > c[TAB] # still autocompletes to 'cd', good
cmd > cd [TAB]
cd exit load save # as if I've typed nothing!
For those of you wondering, this behavior happens with ANY command, not just with cd.
I'm aware that the underlying readline implementation on macOS uses libedit due to GNU licensing. I just haven't seen anyone else (to date) mention this difference on any other forums. A possible solution that comes to mind is to add a conditional for libedit implementations to use get_line_buffer() and redisplay() to mimic the correct behavior. Any pointers in the right direction are appreciated!
Thank you

Related

Makefile on Windows 10 - file not found

After some time I finally managed to successfully install python and pip and run it on my machine using Visual Studio Code.
I am working in virtual environment in python and we have a Makefile with following statement:
test:
source .env && PYTHONPATH=. PY_ENV=testing py.test ${ARGS} --duration=20
File .env lives in the main directory next to Makefile. It contains some environmental variables needed for testing certain APIs.
When I take the line out of the file and run it in my terminal, everything works fine and all tests are running etc.
However if I call the following: make test I am getting this error:
$ make test
source .env && PYTHONPATH=. PY_ENV=testing py.test --duration=20
/usr/bin/sh: line 0: source: .env: file not found
make: *** [test] Error 1
(venv)
To me it looks like when running this command from within Makefile it can't see the .env file but have no idea how to solve it.
The source command isn't looking up the file in the current working directory. As mentioned in man source:
Read and execute commands from filename in the current shell
environment and return the exit status of the last command executed
from filename. If filename does not contain a slash, filenames in
PATH are used to find the directory containing filename.
Change the file path like so:
test:
source ./.env && PYTHONPATH=. PY_ENV=testing py.test ${ARGS} --duration=20
Note that this error does not occur in bash version < 4. This is due to an implementation bug when run under POSIX mode (what make uses, since its default shell is sh, which is usually bash --posix). The correct behaviour was first mentioned in the documentation of bash-2.05 (revision 28ef6c31, file doc/bashref.info):
When Bash is not in POSIX mode, the current directory is searched if
FILENAME is not found in `$PATH'.
These older versions searched the current directory regardless of POSIX mode. It was only in bash-4.0-rc1 (revision 3185942a, file general.c) that this was corrected. Running git diff 3185942a~ 3185942a general.c outputs this section:
## -69,6 +69,7 ## posix_initialize (on)
if (on != 0)
{
interactive_comments = source_uses_path = expand_aliases = 1;
+ source_searches_cwd = 0;
}

Run python module from command line

I don't really know how to ask this question but I can describe what I want to achieve. I would update any edits that would be suggested.
I have a python module that makes use of some command line arguments. Using the module requires some initial setup outside of the python interpreter. The python file that does the setup runs fine, but the problem is that I have to dig through the python installation to find where that file is located i.e. I have to do python full-path-to-setup-script.py -a argA -b argB etc.I would like to call the setup script like this
some-setup-command -a argA -b argB etc.
I want to achieve something like
workon environmnent_name as in the virtualenv module or
pipenv install as in the pipenv module.
I know both of the above commands call a script of some kind (whether bash or python). I've tried digging through the source codes of virtualenv and pipenv without any success.
I would really appreciate if someone could point me to any necessary resource for coding such programs.
If full-path-to-setup-script.py is executable and has a proper shebang line
#! /usr/bin/env python
then you can
ln -s full-path-to-setup-script.py ~/bin/some-command
considering ~/bin exists and is in your PATH,
and you'll be able to invoke
some-command -a argA -b argB
It's a bit difficult to understand what you're looking for, but python -m is my best guess.
For example, to make a new Jupyter kernel, we call
python -m ipykernel arg --option --option
Where arg is the CLI argument and option is a CLI option, and ipykernel is the module receiving the args and options.
Commands that are callable from the command prompt are located in one of the directories in your system's PATH variable. If you are on Windows, you see the locations via:
echo %PATH%
Or if you want a nicer readout:
powershell -c "$env:path -split(';')"
One solution is to create a folder, add it to your system's PATH, and then create a callable file that you can run. In this example we will create a folder in your user profile, add it to the path, then create a callable file in that folder.
mkdir %USERPROFILE%\path
set PATH=%PATH%%USERPROFILE%\path;
setx PATH %PATH%
In the folder %USERPROFILE%\path, we create a batch file with following content:
# file name:
# some-command.bat
#
python C:\full\path\to\setup-script.py %*
Now you should be able to call
some-command -a argA -b argB
And the batch file will call python with python script and pass the arguments you added.
Looking at the above answers, I see no one has mentioned this:
You can of course compile the python file and give executable permissions with
chmod +x filename.py
and then run it as
./filename.py -a argA -b argB ...
Moreover, you can also remove the extention .py (since it is an executable now) and then run it only as
./filename -a argA -b argB ...

How to keep a changed python working directory [duplicate]

I'm trying to write a small script to change the current directory to my project directory:
#!/bin/bash
cd /home/tree/projects/java
I saved this file as proj, added execute permission with chmod, and copied it to /usr/bin. When I call it by:
proj, it does nothing. What am I doing wrong?
Shell scripts are run inside a subshell, and each subshell has its own concept of what the current directory is. The cd succeeds, but as soon as the subshell exits, you're back in the interactive shell and nothing ever changed there.
One way to get around this is to use an alias instead:
alias proj="cd /home/tree/projects/java"
You're doing nothing wrong! You've changed the directory, but only within the subshell that runs the script.
You can run the script in your current process with the "dot" command:
. proj
But I'd prefer Greg's suggestion to use an alias in this simple case.
The cd in your script technically worked as it changed the directory of the shell that ran the script, but that was a separate process forked from your interactive shell.
A Posix-compatible way to solve this problem is to define a shell procedure rather than a shell-invoked command script.
jhome () {
cd /home/tree/projects/java
}
You can just type this in or put it in one of the various shell startup files.
The cd is done within the script's shell. When the script ends, that shell exits, and then you are left in the directory you were. "Source" the script, don't run it. Instead of:
./myscript.sh
do
. ./myscript.sh
(Notice the dot and space before the script name.)
To make a bash script that will cd to a select directory :
Create the script file
#!/bin/sh
# file : /scripts/cdjava
#
cd /home/askgelal/projects/java
Then create an alias in your startup file.
#!/bin/sh
# file /scripts/mastercode.sh
#
alias cdjava='. /scripts/cdjava'
I created a startup file where I dump all my aliases and custom functions.
Then I source this file into my .bashrc to have it set on each boot.
For example, create a master aliases/functions file: /scripts/mastercode.sh
(Put the alias in this file.)
Then at the end of your .bashrc file:
source /scripts/mastercode.sh
Now its easy to cd to your java directory, just type cdjava and you are there.
You can use . to execute a script in the current shell environment:
. script_name
or alternatively, its more readable but shell specific alias source:
source script_name
This avoids the subshell, and allows any variables or builtins (including cd) to affect the current shell instead.
Jeremy Ruten's idea of using a symlink triggered a thought that hasn't crossed any other answer. Use:
CDPATH=:$HOME/projects
The leading colon is important; it means that if there is a directory 'dir' in the current directory, then 'cd dir' will change to that, rather than hopping off somewhere else. With the value set as shown, you can do:
cd java
and, if there is no sub-directory called java in the current directory, then it will take you directly to $HOME/projects/java - no aliases, no scripts, no dubious execs or dot commands.
My $HOME is /Users/jleffler; my $CDPATH is:
:/Users/jleffler:/Users/jleffler/mail:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work
Use exec bash at the end
A bash script operates on its current environment or on that of its
children, but never on its parent environment.
However, this question often gets asked because one wants to be left at a (new) bash prompt in a certain directory after execution of a bash script from within another directory.
If this is the case, simply execute a child bash instance at the end of the script:
#!/usr/bin/env bash
cd /home/tree/projects/java
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
exec bash
To return to the previous, parental bash instance, use Ctrl+D.
Update
At least with newer versions of bash, the exec on the last line is no longer required. Furthermore, the script could be made to work with whatever preferred shell by using the $SHELL environment variable. This then gives:
#!/usr/bin/env bash
cd desired/directory
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
$SHELL
I got my code to work by using. <your file name>
./<your file name> dose not work because it doesn't change your directory in the terminal it just changes the directory specific to that script.
Here is my program
#!/bin/bash
echo "Taking you to eclipse's workspace."
cd /Developer/Java/workspace
Here is my terminal
nova:~ Kael$
nova:~ Kael$ . workspace.sh
Taking you to eclipe's workspace.
nova:workspace Kael$
simply run:
cd /home/xxx/yyy && command_you_want
When you fire a shell script, it runs a new instance of that shell (/bin/bash). Thus, your script just fires up a shell, changes the directory and exits. Put another way, cd (and other such commands) within a shell script do not affect nor have access to the shell from which they were launched.
You can do following:
#!/bin/bash
cd /your/project/directory
# start another shell and replacing the current
exec /bin/bash
EDIT: This could be 'dotted' as well, to prevent creation of subsequent shells.
Example:
. ./previous_script (with or without the first line)
On my particular case i needed too many times to change for the same directory.
So on my .bashrc (I use ubuntu) i've added the
1 -
$ nano ~./bashrc
function switchp
{
cd /home/tree/projects/$1
}
2-
$ source ~/.bashrc
3 -
$ switchp java
Directly it will do: cd /home/tree/projects/java
Hope that helps!
It only changes the directory for the script itself, while your current directory stays the same.
You might want to use a symbolic link instead. It allows you to make a "shortcut" to a file or directory, so you'd only have to type something like cd my-project.
You can combine Adam & Greg's alias and dot approaches to make something that can be more dynamic—
alias project=". project"
Now running the project alias will execute the project script in the current shell as opposed to the subshell.
You can combine an alias and a script,
alias proj="cd \`/usr/bin/proj !*\`"
provided that the script echos the destination path. Note that those are backticks surrounding the script name.
For example, your script could be
#!/bin/bash
echo /home/askgelal/projects/java/$1
The advantage with this technique is that the script could take any number of command line parameters and emit different destinations calculated by possibly complex logic.
to navigate directories quicky, there's $CDPATH, cdargs, and ways to generate aliases automatically
http://jackndempsey.blogspot.com/2008/07/cdargs.html
http://muness.blogspot.com/2008/06/lazy-bash-cd-aliaes.html
https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5827311.html
In your ~/.bash_profile file. add the next function
move_me() {
cd ~/path/to/dest
}
Restart terminal and you can type
move_me
and you will be moved to the destination folder.
You can use the operator && :
cd myDirectory && ls
While sourcing the script you want to run is one solution, you should be aware that this script then can directly modify the environment of your current shell. Also it is not possible to pass arguments anymore.
Another way to do, is to implement your script as a function in bash.
function cdbm() {
cd whereever_you_want_to_go
echo "Arguments to the functions were $1, $2, ..."
}
This technique is used by autojump: http://github.com/joelthelion/autojump/wiki to provide you with learning shell directory bookmarks.
You can create a function like below in your .bash_profile and it will work smoothly.
The following function takes an optional parameter which is a project.
For example, you can just run
cdproj
or
cdproj project_name
Here is the function definition.
cdproj(){
dir=/Users/yourname/projects
if [ "$1" ]; then
cd "${dir}/${1}"
else
cd "${dir}"
fi
}
Dont forget to source your .bash_profile
This should do what you want. Change to the directory of interest (from within the script), and then spawn a new bash shell.
#!/bin/bash
# saved as mov_dir.sh
cd ~/mt/v3/rt_linux-rt-tools/
bash
If you run this, it will take you to the directory of interest and when you exit it it will bring you back to the original place.
root#intel-corei7-64:~# ./mov_dir.sh
root#intel-corei7-64:~/mt/v3/rt_linux-rt-tools# exit
root#intel-corei7-64:~#
This will even take you to back to your original directory when you exit (CTRL+d)
I did the following:
create a file called case
paste the following in the file:
#!/bin/sh
cd /home/"$1"
save it and then:
chmod +x case
I also created an alias in my .bashrc:
alias disk='cd /home/; . case'
now when I type:
case 12345
essentially I am typing:
cd /home/12345
You can type any folder after 'case':
case 12
case 15
case 17
which is like typing:
cd /home/12
cd /home/15
cd /home/17
respectively
In my case the path is much longer - these guys summed it up with the ~ info earlier.
As explained on the other answers, you have changed the directory, but only within the sub-shell that runs the script. this does not impact the parent shell.
One solution is to use bash functions instead of a bash script (sh); by placing your bash script code into a function. That makes the function available as a command and then, this will be executed without a child process and thus any cd command will impact the caller shell.
Bash functions :
One feature of the bash profile is to store custom functions that can be run in the terminal or in bash scripts the same way you run application/commands this also could be used as a shortcut for long commands.
To make your function efficient system widely you will need to copy your function at the end of several files
/home/user/.bashrc
/home/user/.bash_profile
/root/.bashrc
/root/.bash_profile
You can sudo kwrite /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile to edit/create those files quickly
Howto :
Copy your bash script code inside a new function at the end of your bash's profile file and restart your terminal, you can then run cdd or whatever the function you wrote.
Script Example
Making shortcut to cd .. with cdd
cdd() {
cd ..
}
ls shortcut
ll() {
ls -l -h
}
ls shortcut
lll() {
ls -l -h -a
}
If you are using fish as your shell, the best solution is to create a function. As an example, given the original question, you could copy the 4 lines below and paste them into your fish command line:
function proj
cd /home/tree/projects/java
end
funcsave proj
This will create the function and save it for use later. If your project changes, just repeat the process using the new path.
If you prefer, you can manually add the function file by doing the following:
nano ~/.config/fish/functions/proj.fish
and enter the text:
function proj
cd /home/tree/projects/java
end
and finally press ctrl+x to exit and y followed by return to save your changes.
(NOTE: the first method of using funcsave creates the proj.fish file for you).
You need no script, only set the correct option and create an environment variable.
shopt -s cdable_vars
in your ~/.bashrc allows to cd to the content of environment variables.
Create such an environment variable:
export myjava="/home/tree/projects/java"
and you can use:
cd myjava
Other alternatives.
Note the discussion How do I set the working directory of the parent process?
It contains some hackish answers, e.g.
https://stackoverflow.com/a/2375174/755804 (changing the parent process directory via gdb, don't do this) and https://stackoverflow.com/a/51985735/755804 (the command tailcd that injects cd dirname to the input stream of the parent process; well, ideally it should be a part of bash rather than a hack)
It is an old question, but I am really surprised I don't see this trick here
Instead of using cd you can use
export PWD=the/path/you/want
No need to create subshells or use aliases.
Note that it is your responsibility to make sure the/path/you/want exists.
I have to work in tcsh, and I know this is not an elegant solution, but for example, if I had to change folders to a path where one word is different, the whole thing can be done in the alias
a alias_name 'set a = `pwd`; set b = `echo $a | replace "Trees" "Tests"` ; cd $b'
If the path is always fixed, the just
a alias_name2 'cd path/you/always/need'
should work
In the line above, the new folder path is set
This combines the answer by Serge with an unrelated answer by David. It changes the directory, and then instead of forcing a bash shell, it launches the user's default shell. It however requires both getent and /etc/passwd to detect the default shell.
#!/usr/bin/env bash
cd desired/directory
USER_SHELL=$(getent passwd <USER> | cut -d : -f 7)
$USER_SHELL
Of course this still has the same deficiency of creating a nested shell.

CMD in Windows 7 does not execute command (Python Django)

Ok people at this link for pysec as the technical solution is explained we have some code that you must type to the command prompt (i think because it has a dollar sign in front):
$ cd ~/path/to/pysec && python -c "import sqlite3; sqlite3.connect('edgar.db')"
$ mv ./local-settings-example.py ./local-settings.py
$ mkdir ./pysec/data
However whenever i go to C:\Python27\pysec-master which is the location where the pysec file is stored (according to instructions) and type these commands exactly as i see them i get that the system cannot find the path specified.
Like this
C:\Python27\pysec-master>cd ~/path/to/pysec && python -c
cmd response --> The system cannot find the path specified.
C:\Python27\pysec-master>cd ~/path/to/pysec && python -c "import sqlite3; sqlite3.connect('edgar.db')"
cmd response --> The system cannot find the path specified.
C:\Python27\pysec-master>mv ./local-settings-example.py ./local-settings.py
cmd response --> 'mv' is not recognized as an internal or external command, operable program or batch file.
C:\Python27\pysec-master>mkdir ./pysec/data
cmd response --> The syntax of the command is incorrect.
What seems to be the problem? Don't you have to type these commands in the cmd since they have a dollar sign?
ANSWER FOR THIS QUESTION IS PROVIDED FROM THE COMMENTS UNDER THE QUESTION BY USER Stephan
I decided to put the all together in on place>
cd ~..., mv .` and mkdir .\ looks more like unix syntax than windows-cmd. cd and mkdir work on both platforms, but with different syntax. The cmd-version of mv is move.(ANSWER)
also /path/to/pysec tells you, that you should put in the path to pysec, not the string "\path\to\pysec"(ANSWER)
Can we transform these commands to Windows syntax?(QUESTION)
Should we put the path to pysec like this: C:\Python27\pysec-master i mean the full or absolute as it is called path? Because it that tutorial I can see that the example is trimmed as cd ~/path/to/pysec`(QUESTION)
the tilde (~) has a special meaning in unix. I don't speak unix, but I think it means "Systemdrive". The CMD command would be: cd /d "c:\Python27\pysec-master" (in CMD use \, in unix it's /). Instead of mv use move (ANSWER)
Only the third command does not seem to work mkdir ./pysec/data well I think there muse be something different for windows (QUESTION)
mkdir .\pysec\data ... You remember? "in CMD use \, in unix it's /"(ANSWER)
THANK YOU FOR THE SUPPORT

Launch Pycharm from command line (terminal)

I want to try out PyCharm for sage mathematics development. Normally I run eclipse to do sage development, but now I want to try it with PyCharm.
To launch eclipse with sage environment variables, in command line I normally do the following:
sage -sh
cd /path/to/eclipse
./eclipse
The first line loads the sage environment variables, the remainder launches eclipse. How can I do the same thing for pyCharm? (note I am using a Mac and Ubuntu for sage development; the commands above are agnostic to both OSes)
Link 1 is close to the solution I am looking for, however I cannot find a pyCharm.sh anywhere.
Link 2: Jetbrains does not give clear instructions either.
Edit (April 2020): It seems that launcher script creation is now managed in Toolbox App settings.
See the Toolbox App announcement for more details.
--
Open Application Pycharm
Find tools in menu bar
Click Create Command-line Launcher
Checking the launcher executable file which has been created in /usr/local/bin/charm
Open project or file just type $ charm YOUR_FOLDER_OR_FILE
Maybe this is what you need.
You're right that the JetBrains help page isn't very clear. On OS X, you'll want to use the launcher at:
/Applications/PyCharm.app/Contents/MacOS/pycharm
Or, for community edition:
/Applications/PyCharm\ CE.app/Contents/MacOS/pycharm
Unfortunately, adding a symlink to this binary wouldn't work for me (the launcher would crash). Setting an alias worked, though. Add this in your .bash_profile (or whatever shell you use):
alias pycharm="/Applications/PyCharm CE.app/Contents/MacOS/pycharm"
Then, you can run commands with simply pycharm.
With this you can do things like open a project:
pycharm ~/repos/my-project
Or open a specific line of a file in a project:
pycharm ~/repos/my-project --line 42 ~/repos/my-project/script.py
Or view the diff of two files (they don't need to be part of a project):
pycharm ~/some_file.txt ~/Downloads/some_other_file.txt
Note that I needed to pass absolute paths to those files or PyCharm couldn't find them..
Inside the IDE, you can click in:
Tools/Create Command-line Launcher...
Update
It is now possible to create command line launcher automatically from JetBrains Toolbox. This is how you do it:
Open up the toolbox window;
Go to the gear icon in the upper right (the settings window for toolbox itself);
Turn on Generate shell scripts;
Fill the Shell script location textbox with the location where you want the launchers to reside. You have to do this manually it will not fill automatically at this time!
On Mac the location could be /usr/local/bin. For the novices, you can use any path inside the PATH variable or add a new path to the PATH variable in your bash profile. Use echo $PATH to see which paths are there.
Note! It did not work right away for me, I had to fiddle around a little before the scripts were generated. You can go to the gearbox of the IDEA (PyCharm for example) and see/change the launcher name. So for PyCharm, the default name is pycharm but you can change this to whatever you prefer.
Original answer
If you do not use the toolbox you can still use my original answer.
~~For some reason, the Create Command Line Launcher is not available anymore in 2019.1.~~ Because it is now part of JetBrains Toolbox
This is how you can create the script yourself:
If you already used the charm command before use type -a charm to find the script. Change the pycharm version in the file paths. Note that the numbering in the first variable RUN_PATH is different. You will have to look this up in the dir yourself.
RUN_PATH = u'/Users/boatfolder/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/191.6183.50/PyCharm.app'
CONFIG_PATH = u'/Users/boatfolder/Library/Preferences/PyCharm2019.1'
SYSTEM_PATH = u'/Users/boatfolder/Library/Caches/PyCharm2019.1'
If you did not use the charm command before, you will have to create it.
Create the charm file somewhere like this: /usr/local/bin/charm
Then add this code (change version number to your version as explained above):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import struct
import sys
import os
import time
# see com.intellij.idea.SocketLock for the server side of this interface
RUN_PATH = u'/Users/boatfolder/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/191.6183.50/PyCharm.app'
CONFIG_PATH = u'/Users/boatfolder/Library/Preferences/PyCharm2019.1'
SYSTEM_PATH = u'/Users/boatfolder/Library/Caches/PyCharm2019.1'
def print_usage(cmd):
print(('Usage:\n' +
' {0} -h | -? | --help\n' +
' {0} [project_dir]\n' +
' {0} [-l|--line line] [project_dir|--temp-project] file[:line]\n' +
' {0} diff <left> <right>\n' +
' {0} merge <local> <remote> [base] <merged>').format(cmd))
def process_args(argv):
args = []
skip_next = False
for i, arg in enumerate(argv[1:]):
if arg == '-h' or arg == '-?' or arg == '--help':
print_usage(argv[0])
exit(0)
elif i == 0 and (arg == 'diff' or arg == 'merge' or arg == '--temp-project'):
args.append(arg)
elif arg == '-l' or arg == '--line':
args.append(arg)
skip_next = True
elif skip_next:
args.append(arg)
skip_next = False
else:
path = arg
if ':' in arg:
file_path, line_number = arg.rsplit(':', 1)
if line_number.isdigit():
args.append('-l')
args.append(line_number)
path = file_path
args.append(os.path.abspath(path))
return args
def try_activate_instance(args):
port_path = os.path.join(CONFIG_PATH, 'port')
token_path = os.path.join(SYSTEM_PATH, 'token')
if not (os.path.exists(port_path) and os.path.exists(token_path)):
return False
try:
with open(port_path) as pf:
port = int(pf.read())
with open(token_path) as tf:
token = tf.read()
except (ValueError):
return False
s = socket.socket()
s.settimeout(0.3)
try:
s.connect(('127.0.0.1', port))
except (socket.error, IOError):
return False
found = False
while True:
try:
path_len = struct.unpack('>h', s.recv(2))[0]
path = s.recv(path_len).decode('utf-8')
if os.path.abspath(path) == os.path.abspath(CONFIG_PATH):
found = True
break
except (socket.error, IOError):
return False
if found:
cmd = 'activate ' + token + '\0' + os.getcwd() + '\0' + '\0'.join(args)
if sys.version_info.major >= 3: cmd = cmd.encode('utf-8')
encoded = struct.pack('>h', len(cmd)) + cmd
s.send(encoded)
time.sleep(0.5) # don't close the socket immediately
return True
return False
def start_new_instance(args):
if sys.platform == 'darwin':
if len(args) > 0:
args.insert(0, '--args')
os.execvp('/usr/bin/open', ['-a', RUN_PATH] + args)
else:
bin_file = os.path.split(RUN_PATH)[1]
os.execv(RUN_PATH, [bin_file] + args)
ide_args = process_args(sys.argv)
if not try_activate_instance(ide_args):
start_new_instance(ide_args)
macOS
Easy solution without need for any paths:
open -b com.jetbrains.pycharm <file>
You can set it as alias for every-day easier usage (put to your ~/.bash_rc etc.):
alias pycharm='open -b com.jetbrains.pycharm'
Usage:
# open current dir:
pycharm .
# open a file:
pycharm file.py
I normally alias using built-in application launcher (open) from OS X:
alias pc='open -a /Applications/PyCharm\ CE.app'
Then I can type:
pc myfile1.txt myfiles*.py
Though you can't (easily) pass args to PyCharm, if you want a quick way to open files (without needing to use full pathnames to the file), this does the trick.
Use Tools -> Create Command-line Launcher which will install a python script where you can just launch the current working folder using charm .
Very important!
Anytime you upgrade your pyCharm you have to re-create that command line tool since its just a python script that points to a pyCharm configuration which might be outdated and will cause it to fail when you attempt to run charm .
To open PyCharm from the terminal in Ubuntu 16.04, cd into
{installation home}/bin
which in my case was
/home/nikhil/pycharm-community-2018.1.1/bin/
and then type:
./pycharm.sh
On Mac OSX
Update 2019/05 Now this can be done in the JetBrains Toolbox app. You can set it once with the Toolbox, for all of your JetBrain IDEs.
As of 2019.1 EAP, the Create Commmand Line Launcher option is not available in the Tools menu anymore. My solution is to use the following alias in my bash/zsh profile:
Make sure that you run chmod -x ...../pycharm to make the binary executable.
# in your ~/.profile or other rc file to the effect.
alias pycharm="open -a '$(ls -r /Users/geyang/Library/Application\ Support/JetBrains/Toolbox/apps/PyCharm-P/**/PyCharm*.app/Contents/MacOS/pycharm)'"
Useful information for some:
On Linux, installing PyCharm as a snap package automatically creates the command-line launcher named pycharm-professional, pycharm-community, or pycharm-educational. The Tools | Create Command-line Launcher command is therefore not available.
Navigate to the directory on the terminal cd [your directory]
Navigate to the directory on the terminal
use charm . to open the project in PyCharm
Simplest and quickest way to open a project in PyCharm
Steps for someone using zsh on Mac:
emacs ~/.zshrc&
Put this in zshrc---> alias pycharm="/Applications/PyCharm\CE.app/Contents/MacOS/pycharm"
source ~/.zshrc
Launch by typing pycharm in command window
The included utility that installs to /usr/local/bin/charm did not work for me on OS X, so I hacked together this utility instead. It actually works!
#!/usr/bin/env bash
if [ -z "$1" ]
then
echo ""
echo "Usage: charm <filename>"
exit
fi
FILENAME=$1
function myreadlink() {
(
cd $(dirname $1) # or cd ${1%/*}
echo $PWD/$(basename $1) # or echo $PWD/${1##*/}
)
}
FULL_FILE=`myreadlink $FILENAME`;
/Applications/PyCharm\ CE.app/Contents/MacOS/pycharm $FULL_FILE
Update: My answer no longer works as of PyCharm 2018.X
On MacOS, I have this alias in my bashrc:
alias pycharm="open -a /Applications/PyCharm*.app"
I can use it like this: pycharm <project dir or file>
The advantage of launching PyCharm this way is that you can open the current dir in PyCharm using pycharm . (unlike /Applications/PyCharm*.app/Contents/MacOS/pycharm . which opens the PyCharm application dir instead)
Update: I switched to JetBrains Toolbox to install PyCharm. Finding PyCharm has gotten a bit more complex, but so far I was lucky with this monster:
alias pycharm="open -a \"\$(ls -r /Applications/apps/PyCharm*/*/*/PyCharm*.app | head -n 1 | sed 's/:$//')\""
After installing on kubuntu, I found that my pycharm script in ~/bin/pycharm was just a desktop entry:
[Desktop Entry]
Version=1.0
Type=Application
Name=PyCharm Community Edition
Icon=/snap/pycharm-community/79/bin/pycharm.png
Exec=env BAMF_DESKTOP_FILE_HINT=/var/lib/snapd/desktop/applications/pycharm-community_pycharm-community.desktop /snap/bin/pycharm-community %f
Comment=Python IDE for Professional Developers
Categories=Development;IDE;
Terminal=false
StartupWMClass=jetbrains-pycharm-ce
Obviously, I could not use this to open anything from the command line:
$ pycharm setup.py
/home/eldond/bin/pycharm_old: line 1: [Desktop: command not found
/home/eldond/bin/pycharm_old: line 4: Community: command not found
But there's a hint in the desktop entry file. Looking in /snap/pycharm-community/, I found /snap/pycharm-community/current/bin/pycharm.sh. I removed ~/bin/pycharm (actually renamed it to have a backup) and then did
ln -s /snap/pycharm-community/current/bin/pycharm.sh pycharm
where again, I found the start of the path by inspecting the desktop entry script I had to start with.
Now I can open files with pycharm from the command line. I don't know what I messed up during install this time; the last two times I've done fresh installs, it's had no trouble.
open /Applications/PyCharm\ CE.app/ opens up the primary Pycharm Dialogue box to choose the project..
worked for me with macOS 10.13.6 & Pycharm 2018.1
pycharm download & Open in UBUNTU
Download:
download pycharm linux version here : https://www.jetbrains.com/pycharm/download/#section=linux
Extract the download the downloaded tar file using : tar -xvf pycharm-Example-tar.gz
Open:
Navigate to bin directory in the extracted folder.
run : ./pycharm.sh
you can include following command in your script
root#aachutha-Inspiron-N5010:~# pycharm-community &
[1] 5698
This worked for me on my 2017 imac macOS Mojave (Version 10.14.3).
Open your ~/.bash_profile:
nano ~/.bash_profile
Append the alias:
alias pycharm="open /Applications/PyCharm\ CE.app"
Update terminal:
source ~/.bash_profile
Assert that it works:
pycharm
Via Terminal (Linux)
Create a function with bash.
charm() { /usr/local/bin/charm; }
export charm
Via Pycharm
Go into Pycharm
Tap Double Shift (Shift + Shift)
Search For Create Command-line Launcher
Type in Command-line Launcher: /usr/local/bin/charm
Click Ok
You can launch Pycharm from Mac terminal using the open command. Just type open /path/to/App
Applications$ ls -lrt PyCharm\ CE.app/
total 8
drwxr-xr-x# 71 amit admin 2414 Sep 24 11:08 lib
drwxr-xr-x# 4 amit admin 136 Sep 24 11:08 help
drwxr-xr-x# 12 amit admin 408 Sep 24 11:08 plugins
drwxr-xr-x# 29 amit admin 986 Sep 24 11:08 license
drwxr-xr-x# 4 amit admin 136 Sep 24 11:08 skeletons
-rw-r--r--# 1 amit admin 10 Sep 24 11:08 build.txt
drwxr-xr-x# 6 amit admin 204 Sep 24 11:12 Contents
drwxr-xr-x# 14 amit admin 476 Sep 24 11:12 bin
drwxr-xr-x# 31 amit admin 1054 Sep 25 21:43 helpers
/Applications$
/Applications$ open PyCharm\ CE.app/

Categories