-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Text expansion support #1848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Text expansion support #1848
Changes from 17 commits
2e9b478
50d2f90
d3b3e45
ff2e399
8925f7c
358458a
ddcd722
a7b85b1
a7d0a4b
5e7bdf7
e88694b
78957cf
291d766
a2592e4
2e09501
8c43f3d
106f5a5
2bc0bce
f5a9d39
ce594b0
2b2f175
713615e
680c2a2
c2c5081
10500c3
172ea82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ const path = require('path') | |
| const fs = require('sander') | ||
| const { remote } = require('electron') | ||
| const { app } = remote | ||
| const os = require('os') | ||
|
||
|
|
||
| const themePath = process.env.NODE_ENV === 'production' | ||
| ? path.join(app.getAppPath(), './node_modules/codemirror/theme') | ||
|
|
@@ -12,6 +13,16 @@ const themes = fs.readdirSync(themePath) | |
| }) | ||
| themes.splice(themes.indexOf('solarized'), 1, 'solarized dark', 'solarized light') | ||
|
|
||
| const snippetFile = process.env.NODE_ENV === 'production' | ||
| ? path.join(app.getPath('appData'), 'Boostnote', 'snippets.json') | ||
| : path.join(getAppData(), 'Boostnote', 'snippets.json') | ||
|
|
||
| function getAppData () { | ||
| return process.env.APPDATA || (process.platform === 'darwin' | ||
| ? path.join(process.env.HOME, 'Library', 'Preferences') | ||
| : path.join(os.homedir(), '.config')) | ||
| } | ||
|
|
||
| const consts = { | ||
| FOLDER_COLORS: [ | ||
| '#E10051', | ||
|
|
@@ -31,7 +42,8 @@ const consts = { | |
| 'Dodger Blue', | ||
| 'Violet Eggplant' | ||
| ], | ||
| THEMES: ['default'].concat(themes) | ||
| THEMES: ['default'].concat(themes), | ||
| SNIPPET_FILE: snippetFile | ||
| } | ||
|
|
||
| module.exports = consts | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import fs from 'fs' | ||
| import crypto from 'crypto' | ||
| import consts from 'browser/lib/consts' | ||
| import fetchSnippet from 'browser/main/lib/dataApi/fetchSnippet' | ||
|
|
||
| function createSnippet (snippetFile) { | ||
| return new Promise((resolve, reject) => { | ||
| const newSnippet = { | ||
| id: crypto.randomBytes(16).toString('hex'), | ||
| name: 'Unnamed snippet', | ||
| prefix: [], | ||
| content: '' | ||
| } | ||
| fetchSnippet(null, snippetFile).then((snippets) => { | ||
| snippets.push(newSnippet) | ||
| fs.writeFile(snippetFile || consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => { | ||
| if (err) reject(err) | ||
| resolve(newSnippet) | ||
| }) | ||
| }).catch((err) => { | ||
| reject(err) | ||
| }) | ||
| }) | ||
| } | ||
|
|
||
| module.exports = createSnippet |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import fs from 'fs' | ||
| import consts from 'browser/lib/consts' | ||
| import fetchSnippet from 'browser/main/lib/dataApi/fetchSnippet' | ||
|
|
||
| function deleteSnippet (snippet, snippetFile) { | ||
| return new Promise((resolve, reject) => { | ||
| fetchSnippet(null, snippetFile).then((snippets) => { | ||
| snippets = snippets.filter(currentSnippet => currentSnippet.id !== snippet.id) | ||
| fs.writeFile(snippetFile || consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => { | ||
| if (err) reject(err) | ||
| resolve(snippet) | ||
| }) | ||
| }) | ||
| }) | ||
| } | ||
|
|
||
| module.exports = deleteSnippet |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import fs from 'fs' | ||
| import crypto from 'crypto' | ||
| import consts from 'browser/lib/consts' | ||
|
|
||
| function fetchSnippet (id, snippetFile) { | ||
| return new Promise((resolve, reject) => { | ||
| fs.readFile(snippetFile || consts.SNIPPET_FILE, 'utf8', (err, data) => { | ||
| if (err) { | ||
| reject(err) | ||
| } | ||
| const snippets = JSON.parse(data) | ||
| if (id) { | ||
| const snippet = snippets.find(snippet => { return snippet.id === id }) | ||
| resolve(snippet) | ||
| } | ||
| resolve(snippets) | ||
| }) | ||
| }) | ||
| } | ||
|
|
||
| module.exports = fetchSnippet |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import fs from 'fs' | ||
| import consts from 'browser/lib/consts' | ||
|
|
||
| function updateSnippet (snippet, snippetFile) { | ||
| return new Promise((resolve, reject) => { | ||
| const snippets = JSON.parse(fs.readFileSync(snippetFile || consts.SNIPPET_FILE, 'utf-8')) | ||
|
|
||
| for (let i = 0; i < snippets.length; i++) { | ||
| const currentSnippet = snippets[i] | ||
|
|
||
| if (currentSnippet.id === snippet.id) { | ||
| if ( | ||
| currentSnippet.name === snippet.name && | ||
| currentSnippet.prefix === snippet.prefix && | ||
| currentSnippet.content === snippet.content | ||
| ) { | ||
| // if everything is the same then don't write to disk | ||
| resolve(snippets) | ||
| } else { | ||
| currentSnippet.name = snippet.name | ||
| currentSnippet.prefix = snippet.prefix | ||
| currentSnippet.content = snippet.content | ||
| fs.writeFile(snippetFile || consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => { | ||
| if (err) reject(err) | ||
| resolve(snippets) | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| module.exports = updateSnippet |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| import CodeMirror from 'codemirror' | ||
| import React from 'react' | ||
| import _ from 'lodash' | ||
| import fs from 'fs' | ||
|
||
| import consts from 'browser/lib/consts' | ||
|
||
| import dataApi from 'browser/main/lib/dataApi' | ||
|
|
||
| const defaultEditorFontFamily = ['Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'monospace'] | ||
| const buildCMRulers = (rulers, enableRulers) => | ||
| enableRulers ? rulers.map(ruler => ({ column: ruler })) : [] | ||
|
|
||
| export default class SnippetEditor extends React.Component { | ||
|
|
||
| componentDidMount () { | ||
| this.props.onRef(this) | ||
| const { rulers, enableRulers } = this.props | ||
| this.cm = CodeMirror(this.refs.root, { | ||
| rulers: buildCMRulers(rulers, enableRulers), | ||
| lineNumbers: this.props.displayLineNumbers, | ||
| lineWrapping: true, | ||
| theme: this.props.theme, | ||
| indentUnit: this.props.indentSize, | ||
| tabSize: this.props.indentSize, | ||
| indentWithTabs: this.props.indentType !== 'space', | ||
| keyMap: this.props.keyMap, | ||
| scrollPastEnd: this.props.scrollPastEnd, | ||
| dragDrop: false, | ||
| foldGutter: true, | ||
| gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], | ||
| autoCloseBrackets: true | ||
| }) | ||
| this.cm.setSize('100%', '100%') | ||
| let changeDelay = null | ||
|
|
||
| this.cm.on('change', () => { | ||
| this.snippet.content = this.cm.getValue() | ||
|
|
||
| clearTimeout(changeDelay) | ||
| changeDelay = setTimeout(() => { | ||
| this.saveSnippet() | ||
| }, 500) | ||
| }) | ||
| } | ||
|
|
||
| componentWillUnmount () { | ||
| this.props.onRef(undefined) | ||
| } | ||
|
|
||
| onSnippetChanged (newSnippet) { | ||
| this.snippet = newSnippet | ||
| this.cm.setValue(this.snippet.content) | ||
| } | ||
|
|
||
| onSnippetNameOrPrefixChanged (newSnippet) { | ||
| this.snippet.name = newSnippet.name | ||
| this.snippet.prefix = newSnippet.prefix.toString().replace(/\s/g, '').split(',') | ||
| this.saveSnippet() | ||
| } | ||
|
|
||
| saveSnippet () { | ||
| dataApi.updateSnippet(this.snippet).catch((err) => { throw err }) | ||
| } | ||
|
|
||
| render () { | ||
| const { fontSize } = this.props | ||
| let fontFamily = this.props.fontFamily | ||
| fontFamily = _.isString(fontFamily) && fontFamily.length > 0 | ||
| ? [fontFamily].concat(defaultEditorFontFamily) | ||
| : defaultEditorFontFamily | ||
| return ( | ||
| <div styleName='SnippetEditor' ref='root' tabIndex='-1' style={{ | ||
| fontFamily: fontFamily.join(', '), | ||
| fontSize: fontSize, | ||
| position: 'absolute', | ||
|
||
| width: '100%', | ||
| height: '90%' | ||
| }} /> | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| SnippetEditor.defaultProps = { | ||
| readOnly: false, | ||
| theme: 'xcode', | ||
| keyMap: 'sublime', | ||
| fontSize: 14, | ||
| fontFamily: 'Monaco, Consolas', | ||
| indentSize: 4, | ||
| indentType: 'space' | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remoteis never used, please remove it.