Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mschmidtkorth committed Feb 19, 2020
0 parents commit 03ffdad
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 0 deletions.
27 changes: 27 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Contributing to Salesforce DX (SFDX) Status for iTerm2
I'm happy about any ideas, suggestions for enhancements or contributions of code you might have!

# Reporting a Bug
If you think you have found a bug, please

- Check that your bug has not already been reported
- Create a new GitHub issue providing
- Your iTerm version
- Your SFDX version
- An explanation of the bug, providing the exact steps if it is reproducible
- Your expected behavior
- Any debug/error output

# Suggesting an Enhancement
If you have an idea for a new feature, or an enhancement of an existing one, please raise a new GitHub issue.

# Contributing your Code
If you already programmed a new feature or enhancement (awesome!), please

1. Fork it! Clone it locally to start coding.
2. Create your feature branch: `git checkout -b my-new-feature`
3. Make and commit your changes: `git commit -m 'Add new feature'`
4. Push to the feature branch: `git push origin my-new-feature`
5. Submit a Pull Request from your feature branch to the `develop` branch

See [here](https://blog.scottlowe.org/2015/01/27/using-fork-branch-git-workflow/) for a detailed explanation.
Binary file added Example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Salesforce DX (SFDX) Status for iTerm2
Adds the status of Salesforce DX projects to your iTerm2 status bar.

## Requirements

- [iTerm2](https://github.com/gnachman/iTerm2)

## Installation

1. Go to *iTerm2 > Preferences > General > Magic* and check "Enable Python API"
2. Copy `SFDX.py` to `~/Library/Application Support/iTerm2/Scripts/AutoLaunch/`
3. Go to *Scripts > AutoLaunch* and check "SFDX.py" to allow the script as a Status Bar component
4. Go to *Preferences > Profiles > <yourProfile> > Session* and click "Configure Status Bar"
5. Drag & drop the component "SFDX Status" into the Active Components pane (you might need to scroll in the upper pane)
6. Select the component in the active pane, and click "Configure Component"
7. Make your respective configurations
8. `cd` into any directory with a `.force` project folder
9. Check your status bar

## Usage

- Simply open any directory that contains a `.force` folder and watch your status bar change
- If a cloud is displayed but nothing else, the current directory is not a SFDX project folder
- Click on the status bar component to display the org's expiration date

![Example prompt](Example.png)

**Note** The fish prompt for SFDX can be found [here](https://github.com/mschmidtkorth/fish-pure-prompt-salesforce-dx).

## How to Contribute

Please see the [contribution guidelines](CONTRIBUTING.md).

## Changelog

- **0.1.0** (2020-02-19)
- Initial release
69 changes: 69 additions & 0 deletions SFDX.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env python3.7
# encoding: utf-8
import iterm2

aliasOrUsername = ''


async def main(connection):
# Executing 'sfdx force:org:display' takes >5 seconds, which would timeout coro() if executed within. Therefore, 'sfdx force:org:display' is only executed on demand within the onclick handler.
@iterm2.RPC
async def displayExpirationDate(session_id):
await component.async_open_popover(session_id, "<p style='font-family: Arial'>Retrieving org expiration date... <em>(wait)</em></p>", iterm2.Size(300, 30))

from subprocess import Popen, PIPE
import json
p = Popen(['sfdx force:org:display --targetusername=' + aliasOrUsername + ' --json'], stdin = PIPE, stdout = PIPE, stderr = PIPE, universal_newlines = True, shell = True)
stdout, stderr = p.communicate()
result = ''
if stdout:
result = json.loads(stdout)
if stderr:
result = json.loads(stderr)
expiration = ''
if stderr and 'status' in result and result['status'] == 1:
expiration += '(error)'
elif stdout and 'status' in result and (result['status'] == 'Active' or result['status'] == 0):
expiration += result['result']['expirationDate']
elif stdout and 'status' in result and (result['status'] == 'Expired' or result['status'] != 0):
expiration += '(expired)'
elif stdout:
expiration += 'Never - org is a sandbox.'

await component.async_open_popover(session_id, "<p style='font-family: Arial'>The scratch org expires on: <strong>" + expiration + '</strong></p>', iterm2.Size(350, 30))

knobs = [iterm2.CheckboxKnob("Enable expiration date", False, "showExpirationDate")]
component = iterm2.StatusBarComponent(short_description = "SFDX Status", detailed_description = "Provides status info for SFDX project folders", knobs = knobs, exemplar = u"\u2601 SFDC-1234 [email protected]", update_cadence = None, identifier = "com.msk.sfdx")

@iterm2.StatusBarRPC
async def coro(knobs, path = iterm2.Reference("path"), cwd = iterm2.Reference("user.currentDir?")):
import os
import json
from pathlib import Path

currentDir = path
if 'force-app' in currentDir: # User is in subdirectory
currentDir = currentDir.split('force-app')[0] # Get root directory of project folder
if Path(currentDir + '/sfdx-project.json').is_file(): # Current folder is sfdx folder
# Retrieve defaultusername = alias
dir = currentDir if Path(currentDir + '/.sfdx/sfdx-config.json').is_file() else os.environ['HOME'] # Get config from project folder if present, or global config
with open(dir + '/.sfdx/sfdx-config.json') as configFile:
config = json.load(configFile)
global aliasOrUsername
aliasOrUsername = config['defaultusername']

# Retrieve username for alias
with open(os.environ['HOME'] + '/.sfdx/alias.json') as aliasFile:
alias = json.load(aliasFile)

if 'defaultusername' in config and 'orgs' in alias:
return u'\u2601 ' + config['defaultusername'] + u' \u2022 ' + alias['orgs'][config['defaultusername']]
else:
return u'\u2601' # Some error occurred, e.g. file not found or wrong content
else:
return u'\u2601' # No SFDX directory

await component.async_register(connection, coro, timeout = 15.0, onclick = displayExpirationDate)


iterm2.run_forever(main)

0 comments on commit 03ffdad

Please sign in to comment.